CDKで管理しているECSをGitHubActionsでデプロイする方法
概要
CDKで管理しているリソースを自動リリースする仕組み。実際に本番運用している構成となります。
まずは、実際の完成形のGitHubActionsのコードです。
/
├── batch
│ └── Dockerfile
└── cdk
name: dev-batch-deploy
on:
push:
branches:
- main
paths:
- 'batch/**'
workflow_dispatch:
env:
CDK_APPENV: dev
AWS_REGION: ap-northeast-1
AWS_ACCOUNT_ID: <ACCOUNT ID>
AWS_ACCTIONS_ROLE: <dev-github-role>
AWS_ECR_REPOSITORY: <dev-batch-ecr>
AWS_TAG_PATAMETEER_STORE: <docker-batch-tag>
permissions:
id-token: write
contents: read
jobs:
dev-deploy-app-ecs:
name: dev-deploy-app-ecs
runs-on: ubuntu-latest
steps:
# https://github.com/actions/checkout
- name: Checkout
uses: actions/checkout@v4
# https://github.com/aws-actions/configure-aws-credentials
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/${{ env.AWS_ACCTIONS_ROLE }}
aws-region: ${{ env.AWS_REGION }}
# https://github.com/aws-actions/amazon-ecr-login
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
# Build a docker container and
# push it to ECR so that it can
# be deployed to ECS.
cd batch
docker build -t $ECR_REGISTRY/$AWS_ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$AWS_ECR_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$AWS_ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
- name: Update ImageTag Parameter Store
id: update-tag
run: |
aws ssm put-parameter --name $AWS_TAG_PATAMETEER_STORE --value ${{ github.sha }} --type String --overwrite
- name: Set Up Node
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install CDK
id: install-cdk
run: |
npm install -g aws-cdk
cdk --version
- name: Run CDK
id: run-cdk
run: |
cd cdk
npm install
cdk deploy batch-stack --context appEnv=$CDK_APPENV --require-approval never
解説
トリガー
batch配下にアプリが存在し、それらがmainブランチに入った事をきっかけに動作させます。CDKなどの修正などで動かしたい場合も考慮し、手動実行workflow_dispatch
も設定しています。これはdev環境用なのでpush
を使っていますが、prdはworkflow_dispatch
のみで運用を行っています。
on:
push:
branches:
- main
paths:
- 'batch/**'
workflow_dispatch:
環境変数
devとprdでは意図的にyaml自体を分けています。共通化を考えましたが、規模が小さいことから安全に変更していけるよう分けています。envに設定している内容はGitHubのシークレットを使って運用しても良いでしょう。
env:
CDK_APPENV: dev
AWS_REGION: ap-northeast-1
AWS_ACCOUNT_ID: <ACCOUNT ID>
AWS_ACCTIONS_ROLE: <dev-github-role>
AWS_ECR_REPOSITORY: <dev-batch-ecr>
AWS_TAG_PATAMETEER_STORE: <docker-batch-tag>
Jobs Step 1 Checkout
Ubuntuにコードをチェックアウトしています。説明すべき点は少ないです。
jobs:
dev-deploy-app-ecs:
name: dev-deploy-app-ecs
runs-on: ubuntu-latest
steps:
# https://github.com/actions/checkout
- name: Checkout
uses: actions/checkout@v4
Jobs Step 2 OIDC認証
GitHub用にAWSのIAM管理したくないためOIDCを利用します。
GitHub ActionsでAWSにOIDC認証してみたという記事で詳しくAWS側の設定方法を説明していますので参照ください。
# https://github.com/aws-actions/configure-aws-credentials
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/${{ env.AWS_ACCTIONS_ROLE }}
aws-region: ${{ env.AWS_REGION }}
Jobs Step 3 ECR Login
ECRにログインします。
aws-actions/amazon-ecr-login
を利用すればたったこれだけ。とてもシンプル
# https://github.com/aws-actions/amazon-ecr-login
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
Jobs Step 4 Build,Tag,Push
コンテナをビルドし、GitHubハッシュ値でタグをつけてECRへプッシュします。GitHubハッシュ値をタグに使う理由は、いつ時点で作成したコンテナかをタグからプログラムを探せるようにするためです。1つ前のタグを切り戻しをどの箇所にすべきかも簡単に探せることを意識しています。
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
# Build a docker container and
# push it to ECR so that it can
# be deployed to ECS.
cd batch
docker build -t $ECR_REGISTRY/$AWS_ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$AWS_ECR_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$AWS_ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
Jobs Step 6 Update Parameter Store -> Tag
Dockerにつけたタグをパラメーターストアに更新します。これは、後続のCDKデプロイ時にコンテナのデグレが起きないよう同期を取るためです。ECSのデプロイ運用でLatest運用せずCDKと実際のECRバージョンを乖離させない方法で詳しく説明していますのでご参照ください。
- name: Update ImageTag Parameter Store
id: update-tag
run: |
aws ssm put-parameter --name $AWS_TAG_PATAMETEER_STORE --value ${{ github.sha }} --type String --overwrite
Jobs Step 7,8,9 Node & CDK Install -> deploy
cdk deploy
コマンドを愚直に実行することが最大のポイントです。GitHubActionsに存在しているECSデプロイは使ってはいけません。
最初、私はECSのタスク定義を更新するActionsを使っていましたが、CDK Deploy
と共存できない以下の問題が発生しました。
- CDKが裏で作り出す(
.cdkout
配下にできるファイル)Cloudformationは機械的な生成のため、cdk diff
をするだけではActionsを利用したデプロイ後に差分なしと言われる(ここまでは良い) - しかし、実際に
cdk deploy
を動かすとActionsで動かしたあとでは存在していないはずの差分が生まれているようでデプロイが動いてしまう。
- name: Set Up Node
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install CDK
id: install-cdk
run: |
npm install -g aws-cdk
cdk --version
- name: Run CDK
id: run-cdk
run: |
cd cdk
npm install
cdk deploy batch-stack --context appEnv=$CDK_APPENV --require-approval never
さいごに
私のサンプルは少人数で小規模なプロジェクトでした。大規模では上のサンプルに自動テスト
やSlack通知
を追加すると良いと思います。読んでくださった皆様の参考になりましたら幸いです。
Discussion