🤖

Terraform + GitHub ActionsでInfra CI/CDを試す (2022年版)

2022/05/10に公開

去年、「Terraform + GitHub Actions で Infra CI/CD を試す」という題名で記事を書きました。
この記事では、いくつかアップデートを加えて再実装してみたものを記事としてまとめています。

実装サンプルは下記にあります (null resource を定義したサンプルコードを載せています)
https://github.com/taxintt/actions-infra-cicd-sample

Workflowの概要

下記のような構成で workflow を定義しています。

  • A: terraform-ci-{stg, prod}.yaml: xx.tf のファイル変更を Trigger に workflow を実行する
    • tflint
    • terraform validate
    • terraform plan
  • B: terraform-cd-{stg, prod}.yaml: staging / main branch への PR merge を Trigger に workflow を実行する
    • tflint
    • terraform validate
    • terraform apply

リソース追加を想定した一連の開発フローは下記の通りです

  1. feature branch を切って、xxx.tf にリソース定義を追加して修正を commit + push する(A)
  2. 1 の変更を staging branch に merge する(B)
  3. PR review を行い、Approve されたら PR を merge する(B)

google-github-actions/auth (for keyless CI/CD)

下記の記事で基本的な内容はまとまっていますが、理解のために一部重複しますがまとめておきます。
https://zenn.dev/vvakame/articles/gha-and-gcp-workload-identity

2021 年 10 月のアップデートで、GitHub Actions の workflow から OIDC token を発行できるようになりました。
https://github.com/github/roadmap/issues/249

この機能と GCP のWorkload Identity Federationを組み合わせることで、short-lived (default: 3600sec) の credentials を取得できるようになりました。

これまでは、workflow で gcloud コマンドを実行する場合は、Service Account Key を base64 encode した状態で GitHub secret として渡すのが一般的でした。

今回の例では、google-github-actions/authを利用することで、発行された OIDC token を Security Token Service に渡して credential を取得しています。

GitHub Actions の Workflow 側では、jobs.<job_id>.permissionsid-token: 'write' と定義することで、token の発行に必要な権限が付与されます。
https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions

permissions:
  contents: 'write'
  id-token: 'write'

google-github-actions/authでは、Workload Identity Provider と Credential に紐づく Service Account 名を指定しておきます。
これにより、任意の Service Account に紐づいた Credential の発行ができるようになります。

- uses: 'actions/checkout@v3'
- id: 'auth'
  name: 'Authenticate to Google Cloud'
  uses: 'google-github-actions/auth@v0' # https://github.com/google-github-actions/auth
  with:
    create_credentials_file: 'true'
    workload_identity_provider: ${{ secrets.workload_identity_provider }}
    service_account: ${{ secrets.service_account }}
    access_token_lifetime: 1200s   

また、Terraform 関連の Workflow で、事前に gcloud auth login が必要なので、create_credentials_file: trueを設定して、後続の step で Credential を利用するように設定します。
(自動でexportされる環境変数経由でも path を取得できるようです)

- id: 'gcloud-auth-login'
  name: gcloud auth login by workload identity
  run: |-
    gcloud auth login --cred-file="${{ steps.auth.outputs.credentials_file_path }}"

一連の token 発行の流れは、下記 Issue の図がわかりやすいかと思います。
https://github.com/github/roadmap/issues/249

tfcmt

去年の段階では、mercari/tfnotifyを利用していましたが、直近ではメンテナンスも行われているtfcmtを利用しています。

GitHub Actions は組み込みの環境変数から必要なパラメータがセットされるので、tfcmt plan -- terraform planのように定義するだけで Pull request のコメントに terraform plan の結果を投稿できます。
https://suzuki-shunsuke.github.io/tfcmt/getting-started#support-of-ci-platforms

- id: 'setup-tfcmt'
  name: Install tfcmt
  run: |
    sudo curl -fL -o tfcmt.tar.gz https://github.com/suzuki-shunsuke/tfcmt/releases/download/$TFCMT_VERSION/tfcmt_linux_amd64.tar.gz
    sudo tar -C /usr/bin -xzf ./tfcmt.tar.gz
  env:
    TFCMT_VERSION: "v3.2.1"

- id: 'tfcmt'
  name: Terraform plan
  run: |
    tfcmt plan -- terraform plan -no-color
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
    PR_NUMBER: ${{ github.event.number }}

コメントのフォーマットもテンプレートファイルで定義できるようですが、default の状態でも特に不自由ありません。
https://suzuki-shunsuke.github.io/tfcmt/config#default-configuration

tflint

tflint-ruleset-google (GCP)

tflint の GCP 用の ruleset に関しては、下記で開発が進んでいます。
2021 年初旬よりもある程度充実している印象です。
https://github.com/terraform-linters/tflint-ruleset-google

reviewdog/action-tflint

tflint のセットアップ処理は、reviewdog/action-tflintに任せています。

action-tflint の設定で、commit の度に tflint を走らせたいので reporter: github-check として設定しています。

- name: tflint
  uses: reviewdog/action-tflint@master
  with:
    github_token: ${{ secrets.github_token }}
    reporter: github-check # https://github.com/reviewdog/reviewdog/issues/889
    fail_on_error: true
    filter_mode: "nofilter"
    tflint_version: "v0.36.0"
    tflint_rulesets: "google"

最後に

基本的な構成自体は変わっていませんが、google-github-actions/authを利用した keyless CI/CD の登場や tfcmt, tflint などの関連ツールの開発によってある程度機能面では充実してきている印象です。
tfmigrate など CI/CD に組み込んでみたいツールは他にもあるので、機会があればアップデートした内容を記事にしてみようと思います。

参考リンク

Discussion