GitHub ActionsでTerraformを実行する時にTerraform Cloudをバックエンドに指定する
某所で「GitHub ActionsからTerraform Cloudを使おうとしたが上手くいかなかった」という投稿を拝見しました。
うまいこと設定すればちゃんと動かせますのでその方法などについてまとめておきます。
TL; DR
- Terraform Cloudでの
Execution Mode
はデフォルトでRemote
になってる - クレデンシャルをGitHub側のSecretから環境変数として渡す場合は
Execution Mode
をLocal
に変更する
最初に: やりたいこと
- Terraform Github Actionsを使ってGitHub Actionsで
terraform
コマンドを実行したい。 - tfstateはTerraform Cloudに保存したい
このために、リポジトリ上でGitHub Actionsの設定を行い、リポジトリにtfファイルをコミット、PullRequestの作成を行います。
利用するtfファイル
# バックエンドの設定 terraform { backend "remote" { hostname = "app.terraform.io" organization = "your-organization-name" workspaces { name = "your-workspace-name" } } } # プロバイダー provider "google" { project = "your-project-name" region = "us-west1" } # リソースの例 data "google_project" "project" {} output "project_number" { value = "${data.google_project.project.number}" }
この例はGCPプロバイダーを使うようにしています。
Terraform CloudとGCPプロバイダーのクレデンシャルについてはGitHub ActionsのSecretに保存しておいて環境変数(TF_ACTION_TFE_TOKEN
とGOOGLE_CREDENTIALS
)に指定します。
ワークフローファイルの定義
GitHub Actionsのワークフローファイルは以下を利用します。
参考: https://www.terraform.io/docs/github-actions/getting-started/index.html
on: pull_request: types: - opened - synchronize - closed branches: - master name: Terraform jobs: terraform-fmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1.0.0 - name: terraform-fmt uses: hashicorp/terraform-github-actions/fmt@v0.4.4 env: # secrets GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }} # env TF_ACTION_WORKING_DIR: "." terraform-init: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1.0.0 - name: terraform-init uses: hashicorp/terraform-github-actions/init@v0.4.4 env: # secrets GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }} TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }} # env TF_ACTION_WORKING_DIR: "." terraform-validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1.0.0 - name: terraform-init uses: hashicorp/terraform-github-actions/init@v0.4.4 env: # secrets GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }} TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }} # env TF_ACTION_WORKING_DIR: "." - name: terraform-validate uses: hashicorp/terraform-github-actions/validate@v0.4.4 env: # secrets GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # env TF_ACTION_WORKING_DIR: "." terraform-plan: needs: - terraform-fmt - terraform-init - terraform-validate runs-on: ubuntu-latest steps: - uses: actions/checkout@v1.0.0 - name: terraform-init uses: hashicorp/terraform-github-actions/init@v0.4.4 env: # secrets GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }} TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }} # env TF_ACTION_WORKING_DIR: "." - name: terraform-plan uses: hashicorp/terraform-github-actions/plan@v0.4.4 env: # secrets GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }} TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }} # env TF_ACTION_WORKING_DIR: "." terraform-apply: needs: - terraform-plan runs-on: ubuntu-latest steps: - uses: actions/checkout@v1.0.0 - name: terraform-init if: github.event.pull_request.merged == true uses: hashicorp/terraform-github-actions/init@v0.4.4 env: # secrets GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }} TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }} # env TF_ACTION_WORKING_DIR: "." - name: terraform-apply if: github.event.pull_request.merged == true uses: hashicorp/terraform-github-actions/apply@v0.4.4 env: # secrets GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }} TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }} # env TF_ACTION_WORKING_DIR: "."
Secretに忘れずにTerraform CloudとGCPプロバイダーのクレデンシャルを登録しておいてください。
これでPR時にinit
,fmt
,validate
,plan
が実行され、マージしたらapply
も実行されます。
クレデンシャルが見つからないエラーとなる
このままこのアクションを動かすとplan
実行時に以下のようなエラーが出ます。
Error: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information. on terraform.tf line 14, in provider "google": 14: provider "google" ***
原因
tfファイルなどでTerraform Cloudをバックエンドとして指定する際、指定したワークスペースが存在しない場合は新たに作成されます。
そして、新規作成されたワークスペースの場合、Remote Operationsがデフォルトで有効となっています。
Remote Operationsとは、Terraform CLIからplan
やapply
を実行することで実際の処理をリモートのインフラ上で行える仕組みで、現在はTerraform Cloudでのみサポートされています。
Remote Operationsでは環境変数はTerraform Cloudのワークスペース上で定義されたものが利用されます。
なのでGitHub ActionsのSecretを設定、環境変数に指定してもそれが利用されず、クレデンシャルが見つからないというエラーとなります。
対応
ワークスペースの設定でExecution Mode
という項目があります。
これはRemote Operationsの有効/無効を切り替えられるもので、この項目をLocal
に設定することでplan
やapply
はローカル(GitHub Actions上)で実行され、tfstateはTerraform Cloudに保存されるようになります。
まとめ
以下2点を押さえておきましょう。
- Terraform Cloudでの
Execution Mode
はデフォルトでRemote
になってる - クレデンシャルをGitHub側のSecretから環境変数として渡す場合は
Execution Mode
をLocal
に変更する
あと、パブリックなリポジトリでGitHub Actionsを使ってapply
を実行するのは推奨されていない*1のでこの辺も理解した上で利用しましょう。
以上です。