ECS Fargateのタスク定義の取得→更新→反映をShellとjqで自動化
コンテナベースで開発作業していて、更新したコンテナイメージを、ECS(Fargate)上で稼働しているサービスに反映したいという時、ちゃんとした開発ラインならCI/CDパイプライン組んで自動デプロイするトコロですが、諸事情もありますよね?
じゃあ、と手作業でやってみるとこれが結構面倒なので、シェルにしました。
概要
サービスへの反映までに至る流れは、以下のようになります。
- 対象となるサービスにアタッチされているタスク定義を特定し、取得する
- それを基に新たなタスク定義を作成する
- 新たに作成したタスク定義を、元のサービスにアタッチする
なお、所謂Latest運用
はここでは想定していません。
では、何はさておきコードです
スクリプト
#!/bin/bash ECS_CLUSTER_NAME=your-cluster-name ECS_SERVICE_NAME_KEY=your-service-name REPOSITORY_URL=your-ecr-url_or_somewhere TASKDEF_CONTAINER_NAME=your-container-name TASKDEF_CONTAINER_IMAGE="$1" # 1. get target service arn echo "cluster: ${ECS_CLUSTER_NAME}" echo "service key: ${ECS_SERVICE_NAME_KEY}" SERVICE_ARN=$(aws ecs list-services --cluster ${ECS_CLUSTER_NAME} | jq -r '.serviceArns[] | select(. | test("'${ECS_SERVICE_NAME_KEY}'"))') echo "service: $SERVICE_ARN" if [[ -z "${SERVICE_ARN}" ]]; then echo "[ERROR] Service missing." exit 1 fi if [ $(echo "${SERVICE_ARN}" | wc -l) -ne 1 ];then echo "[ERROR] More than one services found." exit 1 fi # 2. get current task-def arn SRC_TASKDEF=$(aws ecs describe-services --cluster ${ECS_CLUSTER_NAME} --services ${SERVICE_ARN} | jq -r '.services[0].taskDefinition') echo "current taskdef: ${SRC_TASKDEF}" # 3. get task-def details and modify it # remove unneeded props and else # override container's image aws ecs describe-task-definition --task-definition ${SRC_TASKDEF} \ | jq '.taskDefinition | del(.taskDefinitionArn, .status, .requiresAttributes, .compatibilities, .revision)' \ | jq '(.containerDefinitions[] | select(.name == "'${TASKDEF_CONTAINER_NAME}'")).image = "'${REPOSITORY_URL}/${TASKDEF_CONTAINER_IMAGE}'"' > /tmp/taskdef.json # 4. register new task-definition NEW_TASKDEF=$(aws ecs register-task-definition --cli-input-json file:///tmp/taskdef.json | jq -r '.taskDefinition.taskDefinitionArn') echo "new taskdef: ${NEW_TASKDEF}" # 5. update service aws ecs update-service --cluster ${ECS_CLUSTER_NAME} --service ${SERVICE_ARN} --task-definition ${NEW_TASKDEF} echo "Done! (wait a while to rolling update..."
仕様
- 埋め込み変数
- 対象サービスの属するクラスタの名前
- 対象サービスの名前(部分一致)
- 対象コンテナの名前: タスク定義の中で、複数のコンテナが定義可能です。対象コンテナを特定するために必要です。
- イメージのあるリポジトリのベースURL
- ex:
xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com
- ex:
- 引数
- コンテナに指定する、新しいイメージのTag
- ex:
$ ./this.sh my-app:0.1.0
- ex:
- コンテナに指定する、新しいイメージのTag
- 不正終了
- 指定されたクラスタに紐付くサービス群から、対象サービスを部分一致検索します。サービスを一意に特定できなかった場合は不正終了します。
要所でjqを使っています。jqは上手く使えば相当強力ですが、あまり職人的な域まで頑張ってしまうと、将来の自分が苦労するので程々にしました(シェルも同様)。
タスク定義のJsonを加工するところは、ニーズ次第で色々あろうと思うので、分かりやすさ優先で書いてます。処理追加等して楽しんで頂ければと思います。jq使ってスッキリ実現できると大変気持ちよいです♪