Terraformで複数GCPプロジェクトをWorkspaceで管理する方法
記事の内容
Terraformで複数GCPプロジェクトをWorkspaceで管理する方法を紹介します。
記事を読むと得られるもの
- StagingやProductionなど複数GCPプロジェクトを一つのTerraform Stateで管理する方法
- それらの環境をTerraform Workspaceで管理する方法
記事の長さ
3分で読めます
複数GCPプロジェクトをTerraformで管理する
GCPでWebサービスを運用する場合、一つのGCPプロジェクトの中に複数環境(Staging,Production等)を同居させることが可能です。しかし、同一プロジェクトに複数の環境を構築してしまうと権限管理がしづらかったり、ステージングに対する操作ミスがProductionに影響してしまうなど、様々な弊害があります。
そのため、複数環境をGCPで運用する場合、環境ごとにGCPプロジェクトを作るべきです。
本記事では、複数環境をTerraformのWorkspaceを利用して作成・運用する方法を紹介します。
作る環境図
こういった環境を作ります。
GCPプロジェクトは3つあり、それぞれ
- TerraformのStateファイルを配置する用のTerraformプロジェクト
- Staging
- Production
になります。
Terraform ProjectにGCSバケットを作成する
まずは、Staging,Production環境用のTerraform Stateファイルを保持するGCSバケットをTerraform GCP Projectに作成します。
Terraform StateはProduction・Stagingなど、どの環境にも属さないため中立なTerraformプロジェクトに配置します。(Terraform Cloudなどを利用する場合、このProjectは不要になります。)
このTerraform ProjectにTerraform State管理用のGCSバケットを作成してください。
コンソール画面から手動で作成してもいいですし、以下のTerraformを実行して作成しても問題ありません。
resource "google_storage_bucket" "terraform-state-store" {
project = var.project_id
name = "terraform-state-bucket-xxxxxxx"
location = "asia-northeast1"
storage_class = "REGIONAL"
versioning {
enabled = true
}
lifecycle_rule {
action {
type = "Delete"
}
condition {
num_newer_versions = 10
}
}
}
Terraform ProjectのGCSをBackendに指定する
TerraformプロジェクトにStateファイル用のGCSバケットが作成できたら、次は、そのGCSバケットをバックエンドとして登録するTerraformのソースを書いていきます。
config.tf
terraform {
required_version = "~> 1.6.0"
required_providers {
google-beta = {
source = "hashicorp/google-beta"
version = "~> 5.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
backend "gcs" {
bucket = "terraform-state-bucket-xxxxxxx"
prefix = "project/state"
}
}
provider "google-beta" {
user_project_override = true
region = "asia-northeast1"
}
provider "google" {
user_project_override = true
region = "asia-northeast1"
}
このconfig.tf
ファイルがあるディレクトリで、terraform init
コマンドを実行するとTerraformプロジェクトにあるGCSにTerraformのStateファイルが作成されます。
Staging, Productionにリソースを作成する
Terraformプロジェクトに存在するGCSバケットに配置されたTerraform Stateファイルを利用して、ProductionプロジェクトとStagingプロジェクトにリソースを作成します。
main.tf
resource "google_compute_network" "vpc_network_production" {
project = "<Production GCP Project ID>"
name = "terraform-network"
}
resource "google_compute_network" "vpc_network_staging" {
project = "<Staging GCP Project ID>"
name = "terraform-network"
}
上記ファイルを作成して、terraform apply
を実行すると、Production GCPプロジェクト・Staging GCPプロジェクト両方にterraform-network
というNetworkを作成することができます。
Workspaceを使って管理する
上記のように、ProductionとStaging用にリソースをそれぞれ書いていってもいいのですが、基本的にProduction・Stagingは同じような構成になるはずです。そのため、TerraformのWorkspace機能を利用すると、同じリソースを何度も書かなくてよくなります。
main.tf
resource "google_compute_network" "vpc_network_production" {
project = terraform.workspace == "production" ? "<Production GCP Project ID>" : "<Staging GCP Project ID>"
name = "terraform-network"
}
上記は現在のTerraform Workspaceの値によって、Project IDを条件分岐しているリソースです。
このようにすることで、共通リソースを複数GCPプロジェクトで使い回すことができます。
Terraform Workspaceの作り方
Terraform Workspaceの作り方は非常に簡単で、以下のコマンドで、作成・選択・一覧が可能です。
$ terraform workspace new production
$ terraform workspace select production
$ terraform workspace list
Project IDをlocalで管理する
毎回、以下の記述を書くのは冗長ですし、環境が増えると三項演算子ネストが発生して、かなり読みづらいソースになってしまいます。
そのため、Project IDとTerraform Workspace名を紐付けたLocalsを作成すると便利です。
locals.tf
locals {
production = {
project_id = "<PRODUCTION PROJECT ID>"
}
staging = {
project_id = "<STAGING PROJECT ID>"
}
}
main.tf
resource "google_compute_network" "vpc_network" {
project = local[terraform.workspace].project_id
name = "terraform-network"
}
このようにworkspace名
をkeyにして、localsを使用することで、Staging・ProductionのProject IDを一括管理できるだけでなく、test環境・QA環境などさらに環境が増えていっても、workspaceの分だけリソースを作成できます。
IAMについて
以上で、TerraformプロジェクトにTerraform Stateファイルを配置して、そこから複数環境のGCPプロジェクトにリソースを作成することができるようになりました。
最後に、IAMについてだけ注意事項です。
ここで解説したTerraformの操作をするサービスアカウントは、TerraformプロジェクトのGCSバケットに対する権限とProduction・Staging環境に対するリソース作成権限が必要です。
複数環境にまたがるSAのため、慎重に管理してください。
また、CICDパイプラインでApplyやPlanを行う構成にする場合、OIDCコネクトを利用し、特定リポジトリの特定ブランチからのみ各操作ができるように制限してください。
note
勉強法やキャリア構築法など、エンジニアに役立つ記事をnoteで配信しています。
Discussion