はじめに
おはようございます。IWSです
私達のチームではECRへのイメージのビルド、プッシュにGitHub Actionsを使っているのですが、ついでにECSのタスク定義も新しいのを作ってくれると便利なタイミングがあるかな〜とおもったので試しに作ってみました。せっかくなのでどういうのを作ったか書き残しておこうかなと思います。
タスク定義を作る
あらかじめビルドしてECRにプッシュするところまでは出来ている状態で作っていきます。
タスク定義の作成には AWS CLI の aws ecs register-task-definition
を使います。
オプションを1つずつ指定していっても使えますが、大変なのでタスク定義のJSONファイルを渡す方法を使いましょう。
既存のタスク定義のJSONを取得する
タスク定義のJSONファイルを1から用意するのは面倒くさいので、今回は元々あるタスク定義を持ってきて必要な部分だけを変えて作ろうかと思います。まずは既存のタスク定義を取得するところからはじめましょう。
タスク定義の取得には aws ecs describe-task-definition --task-definition <タスク定義の名前>
を使います。
コマンドを叩くとこのようなJSONが取得できるはずです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
{ "taskDefinition": { "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:xxxxxxxxxxxx:task-definition/<タスク定義名>:xx", "containerDefinitions": [ { "name": "name", "image": "xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/<ECR名>:<タグ>", "cpu": 0, "portMappings": [ { "containerPort": 80, "hostPort": 80, "protocol": "tcp", "name": "80-tcp" } ], "essential": true, "environment": [ { "name": "ENV", "value": "development" } ], "mountPoints": [], "volumesFrom": [], "dockerSecurityOptions": [], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "hoge", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "hoge" }, "secretOptions": [] }, "systemControls": [] } ], "family": "<タスク定義名>", "taskRoleArn": "<taskRoleArn>", "executionRoleArn": "<executionRoleArn>", "networkMode": "awsvpc", "revision": xx, "volumes": [], "status": "ACTIVE", "requiresAttributes": [ { "name": "com.amazonaws.ecs.capability.logging-driver.awslogs" }, { "name": "ecs.capability.execution-role-awslogs" }, { "name": "com.amazonaws.ecs.capability.ecr-auth" }, { "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19" }, { "name": "com.amazonaws.ecs.capability.task-iam-role" }, { "name": "ecs.capability.execution-role-ecr-pull" }, { "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18" }, { "name": "ecs.capability.task-eni" } ], "placementConstraints": [], "compatibilities": [ "EC2", "FARGATE" ], "requiresCompatibilities": [ "FARGATE" ], "cpu": "256", "memory": "1024", "registeredAt": "2024-06-27T17:21:10.983000+09:00", "registeredBy": "arn:aws:sts::xxxxxxxxxxxx:assumed-role/Administrator/hogefuga" }, "tags": [] } |
これをそのまま使えたら楽なのですが、残念ながらこのままだと使えないので少し整えてあげる必要があります。
JSONを整える
やることは
- taskDefinitionの中身を取り出す
- taskDefinitionArn を削除
- revision を削除
- status を削除
- requiresAttributes を削除
- compatibilities を削除
- registeredAt を削除
- registeredBy を削除
です。
GitHub Actions ではデフォルトで使える jq コマンドで整形すると簡単です。
1 2 |
# 取得したタスク定義JSONからいらない部分を削除 jq '.taskDefinition | del (.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities, .registeredAt, .registeredBy)' > task-def.json |
jqコマンドで整形後のタスク定義JSON
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
{ "containerDefinitions": [ { "name": "name", "image": "xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/<ECR名>:<タグ>", "cpu": 0, "portMappings": [ { "containerPort": 80, "hostPort": 80, "protocol": "tcp", "name": "80-tcp" } ], "essential": true, "environment": [ { "name": "ENV", "value": "development" } ], "mountPoints": [], "volumesFrom": [], "dockerSecurityOptions": [], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "hoge", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "hoge" }, "secretOptions": [] }, "systemControls": [] } ], "family": "<タスク定義名>", "taskRoleArn": "<taskRoleArn>", "executionRoleArn": "<executionRoleArn>", "networkMode": "awsvpc", "volumes": [], "placementConstraints": [], "requiresCompatibilities": [ "FARGATE" ], "cpu": "256", "memory": "1024" } |
これでタスク定義が作れるJSONになりました!
イメージを変える
ここまでで aws ecs register-task-definition
に渡せるJSONファイルが用意できました。ですが、中身の設定は当然前のタスク定義のままです。そのため、このままタスク定義を作成しても前と同じものが出来てしまうだけになります。
今度は中身の設定を変えていきましょう!
今回は使用するイメージ(containerDefinitions[0].image
)のタグの部分だけを変更します。
containerDefinitions[0].image
はこうなっています
1 |
"image": "xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/<ECR名>:<タグ>" |
:
の後がタグになっているので split を使って古いタグを取得して置き換えてしまいましょう
1 2 |
# imageのタグ部分だけを取得する PREVIOUS_IMAGE_TAG=$(cat task-def.json | jq -r '.containerDefinitions[0].image | split(":")[1]') |
古いタグが取得できたらあとは新しく設定するタグと置き換えるだけです。
1 2 |
# $PREVIOUS_IMAGE_TAG(古いタグ) を $IMAGE_TAG(新しいタグ)で置き換え cat task-def.json | jq --arg PREVIOUS_IMAGE_TAG "$PREVIOUS_IMAGE_TAG" --arg IMAGE_TAG "$IMAGE_TAG" '.containerDefinitions[0].image |= sub($PREVIOUS_IMAGE_TAG; $IMAGE_TAG)' > new-task-def.json |
jq の sub() を使うことで対象の部分を置き換えることができます。jqはなんでもできますね……
1 2 3 |
"image": "xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/<ECR名>:<古いタグ>" ↓ "image": "xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/<ECR名>:<新しいタグ>" |
これで新しいタスク定義のJSONファイルができました!
タスク定義を作成
ここまできたらあとは完成したJSONファイルを使ってタスク定義を作るだけです。
1 2 |
# タスク定義を作成 aws ecs register-task-definition --cli-input-json fileb://new-task-def.json |
--cli-input-json
を使うことでパラメーターをJSONファイルで渡すことが出来ます。
このコマンドが成功すればタスク定義にあたらしいリビジョン番号が増え、設定に新しいイメージタグが書かれているはずです。
どうでしょう?タスク定義は出来ましたか?
あとはこのタスク定義を使って aws ecs update-service
なりしてあげれば、新しいタスク定義を使用したECSタスクが立ち上がってくると思います。
最後に自分の作ったコードを一部載せておくので良ければ参考にしてください。
タスク定義作成部分コード
事前にAWS credentialsやイメージのビルドなどをしてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
- name: Task Definition Update id: update-task-definition run: | # Create a new revision of the task definition aws ecs describe-task-definition --task-definition $TASK_DEF_NAME | jq '.taskDefinition | del (.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities, .registeredAt, .registeredBy)' > task-def.json PREVIOUS_IMAGE_TAG=$(cat task-def.json | jq -r '.containerDefinitions[0].image | split(":")[1]') cat task-def.json | jq --arg PREVIOUS_IMAGE_TAG "$PREVIOUS_IMAGE_TAG" --arg IMAGE_TAG "$IMAGE_TAG" '.containerDefinitions[0].image |= sub($PREVIOUS_IMAGE_TAG; $IMAGE_TAG)' > new-task-def.json aws ecs register-task-definition --cli-input-json fileb://new-task-def.json - name: ECS Update id: update-ecs run: | # Update the ECS service with the latest task definition. aws ecs update-service --cluster $ECS_CLUSTER --service $ECS_SERVICE --desired-count $DESIRE_COUNT --task-definition $TASK_DEF_NAME --force-new-deployment |
まとめ
今回はGitHub Actionsでのタスク定義の作成について書きました。
最近はGitHub Actionsを使ってAWSのリソースを作ったりイメージをPushしたりいろいろなことをやったりしています。今回もそのなかで試しにやってみたことを記事にしてみました。いつか何かしらの参考になればうれしいです。
ここまでお読みいただきありがとうございました!