ECS+ALBのローリングアップデートにおけるデプロイにかかる時間とチューニング観点

はじめに

ECS + ALBをよく使いますが、特に開発中などで頻繁にデプロイする場合など、デプロイ完了までの時間が気になったり、早くしたいと思うことがありました
ECS + ALBでのデプロイ時間に関するチューニングポイントを書きます
今回はローリングアップデートにしぼって書きます

タスクのライフサイクルと各状態のチューニング

AWSのドキュメントでタスクのライフサイクルが紹介されています
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-lifecycle.html

AWSドキュメントからタスクのライフサイクルの図

この各状態の補足やチューニングについて書きます

Provisioning

コンテナが動く基盤をプロビジョニングする段階

  • 特に言うことなし

Pending

コンテナを起動する段階

Activating

タスク(コンテナ)が起動した後、ALBのターゲットグループに登録する段階

  • ターゲットグループのヘルスチェック
    • HealthCheckIntervalSeconds
      • デフォルトは30秒 範囲は5~300秒
    • HelthyThresholdCount
      • 非正常なターゲットが正常であるとみなすまでに必要なヘルスチェック連続成功回数
      • デフォルトは5 範囲は2~10
      • ALBでターゲットが新規登録(initializing)する場合は"非正常なターゲット"ではなく、このパラメータは関係なく、1度目のヘルスチェック合格でHealthyとなる
    • HelthCheckGracePeriodSeconds
      • タスク起動直後からこの秒数、ALBからのヘルスチェックの不合格を無視する(つまり起動してからヘルスチェック合格できるような状態になるまで HealthCheckIntervalSeconds * UnhealthyThresholdCount 秒かかる場合とかにこれを利用するといい)
      • ALBからのヘルスチェック開始を遅らせるものだと思ってたけど、ちゃんと読んでみたら違いそう?要検証

ヘルスチェックの合格、不合格までの時間を短くすることで、新タスクの投入や障害タスクのdrainが早くなる
短すぎるとヘルスチェック自体のリクエスト数が増えたり、偽陽性などがありえるので、適切に調整する

Running

  • ローリングアップデート等の場合、新しいタスクがRunningに移行したら旧タスクをDeactivatingに移行する
    • 新タスクがRunningになってから旧タスクがDeactivatingになるまでに約1分かかる(体感)
    • AWSサポートに聞いたところ、この約1分の待ち時間はチューニングできないらしい

Deactivating

ALBからタスクへのコネクションを切る段階

  • ターゲットグループの deregistration_delay
    • ターゲットへの新規リクエスト送信を停止してからターゲットを切り離すまでの時間
    • これを短くすると早く切り離される
    • デフォルトは300秒 設定範囲は0~3600秒

アプリの特性、基本的には最大レスポンスタイムくらいに合わせて適切な時間にする

Stopping

SIGTERMを受け取ってコンテナが終了する段階

  • タスク定義の stopTimeout
    • SIGTERM から SIGKILLまでの待ち時間
    • デフォルトは30秒 最大は120
    • ECS_CONTAINER_STOP_TIMEOUT というECSエージェント変数もある
    • アプリのgraceful shutdownの特性に合わせて設定する

停止中の時間が長くて新しいタスクが起動できないといった問題はありえるので、適切に短くしたい

Deprovisioning

  • 言うことなし

改めてこれらを踏まえたローリングアップデートにおける状態遷移例は以下のようになります

ライフサイクル

ローリングアップデートにおけるチューニング

ECSの基本的なデプロイ戦略であるローリングアップデートにおいて、デプロイ時間に関わるチューニング項目は以下です

  • maximumPercent
    • アップデート時のdesiredタスク数に対するRUNNING, STOPPING, PENDINGといった起動中タスク数の割合
    • デプロイ時の新旧あわせたタスク起動数が、通常時のDesired数からどれだけ上振れていいかの設定
  • minimumHealthyPercent
    • アップデート進行中に維持すべきRunningタスクの割合

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service_definition_parameters.html#sd-deploymentconfiguration

各パラメータの組み合わせによる振る舞いを、Desiredタスク数: 4 のサービスを例に図示します

maximumPercent: 200, minimumHealthyPercent: 100

通常時のRunningタスク数を維持しつつ、一気に新タスクの起動ができるのでデプロイ完了まで早い
デプロイ時にリソース使用量が上振れるのを許容できる場合はこれでいいはず

ローリングアップデート1

maximumPercent: 100, minimumHealthyPercent: 50

リソース使用量の上振れが許容できないが、デプロイ完了を早くしたい場合はこんな感じ

ローリングアップデート2

maximumPercent: 100, minimumHealthyPercent: 70

リソースが限られていて、かつ、デプロイ進行中におけるRunningなタスク数もある程度維持したい場合はこういう感じ
この場合はもっともデプロイの進行が遅い

ローリングアップデート3

おわりに

ALB + ECSにおいてローリングアップデートのデプロイ速度に関連するチューニングポイントを書きました。
ここに書いてないものもあると思います。
デプロイの高速化や、適切なチューニングのお役に立てれば嬉しいです。