はじめに 👋#
こんにちは、Nimbusです。
HCP Terraformを大規模環境で運用してきた中で、 「これは落とし穴だ!」と感じた運用上の課題をTop5形式でまとめました。
これからHCP Terraformを本格導入する方、すでに運用中だけど何か引っかかっている方の 参考になれば幸いです。それでは、Let’s Dive in! 🦄
落とし穴1:トークンの種類による権限の違いを知らない 🔑#
何が起きたか#
「Private Module RegistryにModuleをpublishしようとしたら、権限エラーで失敗…」
実はこれ、私が実際に遭遇した問題です。Organization Tokenを使って
Private Module Registryへのpublishを試みたのですが、何度やっても
unauthorizedエラーが返ってきました。
問題の本質#
HCP Terraformには3種類のトークンが存在しますが、それぞれできることが異なります:
| トークンの種類 | 用途 | Private Module Registry publish |
|---|---|---|
| Organization Token | 組織全体の操作 | ❌ できない |
| Team Token | チーム単位の操作 | ✅ できる |
| User Token | 個人ユーザーの操作 | ✅ できる |
特に厄介なのが、Organization TokenではPrivate Module Registryへのpublishができないこと。 これはTeam TokenまたはUser Tokenでないと実行できません。
UIからは問題なくpublishできたのに、Terraformから実行するとエラーになる… この原因が「使っているトークンの種類」だと気づくまで、かなり時間を要しました。
対策とベストプラクティス 💡#
1. 用途に応じたトークンを使い分ける
# Private Module Registry操作にはTeam Token
provider "tfe" {
token = var.team_token # Organization Tokenではなく
}
2. トークンの管理ルールを明確にする
- チームトークンの作成は手作業で実施
- 発行したトークンはVariable SetsまたはHCP Vaultに保管
- 有効期限は90日として、ライフサイクルはチームで管理
3. ドキュメント化する 各トークンで「できること・できないこと」を表にまとめてチーム共有しましょう。
落とし穴2:VCS連携の見えない依存関係 🔗#
何が起きたか#
ある日、後輩から「VCSプロバイダーからいくつかのリポジトリが見えなくなった」と連絡がありました。
状況整理:
- 登場人物:私(GitHub OrganizationのOwner権限あり)と後輩(Owner権限なし)
- 最初にVCSプロバイダーを作成したのは私
- 作成直後は正常にOrganization内のリポジトリが確認できていた
- 後輩が何かのタイミングでVCSプロバイダーの再認証を実施
- 再認証後、いくつかのリポジトリが見えなくなった
問題の本質#
HCP TerraformのVCS連携は、個人のGitHubアカウントと密に紐付いている
VCSプロバイダーを再認証した際、その操作を行ったユーザーのGitHub権限が VCSプロバイダーのアクセススコープに反映されます。
最初の状態:
VCSプロバイダー(私のOwner権限で作成)
→ Organization内の全リポジトリが見える ✅
後輩が再認証後:
VCSプロバイダー(後輩の権限で再認証)
→ 後輩がアクセスできるリポジトリのみ見える ⚠️
→ Owner限定のリポジトリが見えなくなる ❌
Owner権限を持つ私のユーザーで再認証したら、すべて正常に戻りました。
対策とベストプラクティス 💡#
1. VCS接続の責任者を明確にする
- 誰がVCSプロバイダーを管理するか文書化
- 再認証は必ず管理者権限を持つユーザーが実施
2. 専用アカウントの作成(推奨)
私たちの組織では、個人アカウントに依存しない専用アカウントを作成しています:
専用アカウント:terraform-admin@xxxxx.com
【HCP Terraform側】
- 専用メールアドレスでユーザー登録
- Organization Owner権限を付与
【GitHub側】
- 同じメールアドレスでGitHubアカウント作成
- Organization Owner権限を付与
- このアカウントでVCSプロバイダーを作成・管理
このアプローチのメリット:
- ✅ 個人に依存しない(誰かが退職しても影響を受けない)
- ✅ 権限管理が明確(専用アカウントの権限のみ管理すればよい)
- ✅ 再認証時のリスク低減(常に同じ権限で再認証される)
- ✅ 監査が容易(VCS操作がすべてこのアカウント経由)
3. 定期的な権限確認
- VCSプロバイダーでアクセスできるリポジトリ一覧を定期的に確認
- 想定外のリポジトリが見えなくなっていないかチェック
- 専用アカウントの認証情報を安全に管理(パスワード管理ツールなど)
落とし穴3:WorkspaceのTerraform管理 - ガバナンス vs 利便性のジレンマ ⚖️#
何が起きたか#
「Workspaceの設定を少し変えたいだけなのに、いちいち管理者に依頼しないといけない…」 「自由に触らせたら、OIDC認証ではなくシークレットキーを直接入力された…」
WorkspaceをTerraformで管理するかどうかは、大規模運用では避けて通れない問題です。
問題の本質#
アプローチ1:Terraformで厳格に管理#
✅ メリット:
- ガバナンスを効かせられる(OIDC強制、命名規則統一など)
- 変更履歴がGitに残る
- Policy as Codeで設定を強制
❌ デメリット:
- 利用者の自由度が低い
- カスタマイズのたびに管理者へ依頼→ボトルネック化
- 「ちょっと試したい」ができない
アプローチ2:利用者に自由に触らせる#
✅ メリット:
- 開発速度が上がる
- 管理者がボトルネックにならない
- 柔軟なカスタマイズが可能
❌ デメリット:
- OIDC使わずシークレット直接入力される
- 命名規則が守られない
- セキュリティリスク増大
対策とベストプラクティス 💡#
私たちの組織の選択:厳格にTerraformで管理
私たちの組織では、組織の特性上、ガバナンスを優先し、すべてをTerraformで厳格に管理する方針を取っています。
1. 基盤設定はすべてTerraformで管理
# Workspace作成から設定まですべてコード化
resource "tfe_workspace" "example" {
name = var.workspace_name
organization = var.organization
# VCS連携を設定
vcs_repo {
identifier = var.repository
oauth_token_id = var.oauth_token_id
}
}
2. Google Cloud認証はWorkload Identity(Dynamic Credentials)で統一
私たちの環境ではGoogle Cloud Workload Identityを使った動的クレデンシャルを採用しています。 これにより、シークレットキーの直接入力を根本的に防ぐことができます。
# Workload Identity Poolの設定
resource "google_iam_workload_identity_pool" "pool" {
workload_identity_pool_id = "hcp-terraform-pool"
display_name = "HCP Terraform Pool"
description = "Pool for HCP Terraform workspaces"
}
# Workload Identity Providerの設定
resource "google_iam_workload_identity_pool_provider" "hcp_terraform" {
workload_identity_pool_id = google_iam_workload_identity_pool.pool.workload_identity_pool_id
workload_identity_pool_provider_id = "hcp-terraform-provider"
display_name = "HCP Terraform Provider"
oidc {
issuer_uri = "https://app.terraform.io"
}
attribute_mapping = {
"google.subject" = "assertion.sub"
"attribute.terraform_workspace_id" = "assertion.terraform_workspace_id"
"attribute.terraform_organization_id" = "assertion.terraform_organization_id"
}
}
# サービスアカウントとの紐付け
resource "google_service_account_iam_binding" "workload_identity" {
service_account_id = google_service_account.terraform_sa.name
role = "roles/iam.workloadIdentityUser"
members = [
"principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.pool.name}/attribute.terraform_workspace_id/${var.workspace_id}"
]
}
3. Variable Setsで認証情報を一元管理
各WorkspaceにはVariable Setを通じてWorkload Identity設定を自動適用:
# Variable Set作成
resource "tfe_variable_set" "gcp_workload_identity" {
name = "gcp-workload-identity-credentials"
description = "Google Cloud Workload Identity settings"
organization = var.organization
}
# Workload Identity有効化フラグ
resource "tfe_variable" "enable_gcp_provider_auth" {
key = "TFC_GCP_PROVIDER_AUTH"
value = "true"
category = "env"
variable_set_id = tfe_variable_set.gcp_workload_identity.id
}
# Workload Providerの指定
resource "tfe_variable" "workload_provider_name" {
key = "TFC_GCP_WORKLOAD_PROVIDER_NAME"
value = google_iam_workload_identity_pool_provider.hcp_terraform.name
category = "env"
variable_set_id = tfe_variable_set.gcp_workload_identity.id
}
# サービスアカウントの指定
resource "tfe_variable" "service_account_email" {
key = "TFC_GCP_RUN_SERVICE_ACCOUNT_EMAIL"
value = google_service_account.terraform_sa.email
category = "env"
variable_set_id = tfe_variable_set.gcp_workload_identity.id
}
このアプローチで実現できること:
- ✅ シークレットキーの直接入力を防止(そもそもできない仕組み)
- ✅ 認証情報の一元管理(Variable Setで統一)
- ✅ セキュリティの強化(短期トークンを自動生成)
- ✅ 監査の容易化(誰がいつアクセスしたか追跡可能)
- ✅ 設定の標準化(すべての設定がコードとして履歴に残る)
トレードオフ:得られたものと失ったもの
正直に言うと、この厳格な管理にはデメリットもあります:
✅ 得られたもの:
- 強固なガバナンス体制
- 設定ミスの大幅な削減
- セキュリティの向上
- 変更履歴の完全な可視化
❌ 失ったもの:
- 開発者の自由度
→ 変数の値をちょっと変えたいだけなのに管理者に依頼
→ 通知設定の変更すら自分でできない
- 開発スピード
→ 管理者がボトルネックになる
→ 「プロジェクト内だけでも自由にさせてほしい」という声
実際に開発者から聞いた声:
- 「変数の値を更新するだけなのに、なぜPull Requestが必要なの?」
- 「通知設定くらい自分で変えさせてほしい…」
- 「プロジェクト内の設定くらいは自由にさせてほしい」
これらの声は十分理解できます。しかし、私たちの組織では、組織の特性上、ガバナンスを優先せざるを得ないという判断をしています。
組織によって優先順位は異なる
重要なのは、どちらが正解というわけではないということです:
| 優先事項 | 推奨アプローチ |
|---|---|
| ガバナンス・監査対応が最優先 | Terraformで厳格に管理 |
| 開発スピード・柔軟性が最優先 | 利用者に開放 |
| 両方のバランスを取りたい | 段階的管理(重要な設定はTerraform、それ以外は開放) |
私たちのように金融・小売・医療など規制の厳しい業界では、前者を選ばざるを得ないことが多いです。 一方、スタートアップや開発スピード重視の組織では、後者が適しているでしょう。
判断のポイント:
- 組織のコンプライアンス要件はどの程度厳しいか?
- セキュリティインシデントが発生した場合の影響は?
- 開発者の不便さと、ガバナンス強化、どちらを優先すべきか?
- 管理者のリソースは十分にあるか?
落とし穴4:Workspace設計ミス - ライフサイクルの混在 🔄#
何が起きたか#
「検証用のデータベースを削除したいのに、本番リソースと同じWorkspaceで管理してて消せない…」 「不要なリソースが残り続けて、毎月無駄なコストが発生している…」
問題の本質#
ライフサイクルが異なるリソースを1つのWorkspaceに詰め込んでしまった
❌ 悪い例:
Workspace: myapp-prod
├─ 本番データベース(常時稼働・絶対に消せない)
├─ 検証用データベース(開発時のみ・消したい)
└─ テスト用インスタンス(たまに使う・消したい)
→ 検証用だけ消したいのに、terraform destroyすると全部消える!
→ 仕方なく放置...コストだけがかさむ
これは単に「環境を分ける」だけでは解決しません。 同じ本番環境でも、常時稼働が必要なものと一時的なものは分離すべきです。
対策とベストプラクティス 💡#
正しい設計:Volatility(変動性)でグルーピング
✅ 良い例:
Workspace: myapp-prod-core
└─ 本番データベース(常時稼働・変更頻度:低)
Workspace: myapp-prod-testing
└─ 検証用データベース(一時的・変更頻度:高)
→ 不要になったらWorkspaceごと削除可能!
Workspace: myapp-prod-temporary
└─ テスト用インスタンス(スポット使用)
→ 使用後は即削除
Workspace設計の3つの軸:
- Environment(環境): dev / staging / prod
- Lifecycle(ライフサイクル): permanent / temporary / ephemeral
- Component(コンポーネント): network / compute / data
具体的な命名規則:
{プロジェクト}-{環境}-{ライフサイクル}-{コンポーネント}
例:
- payment-prod-permanent-database
- payment-prod-temporary-testing
- payment-dev-ephemeral-sandbox
さらに便利な機能:Automatically Destroy
HCP Terraformには、一時的なWorkspace向けのAutomatically Destroy機能があります(プランによって利用可否が異なります)。
resource "tfe_workspace" "temporary" {
name = "myapp-prod-temporary"
organization = var.organization
# 自動削除の設定
auto_destroy_at = "2025-12-31T23:59:59Z" # 指定日時に自動destroy
}
この機能のメリット:
- ✅ 削除忘れを防止(指定日時に自動的にterraform destroy実行)
- ✅ コスト削減の自動化(手動で削除する必要がない)
- ✅ 一時的な検証環境に最適(検証期間終了後、自動的にクリーンアップ)
使用例:
検証用Workspace: myapp-prod-feature-test
→ auto_destroy_at: "2025-02-28T23:59:59Z"(2週間後に自動削除)
→ 検証終了後、自動的にリソースが削除される
UIからも設定可能で、Workspace設定画面から「Auto-destroy」のスケジュールを設定できます。
落とし穴5:Variable Setsのスコープがカオス化 📦#
何が起きたか#
「あれ?この変数どのWorkspaceに適用されてるんだっけ…?」 「本番環境なのに、開発用のGCP認証情報が適用されてる!」
大規模運用になると、Variable Setsの管理が一気にカオス化します。
問題の本質#
Variable Setが乱立し、誰も全体像を把握していない
カオスの実例:
Variable Set: gcp-credentials
→ 適用先:全Workspace(本番も開発も!)😱
Variable Set: gcp-prod-only
→ 適用先:なぜか開発環境のWorkspaceにも適用されている...
Variable Set: common
→ 適用先:誰も把握していない
→ 中身:謎の変数が大量に入っている
Variable Set: gcp-creds-prod
Variable Set: gcp-credentials-production
Variable Set: prod-gcp-auth
→ 全部同じ用途なのに命名がバラバラ...
なぜこうなるか:
- Variable Setsの命名規則がない
- スコープ(どのWorkspaceに適用するか)の設計がない
- 個人が勝手にVariable Setを作成してしまう
- 不要になったVariable Setを削除していない
対策とベストプラクティス 💡#
1. 命名規則を統一する
{環境}-{プロバイダー}-{用途}
例:
✅ prod-gcp-credentials
✅ dev-gcp-service-account
✅ staging-gcp-workload-identity
✅ global-common-vars(全環境共通)
2. タグベースでスコープを制御
# Workspaceにタグを付与
resource "tfe_workspace" "example" {
name = "myapp-prod"
organization = var.organization
tags = {
environment = "prod"
cloud = "gcp"
component = "api"
}
}
# Variable Setはタグで適用範囲を指定
resource "tfe_variable_set" "prod_gcp" {
name = "prod-gcp-credentials"
organization = var.organization
}
# タグに基づいてVariable Setを適用
resource "tfe_workspace_variable_set" "prod_gcp_assignment" {
for_each = {
for ws in data.tfe_workspace_ids.prod_workspaces.ids : ws => ws
}
workspace_id = each.value
variable_set_id = tfe_variable_set.prod_gcp.id
}
data "tfe_workspace_ids" "prod_workspaces" {
organization = var.organization
tag_names = ["environment:prod"]
}
3. Variable SetもTerraformで管理
# IaCで管理することで:
# - 誰が何を作ったか履歴に残る
# - レビュープロセスを挟める
# - 不要なVariable Setを検出しやすい
resource "tfe_variable_set" "example" {
name = var.variable_set_name
description = var.description
organization = var.organization
}
4. 定期的な棚卸し
- 月次でVariable Setの一覧を確認
- 使われていないVariable Setを削除
- 命名規則に従っていないものを修正
実装例:スコープ管理のマトリックス
| Variable Set名 | 適用タグ | 対象Workspace数 | 用途 |
|---|---|---|---|
| prod-gcp-credentials | environment:prod, cloud:gcp | 15 | 本番GCP認証 |
| dev-gcp-credentials | environment:dev, cloud:gcp | 30 | 開発GCP認証 |
| global-common-vars | (全Workspace) | 195 | 組織名など |
まとめ 💡#
HCP Terraformは強力なツールですが、大規模運用になると様々な落とし穴があります。 今回紹介した5つの落とし穴を意識することで、より安全で効率的な運用が可能になります。
運用の鉄則:#
✅ トークンの種類と権限を理解する
- 用途に応じた適切なトークンを選択
- 管理ルールを明確にする
✅ VCS連携は組織アカウントで管理
- 個人アカウントに依存しない
- 再認証の影響範囲を理解する
✅ ガバナンスと利便性のバランスを取る
- セキュリティは厳格に、開発効率は柔軟に
- Variable Setsで共通設定を強制
✅ ライフサイクルでWorkspaceを分離
- 常時稼働 vs 一時的で分ける
- コスト最適化につながる
✅ Variable Setsは命名規則とタグで管理
- カオス化を防ぐ仕組みを最初から作る
- 定期的な棚卸しを忘れずに
おわりに ✨#
大規模なHCP Terraform運用は試行錯誤の連続でした。 今回紹介した落とし穴は、すべて実際に遭遇し、痛い目を見た経験から学んだものです。
これらの経験が皆さんの運用改善に少しでも役立てば嬉しいです。
「こんな落とし穴もあった!」というご意見や質問があれば、 ぜひコメントやSNSで教えてください。
それでは、また次回お会いしましょう!See ya 👋🏻
