Closed3
[Terraform + GithubActions] 複数環境で上手にTerraformの変更を適用するアイディア
課題
TerraformにはWorkspaceと言う環境を分ける際に便利な機能が存在する。環境ごとにTerraformの適用を切り分ける際、GithubActionsを用いた最適解が分からずに困っている。
前提条件
開発、ステージ、本番の3環境があると想定し、以下のディレクトリ構造をもとに解決策を模索する。
├── bootstrap
│ ├── env
│ │ ├── dev.tfvars
│ │ ├── prod.tfvars
│ │ └── staging.tfvars
│ └── terraform-code.tf
└── network
├── env
│ ├── dev.tfvars
│ ├── prod.tfvars
│ └── staging.tfvars
└── terraform-code.tf
[予備知識] 手動での運用
手動で環境を切り替える際の運用例は以下の通り。
$ cd bootstrap/
$ terraform workspace -h
Usage: terraform [global options] workspace
new, list, show, select and delete Terraform workspaces.
Subcommands:
delete Delete a workspace
list List Workspaces
new Create a new workspace
select Select a workspace
show Show the name of the current workspace
$ terraform workspace select dev
$ terraform apply -var-file=env/dev.tfvars
Terraformコードは同じものを利用し、変数ファイルを環境に合わせて指定することでコードの簡略化が可能となる。
調べた事
- https://github.com/technote-space/get-diff-action
- https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#using-environment-variables-in-a-matrix
- https://zenn.dev/rinchsan/articles/de981e561eb36ebfab70
- https://github.community/t/multiple-if-conditional-with-always-is-always-true/128840
- https://www.runatlantis.io/
結論
Atlantis がすごく良さげ。
それ以外の方法
以下は、Atlantisと似たようなことを自作で行う場合の例です。
Workflowを作る。
[.github/workflows/deploy-to-bootstrap.yaml]
name: terraform-project
on:
push:
paths:
- "terraform/bootstrap/**"
branches:
- 'main'
pull_request:
paths:
- "terraform/bootstrap/**"
defaults:
run:
working-directory: terraform/bootstrap
jobs:
terraform-example:
runs-on: ubuntu-latest
strategy:
matrix:
site: [ "dev", "staging", "prod" ]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Check diff
id: diff
uses: technote-space/get-diff-action@v6
with:
FILES: |
${{ matrix.site }}.lastupdate
- name: Setup Terraform
if: ${{ contains(env.MATCHED_FILES, matrix.site) }}
uses: hashicorp/setup-terraform@v1
- name: Terraform Init
id: init
if: ${{ contains(env.MATCHED_FILES, matrix.site) }}
run: terraform init
- name: Terraform Validate
id: validate
if: ${{ contains(env.MATCHED_FILES, matrix.site) }}
run: terraform validate
- name: Terraform Plan
id: plan
if: ${{ contains(env.MATCHED_FILES, matrix.site) && github.event_name == 'pull_request' }}
run: terraform plan -var-file=env/${{ matrix.site }}.tfvars
- name: Terraform Apply
if: ${{ contains(env.MATCHED_FILES, matrix.site) && github.ref == 'refs/heads/master' && github.event_name == 'push' }}
run: terraform apply -auto-approve -var-file=env/${{ matrix.site }}.tfvars
フォルダ構成は以下の通り。
├── change-when-to-apply
│ ├── dev.lastupdate
│ ├── prod.lastupdate
│ └── staging.lastupdate
├── env
│ ├── dev.tfvars
│ ├── prod.tfvars
│ └── staging.tfvars
└── terraform-code.tf
使い方例として、change-when-to-apply
フォルダ内の変更対象の環境ファイルをcommitすると、その環境のみterraformコマンドを実行する、という感じです。
このスクラップは2022/03/15にクローズされました