☕️

ecspresso advent calendar 2020 day 13 - run

2020/12/13に公開

Amazon ECS のデプロイツールである ecspresso の利用法をまとめていく ecspresso Advent calendar 13日目です。

ECS上で動作するタスク

ECS クラスタ上で動作しているタスクは、動作の管理方法によって2種類に分けられます。
一つはこれまでに説明してきた、ECSサービスとして管理されているタスク、もう一つはサービスとは無関係に単体で動作するタスクです。

サービスとして動作するタスクは、ECSサービスの desiredCount (要求するタスク数) が増減することで ECS サービスによって実行されたり停止されたりします。タスクはサービスに必要な状態を維持するための群として扱われます。あるタスクが意図せず終了すると、サービスによって自動的に別のタスクが起動され、サービス内のタスク数が維持されます。

サービスとは無関係に、単体で動作するタスクも存在します。単発のコマンド実行を行うために利用者が必要なタイミングで起動するタスクや、EventBridge(CloudWatch Events) からスケジュールで起動するタスクは単体のタスクです。これらのタスクは、意図せずに終了しても自動的に起動し直されたりはしません。

タスクを単体で実行する run コマンド

ecspresso run は、タスクを単体で起動するコマンドです。

単体のタスクはサービスとは本来無関係のものですが、実運用ではサービスとして持続的に動作するアプリケーションが存在している状態で、補助的に単体タスクを実行することが多くあります。

そのため ecspresso run では、タスク実行時に必要になる networkConfiguration, launchType などの属性は、サービス定義の内容を参照して実行するようになっています。

run コマンドの実行例

3日目 既存ECSサービスの取り込み で生成した設定を元に、単体タスクを実行する例を示します。

このサービスは nginx:latest のイメージを利用して Web サーバーを起動するものでした。ここでは nginx のバージョンを表示するコマンド nginx -v を単体タスクとして実行してみます。

オプションなしで ecspresso run を実行すると、以下の処理が行われます。

  1. タスク定義ファイル(テンプレート)を元に新しいタスク定義を登録
  2. そのタスク定義を使用して、1個のタスクを起動する
  3. 起動したタスクが出力したログを読み取る
  4. タスクが終了するまで待機する

タスクが起動した時に実行されるコマンドは、タスク定義内のコンテナに指定された command 要素で決定されます。特に指定がなければコンテナイメージの Dockerfile に記述されているコマンドが実行されます。つまり ecspresso run 時になにも指定しないと、サービスから起動した場合と同様に nginx が Web サーバーとして起動してしまいます。

ここでは nginx -v を実行したいので、run コマンドの --overrides オプションに次の JSON を指定して、コンテナイメージやタスク定義で指定されている動作を上書きします。タスク定義内の namenginx であるコンテナに対して、command["nginx", "-v"] で上書きする、という意味になります。--overrides に指定できる引数の仕様は、aws-cli の aws ecs run-task コマンドのものと同等です。

{
  "containerOverrides": [
    {
      "name": "nginx",
      "command": [ "nginx", "-v" ]
    }
  ]
}

実際のコマンドの実行例です。

$ ecspresso --config config.yaml run \
  --overrides='{"containerOverrides":[{"name":"nginx", "command":["nginx", "-v"]}]}'
2020/12/13 22:56:12 nginx-service/ecspresso-demo Running task
Service: nginx-service
Cluster: ecspresso-demo
TaskDefinition: first-run-task-definition:3
Deployments:
   PRIMARY first-run-task-definition:3 desired:1 pending:0 running:1
Events:
2020/12/13 22:56:13 nginx-service/ecspresso-demo Registering a new task definition...
2020/12/13 22:56:13 nginx-service/ecspresso-demo Task definition is registered first-run-task-definition:4
2020/12/13 22:56:13 nginx-service/ecspresso-demo Running task
2020/12/13 22:56:15 nginx-service/ecspresso-demo Task ARN: arn:aws:ecs:ap-northeast-1:123456789012:task/ecspresso-demo/7d479cf73a6447b09e953da68c61bc99
2020/12/13 22:56:15 nginx-service/ecspresso-demo Watching container: nginx
2020/12/13 22:56:15 nginx-service/ecspresso-demo Waiting for run task...(it may take a while)
2020/12/13 22:56:15 nginx-service/ecspresso-demo logGroup: /ecs/first-run-task-definition
2020/12/13 22:56:15 nginx-service/ecspresso-demo logStream: ecs/nginx/7d479cf73a6447b09e953da68c61bc99
2020/12/13 22:56:46 /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
2020/12/13 22:56:46 /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
2020/12/13 22:56:46 /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
2020/12/13 22:56:46 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
2020/12/13 22:56:46 10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
2020/12/13 22:56:46 /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
2020/12/13 22:56:46 /docker-entrypoint.sh: Configuration complete; ready for start up
2020/12/13 22:56:46 nginx version: nginx/1.19.5
2020/12/13 22:57:25 nginx-service/ecspresso-demo Run task completed!
  1. 新しいタスク定義 first-run-task-definition:4 が登録され
  2. タスク ID 7d479cf73a6447b09e953da68c61bc99 が起動され
  3. ログストリーム ecs/nginx/7d479cf73a6447b09e953da68c61bc99 を読み取り
  4. nginx version: nginx/1.19.5 が表示され
  5. タスクが正常に終了しています

ログの表示

ecspresso run は、タスク定義のログ出力設定が CloudWatch Logs にログを送信するようになっている場合、自動的にそのロググループとログストリームを読み取って出力します。

ログを表示する対象コンテナは、--watch-container オプションで指定されている名前のコンテナです。指定されない場合は、タスク定義の一番最初に定義されているコンテナが選択されます。

コマンドの終了ステータス

ecspresso run で起動したタスクが正常終了した場合は、ecspresso run も正常終了するため exit 0 で終了します。

タスクが異常終了した場合には、run FAILED. Container: nginx, Exit Code: 1 のようにログにコンテナの exit code を出力します。コンテナの exit code が 0 以外のいくつであっても、ecspresso run 自体は exit 1 で終了します。

run コマンドのオプション

usage: ecspresso run [<flags>]

run task

Flags:
  --help                    Show context-sensitive help (also try --help-long and --help-man).
  --config=CONFIG           config file
  --debug                   enable debug log
  --color                   enalble colored output
  --dry-run                 dry-run
  --task-def=TASK-DEF       task definition json for run task
  --no-wait                 exit ecspresso after task run
  --overrides=""            task overrides JSON string
  --skip-task-definition    skip register a new task definition
  --count=1                 the number of tasks (max 10)
  --watch-container=WATCH-CONTAINER  
                            the container name to watch exit code
  --latest-task-definition  run with latest task definition without registering new task definition

--task-def

設定ファイル(config.yaml)に指定されたタスク定義ファイルではなく、引数で指定したタスク定義ファイルを読み込んで使用します。

通常のサービスとしての動作させるものとは別のタスク定義で実行したい場合に使用します。

--skip-task-definition

新しいタスク定義を登録しません。タスクを実行するためのタスク定義は、現在ECSサービスに設定されているものを使用します。サービス定義ファイルで指定されている値ではなく、AWS上のECSサービスに設定されている値が使用されるので注意してください。

--latest-task-definition

新しいタスク定義を登録しません。タスクを実行するためのタスク定義は、現在ECS上に存在する「最新のタスク定義」(一番リビジョンが大きいもの)を使用します。

--no-wait

タスクの起動処理に成功した場合、タスクの終了を待たずに即座に終了します。長時間かかるタスクを実行する場合など、結果は別途確認する場合に利用します。

--overrides

タスクの動作を上書きする設定を JSON 文字列で指定します。指定できる内容は aws-cli の aws ecs run-task のものと同様です。

--count

タスクを実行する個数を指定します。デフォルトは 1 です。

--watch-container

ログの読み取りと、終了コードの検出に使用するコンテナ名を指定します。このコンテナ名とは、タスク定義内のコンテナの name 要素です。


14日目は、デプロイやタスク実行を伴わずにタスク定義を単体で登録する方法を説明します。

https://zenn.dev/fujiwara/articles/ecspresso-20201214

Discussion