CircleCI OrbsでECRへのpushとECSのBlue/Greenデプロイメントを自動化する

インフラ

こんにちは。Enjoy IT Life管理人の仁科(@nishina555)です。

前回、CodeDeployを利用してECS FargateをBlue/GreenデプロイするでCodeDeployを利用したBlu/Greenデプロイメントの設定方法と実行手順について紹介しました。

CodeDeployを利用してECS FargateをBlue/Greenデプロイする

2020年6月30日

CodeDeployによるBlue/Greenデプロイメントはサービスの更新がトリガになります。
ですので、『ECRへDockerイメージをpush』→『タスク定義の新規リビジョンの作成』→『サービスに記述されているタスク定義のリビジョンを変更』という手順をふむことでCodeDeployが実行されます。

今回はCodeDeployが実行されるまでのプロセスをCircleCIで自動化する方法について紹介します。
なお、Circle CIはバージョン2.1を利用します。

ECR・ECSの自動化で必要になるOrbについて

CircleCI 2.1からはCircleCI Orbsと呼ばれる共通パッケージが利用できるようになりました。
Orbを活用することで設定ファイルの記述が簡潔になります。

今回はCircleCI 2.1を利用するため、Orbを活用してECR・ECSの自動化を行います。ECR・ECSの自動化で必要になるOrbは以下の2つです。

なお、今回利用するOrbのバージョンはそれぞれcircleci/aws-ecr@6.8.1circleci/aws-ecs@1.1.0です。

CircleCIでECRへDockerイメージのpushを行う方法

circleci/aws-ecrで利用される主なパラメータは下記の通りです。

パラメータ 説明 必須 デフォルト タイプ
aws-access-key-id アクセスキー no AWS_ACCESS_KEY_ID env_var_name
aws-secret-access-key シークレットキー no AWS_SECRET_ACCESS_KEY env_var_name
account-url リポジトリURL no AWS_ECR_ACCOUNT_URL env_var_name
repo リポジトリ名 yes N/A string
region リージョン no AWS_REGION env_var_name
tag タグ no latest string

そのほか利用できるパラメータについてはcircleci/aws-ecrのドキュメントを参考にしてください。

設定ファイルは以下のようになります。

circle/.config.yml

orbs:
  aws-ecr: circleci/aws-ecr@6.5.0
version: 2.1
workflows:
  build-and-deploy:
    jobs:
      - aws-ecr/build-and-push-image:
            aws-access-key-id: xxxxx
            aws-secret-access-key: xxxx
            account-url: xxx.com
            repo: sample-app
            region: ap-northeast-1
            tag: '${CIRCLE_SHA1}'

CIRCLE_SHA1は『現在のビルドの最後のコミットに関するSHA1ハッシュ値』が保存されているCircleCIの定義済み環境変数です。
latestタグによるDockerイメージの管理を避けるためにコミットのハッシュ値をタグ名に利用しています。

CIRCLE_SHA1を利用すると以下のようなタグ名でECRへDockerイメージがpushされます。

Orbで利用されるパラメータのデフォルト値をCircleCI側の環境変数に保存することで、設定ファイルでの記述を省略できます。

環境変数は『Project Settings』の『Environment Variables』から追加できます。

特に秘匿情報をCircleCIの設定ファイルに直接記述するのはセキュリティ上よくないので、環境変数で管理をするようにしましょう。

CircleCI側の環境変数を利用して設定ファイルの記述を省略した例が以下になります。

circle/.config.yml

orbs:
  aws-ecr: circleci/aws-ecr@6.5.0
version: 2.1
workflows:
  build-and-deploy:
    jobs:
      - aws-ecr/build-and-push-image:
            repo: sample-app
            tag: '${CIRCLE_SHA1}'

CircleCIでECSのデプロイメントを行う方法

circleci/aws-ecsで利用される主なパラメータは下記の通りです。

パラメータ 説明 必須 デフォルト タイプ
aws-access-key-id アクセスキー no AWS_ACCESS_KEY_ID env_var_name
aws-secret-access-key シークレットキー no AWS_SECRET_ACCESS_KEY env_var_name
aws-region リージョン名 no $AWS_REGION string
family ファミリー名 yes N/A string
cluster-name クラスター名 yes N/A string
service-name サービス名 no string
container-image-name-updates コンテナのイメージ・タグの更新 no string

CodeDeployを利用したBlue/Greenデプロイメントを行う場合は追加で以下のパラメータを設定する必要があります。

パラメータ 説明 デフォルト タイプ
codedeploy-application-name アプリケーション名 string
codedeploy-deployment-group-name デプロイグループ名 string
codedeploy-load-balanced-container-name コンテナ名 string
codedeploy-load-balanced-container-port ポート番号 80 integer
CodeDeployを利用する場合は『deployment-controller』パラメータをCODE_DEPLOY(デフォルトはECS)にする必要があるので注意してください。

そのほか利用できるパラメータについてはcircleci/aws-ecsのドキュメントを参考にしてください。

設定ファイルは以下のようになります。

circle/.config.yml

orbs:
  aws-ecr: circleci/aws-ecr@6.5.0
  aws-ecs: circleci/aws-ecs@1.2.0
version: 2.1
workflows:
  build-and-deploy:
    jobs:
      - aws-ecr/build-and-push-image:
            repo: sample-app
            tag: '${CIRCLE_SHA1}'
      - aws-ecs/deploy-service-update:
            requires:
              # ECRへのpushが完了してからjobを実行する
              - aws-ecr/build-and-push-image
            service-name: 'sample-service'
            family: 'sample-app-task'
            cluster-name: 'sample-app'
            container-image-name-updates: 'container=web,tag=${CIRCLE_SHA1}'

            # CodeDeployを利用する場合は以下のparametersを追加
            deployment-controller: 'CODE_DEPLOY'
            codedeploy-application-name: 'AppECS-sample-app-sample-service'
            codedeploy-deployment-group-name: 'DgpECS-sample-app-sample-service'
            codedeploy-load-balanced-container-name: 'web'

CircleCIが起動すると、まずECRへDockerイメージをpushするjobが実行され、続いてCodeDeployによるBlue/Greenデプロイメントを実施するjobが実行されます。

参考: CircleCIのjobを制御する方法

Dockerイメージのpushとデプロイメントの実施はリリース時のみ必要な作業ですので、コードプッシュをするたびにECR・ECSに関するjobを実行する必要はありません。

jobの制御をするにはCircleCIのfiltersオプションを利用します。filtersを利用することで、jobを実行する対象のブランチ名もしくはタグ名の指定ができます。1

たとえばvから始まるgitタグがついている場合のみjobを実行する設定は以下の通りです。

circle/.config.yml

orbs:
  aws-ecr: circleci/aws-ecr@6.5.0
  aws-ecs: circleci/aws-ecs@1.2.0
version: 2.1
workflows:
  build-and-deploy:
    jobs:
      - aws-ecr/build-and-push-image:
            repo: sample-app
+           tag: '${CIRCLE_TAG}'
-           tag: '${CIRCLE_SHA1}'
+           filters:
+             tags:
+               # vから始まるタグの場合のみjobを実施
+               only: /^v.*/
+             branches:
+               # 全てのブランチでjobをスキップ
+               ignore: /.*/
      - aws-ecs/deploy-service-update:
            requires:
              - aws-ecr/build-and-push-image
+           filters:
+             tags:
+               # vから始まるタグの場合のみjobを実施
+               only: /^v.*/
+             branches:
+               # 全てのブランチでjobをスキップ
+               ignore: /.*/
            service-name: 'sample-service'
            family: 'sample-app-task'
            cluster-name: 'sample-app'
+           container-image-name-updates: 'container=web,tag=${CIRCLE_TAG}'
-           container-image-name-updates: 'container=web,tag=${CIRCLE_SHA1}'
            deployment-controller: 'CODE_DEPLOY'
            codedeploy-application-name: 'AppECS-sample-app-sample-service'
            codedeploy-deployment-group-name: 'DgpECS-sample-app-sample-service'
            codedeploy-load-balanced-container-name: 'web'

CIRCLE_TAGは『ビルドが実行されているgitのタグ名』が保存されているCircleCIの定義済み環境変数です。

上記のように設定ファイルを変更することで、gitタグがついた場合のみaws-ecr/build-and-push-imageaws-ecs/deploy-service-updateのjobが実行されます。

gitタグをDockerイメージのタグとして利用できるため、ECR・ECSを利用したデプロイの場合はタグでjobを制御することをオススメします。

なお、gitタグの作成はリポジトリの『Releases』からできます。

まとめ

以上でCircleCI Orbsを利用した、DockerイメージpushとBlue/Greenデプロイメントの自動化手順について紹介を終わります。

今回のまとめ
  • CircleCI 2.1から利用できるOrbを活用することで設定が簡潔になる
  • デプロイの自動化はcircleci/aws-ecrとcircleci/aws-ecsのOrbを利用
  • ECR・ECSの自動化をする際はタグ名でjob実行の制御をするとよい

この記事がいいなと思いましたらTwitter(@nishina555)のフォローもよろしくお願いします!