ECSタスク定義のヘルスチェックコマンドを設定してみた

2022.02.17

こんにちは!DA(データアナリティクス)事業本部 サービスソリューション部の大高です。

ECSのタスク定義では、コンテナ定義のパラメータとして「ヘルスチェックコマンド」を設定することができます。

今回、このヘルスチェックコマンドを設定してみたので書き残しておきたいと思います。

やりたいこと

今回設定するECSのタスクでは、ウェブサーバを動かしており、既に以下のようなヘルスチェックコマンドを設定しています。

CMD-SHELL, curl -f http://localhost/ || exit 1

ただ、今回はさらに独自のチェック処理も追加で組み込んで「両方のチェックがOKだったら問題ない」という判断にしたいと思います。

ヘルスチェックコマンドとその意味

設定するパラメータは、以下のドキュメントにも記載のある「ヘルスチェックコマンド」です。

タスク定義パラメータ - Amazon ECS

例として以下が記載されています。

CMD-SHELL, curl -f http://localhost/ || exit 1

このコマンドの意味については、Dockerのドキュメントに記載があります。

Docker Engine API v1.38 Reference

CMD-SHELLとは?

まず一番左側の CMD-SHELL ですが、これは「システムのデフォルトシェルでカンマのあとに続くコマンドを実行する」ことを示しています。

また、こちらは試せていませんがCMDと定義することで、カンマのあとに続くコマンドを直接実行することもできるようです。

CMD-SHELLにわたすコマンド

カンマのあとに続くコマンドですが、このコマンド curl -f http://localhost/ || exit 1 の意味を考えてみます。

$ curl --help
(...snip...)
-f, --fail          Fail silently (no output at all) on HTTP errors
(...snip...)

まず、curl -f http://localhost/ はHTTPエラーで失敗した際に出力なしでエラー終了するオプションのようです。

エラーの場合の挙動を試してみます。

% curl -f http://localhost/ 
curl: (7) Failed to connect to localhost port 80: Connection refused

% echo $?                              
7

ちょっと想定外でしたが、curlコマンドの出力は出ましたね。echo $?は直前のコマンドの終了コードを出力するコマンドです。コード7を出力しています。ちなみに正常終了時はコード0なので今回は異常終了扱いですね。

次に、このcurlコマンドのあとの演算子||です。これは、左側のコマンドが失敗した場合に、右側のコマンドが実行されます。

つまり、curl -f http://localhost/が失敗したら(終了コードが0以外だったら)exit 1が実行されてエラー終了するということですね。(正常終了はexit 0

今回やりたいことは「追加のチェックを入れたい」なので、以下のようにcurlコマンドのあとに&&演算子を入れてfoobarコマンドを併せて評価させ、その結果がエラーだったらエラー終了としたいと思います。

curl -f http://localhost/ && foobar || exit 1

なお、&&演算子は左側から評価されるので、この場合だとcurlコマンドが先に評価されます。

追加チェック用に用意するコマンドについて

追加チェック用にコマンドを用意しますが、今回はPythonで作成してCLI実行できるようにしました。

詳細は割愛しますが、このCLIコマンドは正常終了時には0を返し、異常終了時には1を返します。

設定してみた

では、実際に設定してみます。

タスク定義画面から「新しいリビジョンを作成」をクリックし、「コンテナの定義」のコンテナ名リンクをクリックして編集画面を表示します。

表示されたら「ヘルスチェック」の「コマンド」を任意のコマンドに変更します。

あとは「コンテナ定義」の編集画面で「更新」し、タスク定義画面に戻ったら画面右下の「作成」ボタンでタスク定義を作成します。

タスク定義が作成できたら、タスクを起動しなおして確認します。以下はヘルスチェック失敗時のログです。

このログでは4回ヘルスチェックによってアクセスされた通信履歴のログが表示されています。これはヘルスチェックの定義で「再試行」を3として定義していたので、初回のチェックを含めて合計4回チェックがされてエラー終了しています。

気になったこと

今回追加したチェック用Pythonコマンドでは、エラー時にログを出力したいと考えていました。

エラー時にprintで標準出力にエラーを表示するようにしてみたのですが、この出力はECSタスク側のログに表示されませんでした。

そもそもECSタスクのログにはウェブサーバー側のログが表示されているので、ヘルスチェック時のログはこのログには表示されないようです。

まとめ

以上、ECSタスク定義のヘルスチェックコマンドを設定してみました。

挙動としては想定どおりにうまく動いたので、今後複雑な条件でヘルスチェックを行いたい場合にはPythonで作成したCLIコマンドなどを用いて同様に対応したいと思います。

どなたかのお役に立てば幸いです。それでは!