CircleCIでAWS CDKのデプロイパイプラインを作る


はじめに

この記事はCircleCI Advent Calendar 2021の19日目の記事です。

自分のチームではAWS CDKを使って、インフラ管理をしています。
下記記事でAWS SAM CLIのデプロイパイプラインを構築しましたが、AWS CDKでも同様のものを作りました。

今回もCircleCIでAWS CDKのデプロイパイプラインを作っていきます。

全体図

デプロイフローは下記になります。
GitHubでリリースタグを作成したら、CircleCIがデプロイを動かす仕組みです。

意識したポイント

AWS CDK

Stackの依存関係を明示する

人力でやる場合は、構築順番を意識することができますが、CIツールで実行するにはそうもいきません。
下記の記事にあるように依存関係は addDependency を使って明示していきます。

// AWS NAT Gatewayを作るStackはVPCを作成するStackとElastic IPを作成するStackに依存する
const natGateway = new NatGateway()
natGateway.node.addDependency(vpc)
natGateway.node.addDependency(eip)

このように依存関係を明示し、プログラムで順番通りに実行されるようにします。

環境で切り替える値を切り出す

環境ごとに値を切り替えたい時があると思います。

例えば、Amazon Route 53のプライベートゾーンに登録する関連システムのドメイン

こういった機微情報でないものは、cdk.jsonに切り出すようにしました。
下記のように環境ごとに構造化をし、プログラム上で読み出すようにしました。

cdk.json
{
  "context": {
    "staging": {
      "hoge": {
        "fuga": "hoge"
      }
    },
    "production": {
      "hoge": {
        "fuga": "hogefuga"
      }
    }
  }
}

設定した値は tryGetContext で取得します。
パラメータは実行時に -c env=環境名 を渡します。

const app = new cdk.App();

// 実行時に -c env=環境名 を渡す
const env: string = app.node.tryGetContext('env')

// 渡されたenvに該当する値を拾ってくる
const context = app.node.tryGetContext(env)

こうして、環境ごとに値を切り替える手間を省きました。

CircleCI

Jobをまとめる

本番環境以外に検証用の環境も用意しています。
それらの環境へのデプロイもCircleCIでやるため、ファットにならないようにJobをまとめます。

下記のようにJobは環境名を受け取るようにしておき、環境変数はWorkflowのcontextで渡すようにしました。
こうすることで同じようなJobを何度も書かなくて良くなりました。

jobs:
  deploy:
    (中略)
      - run:
          name: deploy
          command: yarn cdk deploy "*" -c env=${APP_ENV}

workflows:
  version: 2
  default:
    jobs:
       (中略)
  deploy-staging:
    jobs:
       (中略)
      - deploy:
          context: staging
  deploy-prd:
    jobs:
      (中略)
      - deploy:
          context: production

変更セットを確認できるようにする

レビュアーに何が変更されるかわかりやすくするため、AWS CDKで変更セットを確認できるようにします。
AWS CloudFormationやAWS SAM CLIでは --no-execute-changeset を付け加えると、事前に変更セットの確認ができました。

AWS CDKではdiffコマンドが用意されているので、下記を実行して差分確認ができました。

yarn cdk diff "*"  || :

余談
自分の環境だけかもしれませんが、差分があるときに exit 1 が返ってきて、CircleCIが落ちてしました。
--fail をつけているときは上記挙動だがつけていなくても起きました。

差分があること自体は期待値なので、 || : で握りつぶすようにしました…。
この辺はモヤモヤしているので時間を見つけて調べます。

まとめ

いかがだったでしょうか?
使い慣れているCircleCIで、AWS CDKのデプロイパイプラインを作ってみました。
参考になれば幸いです。

以上、最後まで読んでいただきありがとうございました。

参考資料