(O+P)ut

アウトプット



(O+P)ut

エンジニアのアウトプット

【AWS/ECS】コンテナの停止とALBのターゲットグループからの解除タイミングについて

スポンサーリンク

はじめに

ECSのサービスがApplication Load Balancerの後段にある場合、ECSがコンテナを停止(SIGTERMの送信)する前に、ターゲット グループからタスクを解除する挙動をします。具体的には以下のフローとのこと。

Graceful shutdowns with ECS より抜粋

本記事では、この挙動をタスクの再起動時に以下を計測することで確認しました。

  • ターゲットグループに登録されているターゲットと状態
  • ECSタスクで起動しているタスク数
  • ECSタスクのログ
環境情報
  • ECS Fargate 1.4
  • aws-cli/2.15.5

事前準備

以下の構成を準備し、Task数は1としてApacheコンテナを用意。ALBからのヘルスチェックは最短の間隔にします。

ALB経由でECSのTaskに通信を行う

この状態で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サービス同士としてうまくできています。実際、再起動中に全ての通信で正常な応答が返ってきていました。

以上、ご参考になれば幸いです。