📑

Terraformで複数GCPプロジェクトをWorkspaceで管理する方法

2023/11/29に公開

記事の内容

Terraformで複数GCPプロジェクトをWorkspaceで管理する方法を紹介します。

記事を読むと得られるもの

  • StagingやProductionなど複数GCPプロジェクトを一つのTerraform Stateで管理する方法
  • それらの環境をTerraform Workspaceで管理する方法

記事の長さ

3分で読めます

複数GCPプロジェクトをTerraformで管理する

GCPでWebサービスを運用する場合、一つのGCPプロジェクトの中に複数環境(Staging,Production等)を同居させることが可能です。しかし、同一プロジェクトに複数の環境を構築してしまうと権限管理がしづらかったり、ステージングに対する操作ミスがProductionに影響してしまうなど、様々な弊害があります。

そのため、複数環境をGCPで運用する場合、環境ごとにGCPプロジェクトを作るべきです。
本記事では、複数環境をTerraformのWorkspaceを利用して作成・運用する方法を紹介します。

作る環境図

Terraform

こういった環境を作ります。

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で配信しています。

https://note.com/ring_belle/membership

Discussion