Amazon ECS サービスのスロットリング(コンテナ無限起動)をCloudWatch Eventsで検知する

Amazon ECSサービスによるコンテナの無限起動をCloudWatch Eventsで検知する方法
2018.05.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ども、大瀧です。
Amazon ECSのサービススケジューラは、ECSでサーバーアプリケーションを実行するための機能です。Auto Scalingなどもありますが、事前に設定したコンテナ数を維持するようにコンテナを適宜起動したり、コンテナのリビジョン管理をしてくれます。

コンテナ(ECSではタスクと呼びます)の実行を妨げる要因は様々あり、「起動しようとするけど動かずタスクの停止と起動を繰り返す」という無限ループ(スロットリング状態)になることがしばしばあります。本ブログでは、これを検知するためにCloudWatch Eventsを利用する手法をご紹介します。

ECSタスクのライフサイクルとループのパターン

ECSはDockerコンテナおよびその集合をタスク、タスクの状態をステータスとして把握し、そのライフサイクルを管理します。通常のライフサイクルはPENDING(実行待ち)RUNNING(実行中)STOPPED(終了済み)で遷移します。サーバーアプリケーションであれば、RUNNINGが持続する想定ですね。

今回のテーマである無限ループのパターンは、以下の2通りがあります。

  1. PENDINGSTOPPEDのループ
  2. PENDINGRUNNINGSTOPPEDのループ

1の場合はECSクラスタ側でリソースの空きがない、イメージ名が不正などコンテナの外的要因でひっかかるケースですね。こちらはECS側でループを検知し、タスクの再実行を最長15分まで待つ仕組みがあります。

いわゆるエクスポネンシャルバックオフと同様の、サーキットブレーカー的なアプローチですね。

一方で、2の場合は連続実行しない実行プロセスを指定している、実行に必要な環境変数の指定漏れなどコンテナの内部処理が原因で終了するケースで、一度はコンテナが起動します。コンテナが終了し規定のコンテナ数(desiredCount)が不足してECSサービスがそれを補充するというECSとしては通常のフローになるため、調整ロジックがはたらかない点に注意が必要です。

CloudWatch Eventsでタスクのステータス遷移をカウントする

先述のいずれのループでも、それを検知するための専用の仕組みは特に提供されていません。ECSのDescribeServices APIのレスポンスには直近100件のイベントが含まれるので、それをAWS Management ConsoleやAWS CLIで確認するのが最も手軽なチェック方法になります。

これだと運用が辛いので、ここではCloudWatch EventsでECSタスクのステータス変更をカウントし、それをCloudWatch Alarmで検知する手法をやってみます。なお、「CloudWatchのメトリクスを使えばいいのでは?」という疑問を持たれるかもしれませんが、ECSのメトリクスは2018年5月現在、リソース使用率に関するもののみでタスク実行などイベントに関するメトリクスはありません。欲しい。

設定手順

AWS Management ConsoleのCloudWatch管理画面から[イベント]-[ルール]を選択し、[ルールの作成]ボタンをクリックします。

ルールの作成画面では、まずは以下の要領でイベントソースを選択します。

  • 「イベントパターン」(既定)を選択
  • [一致するイベントパターンの構築...]は「サービス別のイベント」を選択
  • [サービス名]は「EC2 Container Service(ECS)」 *1を選択
  • [イベントタイプ]は「状態変更」を選択
  • detail typeは「Specific detail type(s)」から「ECS Task State Change」を選択
  • clusterは全クラスタ、特定のクラスタのみ指定のどちらでもOK

選択できる最も細かいイベント種別が「状態変更」なので、RUNNINGへの変更、STOPPEDの変更など全てがカウントされることに注意してください。

ターゲットは今回の目的(CloudWatchメトリクスを取りたい)としては特に不要ですが必須の項目なので、サブスクリプションなしのダミーのSNSトピックを事前に作成し、ここでは指定しました。

次の画面で任意のルール名(今回はECSTaskStateChangeNotifyとしました)を入力し、ルールを作成すればOKです。メトリクスが収集されるまで数分待ちCloudWatchのメトリクス一覧画面を見てみると、「イベント」(CloudWatch Events)のメトリクスが出てくるのでクリックします。

[ルール名別]をクリックすると、先ほど作成したECSTaskStateChangeNotifyのメトリクスがリストされます。これらのうち「呼び出し (Invocations)」がステータス変更を検知したカウント数です。

あとは"1時間ごと"の"合計値"などメトリクスの設定を調整し、鐘のアイコンからCloudWatchアラームを仕掛ければ通知設定は完了です。

しきい値の調整と留意点

アラーム設定ではしきい値の調整が必要です。正常時とループ時のトレンドをある程度観察した上で設定するのが良いでしょう。判断する際の留意点を記します。

  • タスクの全てのステータス変更をカウントするので、カウントの値はタスク実行数の2倍か3倍になることを考慮すること
  • コンテナのリビジョンアップやスケールアウトによる変更もカウントされるので、それに伴うアラーム通知が許容できること

まとめ

Amazon ECSサービスによるコンテナの無限起動をCloudWatch Eventsで検知する方法をご紹介しました。検知条件がユルいので完璧な監視手法というわけではありませんが、気づくためのトリガーとしては十分使えるかなと思います。ECS運用の役に立てられれば幸いです。

脚注

  1. 古いサービス名ですね。。。(^^;