
CodePipeline で承認プロセスを設けた Terraform workspace の CI/CD パイプライン実装
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
先日、CodeCommit への push をトリガーに terraform apply をサクッと実行するシンプルなパイプラインの記事を投稿しました。
今回はもうちょっと発展させて以下のような要件を取り込んでみたいと思います。
- terraform workspace 環境でも使えるようにしたい
- 本番環境は
terraform applyの前に承認者による承認プロセスを入れたい
イメージは以下のとおりです。
開発環境向け
1-1. develop ブランチへ push
1-2. dev workspace に terraform apply を実行
本番環境向け
2-1. develop ブランチから master ブランチへ merge
2-2. prod workspace で terraform plan を実行
2-3. 承認者に後続処理の承認要求をメール通知
2-4. 本番用パイプラインで後続処理を「承認」
2-5. prod workspace で terraform apply を実行
概要がわかっていただけたかと思いますので、それではパイプラインを構築していきます。
Terraform Backend の作成
S3 および DynamoDB を使った Terraform Backend ですが、この部分は変更がありませんので前回の記事を参照ください。
Terraform workspace の作成
workspace の作成はパイプラインに入れる必要はありません。以下のコマンドをローカル実行し、事前に作成しておきます。
$ terraform workspace new dev Created and switched to workspace "dev"! You're now on a new, empty workspace. Workspaces isolate their state, so if you run "terraform plan" Terraform will not see any existing state for this configuration. $ terraform workspace new prod Created and switched to workspace "prod"! You're now on a new, empty workspace. Workspaces isolate their state, so if you run "terraform plan" Terraform will not see any existing state for this configuration. $ terraform workspace list default dev * prod
以上で OK です。ちなみに Terraform workspace 環境の場合、S3 や DynamoDB の backend は以下のように env: 階層が追加され、tfstate も LockID も分離して管理されます。
CodeCommit の作成
こちらも手順としては変更ありませんので前回の記事を参照ください。
構成としては、develop および master ブランチの 2 つが存在する状態です。
dev 用 CI/CD パイプライン
CodePipeline の作成
基本的には前回の記事と同じなので、前回手順を参考にすすめてください。一部、buildspec.yml の書き方を変えたので、[Build -optional] での環境変数のみ、下記のように変更しています。(前回の手順だと、[CodePipeline 作成]の手順12.の箇所です)
| Name | Value | Type | 説明 |
|---|---|---|---|
| TF_VERSION | 0.12.19 | Plaintext | Terraform バージョン |
| TF_CMD | apply | Plaintext | terraform コマンド |
| TF_WS | dev | Plaintext | workspace 名 |
| TF_OPT | -input=false -auto-approve -no-color | Plaintext | terraform コマンドのオプション |
前回までは Build プロジェクトのなかで terraform plan と terraform apply を実行してたのですが、開発環境においては事前に自分で terraform plan 流してるだろうし、ダメならコケて終わりなので必要ないかと思って外しました。
また、terraform plan と terraform apply ではオプションが異なるのですが buildspec.yml を共通化したかったので、コマンドオプションも TF_OPT 環境変数に入れて渡すことにしました。
workspace 対応のために、workspace 名の指定が必要となりましたので、こちらは TF_WS に入れることにしました。buildspec.yml は以下のとおり。
version: 0.2
phases:
install:
runtime-versions:
docker: 18
commands:
- yum install unzip -y
- wget https://releases.hashicorp.com/terraform/"$TF_VERSION"/terraform_"$TF_VERSION"_linux_amd64.zip
- unzip terraform_"$TF_VERSION"_linux_amd64.zip
- mv terraform /usr/local/bin/
pre_build:
commands:
- terraform init -input=false -no-color
- terraform workspace select $TF_WS -no-color
build:
commands:
- terraform $TF_CMD $TF_OPT
post_build:
commands:
- echo terraform $TF_CMD completed on `date`
CodeBuild 用の IAM ロール設定
前回同様に、今回も CodeBuild 用 IAM ロールに AdministratorAccess ポリシーをアタッチして検証しました。
prod 用 CI/CD パイプライン
CodePipeline の作成
dev 用のパイプラインは 2 つのステージ(ソースアーティファクトの作成、terraform apply)のみでしたが、prod 用は以下のような 4 つのステージを作成していきます。
- ソースアーティファクトの作成
terraform planを実行- 承認プロセス
terraform applyを実行
それでは Create pipeline から開始します。
1. CodePipeline 管理コンソールから Create pipeline をクリック
2. パイプライン名を入力し、New service role を選択して Next を選択
3. ソースプロバイダーに AWS CodeCommit を選択。該当のリポジトリと、master ブランチを指定
4. 検出オプションは Amazon CloudWatch Events (recommended) を選択して Next を選択
5. ビルドプロバイダーに AWS CodeBuild を選択
6. Create Project をクリックし、ビルドプロジェクトを作成(別のウィンドウが起動します)
7. プロジェクト名を入力
8. [Environment Image]で Managed image を選択し、以下のように選択
- Operating system:
Amazon Linux2 - Runtime:
Standard - Image:
aws/codebuild/amazonlinux2-x86_64-standard:2.0 - Image version:
Always use the latest image for this runtime version - Environment type:
Linux
9. [Privileged] の下にあるチェックボックスにチェックを入れ、New service role を選択
10. Buildspec のセクションは、Use a buildsped file を選択
11. Log セクションで、CloudWatch logs にチェックを入れ Continue to CodepiPeline をクリック
12. 元のウィンドウに戻り、[Environment variables] で以下の環境変数を設定し Next をクリック
| Name | Value | Type | 説明 |
|---|---|---|---|
| TF_VERSION | 0.12.19 | Plaintext | Terraform バージョン |
| TF_CMD | plan | Plaintext | terraform コマンド |
| TF_WS | prod | Plaintext | workspace 名 |
| TF_OPT | -input=false -lock=false -no-color | terraform コマンドのオプション |
13. CodeDeploy は不要ですので、Skip deploy stage をクリック
14. Create pipeline でパイプラインを作成
CodeBuild 用の IAM ロール設定
- IAM 管理コンソールを開き、[Roles]から先ほど CodeBuild 設定のなかで作成した IAM ロールを検索し、IAM ロール名をクリック
- [Permissions]タブを開き、[Attach policies]をクリック
- ビルド対象のリソース管理に必要なポリシーをアタッチ。(今回も AdministratorAccess をアタッチしましたが、必要に応じて必要な権原に絞り込んでください)
SNS 設定
次に、承認要求のメールを通知するための SNS 設定を行います。
1. SNS 管理コンソールを開き、[Topics] から Create topic をクリック
2. トピック名 を入力し、Create topic をクリック
3. トピック一覧に戻り、作成したばかりのトピックをクリック
4. Subscriptions タブから Create subscription をクリック
5. 3.で作成したトピック、プロトコル(Email)、Endpiont(Email アドレス) を指定し、Create subscription をクリック
6. Confirm メールが届くので、リンクをクリックし Confirm する
承認ステージの追加
CodePipeline 管理コンソールに戻り、prod 用パイプラインに承認ステージを追加します。
1. CodePipeline 管理コンソールから prod 用パイプラインを開き、Edit をクリック
2. [Build] ステージの下にある Add Stage をクリック
3. ステージ名を入力し、Add stage をクリック(私は terraform-apply-prod-approval としました)
4. 作成したステージ内の Add action group をクリック
5. アクション名を入力、アクションプロバイダで Manual approval を選択。SNS topic ARN は先ほど作成したものを指定し、必要に応じてコメントを入力し、Done
terraform apply ステージの追加
承認プロセスが完了した後の terraform apply を実行するステージを設定します。
1. CodePipeline 管理コンソールから prod 用パイプラインを開き、Edit をクリック
2. 承認ステージの下にある Add Stage をクリック
3. ステージ名を入力し、Add stage をクリック(私は terraform-apply-prod としました)
4. 作成したステージ内の Add action group をクリック
5. アクション名を入力、アクションプロバイダで AWS CodeBuild を選択。その後は、基本的には dev 環境と同じように Build project の設定を進めます。Add environment variable については、以下のように設定し、Done
| Name | Value | Type | 説明 |
|---|---|---|---|
| TF_VERSION | 0.12.19 | Plaintext | Terraform バージョン |
| TF_CMD | apply | Plaintext | terraform コマンド |
| TF_WS | prod | Plaintext | workspace 名 |
| TF_OPT | -input=false -auto-approve -no-color | Plaintext | terraform コマンドのオプション |
これでパイプラインとしては完成です。
CI/CD パイプラインの検証
dev 環境に push
前回の記事と同じ config.tf を含めて、以下のファイルを準備します。
- config.tf
- buildspec.yml (上記参照)
- s3.tf (今回も S3 バケットの作成で動作確認します)
バケット名が重複しないように terraform.workspace を付与しています。実行する workspace によって dev や prod の値が入ります。
resource "aws_s3_bucket" "cm-terraform-000" {
bucket = "cm-terraform-${terraform.workspace}-000"
acl = "private"
}
terraform {
required_version = ">= 0.12.0"
backend "s3" {
encrypt = true
bucket = "terraform-tfstate"
dynamodb_table = "terraform-state-lock"
key = "terraform.tfstate"
region = "ap-northeast-1"
}
}
develop 環境に push します。
marumo.atsushi@:~/Project/terraform-cicd (develop) $ ls -l total 40 -rw-r--r-- 1 marumo.atsushi staff 575 1 22 18:39 buildspec.yml -rw-r--r-- 1 marumo.atsushi staff 336 1 21 09:22 config.tf -rw-r--r-- 1 marumo.atsushi staff 121 1 24 05:49 s3.tf $ git push Warning: Permanently added 'git-codecommit.ap-northeast-1.amazonaws.com,52.119.218.16' (RSA) to the list of known hosts. Counting objects: 3, done. Delta compression using up to 4 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 307 bytes | 307.00 KiB/s, done. Total 3 (delta 2), reused 0 (delta 0) To ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/terraform-cicd 54edaa2..cf564d9 develop -> develop
dev 用パイプラインの確認
dev 用の CodePipeline が正常に実行されていることを確認します。
S3 バケット cm-terraform-dev-000 が作成されていることを確認します。
dev 用のパイプラインが正常に動作していることが確認できましたね。
develop → master への merge
それでは prod 用のパイプラインを動作させるために、develop ブランチを master ブランチに merge しましょう。
CodeCommit 管理コンソールからリポジトリの develop ブランチを開き、Create pull request をクリック。
Destination に master、Source に develop を指定し、Title および必要に応じて Description を入力し、Create pull request をクリック。
作成したプルリクエストを開き、Merge をクリック。
Merge strategy は任意のものを指定します。merge 後にブランチを削除したくない場合は Delete source branch develop after merging? のチェックを外し、Merge pull request をクリック。
これで prod 用のパイプラインがトリガーされることになります。
prod 用パイプラインの確認
prode 用の CodePipeline を開くと、master ブランチへの merge によってパイプラインが動作しているはずです。Build(terraform plan) ステージが実行された後、承認ステージの terraform-apply-prod-approval で Pending していることが判りますね。
SNS トピックのサブスクリプションで指定したアドレスに以下のようなメールが届きます。
リンクをクリックすると CodePipeline 管理コンソールが開きますので、Build ステージの terraform_plan の Details をクリックし、変更内容を確認します。
変更内容に問題がなければ、承認ステージ内の Review をクリック。必要に応じてコメントを入力し、Approve をクリック。
承認後、terraform_apply ステージが実行されていることを確認します。
S3 バケット cm-terraform-prod-000 が作成されていることを確認します。
正常に作成されていることが確認できましたね!検証は以上です!
さいごに
Terraform workspace を利用した環境での CI/CD パイプラインを試してみました。本番環境へのデプロイは、必要最低限の安全措置を承認プロセスを設けることで確保しています。
これが正解というワケではなく、あくまで 1 つの案として参考にしていただければと思います。
以上!大阪オフィスの丸毛(@marumo1981)でした!
























