Github Actions で実現する Terraform plan, apply 自動化
株式会社スリーシェイク / parupappa
チームリーダー / SRE / 従業員規模: 101名〜300名 / エンジニア組織: 51名〜100名
ツールの利用規模 | ツールの利用開始時期 | 事業形態 |
---|---|---|
11名〜50名 | 2024年7月 | B to B |
ツールの利用規模 | 11名〜50名 |
---|---|
ツールの利用開始時期 | 2024年7月 |
事業形態 | B to B |
アーキテクチャ
導入の背景・解決したかった問題
導入背景
ツール導入前の課題
【今回のケース:terraform リポジトリに対して実行することを想定】 Google Cloud の Project に対して、terraform plan, apply をローカルから実行していました。ローカルから実行することでメリットや管理面の楽さも一定ありますが、プロダクトの環境が増え、plan, apply する Project が増えてくると、運用保守性や人的ミスといったことが懸念されていました。
どのような状態を目指していたか
terraform plan, applyをGithub上でのレビューを介して自動化し、運用負荷の低減を目指しました。
導入の成果
GitHub Actionsを使うことで、terraform plan, apply 時のトリガーの設定や、CIでのterraform セットアップなどの自動化が実現できました。
導入前に解決したかった課題に対しては以下のように解決されました。
- プルリクエストをトリガーとして変更のあった環境に対して自動でterraform planが実行される
- terraform plan の結果をgithub上にコメントとして表示することで、レビューを効率化
- ローカル環境に依存しないことにより、terraformのバージョン管理や環境依存の問題を解消
参考までに、実際に作成したGithub Actions上でterraformのplanを実行するワークフローを掲載します。
▼ plan 自動化(plan.yaml)
name: terraform plan
run-name: terraform plan
on:
pull_request:
paths:
- "terraform/**/*.tf"
- "!terraform/**/README.md"
env:
# Google Cloud Project情報を定義
PROJECT_MAPPING: '{ "project-id": "XXXXXXXXX" }'
jobs:
filter:
runs-on: ubuntu-latest
outputs:
workdirs: ${{ steps.set_workdirs.outputs.workdirs }}
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
module: terraform/module/**
project-id: terraform/projects/project-id/**
- name: Setup working-directory
id: set_workdirs
run: |
if echo "${{ steps.filter.outputs.changes }}" | grep -q 'module' ; then
echo "Run terraform plan in all projects."
echo 'workdirs=["project-id"]' >> "$GITHUB_OUTPUT"
else
echo "Run terraform plan in changed projects."
echo "workdirs=${{ toJson(steps.filter.outputs.changes) }}" >> "$GITHUB_OUTPUT"
fi
terraform-plan:
needs: filter
if: ${{ needs.filter.outputs.workdirs != '[]' }}
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
pull-requests: write
strategy:
fail-fast: false
matrix:
project: ${{ fromJSON(needs.filter.outputs.workdirs) }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set Project Number
id: set_project_num
shell: bash
run: |
echo "PROJECT_ID=${{ matrix.project }}" >> "$GITHUB_ENV"
echo "PROJECT_NUM=${{ fromJson(env.PROJECT_MAPPING)[matrix.project] }}" >> "$GITHUB_ENV"
# Composite action
- name: Setup Terraform with Aqua
uses: ./.github/actions/setup_terraform
with:
aqua_version: v2.31.0
project_id: ${{ env.PROJECT_ID }}
workload_identity_provider: "projects/${{ env.PROJECT_NUM }}/locations/global/workloadIdentityPools/github-pool/providers/github-provider"
- name: Terraform Plan
id: plan
run: |
tfcmt -var "target:${{ matrix.project }}" --config "$(git rev-parse --show-toplevel)"/.github/tfcmt.yaml plan -patch -- terraform plan -no-color -input=false
working-directory: "./terraform/projects/${{ matrix.project }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
▼ plan 自動化 - Composite Action(action.yaml)
name: Setup 'Terraform'
description: 'Setup Terraform'
inputs:
aqua_version:
description: 'The version of Aqua to use'
required: true
project_id:
description: 'The project ID to use'
required: true
workload_identity_provider:
description: 'The workload identity provider to use'
required: true
runs:
using: "composite"
steps:
- name: auth-google
uses: google-github-actions/auth@v2
with:
project_id: ${{ inputs.project_id }}
workload_identity_provider: ${{ inputs.workload_identity_provider }}
# Cache Aqua tools
- name: Cache Tools
id: cache-tools
uses: actions/cache@v4
with:
path: ~/.local/share/aquaproj-aqua
key: cache-tools-${{ hashFiles('aqua.yaml') }}
# aqua.yamlから取得したパッケージをインストール
- name: Setup Aqua
uses: aquaproj/aqua-installer@v3.0.1
with:
aqua_version: ${{ inputs.aqua_version }}
aqua_opts: "" # Lazy install(aqua i -l) がデフォルトで有効になっているため、aqua_optsに空文字を指定して'-l'オプションを取り除く
- name: Terraform fmt
id: fmt
shell: bash
run: terraform fmt -recursive -check -diff
continue-on-error: true
- name: Terraform Init
id: init
shell: bash
run: terraform init
working-directory: ./terraform/projects/${{ inputs.project_id }}
- name: Terraform Validate
id: validate
shell: bash
run: terraform validate -no-color
導入時の苦労・悩み
Terraformのディレクトリ構成・module構成に依存した仕組みを作成するのにコツが入ります。モノレポまたはポリレポで運用するかは組織によって異なると思いますが、いずれにせよその構成を理解した上で、意図した環境のみにplan, apply する方法を考える必要があります(path-filterやmatrixなどの使用を検討)。
導入に向けた社内への説明
上長・チームへの説明
GitHub Actionsの導入については、既に他プロダクトで導入・運用実績があるため、大きな障壁なく導入が進みました。
一方で、Self Hosted Runner を使うのかなどの実行するプラットフォームについては、組織・プロダクトの成熟度や親和性を考慮した上で検討する必要があり、使用を想定するチームと認識合わせをする必要があると感じています。
弊社では基本的に、Github Actions自体は、SRE, Application Engineer 問わず共通インターフェースとして技術的議論ができる知見があるため、導入はスムーズでした。
活用方法
よく使う機能
Workflow dispatch: 手動でワークフローをトリガーする機能です。
Workflow call: ワークフローを別のワークフローから呼び出したい時に使用する機能です。
Concurrency: ワークフローの依存関係の制御を実現する機能です。
Composite Action: GitHub Actions 上のワークフローを共通化する機能です。
ツールの良い点
- リポジトリとしてGithubを使用している場合の、CI/CDを実行するプラットフォームとしてはデファクトスタンダートとなっているため、エンジニアのロール問わず知見が共有されている
- 上記効果により周辺エコシステムを含めたknowledgeが豊富で、実現したいことはだいたい調べば出るようになっている
ツールの課題点
- Github Actions 単体で見ると特になし(本当にステキなサービスです)
株式会社スリーシェイク / parupappa
チームリーダー / SRE / 従業員規模: 101名〜300名 / エンジニア組織: 51名〜100名
3-shake. inc, SRE 2023 AWS Jr.Champions / 2023-2024 AWS All Certification Engineers
よく見られているレビュー
株式会社スリーシェイク / parupappa
チームリーダー / SRE / 従業員規模: 101名〜300名 / エンジニア組織: 51名〜100名
3-shake. inc, SRE 2...