CLIを使ってECSのタスク定義更新を楽にする方法

こんにちは、インフラエンジニアの土肥です。

なるべくGUIでの手動設定を避けるために、CLIからタスク定義の更新を行いたいと思ったとき少し工夫が必要でしたのでご紹介します。

やりたいこと

  1. 既存タスク定義情報のJSONをコマンドで取得
  2. 必要な部分を変更
  3. 新しいリビジョンをコマンドで作成

という流れをやりたかったのですが、コマンドで取得したJSONはそのままでは登録出来ないので整形する手順を入れてあげる必要があります。

難易度が高いものではないですがこの記事を読んだ方の手間を少しでも削減するために記載します。

やったこと

前提として更新対象のタスク定義は作成済みの状態で作業しています。

  1. 既存タスク定義情報のJSONをdescribe-task-definitionで取得
  2. 結果をjqで整形
  3. 必要な部分の変更
  4. register-task-definitionで新しいリビジョンを作成

既存のタスク定義を取得

タグを設定している場合は—includeオプションの指定が必要です。

オプションを付けないとタグが設定されていても空配列で結果が返ってきてしまいます。

$ aws ecs describe-task-definition --task-definition aitp-sample --include TAGS > task_def_org.json

そのまま登録してみる

取得したJSONをそのま登録できると嬉しいのですが、そもそもJSONの書式が異なるためエラーになります。

$ aws ecs register-task-definition --cli-input-json file://task_def_org.json
Parameter validation failed:
Missing required parameter in input: "family"
Missing required parameter in input: "containerDefinitions"
Unknown parameter in input: "taskDefinition", must be one of: family, taskRoleArn, executionRoleArn, networkMode, containerDefinitions, volumes, placementConstraints, requiresCompatibilities, cpu, memory, tags, pidMode, ipcMode, proxyConfiguration, inferenceAccelerators, ephemeralStorage

結果をjqで整形

登録時に不要なキーが含まれていることと、JSONの書式が異なっていることがエラーの原因ですので登録可能な書式に整形します。

タグを含める場合は以下のようなコマンドになります。

$ jq '{ "containerDefinitions": .taskDefinition.containerDefinitions, "family": .taskDefinition.family, "executionRoleArn": .taskDefinition.executionRoleArn, "networkMode": .taskDefinition.networkMode, "volumes": .taskDefinition.volumes, "placementConstraints": .taskDefinition.placementConstraints, "requiresCompatibilities": .taskDefinition.requiresCompatibilities, "cpu": .taskDefinition.cpu, "memory": .taskDefinition.memory, "tags": .tags }' task_def_org.json > task_def.json

タグを含めない場合はtaskDefinitionの中に全て必要なキーが含まれているので少し短くできます。

$ jq '.taskDefinition | del (.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities, .registeredAt, .registeredBy)' task_def_org.json > no_tag_task_def.json

変更箇所を編集する

今回は環境変数を追加します。

$ git diff                                                                            
diff --git a/task_def.json b/task_def.json
index cab97e7..37840a7 100644
--- a/task_def.json
+++ b/task_def.json
@@ -18,6 +18,10 @@
         {
           "name": "env",
           "value": "env-sample"
+        },
+        {
+          "name": "dbhost",
+          "value": "hogehoge"
         }
       ],
       "mountPoints": [],

gitで管理出来て変更のチェックがしやすいのも利点ですね。

登録する

最後にregister-task-definitionコマンドで登録して完了です。

$ aws ecs register-task-definition --cli-input-json file://task_def.json
{
    "taskDefinition": {
        "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:******:task-definition/aitp-sample:2",
        "containerDefinitions": [
            {
                "name": "sample-container",
                "image": "nginx:latest",
                "cpu": 0,
                "portMappings": [
                    {
                        "containerPort": 80,
                        "hostPort": 80,
                        "protocol": "tcp"
                    }
                ],
                "essential": true,
                "entryPoint": [],
                "command": [],
                "environment": [
                    {
                        "name": "env",
                        "value": "env-sample"
                    },
                    {
                        "name": "dbhost",
                        "value": "hogehoge"
                    }
                ],
-- 省略 --

最後に

更新のたびに同じコマンドを実行するので、スクリプトやMakefileでまとめてしまうとさらに運用が楽になるかと思います。

JQ='{ "containerDefinitions": .taskDefinition.containerDefinitions, \
	"family": .taskDefinition.family, "executionRoleArn": .taskDefinition.executionRoleArn, \
	"networkMode": .taskDefinition.networkMode, "volumes": .taskDefinition.volumes, \
	"placementConstraints": .taskDefinition.placementConstraints, \
	"requiresCompatibilities": .taskDefinition.requiresCompatibilities, \
	"cpu": .taskDefinition.cpu, "memory": .taskDefinition.memory, "tags": .tags }'

fetch:
	aws ecs describe-task-definition --task-definition aitp-sample --include TAGS | jq $(JQ) > task_def.json

reg:
	aws ecs register-task-definition --cli-input-json file://task_def.json

関連するタグ