Terraform CloudでWorking Directoryを設定したVCS Triggerとapplyをやってみた
はじめに
こんにちは、データ事業本部の渡部です。
今回はTerraform Cloudを使って、Working Directory(作業ディレクトリ)のブランチ更新をトリガーにしたapplyをやってみます。
今回の検証のきっかけとしては、最近になってWorkspaceの運用を見直すこととなり、Workspaceごとにapplyするリソースを選択したり、変数をTerraform CloudのVariablesではなくtfvarsファイルでWorkspaceごとに定義をしたくなったことにあります。
これまでTerraformプロジェクトのルートディレクトリのmainブランチのマージをトリガーにTerraformを動かしていましたが、それだと上記の要求を満たせません。
どうしようかとTerraform Cloudを眺めていたらVersion Controlで、Terraform Working Directory
とAutomatic Run triggering
を見つけました。
これはイケそうと思い、早速触ってみる次第です。
やってみる
Terraformの設定ファイルの作成
Terraformは以下の構成です。GitHubで管理します。
.
├── modules
│ ├── s3
│ │ ├── main.tf
│ │ └── variables.tf
│ └── sns
│ ├── main.tf
│ └── variables.tf
└── workspace
├── test-a
│ ├── README.md
│ ├── main.tf
│ ├── terraform.auto.tfvars
│ └── variables.tf
└── test-b
├── README.md
├── main.tf
├── terraform.auto.tfvars
└── variables.tf
test-a配下はmodules/s3を呼びバケットを作成、test-b配下はmodules/snsを呼びSNSトピックを作成するようにしています。
以下はS3を作成する資材の3ファイル分の抜粋です。SNSも同じようにworkspace側で変数を定義して、modulesに渡しています。
resource "aws_s3_bucket" "this" {
bucket = var.bucket_name
tags = {
Name = var.bucket_name
}
}
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
module "s3_bucket" {
source = "../../modules/s3"
bucket_name = var.bucket_name
}
bucket_name = "test-a-cm-watanabe"
Terraform Cloudの設定
Terraform Cloudには2つのWorkspaceを用意しました。
GitHubとの連携は以下を参考に設定します。
さて今回の肝である設定ですが、Terraform Working Directory
に設定したい作業ディレクトリを設定します。
ここで設定したディレクトリの設定ファイルをもとにTerraformがinitしたりplanしたりapplyすることになります。
今回はワークスペース単位で作業ディレクトリを用意しているので、それぞれのワークスペースで作業ディレクトリを設定します。
続いてAutomatic Run triggering
の設定では、Only trigger runs when files in specified paths change
を選択します。
ここではVCSとして設定したリポジトリのどこのディクトリが変更あった際にTerraformをRunさせるかを設定します。
今回はWorking Directoryが変更時にRunさせたかったので、Prefixesを選択しました。自動的にWorking Directoryが表示されるので、そのままにします。
それぞれのWorkspaceのVariablesで、Terraform CloudからAWSのリソースを操作する際に必要な資格情報として、Environment Variableを設定します。
私の環境ではすでに準備していたのですが、OIDCでAWSと連携をさせておく必要があります。
詳しい手順は以下をご参考ください。
なおその他のVariablesはterraform.auto.tfvarsから値を渡すため、設定をしていません。
こちらでWorkspaceの設定は完了です。
実行
Terraformを動かすために、GitHubにREADME.mdをtest-aワークスペース作業ディレクトリ(./workspace/test-a)に対して配置しました。
planが動きました。
test-bのワークスペースの方はterraformが動いていません。作業ディレクトリの設定がしっかり反映されていますね。
test-bの作業ディレクトリ(./workspace/test-b)に対しても同じようにREADMEを配置しました。
test-bのワークスペースのTerraformが動きました。
どちらもapplyをして、試しにS3コンソールを確認すると、バケットが作成されてました。
さいごに
いかがでしたでしょうか。
Terraform Cloud/Enterpriseで作業ディレクトリを分けつつWorkspaceごとにモジュールを選択して管理するにはWorkingDirecoryをWorkspaceに設定するこの方法がよさそうです。
ちなみに私はこれまでTerraform OSSのWorkspaceと、Terraform Cloud/EnterpriseのWorkspaceを同じものと思っていましたが、異なるものと認識した方がいいなと思いました。
というのも前者はステート分割の単位ですが、後者はTerraform Cloud/Enterpriseでリソースを管理するには必要なもので環境を定義する単位です。変数や実行履歴・ポリシーや権限など、ステート分割の単位より広い意味を持っていると思いました。
OSSのWorkspaceは同じTerraformでステート分割をしてリソース管理ができることに秀でており、複数の環境を払い出す際もWorkspaceで払い出すことにより、プラグインを再利用することができるよねという理解です。
一方作業ディレクトリを用意した払い出しはプラグインの再利用はせずに、そのディレクトリごとにプラグインをインストールをすることになります。
そのためWorkspaceと作業ディレクトリは相入れない関係のように思っていました。
しかしTerraform Cloud/Enterpriseにおける作業ディレクトリはコードの場所を示すポインタの補完的役割を担っています。
これによって1リポジトリで複数のリソースを管理するモノレポ構成でも、Workspaceと作業ディレクトリで柔軟に管理可能となるわけです。
以上です。
どなたかのご参考になれば幸いです。