はじめに
ECSのサービスがApplication Load Balancerの後段にある場合、ECSがコンテナを停止(SIGTERMの送信)する前に、ターゲット グループからタスクを解除する挙動をします。具体的には以下のフローとのこと。
本記事では、この挙動をタスクの再起動時に以下を計測することで確認しました。
- ターゲットグループに登録されているターゲットと状態
- ECSタスクで起動しているタスク数
- ECSタスクのログ
環境情報
- ECS Fargate 1.4
- aws-cli/2.15.5
事前準備
以下の構成を準備し、Task数は1としてApacheコンテナを用意。ALBからのヘルスチェックは最短の間隔にします。
この状態でApacheコンテナのサービスの再起動を行い、新たなタスクがターゲットグループに登録されるタイミングや新たなタスクに通信が割り振りされるタイミング、元のタスクがターゲットグループから切り離されるタイミング、元のタスクにcurlコマンドが届かなくなるタイミングを確認しました。
尚、定期的に情報を確認するコマンド以下です。
# ECSのサービスとして"runningCount"と"pendingCount"を確認 $ aws ecs describe-services --services apache --cluster xx
# Target数と"TargetHealth"の状態を確認 $ aws elbv2 describe-target-health --target-group-arn xx
時系列
経過秒 | イベント |
---|---|
0s | ECSクラスターに対してApacheサービスの再起動を指示 |
17s | タスクのpendingCountが0→1になる |
58s | "TargetHealth"の"State"が"initial"のTargetが表示される |
68s | タスクのpendingCountが1→0, runningCountが1→2になる |
70s | TargetHealthの"State"が"initial"から"healthy"となる |
72s | 新たに起動したタスクで応答処理が行われる |
110s | タスクのrunningCountが2→1になる |
123s | TargetHealthの"State"が"healthy"から"draining"となる |
129s | 元々動いていたタスクで最後の応答処理が行われる |
考察
今回の流れを抽象化すると、以下のようになっています。
- > New ECS Task Creation
- > New ECS Task - Created
- > New ECS Task - Activating
- > New TG Target - Registered
- > New ECS Task - Running
- > New TG Target - Health Status: Healthy
- > Old ECS Task - Deactivating
- > Old TG Target - Health Status: Draining
- > Old ECS Task - Stopping
- > Old ECS Task - Deleted
ポイントは、ALBのヘルスチェックによるターゲットの切り離しとは独立してECSのタスクのActivate/Deactivateを元にターゲットグループが追加/削除されている点にあります。
これによって「ヘルスチェックエラーによる切り離しより前にコンテナが停止してしまってエラーが発生する」という事象を防ぐ機構になっているのだと思いました。
尚、参考までにTargetGroupを確認した際の「initial」「draiing」の全文を載せておきます。
{ "Target": { "Id": "xx", "Port": 80, "AvailabilityZone": "ap-northeast-1a" }, "HealthCheckPort": "80", "TargetHealth": { "State": "initial", "Reason": "Elb.RegistrationInProgress", "Description": "Target registration is in progress" } }
{ "Target": { "Id": "xx", "Port": 80, "AvailabilityZone": "ap-northeast-1a" }, "HealthCheckPort": "80", "TargetHealth": { "State": "draining", "Reason": "Target.DeregistrationInProgress", "Description": "Target deregistration is in progress" } },
終わりに
ECSとTargetGroupが連動することで通常のヘルスチェックの切り離しとは異なる動きとなりますが、AWSサービス同士としてうまくできています。実際、再起動中に全ての通信で正常な応答が返ってきていました。
以上、ご参考になれば幸いです。