0
0

AWS CodeBuild と GitHub で実現する Terraform CI/CD 入門

Last updated at Posted at 2024-08-06

想定読者

AWS CodeBuild と GitHub による Terraform の CI/CD 実装例を紹介します。

  • Terraform の CI/CD ワークフローを実装したい人
  • AWS CodeBuild の具体的な使用例をみたい人

構成図

architecture.png

CodeBuild のビルドプロジェクトを 2 つ作成します。
それぞれプルリクエスト作成/更新とマージに対応します。

terraform apply が同時に実行される可能性がある場合は tfstate の破損を防ぐために DynamoDB による state lock を追加してください。

details GitHub Actionsについて

GitHub Actions を利用すると CI/CD に関連するリソースが GitHub に閉じるため、よりシンプルに利用できます。GitHub Enterprise(いわゆるオンプレ版)の利用が必須の場合、GitHub Actions を使うにはセルフホストランナーを用意する必要があります。インフラを自前で用意することが大変な場合、この記事のように AWS アカウントで CodeBuild を利用するという選択肢が考えられます。GitHub Actions であっても CI/CD の基本概念は同じため、参考にしてください。

tfnotify

Terraform の plan/apply 結果を GitHub や Slack に通知してくれるツールです。

事前準備

リポジトリ

GitHub にて新規にリポジトリを作成します。
プライベートリポジトリで問題ありません。

repo_create.png

アクセストークン

GitHub にて 個人のアクセストークンを払い出します。
tfnotify が GitHub に通知をするために利用します。
Settings > Developer Settings > Personal access tokens > Tokens (classic) より作成できます。
権限は repo:status public_repo のみで大丈夫です。

ghp_token.png

ウィンドウを閉じるとトークンは二度と確認できません。きちんとメモしておきましょう。

IAM

Terraform 実行に必要な権限を付与した IAM ロールを作成します。
本記事では IAM ポリシー AmazonS3FullAccess を利用します。
信頼関係では CodeBuild を許可しましょう。

iam_role1.png
iam_role2.png
iam_role3.png

S3

Terraform のバックエンド用 S3 バケットを作成します。
デフォルト値から変える設定はありません。

s3_tfstate.png

構築

GitHub

サンプルコードを参考に、CI/CD 用のコードをプッシュします。

repository.txt
├── README.md
├── codebuild
│   ├── buildspec_apply.yml
│   ├── buildspec_plan.yml
│   └── tfnotify.yml
└─── environments
    ├── main.tf
    └── provider.tf

CodeBuild が plan 時に利用する buildspec_plan.yml は以下です。

buildspec_plan.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}"

CodeBuild が apply 時に利用する buildspec_apply.yml は以下です。

buildspec_apply.yml
version: 0.2

env:
  variables:
    TFDIR: "environments"
    TFNCONF: "codebuild/tfnotify.yml"
    TITLE: "Terraform Apply"
    MSG: "Apply 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:
      - |
        APPLY=$(terraform -chdir="${TFDIR}" apply -auto-approve -no-color 2>&1)
        echo "${APPLY}" | tfnotify --config "${TFNCONF}" apply --title "${TITLE}" --message "${MSG}"

CI/CD が頻繁に実行される場合は terraform tfnotify のインストールを毎回行わずに済むよう、カスタムイメージを利用しましょう。docker build を行い ECR にプッシュすることで CodeBuild から利用可能です。

tfnotify 用の設定ファイルは以下です。
こちらは plan と apply を 1 ファイルにまとめられます。

tfnotify.yml
---
ci: codebuild
notifier:
  github:
    token: $GITHUB_TOKEN
    repository:
      owner: "YOUR_GITHUB_USERNAME"
      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 用のリソースのスクリーンショットは省略しますが、同様に作成します。

デフォルト値から変更していない箇所は、スクリーンショットを撮っていません。
名前やログ出力先などもビルドプロジェクトに合わせて適宜変更してください。

codebuild1.png
codebuild2.png

OAuth 連携が初回の場合、このような画面に遷移します。

oauth.png

codebuild3.png

「プライマリソースのウェブフックイベント」が変わることに注意します。

  • plan 用ビルドプロジェクト
    • PULL_REQUEST_CREATED PULL_REQUEST_UPDATED PULL_REQUEST_REOPEND
  • apply 用ビルドプロジェクト
    • PULL_REQUEST_MERGED

codebuild4.png
codebuild5.png

サービスロールの編集を許可する場合は、自動的に IAM ロールに必要なポリシーがアタッチされます。許可しない場合、事前に必要な権限を付与しておく必要があります。

https://dev.classmethod.jp/articles/codebuild-service-role-checkbox/

codebuild6.png

個人用の AWS アカウントでない場合、アクセストークンはプレーンテキストではなく Secrets Manager を利用してください。

codebuild7.png
codebuild8.png

ストリーム名を空にすることで、ビルドごとに別のストリームにログを記録します。

2 つのビルドプロジェクトが作成できました。

codebuild9.png

CI/CD ワークフロー

実際に Terraform コードを記載し CI/CD ワークフローを回します。
今回は S3 バケットを作成します。 main.tf に以下を記載してプッシュします。

main.tf
resource "aws_s3_bucket" "my_bucket" {
  bucket = "ci-codebuild-terraform-20231026-my-bucket"
}

プルリクエストを作成しました。

pr1.png
pr1_file.png

すると tfnotify により plan 結果が通知されます。
レビュアーはこの結果を確認することで、マージ可否を簡単に判断できるようになります。

pr2.png

terraform initterraform plan で失敗していないことが checks からも分かります。

pr3.png

レビュアーから Approve されたらマージしましょう。

pr4.png

マージ後 terraform apply の結果が通知されます。

pr5.png

plan が通っても apply が失敗するケースはよくあるため、きちんと結果を確認しましょう。

以上、CI/CD ワークフローの一例でした。

まとめ

CodeBuild を使うことで、Terraform の CI/CD が実現できました。
プルリクエストをベースとすることで、作業ミスや認識齟齬をグッと減らすことができます。
また tfnotify は plan や apply 結果が プルリクエスト内で確認できるため、レビュー負荷が軽減されます。
CI/CD を未経験の方はぜひ試してみて欲しいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0