💡

【Terraform】ディレクトリ構成について

2023/05/10に公開

ポイント

Terraform を使用する上で、ファイル構造は欠かせない考慮事項です。

Terraform は、plan や apply を実行するカレントディレクトリに存在する「 .tf 」拡張子のすべてのファイルを読み込むという仕様があります。

したがって、以下の2通りのファイル構造は我々から見てくれは違いますが、Terraform は同じものと認識します。

#main.tf内にリソースの定義などをすべてひとまとめにするパターン
terraform
|
|-main.tf
|-outputs.tf
|-provider.tf
#便宜的にファイルを分けるパターン(可読性を高めるため,こうすることが多い)
terraform
|
|-azure_virtual_machines.tf
|-azure_virtual_network.tf
|-azure_subnet.tf
|-azure_route.tf
|-outputs.tf
|-variable.tf
|-provider.tf

後者は前者に比べて,ファイルが増えていますが,可読性や保守性は高いです。

どのファイルにどのリソースの定義があるのか一目瞭然ですし,レビュー時にも差分確認がしやすくなります。

前者は,最初のうちは書いていて楽ですが,開発が進んでいくうちに膨大なファイルになっていきます。そうなると,コードが変更しずらくなり保守性が下がります。

単一構成

単一構成はすべてのリソースやデータ定義を一つのファイルに記載する方法です。
※ポイントに書いたひとまとめにする方法。

保守性が著しく低下し,可読性も低い構造になります。

運用で Terraform のコードを修正する場面を想定するとあまりやりたくない構造です。

#main.tf内にリソースの定義などをすべてひとまとめにするパターン
terraform
|
|-main.tf
|-outputs.tf
|-provider.tf

環境分離

プロジェクトでは,本番環境だけを使っているというところは稀だと思います。

本番環境,検証環境,QA環境など使用用途によって環境を分けているのが多いです。

その環境間では互いに独立したリソースを構築して運用する必要があります(試験環境のリソースが本番環境のリソースに影響を与えることがない)。

その場合,Terraform としては環境ごとに異なるディレクトリを作成して管理する必要があるということになります。

ポイント にも記載した通り,Terraform の実行はディレクトリ単位です。

したがって,環境ごとにディレクトリを分けて管理を行うことが一般的です。

以下の例では,本番環境を「prod」,試験環境を「dev」としています。

試験環境にリソースをデプロイする際には,カレントディレクトリを「dev」にした上で実行します。

一方,本番環境では「prod」に $cd した上で実行します。

terraform
|
|-prod
|		|
|		|-azure_virtual_machines.tf
|		|-azure_virtual_network.tf
|		|-azure_subnet.tf
|		|-azure_route.tf
|		|-outputs.tf
|		|-variable.tf
|		|-provider.tf
|
|-dev
|		|
|		|-azure_virtual_machines.tf
|		|-azure_virtual_network.tf
|		|-azure_subnet.tf
|		|-azure_route.tf
|		|-outputs.tf
|		|-variable.tf
|		|-provider.tf
|

Workspace 機能

Terraform では,一つのテンプレートから環境ごとにパラメータの違ったリソースを作成することができる workspace という機能が存在します。

workspace はとても複雑な機能なので,ここではリンク紹介のみとして,割愛します。

💡 ただし,Terraform 公式としては,本番環境や試験環境との環境分離でこの workspace 機能を使用することは推奨していません。
環境差分の取り込みとして使うのであれば module を積極的に使用するのがいいと思います。コードであればレビュー時にミスを防げますが,Workspace は作業時のヒューマンエラーが懸念されます。そのような観点でも本番環境と試験環境の分離で使用するのはやめたほうがいいです。

そもそもセキュリティ的に試験環境と本番環境どっちも弄れるような権限管理は杜撰なので,そこから考えたほうがいいです。

In particular, organizations commonly want to create a strong separation between multiple deployments of the same infrastructure serving different development stages (e.g. staging vs. production) or different internal teams. In this case, the backend used for each deployment often belongs to that deployment, with different credentials and access controls. Named workspaces are not a suitable isolation mechanism for this scenario.

めちゃめちゃ参考になる記事Terraform Workspaceを2年以上運用しての振り返り

State: Workspaces | Terraform | HashiCorp Developer

では,Workspace は何に使うのか?

これはテストに使います。

Terraform での環境構築を実施していると一度は経験する「plan はできるけど apply でエラー吐く」というやつを事前にテストできます。

これは非常にありがいたいですね。

State: Workspaces | Terraform | HashiCorp Developer

依存関係

Terraform には appply 時の構築順序を自動で調整する機能はデフォルトで存在します。

ただし,依存関係を補完する機能は持っていないです。

したがって,循環依存が恐いです。リソースが壊れやすくなります。

コンポーネントを作成するときに,コンポーネント間の依存関係を明示的に設計することが重要です。

エラーが出たときなどにコンポーネント間の依存関係を把握していれば,解決までの時間を短縮できます。

モジュール化と分離

モジュールについては以下のサイトによくまとまっているのでここでは割愛します。

モジュール化することでパラメータが少し違うだけ,導入するソフトウェアが違うだけ,のようなベースが変わらないけど環境で差分があるリソースの作成などを効率的に行うことが可能です。

複数環境を使用しているプロジェクトなどでよく利用する機能です。

モジュールの使い方 - Terraformのきほんと応用

Discussion