[アップデート] Amazon ECS マネージドデーモンが重要度の低いデーモンをサポートするようになりました
はじめに
皆様こんにちは、あかいけです。
Amazon ECS Managed Instancesでマネージドデーモンを使っていますか?
これはセキュリティ監視やロギングなどのエージェントをアプリケーションと分離して管理できる便利な機能ですが、これまでは「デーモンタスクが落ちたら、コンテナインスタンスごとドレインして入れ替える」という潔い挙動しかありませんでした。
しかし先日マネージドデーモンの重要度を設定できるようになるアップデートがありました。
これアップデートにより、デーモンを重要度が低い設定すれば、デーモンが落ちてもアプリケーションタスクは停止することなく、継続できるらしいです。
というわけで挙動を検証してみました。
アップデートの概要
Amazon ECS マネージドデーモンとは
Amazon ECS マネージドデーモンは、Amazon ECS Managed Instances上のすべてのコンテナインスタンスに、デーモンタスクを1つ確実に配置 / 管理してくれる機能です。
アプリケーションのデプロイとはライフサイクルが分離されているため、アプリを再デプロイすることなくデーモンだけを更新でき、更新はローリングデプロイでクラスター内の全コンテナインスタンスに展開されます。
またアプリケーションタスクより先にデーモンタスクが起動する点も特徴で、「ロギングやトレーシングのためのコンテナが起動する前にアプリが処理を始めてしまう」といった問題を防いでくれます。
今回のアップデート
今回追加されたのは、デーモンに重要度を設定できるという変更です。
ドキュメントにてこの機能は以下のように説明されています。
Critical - The default. Amazon ECS starts the daemon task before it places application tasks on the instance, and if the daemon task stops or becomes unhealthy, Amazon ECS drains and replaces the container instance.
Non-critical - Set the
criticalparameter tofalse. The daemon task operates independently of container instance health. If a non-critical daemon task fails, stops, or becomes unhealthy, Amazon ECS keeps the container instance active. Existing application tasks keep running, and Amazon ECS keeps placing new application tasks on it. A non-critical daemon never blocks instance registration, so application tasks can be placed immediately even if the daemon fails to start.
要約すると以下の2択が選べるようになりました。
- Critical
- 従来通りの挙動、デフォルトだとこちらの設定になる
- デーモンタスクが停止 / 異常になったら、コンテナインスタンスごとドレインして入れ替える
- Non-critical
- デーモンの状態に関わらず、コンテナインスタンスはアクティブのまま
- そのため既存 / 新規のアプリケーションタスクは影響を受けない
検証してみる
検証環境について
検証用のインフラはTerraformで構築しました。
コードは以下のGitHubリポジトリに置いています。
なおブログを書いた時点の最新のプロバイダー(terraform-provider-aws v6.63.0)では、デーモンタスクのリソース(aws_ecs_daemon)で重要度は指定できませんでした。
そのため重要度の切り替えはAWSマネジメントコンソールから行ってみます。
重要度がクリティカルな場合にデーモンを停止する(従来の挙動)
まずは比較として従来の挙動を確認します。
アプリタスク(ecs-daemon-critical-app)とデーモンタスク(ecs-daemon-critical-daemon)が1つのコンテナインスタンス上でそれぞれ稼働している状態です。

このデーモンタスクを手動で停止してみます。

すると元のコンテナインスタンスが登録解除中のステータスになり、代わりに新しいコンテナインスタンスがすでにアクティブとして立ち上がります。

タスク一覧では元のコンテナインスタンス上にあったアプリタスク・デーモンタスクの両方が「停止済み」になり、新しいインスタンス上でアプリタスク・デーモンタスクの両方が「実行中」として起動しているのが分かります。

ドキュメントの説明通り、 重要度がクリティカルだとデーモンタスクの障害によってコンテナインスタンスの入れ替えが発生することが確認できました。
重要度が非クリティカルな場合にデーモンを停止すると(今回のアップデートで追加)
続いて、このデーモンの重要度を非クリティカルに変更してみます。
マネジメントコンソール上だと「重要」のチェックを外して保存することで設定できます。

更新するとローリングデプロイが走り、コンテナインスタンスが入れ替わっていきます。
なおこの時点では重要度がクリティカルの設定からの移行なので、ドレインが発生するようです。

これで、非クリティカル設定のデーモンタスクが新しいコンテナインスタンス上で稼働している状態になりました。

重要度が非クリティカルなタスクを停止する
では非クリティカルなデーモンタスクが正常に稼働していることを確認した上で、

このデーモンタスクを、先ほどと同様に手動で停止させてみます。
すると、コンテナインスタンス一覧では該当インスタンスがアクティブを維持したまま、ドレインが発生しませんでした。

タスク一覧を見ると、アプリタスクは「実行中」のまま継続し、デーモンタスクだけが「停止済み」になっています。

ドキュメントに書かれている通り、アプリケーションタスクは無停止で継続することが実機でも確認できました。
停止した重要度が非クリティカルなタスクを復旧する
ここで気になったのが、「止まったデーモンタスクは、どうやって復旧させるのか?」という点です。
まずデーモンのパラメータを変えずに、更新だけしてみます。

この場合は、デーモンタスクは復旧しませんでした。
更新は問題なく完了するものの、既にデーモンが停止しているコンテナインスタンスへは何も配置されないという結果でした。
次に、デーモンタスク定義を新しいリビジョン(3)に切り替えて、改めて更新を実行してみました。(リビジョンの設定内容は古いリビジョンと同様)

今回はローリングデプロイが発生しました。

コンテナインスタンス一覧を見ると、デーモンが停止していた元のコンテナインスタンスがドレイン中になり、新しいインスタンスがアクティブとして立ち上がっています。

最終的に、タスク一覧では新しいインスタンス上でアプリタスク(app:3)とデーモンタスク(daemon:3)の両方が「実行中」になり、デーモンが復旧しました。

つまり「デーモンタスク定義の更新などでコンテナインスタンスが入れ替わる」といった場合に新規コンテナインスタンス側でデーモンが起動します。
なおこの挙動もドキュメントにも明記されていました。
When you update a daemon to a new task definition revision, Amazon ECS performs a rolling deployment across all instances in the associated capacity providers. During the deployment, Amazon ECS drains a configurable percentage of instances simultaneously, provisions replacement instances with the updated daemon, and replaces your Amazon ECS service tasks automatically.
そのためデーモンが停止したコンテナインスタンスでは、同一のコンテナインスタンスでデーモンが復旧することはないと言えます。
初めから起動ができないデーモンをデプロイしてみる
ここまでは「一度正常に起動したデーモンを手動で停止する」ケースを見てきました。
ただドキュメントでは「デーモンタスクがそもそも起動に失敗する」場合の挙動について記載があり、どちらかというとこのユースケースを想定しているように見えます。
Criticality controls what Amazon ECS does when a daemon task doesn't start, or stops later. For a critical daemon, a task that fails to start keeps the instance from becoming active.
というわけでこちらも試してみました。
新しいコンテナをビルドするのは面倒だったので、デーモンタスク定義にて存在しない適当なイメージを指定して新しいリビジョン(4)作成しました。

重要度が非クリティカルな場合
まずは非クリティカルのまま、このリビジョン4に更新してみます。

結果はデーモンタスク(ecs-daemon-critical-daemon:4)はCannotPull...で停止していますが、アプリタスク(ecs-daemon-critical-app:3)はきちんと実行中になっています。

その後もアプリタスクは特に問題なく稼働を続けており、デーモン(daemon:4)はCannotPull...で停止したまま、対応するインスタンス自体も入れ替わっていますが、アプリタスクへの影響はありませんでした。

というわけで、一度も起動できていないデーモンであっても、非クリティカルであればインスタンスの登録・アプリタスクの配置はブロックされないことが確認できました。
重要度がクリティカルな場合(従来の挙動)
次に同じ「起動しないデーモン(リビジョン4)」を、今度は重要にチェックを入れた状態で更新してみます。

デプロイ開始直後は、非クリティカルのときと同様に新しいコンテナインスタンスが立ってはCannotPull...で失敗する、という状況が繰り返し発生しましたが、最終的にはアプリタスクのみ実行中のステータスで残りました。

デーモンの「デプロイ」タブを確認すると、デプロイサーキットブレーカーが作動し、自動的にロールバックされていたことが分かりました。

これによりデーモンタスクの起動失敗が3回続いた時点でサーキットブレーカーが働き、デプロイ全体が「ロールバックが成功」というステータスで終了しています。
とはいえ、ロールバックが完了するまでの間はコンテナインスタンスの起動・失敗が繰り返され、アプリタスクの新規配置も不安定になっていたので、決して無視できる影響ではないでしょう。
さいごに
以上、Amazon ECS マネージドデーモンの重要度オプションを実際に検証してみました。
今回の触ってみて感じたのは、「デーモンが落ちても放置しておけばOK」という機能ではなく、「デーモンが落ちてもアプリは停止しないが、デーモン自体の復旧は別途考慮する必要がある機能」ということです。
なので実際のシステムに導入するなら、以下あたりが現実的な使い分けかなと思いました。
- ロギングやメトリクス収集のエージェントのような、「一時的に止まってもアプリの提供は継続したい」デーモンはnon-criticalにしておく
- ただし放置すると気づかないうちに「デーモンがいないインスタンス」が増えていくので、EventBridgeイベントなどと組み合わせて「デーモンが落ちたら検知し、タスク定義を更新して復旧させる」運用フローとセットで導入する
- 逆にService ConnectのプロキシやCSIドライバのような、無いとアプリがまともに機能しないデーモンはcriticalのままにしておく
今後導入する際は、まずこのあたりの運用フローを固めてから使ってみようと思います。









