Github Actions から AWS Fargate にリリースする先をスイッチさせたい

先日から、AWS Forgate を試していますが、実際にサービスで使うことを考え始めています。
手始めに本番用とテスト環境と 2 つのデプロイ先に同じソースコードを任意にデプロイできるようにしたいと考えます。

今回は、Github Actions の処理でデプロイ先を切り替えて見ます。

実装

前提

  • Forgate のデプロイ先が、用意されている
    • クラスター 2 つ、サービスも作成済み

今回は、テスト用に以下が用意されているものとします。

  • dev-cluster-for-forgate-service
  • dev-cluster-for-forgate

本番用には以下が用意されているものとします。

  • cluster-for-forgate-service
  • cluster-for-forgate

作成

.github\workflows\deploy.yml を用意します。
前提として、改変前のものは、AWS Fargate で、Deno を動かす をベースとします。

.github\workflows\deploy.yml
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
name: deploy-task
on:
push:
# 追加したところ(1)
tags:
- deploy-*
- dev-deploy-*

jobs:
build-and-push:
runs-on: ubuntu-18.04
timeout-minutes: 300

steps:
- uses: actions/checkout@v1

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: ${{ secrets.AWS_ECR_REPO_NAME }}
run: |
IMAGE_TAG=$(echo ${{ github.ref }} | sed -e "s#refs/tags/##g")
echo $ECR_REGISTRY
echo $ECR_REPOSITORY
echo $IMAGE_TAG
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"

- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: task-definition.json
container-name: nginx-container
image: ${{ steps.build-image.outputs.image }}

# 追加したところ(2)
- name: deploy choice target
id: deploy-choice-target
run: |
if [ `echo ${{ steps.build-image.outputs.image }}|grep dev-deploy` ]; then
echo Deploy DEV
echo "::set-output name=service-name::dev-cluster-for-forgate-service"
echo "::set-output name=cluster-name::dev-cluster-for-forgate"
else
echo Deploy PROD
echo "::set-output name=service-name::cluster-for-forgate-service"
echo "::set-output name=cluster-name::cluster-for-forgate"
fi

# 追加したところ(3)
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ steps.deploy-choice-target.outputs.service-name }}
cluster: ${{ steps.deploy-choice-target.outputs.cluster-name }}
wait-for-service-stability: true

追加したところ(1)

以前のものは、タグdeploy-* だけ受け入れていたが、タグdev-deploy-* を受け入れられるように追加。
このタグの種類を判定し、デプロイ先環境を切り替える。

追加したところ(2)

デプロイ先の選択のステップを追加した箇所。
build-image ステップで設定される image 名に、dev-deploy の文字列が含まれるかを判別します。
結果に基づき、service-namecluster-nameにデプロイ先のサービス名と、クラスター名を設定する。
この設定については、secretsに設定する形を取った方がよいと感じますが動作確認なのでこの通りです。

追加したところ(3)

aws-actions/amazon-ecs-deploy-task-definition@v1の、serviceclusterの設定を先に実行したステップで設定したものを使用します。

動作

dev-deploy-hogehogeのタグを付与して push すると、テスト用環境 dev-cluster-for-forgate-serviceにデプロイ。
deploy-hogehogeのタグを付与して push したときには、本番用環境 cluster-for-forgate-serviceにデプロイ。

それぞれが達成されます。


こんな形で、1 つのタスク内でスイッチしましたが、単純にほとんど内容が同じタスクを 2 つ書いても実現できるなと後で気が付きました。
ただ、これはメンテナンス性からは避けるべきとも感じたところです。
あとやってみて良かった点としては、set-outputsteps.hoge.outputs.hugaの使い方をちゃんと理解できたことでした。

ではでは。