概要: 本記事では、Terraformワークスペースが非推奨とされている背景を解説し、代わりに推奨されるGitOpsをベースとしたIaCワークフローの全体像を提示します。従来の運用から脱却し、より堅牢で効率的なインフラ管理を実現するための具体的なアプローチと実践的なノウハウを提供します。
Terraformワークスペース非推奨の真意と最新IaCワークフローの全体像
Terraformワークスペースの誤解と本来の目的
TerraformのCLIワークスペース機能は、単一のTerraform構成ディレクトリ内で、一時的な実験環境や機能検証のためにバックエンド(Stateファイル保存先)を動的に切り替えることを本来の目的としています。例えば、新しいTerraformバージョンへの移行テストや、特定の機能開発のためのサンドボックス環境を素早く立ち上げ、検証後に破棄するようなケースで有効です。これは、本番環境と開発環境を永続的に分離して管理するための機能ではありません。
多くの場合、dev/stg/prodといった環境ごとのインフラを管理する目的でワークスペースが利用されてきましたが、これは機能の想定外の使い方であり、かえって運用リスクを高める要因となっていました。
なぜワークスペースは非推奨とされたのか?具体的なリスク
Terraform公式が環境分離におけるワークスペース利用を非推奨とする背景には、複数の重大なリスクが存在します。第一に、Stateファイルの誤操作リスクです。terraform workspace selectコマンドによる切り替え忘れは、意図しない環境への変更適用や、最悪の場合、本番環境のインフラを破壊する可能性に直結します。第二に、環境間でのコードの密結合です。単一のコードベース内で環境差異を吸収しようとすると、HCL(HashiCorp Configuration Language)が複雑化し、可読性やメンテナンス性が低下します。最後に、アクセス制御の困難化が挙げられます。ワークスペースではきめ細やかな環境ごとのアクセス権限設定が難しく、セキュリティ面での課題が生じやすいため、長期的なインフラ管理には不向きと判断されました。
現代IaCワークフローの主流:GitOpsとディレクトリ分離
現代のInfrastructure as Code(IaC)ワークフローでは、GitOpsをベースとした「ディレクトリ分離(またはスタック分離)」が主流です。これは、環境ごとに異なるディレクトリを用意し、それぞれのディレクトリで独立したTerraformコードとStateファイルを管理するアプローチです。例えば、environments/dev/、environments/prod/のように構造化します。この方式では、各環境のインフラ定義が明確に分離されるため、コードの可読性が向上し、意図しない環境への変更適用リスクを大幅に低減できます。また、すべてのインフラ変更をGitリポジトリ経由で行うため、監査可能性が格段に高まります。デジタル庁の調査によると、2024年7月時点でデジタル社会への賛同率は50.9%に達しており、社会全体でデジタル変革が進む中で、IaC市場も2026年から2034年にかけて年平均成長率(CAGR)20.30%で成長すると予測されています(Global Information, Inc.)。
Terraformワークスペースは一時的な利用を想定しており、永続的な環境分離にはディレクトリ分離(GitOps)が推奨されます。
これにより、誤操作リスクを減らし、堅牢なIaCワークフローを構築できます。
出典:デジタル庁、Global Information, Inc.
GitOpsで実践するTerraformワークフロー構築ステップ
GitOps導入の第一歩:リポジトリ構造の設計
GitOpsをTerraformワークフローに導入する最初のステップは、Gitリポジトリの構造設計です。最も推奨されるのは、環境ごとにディレクトリを分離するアプローチです。具体的には、リポジトリルート直下にenvironments/ディレクトリを作成し、その中にdev/、stg/、prod/といった環境別のサブディレクトリを配置します。各環境ディレクトリ内には、その環境固有のTerraform構成ファイル(main.tf、variables.tf、terraform.tfvarsなど)と、バックエンド設定を記述します。
さらに、共通して利用するTerraformモジュールはmodules/ディレクトリに集約するか、別のリポジトリで管理し、各環境のmain.tfから参照するように設計することで、コードの再利用性を高めつつ、環境ごとの独立性を保つことができます。この明確な構造により、どの環境にどのような変更が適用されるかが一目で分かり、視覚的な理解と操作ミス防止に繋がります。
CI/CDパイプラインで自動化するTerraform実行プロセス
GitOpsの中核は、CI/CDパイプラインによるTerraform実行の自動化です。このプロセスは、主に以下のステップで構成されます。まず、開発者がインフラ変更をGitリポジトリにプッシュし、Pull Request(PR)を作成します。PRが作成されると、CI/CDパイプラインが自動的にトリガーされ、対象環境に対してterraform planコマンドを実行します。この結果はPRのコメントとして表示され、変更内容がレビューアに明確に伝わります。
レビューと承認が完了した後、PRがマージされると、CI/CDパイプラインは再度トリガーされ、自動的にterraform applyコマンドを実行し、インフラに変更を適用します。この一連の流れにより、人為的なコマンド実行ミスを排除し、インフラの状態とGitリポジトリのコードが常に同期される状態を保つことができます。手動でのTerraform操作を極力減らすことで、安定性と監査性が向上します。
Gitブランチ戦略とPull Request活用術
GitOpsにおける効果的なブランチ戦略とPull Request(PR)の活用は、チームでのIaC運用の鍵となります。一般的には、環境ごとに長期ブランチを設ける「環境ブランチ」戦略(例: mainブランチが本番、developブランチが開発)と、すべての変更をmainブランチに集約し、環境ごとのデプロイはタグやディレクトリパスに基づいて行う戦略があります。どちらの戦略を選択するにしても、すべてのインフラ変更は必ずフィーチャーブランチで作業し、PRを作成してレビューを受けるプロセスを徹底することが重要です。
PRのレビューでは、terraform planの結果だけでなく、コードの品質、セキュリティ、運用影響などを多角的に確認します。特に、インフラエンジニアは、単なるサーバー構築だけでなく、こうしたIaCを活用した「プラットフォームエンジニアリング」的な役割(自動化・効率化)を担う存在として再定義されています(厚生労働省 job tag)。このプロセスを通じて、チーム全体でインフラの現状と変更内容を共有し、リスクを最小限に抑えながらインフラを継続的に改善していくことが可能になります。
- Terraformコードの環境別ディレクトリ分離は完了していますか?
- すべてのインフラ変更がGitリポジトリを通じて行われていますか?
- Pull Request(PR)ベースのコードレビュープロセスを導入していますか?
- CI/CDパイプラインで自動的にTerraform Planが実行されていますか?
- 承認後にTerraform Applyが自動実行される仕組みを構築していますか?
- StateファイルはS3などのリモートバックエンドで管理されていますか?
出典:厚生労働省 職業情報提供サイト job tag
環境別Terraform管理戦略とGitLab連携の具体例
複数環境を安全に管理するディレクトリ構成
複数環境を安全かつ効率的に管理するためには、明確なディレクトリ構成が不可欠です。GitOpsでは、以下のような構成が一般的に採用されます。
.
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ ├── stg/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ └── prod/
│ ├── main.tf
│ ├── variables.tf
│ └── terraform.tfvars
├── modules/
│ ├── vpc/
│ │ └── ...
│ ├── ec2/
│ │ └── ...
│ └── ...
└── .gitlab-ci.yml
この構成では、environments/配下の各ディレクトリが独立したTerraformスタックを形成し、それぞれが自身のStateファイルを管理します。共通して使用するリソース(例: VPC、EC2インスタンス)はmodules/ディレクトリにモジュールとして定義し、各環境のmain.tfから参照します。これにより、コードの重複を避けつつ、環境ごとの差異はterraform.tfvarsやvariables.tfで柔軟に管理することが可能になります。この構造は、環境間の依存関係を最小限に抑え、個別のデプロイを容易にします。
GitLab CI/CDを活用したTerraform自動化の実際
GitLab CI/CDは、Terraformワークフローを自動化するための強力なツールです。.gitlab-ci.ymlファイルにパイプラインを定義することで、前述のGitOps原則を実装できます。例えば、以下のようなジョブを定義可能です。
terraform planジョブ: Merge Request(MR)が作成されるたびに、対象の環境ディレクトリでterraform planを実行し、その結果をMRのコメントとして表示します。これにより、変更が実際に適用される前に、意図した通りの変更が行われるかを確認できます。terraform applyジョブ: MRが承認され、mainブランチなどにマージされた際に、自動的にterraform applyを実行します。このジョブは、通常、特定の環境(例:prod)へのデプロイの場合、手動承認のステップを挟むなど、安全策を講じることが推奨されます。
GitLabの環境機能と連携させることで、デプロイ先の環境を明確に識別し、パイプラインの実行履歴とインフラの状態をより密接に紐付けることができます。これにより、変更の追跡と問題発生時の原因特定が容易になります。
モジュールと状態ファイル管理のベストプラクティス
Terraformのモジュールと状態(State)ファイル管理は、IaCの堅牢性を高める上で非常に重要です。モジュールは、再利用可能なインフラコンポーネントを定義するために用いられ、バージョン管理と組み合わせることで、一貫性のあるインフラ構築を可能にします。モジュールは、単一の機能に特化させ、シンプルなインターフェースを持つように設計することがベストプラクティスとされます。
一方、StateファイルはTerraformが管理するリソースの実際の状態を記録するものであり、その管理は最も慎重に行う必要があります。GitOpsワークフローでは、Stateファイルは決してGitリポジトリに直接コミットせず、Amazon S3、Azure Storage Account、Google Cloud Storageなどのリモートバックエンドに保存します。さらに、これらのバックエンドでは、Stateファイルのロック機能(例: DynamoDB for S3)を有効にし、複数のユーザーが同時にterraform applyを実行することによるStateファイルの破損を防ぐべきです。これにより、一貫性と信頼性の高いインフラ運用が可能になります。
出典:Terraform公式ドキュメント (HashiCorp)
Terraformワークフロー移行時の落とし穴とgitignoreの注意点
ワークスペースからGitOpsへの移行で直面する課題
既存のTerraformワークスペース運用からGitOpsベースのディレクトリ分離へ移行する際には、いくつかの課題に直面する可能性があります。まず、既存のワークスペースで管理されているStateファイルを、新しいディレクトリ構造に合わせた個別のStateファイルへと移行・再構成する必要があります。これはterraform state mvコマンドや、場合によっては手動でのStateファイル編集を伴う複雑な作業となり得ます。Stateファイルの整合性を保ちながら移行するためには、細心の注意と十分なテスト期間が求められます。
次に、CI/CDパイプラインの再構築です。ワークスペースに依存していた既存のスクリプトやパイプライン設定は、ディレクトリ分離モデルに対応するように全面的に見直す必要があります。各環境ディレクトリに対して個別にTerraformコマンドを実行できるよう、パス指定や変数の渡し方を調整しなければなりません。この移行プロセスは、システムの停止時間やデプロイリスクを最小限に抑えるため、段階的に進めることが推奨されます。
.gitignoreで管理すべきファイルと避けるべきファイル
Terraformプロジェクトにおける.gitignoreファイルは、バージョン管理システムに含めるべきでないファイルを適切に除外するために非常に重要です。管理すべきファイルは、Terraform構成ファイル(.tfファイル)や変数定義ファイル(.tfvarsファイル)、そしてCI/CDパイプラインの定義ファイル(.gitlab-ci.ymlなど)です。これらはインフラの状態を定義する「コード」そのものであり、バージョン管理することで変更履歴を追跡し、共同作業を可能にします。
一方、絶対にGitリポジトリから除外すべきファイルは、Terraform Stateファイル(.tfstate、.tfstate.backup)です。Stateファイルにはインフラの実際の状態が記述されており、機密情報が含まれる可能性もあります。これらはS3などのリモートバックエンドで管理し、Gitからは除外します。また、一時的に生成される.terraform/ディレクトリや、プロバイダの認証情報を含む可能性のあるファイルもgitignoreに含めるべきです。適切な.gitignore設定は、セキュリティリスクを低減し、クリーンなリポジトリを保つ上で不可欠です。
抽象化の罠を回避する設計思想
「コードのDRY (Don’t Repeat Yourself)」原則はソフトウェア開発において重要ですが、IaCにおいては過度な抽象化が「抽象化の罠」に陥る可能性があります。ワークスペースを使って無理にコードを共通化しようとすると、環境ごとの微細な設定変更が複雑な条件分岐やTerraformの機能(例: Count, For_each)を多用することになり、かえってコードの可読性を損ない、運用負荷を高めることがあります。環境間の差異が小さく見えても、将来的に変更要求が増えることで、共通コードが複雑化し、特定環境でのみ発生するバグの特定が困難になるケースが報告されています。
この罠を回避するためには、ある程度のコードの繰り返し(WET: Write Everything Twice)を許容し、各環境のコードをシンプルに保つ方が、長期的なメンテナンスコストが低くなる場合があります。共通モジュールはあくまで再利用可能な基本的なブロックに限定し、環境固有の複雑性はそれぞれの環境ディレクトリ内で管理する設計思想が推奨されます。これにより、コードの理解が容易になり、変更の影響範囲を限定しやすくなります。
出典:Terraform公式ドキュメント (HashiCorp)
【ケース】ワークスペース運用で起きた環境混同リスクからGitOpsで安定化へ
ワークスペース運用における環境混同トラブルの経緯(架空のケース)
ある中堅IT企業のインフラチームでは、これまでTerraformワークスペースを環境分離のために利用していました。開発、ステージング、本番の各環境がそれぞれdev、stg、prodというワークスペースで管理されており、インフラエンジニアはterraform workspace select devのようにコマンドを切り替えて作業していました。しかし、ある日、新機能リリース前の最終確認として、ステージング環境のインスタンスタイプを一時的に引き上げる作業が発生しました。担当エンジニアは通常通りterraform planを実行し、問題がないことを確認しましたが、実はその前に本番環境のログ調査のためにprodワークスペースに切り替えており、その切り替えを元に戻すのを忘れていました。結果として、確認すべきはステージング環境のプランであったにもかかわらず、本番環境のプランを確認し、そのままterraform applyを実行。意図せず本番環境のインスタンスタイプが変更されるというトラブルが発生しました。幸いにも、変更内容は一時的なリソース増強で済み、即座に元に戻されたため大きな障害には至りませんでしたが、チームは再発防止策の検討を余儀なくされました。
GitOps導入による環境安定化への具体的なアプローチ
この環境混同トラブルを機に、インフラチームはGitOpsへの移行を決断しました。具体的なアプローチは以下の通りです。
- ディレクトリ分離の徹底:既存のモノリシックなTerraform構成を、
environments/dev、environments/stg、environments/prodといったディレクトリ構造に完全に分離しました。各ディレクトリは独立したStateファイルをリモートバックエンド(Amazon S3)で管理するように設定を変更しました。 - CI/CDパイプラインの構築:GitLab CI/CDを導入し、すべてのインフラ変更をPull Request(MR)経由で行うワークフローを確立しました。開発者がフィーチャーブランチで変更を加えMRを作成すると、対応する環境のディレクトリで自動的に
terraform planが実行され、結果がMRにコメントとして表示されるようにしました。 - デプロイプロセスの厳格化:ステージング環境へのデプロイはMRマージで自動実行されるようにし、本番環境へのデプロイは、特定の承認者によるMR承認後、手動でのジョブトリガーが必要なように設定しました。これにより、誤操作による本番環境への意図しない変更リスクを排除しました。
このGitOpsへの移行により、インフラ変更はすべてGitの変更履歴として残り、誰が、いつ、どのような変更を行ったかが明確に追跡可能になりました。これにより、監査性が大幅に向上し、類似の環境混同リスクを根本的に解決する一歩となりました。
移行後の継続的な運用改善とチーム内での意識統一
GitOpsへの移行は一度きりのイベントではなく、継続的な運用改善とチーム内の意識統一が重要です。移行後も、インフラチームは定期的にCI/CDパイプラインの定義を見直し、より効率的で安全なプロセスを追求しました。例えば、Terraformのバージョンアップ時には、まず開発環境でテストし、段階的に上位環境へと適用する手順をパイプラインに組み込みました。また、環境ごとのインフラの差異を極力少なくするため、共通モジュールの利用を推進し、各環境固有の設定は最小限に抑えるよう努めました。
チーム内では、月に一度の定例ミーティングでインフラ変更に関するレビューと情報共有を行い、メンバー全員が最新の運用方針とベストプラクティスを理解する機会を設けました。これにより、新しいワークフローがチーム全体に定着し、インフラ運用の安定性が大きく向上しました。組織のデジタル化が進む中で、こうしたIaCを活用した「プラットフォームエンジニアリング」的なアプローチは、今後のインフラ運用の標準となっていく可能性があります。
まとめ
よくある質問
Q: Terraformワークスペースは本当に使ってはいけないのか?
A: 新規プロジェクトでは推奨されませんが、既存環境からの移行コストを考慮し、理解した上で利用するケースもあります。ただし、公式からは非推奨とされています。
Q: ワークスペースの代替となる管理方法は何か?
A: 複数のTerraform設定ファイルやディレクトリを分けて管理し、Gitブランチ戦略やCI/CDパイプラインと組み合わせるGitOpsワークフローが主流です。
Q: `terraform workspace` コマンドは今後使えなくなるのか?
A: コマンド自体は既存環境の互換性維持のため残りますが、その利用を前提とした設計は推奨されません。将来的には機能が限定される可能性もあります。
Q: GitOpsをTerraformに導入するメリットは何か?
A: インフラ構成のコード化、バージョン管理、レビュープロセスによる品質向上、自動デプロイによる人的ミス削減、変更履歴の追跡容易性などが挙げられます。
Q: `terraform gitignore` の設定で重要なことは?
A: `.terraform` ディレクトリ、`.terraform.lock.hcl`、`.tfstate*` ファイル、認証情報を含むファイルなどは必ず無視するべきです。これらは環境固有または機密情報のためです。
