AWS CodeBuild と GitHub で実現する Terraform CI/CD 入門
想定読者
AWS CodeBuild と GitHub による Terraform の CI/CD 実装例を紹介します。
- Terraform の CI/CD ワークフローを実装したい人
- AWS CodeBuild の具体的な使用例をみたい人
構成図
CodeBuild のビルドプロジェクトを 2 つ作成します。
それぞれプルリクエスト作成/更新とマージに対応します。
GitHub Actionsについて
GitHub Actions を利用すると CI/CD に関連するリソースが GitHub に閉じるため、よりシンプルに利用できます。筆者の参画する案件では GitHub Enterprise(いわゆるオンプレ版)が提供されていますが、GitHub Actions を利用するためにセルフホストランナーを用意する必要がありました。インフラを自前で用意することを嫌ったため、チームの AWS アカウントで CodeBuild を利用することとしました。基本的な概念は同じため、参考にしてください。
tfnotify
Terraform の plan/apply 結果を GitHub や Slack に通知してくれるツールです。
事前準備
リポジトリ
GitHub にて新規にリポジトリを作成します。
プライベートリポジトリで問題ありません。
アクセストークン
GitHub にて 個人のアクセストークンを払い出します。
tfnotify が GitHub に通知をするために利用します。
Settings > Developer Settings > Personal access tokens > Tokens (classic)
より作成できます。
権限は repo:status
public_repo
のみで大丈夫です。
IAM
Terraform 実行に必要な権限を付与した IAM ロールを作成します。
本記事では IAM ポリシー AmazonS3FullAccess
を利用します。
信頼関係では CodeBuild を許可しましょう。
S3
Terraform のバックエンド用 S3 バケットを作成します。
デフォルト値から変える設定はありません。
構築
サンプルコードはこちら。
GitHub
サンプルコードを参考に、CI/CD 用のコードをプッシュします。
Terraform コードの main.tf
は後続の CI/CD ワークフロー体験で使うため、プッシュしないでください。
CodeBuild が plan 時に利用する buildspec_plan.yml
は以下です。
apply を行う buildspec_apply.yml
については、リポジトリを確認してください。
version: 0.2
env:
variables:
TFDIR: "environments"
TFNCONF: "codebuild/tfnotify.yml"
TITLE: "Terraform Plan"
MSG: "Plan detail via tfnotify"
phases:
install:
commands:
# terraform
- curl -sL https://releases.hashicorp.com/terraform/1.6.2/terraform_1.6.2_linux_amd64.zip > terraform.zip
- unzip terraform.zip
- cp terraform /usr/local/bin
# tfnotify
- curl -sL https://github.com/mercari/tfnotify/releases/download/v0.8.0/tfnotify_linux_amd64.tar.gz > tfnotify.tar.gz
- tar -zxvf tfnotify.tar.gz
- cp tfnotify /usr/local/bin
pre_build:
commands:
- terraform -chdir="${TFDIR}" init -no-color
build:
commands:
- |
PLAN=$(terraform -chdir="${TFDIR}" plan -no-color 2>&1)
echo "${PLAN}" | tfnotify --config "${TFNCONF}" plan --title "${TITLE}" --message "${MSG}"
tfnotify 用の設定ファイルは以下です。
こちらは plan と apply を 1 ファイルにまとめられます。
---
ci: codebuild
notifier:
github:
token: $GITHUB_TOKEN
repository:
owner: "teradatky"
name: "ci-codebuild-terraform-20231026"
terraform:
plan:
template: |
{{ .Title }} <sup>[CI link]( {{ .Link }} )</sup>
{{ .Message }}
{{if .Result}}
<pre><code>{{ .Result }}
</pre></code>
{{end}}
<details><summary>Details (Click me)</summary>
<pre><code>{{ .Body }}
</pre></code></details>
apply:
template: |
{{ .Title }} <sup>[CI link]( {{ .Link }} )</sup>
{{ .Message }}
{{if .Result}}
<pre><code>{{ .Result }}
</pre></code>
{{end}}
<details><summary>Details (Click me)</summary>
<pre><code>{{ .Body }}
</pre></code></details>
CodeBuild
ビルドプロジェクトを 2 つ作成します。
以下に plan 用ビルドプロジェクトを作成するスクリーンショットを載せています。
apply 用のリソースのスクリーンショットは省略しますが、同様に作成します。
2 つのビルドプロジェクトが作成できました。
CI/CD ワークフロー
実際に Terraform コードを記載し CI/CD ワークフローを回します。
今回は S3 バケットを作成します。 main.tf
に以下を記載してプッシュします。
resource "aws_s3_bucket" "my_bucket" {
bucket = "ci-codebuild-terraform-20231026-my-bucket"
}
プルリクエストを作成し、マージするまでの流れを記載します。
実際のプルリクエストはこちらから確認できます。
プルリクエストを作成しました。
すると tfnotify
により plan 結果が通知されます。
レビュアーはこの結果を確認することで、マージ可否を簡単に判断できるようになります。
terraform init
や terraform plan
で失敗していないことが checks からも分かります。
レビュアーから Approve されたらマージしましょう。
マージ後 terraform apply
の結果が通知されます。
以上、CI/CD ワークフローの一例でした。
まとめ
CodeBuild を使うことで、Terraform の CI/CD が実現できました。
プルリクエストをベースとすることで、作業ミスや認識齟齬をグッと減らすことができます。
また tfnotify は plan や apply 結果が プルリクエスト内で確認できるため、レビュー負荷が軽減されます。
CI/CD を未経験の方はぜひ試してみて欲しいです。
Discussion