CodePipeline で簡単 Terraform CI/CD パイプラインの実装
今回は、CodeCommit への push をトリガーに CodeBuild で terraform apply
する CodePipeline を作成してみたいと思います。ざっくり環境は以下のとおりです。
環境
- Terraform Backend
- S3
- DynamoDB
- CodeCommit
- CodeBuild
- CodePipeline
Terraform Backend の作成
今回は CI/CD パイプラインを使って Terraform を管理しますので、tfstate ファイルは共有可能な場所に保存する必要があります。また、このパイプラインは複数人が利用することが想定されるため、git push
のタイミングによっては、同時に terraform apply
が動作し tfstate に競合が発生してしまう可能性があります。
これらの課題は Terraform の Backend 機能を利用することで簡単に以下のような設定を行うことが出来ます。
- tfstate の保存先に S3 を利用
- DynamoDB を利用した State Locking の実装
それでは Backend で利用する S3 バケット、および DynamoDB テーブルを作成します。
S3 バケットの作成
- S3 管理コンソールを開き
Create Bucket
をクリック - S3 バケット名を入力、リージョンを選択して[次へ]をクリック
- バージョニングとデフォルト暗号化を有効にして[次へ]をクリック
Block all public access
を選択して[次へ]をクリックし、バケットを作成
DynamoDB テーブルの作成
- DynamoDB 管理コンソールを開き、
Create table
をクリック - 任意のテーブル名を指定。例えば
terraform-state-lock
のように指定します - 図のように、主キーとして
LockID
を指定し、Use default settings
にチェックして作成
Terraform 設定ファイル
Terraform
ブロックの Backend
設定で、先ほど作成したバケット名およびテーブル名を指定します。
terraform { required_version = ">= 0.12.0" backend "s3" { encrypt = true bucket = "terraform-tfstate" <-- S3 バケット名 dynamodb_table = "terraform-state-lock" <-- DynamoDB テーブル名 key = "terraform.tfstate" region = "ap-northeast-1" } } provider "aws" { region = "ap-northeast-1" version = "~> 2.45" }
CodeCommit 作成
- CodeCommit 管理コンソールから、
Create repository
をクリック - リポジトリ名を入力し、
Create
で作成します。作成後にリポジトリに移動します。 Create file
をクリック
4. readme.md のようなサンプルファイルを作成し、Commit changes
をクリック
5. 今回は develop
ブランチを使いたいので、左のメニューから Branches
を開き Create branch
をクリック
6. ブランチ名に develop
を入力、from に master
を指定し、Create branch
をクリックしてブランチを作成
CI/CD パイプライン
CodePipeline 作成
- CodePipeline 管理コンソールから
Create pipeline
をクリック - パイプライン名を入力し、
New service role
を選択してNext
を選択
3. ソースプロバイダーに AWS CodeCommit
を選択。先ほど作成したリポジトリと、develop
ブランチを指定
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
- キー名:
TF_VERSION
- 値:
0.12.19
- タイプ:
Plaintext
13. CodeDeploy は不要ですので、Skip deploy stage
をクリック。
14. Create pipeline
でパイプラインを作成
CodeBuild 用の IAM ロール設定
- IAM 管理コンソールを開き、[Roles]から先ほど CodeBuild 設定のなかで作成した IAM ロールを検索し、IAM ロール名をクリック
- [Permissions]タブを開き、[Attach policies]をクリック
- ビルド対象のリソース管理に必要なポリシーをアタッチ。(今回は
AdministratorAccess
をアタッチしましたが、必要に応じて必要な権原に絞り込んでください)
CI/CD パイプラインの検証
CodeCommit への Git 接続設定
CodeCommit への接続は、IAM ユーザを作成して SSH や HTTPS で接続できます。設定方法等については、以下の記事を参照ください。
構成ファイルの準備
先ほど作成した config.tf
を含めて、以下のファイルを準備します。
- config.tf
- buildspec.yml
- s3.tf (今回は S3 バケットの作成で動作確認します)
buildspec.yml では、Terraform のダウンロード、インストールを行います。バージョンの指定は CodePipeline 設定のなかで CodeBuild 向けの環境変数として設定した TF_VERSION
で指定します。pre_build 内の terraform init
や terraform plan
でエラーがあった場合は、build は実行されずエラー終了します。今回は特に承認処理等を入れていないので、terraform plan
が正常処理されると、そのまま terraform apply
まで実行されます。(ローカル環境で事前に terraform plan を行い、変更、削除されるリソースを確認してください)
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 plan -input=false -no-color build: commands: - terraform apply -input=false -auto-approve -no-color post_build: commands: - echo terraform apply completed on `date`
S3 バケットを 1 つ作成するだけの簡単な tf ファイルとしました。
resource "aws_s3_bucket" "cm-terraform-000" { bucket = "cm-terraform-000" acl = "private" }
CodeCommit リポジトリへの push
CodeCommit リポジトリの develop ブランチに push します。
marumo.atsushi@:~/Project/terraform-cicd (develop) $ ls -l total 32 -rw-r--r-- 1 marumo.atsushi staff 607 1 21 08:51 buildspec.yml -rw-r--r-- 1 marumo.atsushi staff 314 1 21 08:51 config.tf -rw-r--r-- 1 marumo.atsushi staff 6 1 21 08:46 readme.md -rw-r--r-- 1 marumo.atsushi staff 192 1 21 08:51 s3.tf $ git add . $ git commit -m "Initial commit" [develop 8b78804] Initial commit 3 files changed, 48 insertions(+) create mode 100644 buildspec.yml create mode 100644 config.tf create mode 100644 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: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (5/5), 883 bytes | 883.00 KiB/s, done. Total 5 (delta 0), reused 0 (delta 0) To ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/terraform-cicd ea86283..8b78804 develop -> develop
しばらくすると CodePipeline が動作し、CodeBuild が実行されます。
もしエラーになっている場合は、ビルドプロジェクトの [Details] をクリックし、ビルド実行時の Tail ログを確認しながらトラブルシューティングしてください。
S3 バケットも正常に作成されていますね。
検証は以上です。
さいごに
Code シリーズを使った簡単な Terraform CI/CD パイプラインを作成してみました。今回は単に terraform apply
を実行する単純なパイプラインでしたので、次は Terraform workspace と絡めて、環境によっては terraform apply
前に承認プロセスを必要とするようなパイプラインを検討してみたいと思います。
以上!大阪オフィスの丸毛(@marumo1981)でした!