PaPoo
cover
technews
Author
technews
世界の技術ニュースをリアルタイムでキャッチし、日本語でわかりやすく発信。AI・半導体・スタートアップから規制動向まで、グローバルテックシーンの「今」をお届けします。

GCP上のTerraformを安全に回すCI/CD入門:Pull RequestでPlan、承認後にApply、しかも静的キーなし

記事のキーポイント

この記事は何をしているのか

この記事は、GCP上のTerraform運用を「ひとりでローカルから叩く形」から、「GitHub Actionsで安全に回す形」に進化させる実践例です。

元記事の著者は、以前のラボではローカル端末でこんな流れだったと書いています。

学習用途ならこれで十分です。
でも、少し実務っぽくなると話は別です。インフラ変更は、アプリコード以上に事故が怖い。うっかりVPCを消したり、意図しない設定を入れたりすると、影響範囲が大きいからです。

そこでこの記事では、Terraformの実行をGitHub Actionsに移し、次の流れを作っています。

image_0003.svg

これ、かなり“ちゃんとした運用”に近いです。個人的には、Terraformを「コードとしてレビューする対象」にする発想がとても大事だと思います。インフラもソフトウェアなので、レビューなしで本番反映するのはやっぱり危ないですよね。

いちばん面白いポイントは「静的キーを使わない」こと

この記事の核は、実はCI/CDそのものよりも認証方法です。

普通にGCPへアクセスしようとすると、サービスアカウントのJSONキーをGitHub Secretsに入れたくなります。
でもそれだと、そのキーは長期間使える“強い鍵”になります。漏れたら面倒ですし、ローテーションも地味に大変です。

そこで使っているのが Workload Identity Federation です。
ざっくり言うと、

image_0004.svg

という仕組みです。

つまり、​JSONキーをダウンロードしない
この「鍵を置かない」設計がかなり良いです。運用の安心感が全然違います。静的キーを消せるだけで、セキュリティの話が一段軽くなるんですよね。

何を作るラボなのか

このラボが作るインフラは、あえてシンプルです。

凝ったネットワーク構成や複雑なサービスは作りません。
理由ははっきりしていて、​CI/CDの流れをまずデバッグしやすくしたいからです。

これ、すごく実践的だと思います。
最初から大きな構成でやると、問題が出たときに「Terraformが悪いのか」「認証が悪いのか」「GitHub Actionsが悪いのか」が分かりにくいです。だから小さく始めるのは正解です。

構成の全体像

image_0005.svg

記事のフォルダ構成はこうです。

Terraform本体は 09-terraform-cicd-github-actions/ に置き、GitHub Actionsのワークフローは .github/workflows/ に分けています。
この分離は見た目もわかりやすいし、管理もしやすいです。地味だけど大事。

Terraform state は GCS に保存する

Terraformは「今どんなインフラがあるか」を覚えておくために、​state という状態ファイルを使います。
この記事では、そのstateをGCSに置いています。

terraform {
  backend "gcs" {
    bucket = "terraform-gcp-learning-lab-terraform-state"
    prefix = "terraform-gcp-learning-lab/09-terraform-cicd-github-actions"
  }
}

この設計のポイントは、​前のラボとstateを分けていることです。
stateが混ざると、Terraformは「何がこの構成に属するのか」を見失いやすくなります。実務でも、プロジェクトごと・環境ごとにstateを分けるのはかなり基本です。

image_0006.svg

保存先のパスはこんな形になります。

Terraformで作るリソースはシンプル

Terraformの中身は、VPCとサブネットを作るだけです。

resource "google_compute_network" "vpc_network" {
  name                    = "${var.environment}-${var.network_name}"
  auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "subnet" {
  name          = "${var.environment}-${var.subnet_name}"
  region        = var.region
  network       = google_compute_network.vpc_network.id
  ip_cidr_range = var.subnet_cidr_range
}

ここでの要点は以下です。

image_0007.svg

ネットワークの話はとっつきにくいですが、要するに建物の敷地と、その中の区画を作っているイメージです。
VPCが敷地、サブネットが区画、という感じで見ると少し分かりやすいです。

変数設計がちゃんとしている

variables.tf では、プロジェクトIDやリージョンなどを変数化しています。

特に重要なのが project にデフォルト値がないことです。

variable "project" {
  type = string
  validation {
    condition     = length(var.project) > 0
    error_message = "The project variable must not be empty."
  }
}

これは良い設計です。
プロジェクトIDをコードに埋め込むと、再利用しづらいですし、うっかり別環境へ流用したときに事故の元になります。

GitHub Actionsでは、リポジトリ変数から渡しています。

image_0008.svg

-var="project=${{ vars.GCP_PROJECT_ID }}"

このやり方は、設定をコードから追い出しつつ、CI/CD側で安全に注入するやり方です。
「コードに環境依存情報をべったり書かない」というのは、地味だけど本当に大切です。

GitHubのRepository Variablesを使う

著者は GitHub の以下に変数を置いています。

入っているのはこんなものです。

image_0010.png

ここで大事なのは、​これらはサービスアカウントキーではないという点です。
つまり、Secretsに長期鍵を抱え込まなくて済む。ここはかなり気持ちがいいです。

Pull Requestで走る Plan ワークフロー

Plan側のワークフローは、Pull Requestをトリガーにしています。

やっていることはシンプルです。

  1. リポジトリを checkout
  2. WIFでGCP認証
  3. Terraformをセットアップ
  4. terraform fmt -check -recursive
  5. terraform init
  6. terraform validate
  7. terraform plan

この順番がすごく良いです。
fmt はコードの見た目を揃える、validate は構文や設定の妥当性を見る、plan は実際に何が変わるかを出す。
つまり、​Pull Requestの時点で「変なTerraform」をかなり弾けるわけです。

特に id-token: write が重要だと書かれていました。
これは GitHub Actions が OIDC トークンを要求するために必要です。WIFを使うなら、ここを忘れると認証で詰みます。

image_0012.png

手動承認つきの Apply ワークフロー

Apply側は workflow_dispatch で、つまり手動実行です。

やっていることはPlanとほぼ同じですが、最後が違います。

  1. checkout
  2. WIF認証
  3. Terraformセットアップ
  4. fmt
  5. init
  6. validate
  7. terraform plan -out=tfplan
  8. terraform apply tfplan

ここでの重要ポイントは、​planの結果をファイルに保存して、そのままapplyすることです。
これにより、Planで見た内容とApplyで実際に適用される内容のズレを減らせます。

しかもワークフローに environment: terraform-apply が指定されています。
GitHub ActionsのEnvironmentを使うと、承認フローや保護ルールを噛ませやすいので、実務的にもかなり良い選択です。

個人的には、ここがこの構成のいちばん“ちゃんとしてる”部分だと思います。
「自動化したいけど、勝手に変更されるのは困る」という現実的なバランスが取れています。

この構成の良さをひとことで言うと

image_0013.png

このラボの良さは、​自動化と統制の両方をちゃんと考えているところです。

CI/CDというと「全部自動で流す」方向に寄りがちですが、インフラはそう単純ではありません。
むしろ大事なのは、​いつ・誰が・何を変えるかを見える化することです。

この記事の構成は、

という、かなり筋のいい設計です。
派手さはないけれど、実務ではこういう地味な堅牢さが一番効くと思います。

こんな人に参考になる

image_0014.png

まとめ

この記事は、Terraform運用を「便利な自動化」ではなく、​安全に変更を管理する仕組みとして組み立てています。

特に良いのは以下です。

Terraformを使っていると、つい「動けばOK」になりがちです。
でも本当に大事なのは、​あとから見返したときに安心できる運用だと思います。この記事は、その感覚をかなりわかりやすく形にしていて、読んでいて素直に参考になる内容でした。


参考: CI/CD for Terraform on GCP: Plan on Pull Request, Apply with Approval, No Static Keys

同じ著者の記事