はじめに
Terraformのmodule化を使用したディレクトリ構成を試していたところ、変数の値が呼び出せずエラーが発生してしまい、少し迷ったので備忘録として記事にしました。
なぜ変数の値を渡せなかったか?
以下のディレクトリ構成を想定しています。
TechBull-project/
├── dev/
│ ├── main.tf
│ ├── variables.tf
│ └── terraform.tfvars
│
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── ec2/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
当初、modules/配下にも.tfvarsファイルを作成して、各モジュールで変数の値を定義しようとしましたが、
Terraformの仕様上、.tfvarsファイルはルートモジュール(カレントディレクトリ)でのみ有効であり、
モジュール内のmain.tfなどからは参照されませんでした。
これは、.tfvarsはあくまでルートモジュールのvariables.tfに対して値を紐づけするためのファイルであり、
モジュール内部では、variables.tfに変数を宣言し、呼び出し元から値を渡す必要があるためでした。
また、Terraformには変数の優先順位があるらしく、variables.tfでdefaultを指定した値より、terraform.tfvarsの値が優先されるようです。
そのため、環境ごとに設定を切り替える場合は、terraform.tfvarsを活用することで、ルートモジュール(カレントディレクトリ)側で環境ごとの変数を切り替えられるため便利なのかなと感じました。
■公式ドキュメント
■以下抜粋
仕様について
以下のセクションでは、これらのオプションについて詳しく説明します。このセクションは子モジュールには適用されません。子モジュールでは、入力変数の値は親モジュールの設定で割り当てられます( モジュールの説明を参照) 。
[省略]
変数定義(.tfvars)ファイル
多数の変数を設定するには、変数定義ファイル(ファイル名が または で終わる.tfvars )でそれらの値を指定し.tfvars.json、そのファイルをコマンド ラインで で指定すると 便利です-var-file。
[省略]
変数定義ファイルは、Terraform 言語ファイルと同じ基本構文を使用しますが、変数名の割り当てのみで構成されます。
優先順位について
変数定義の優先順位
上記の変数設定メカニズムは、任意の組み合わせで使用できます。同じ変数に複数の値が割り当てられている場合、Terraformは最後に見つかった値を使用し、それ以前の値は上書きされます。ただし、単一のソース内で同じ変数に複数の値を割り当てることはできません。Terraform は次の順序で変数をロードします。後のソースが前のソースよりも優先されます。
- 環境変数(variablesのdefault設定等)
- ファイルterraform.tfvars(存在する場合)。
- ファイルterraform.tfvars.json(存在する場合)。
- 任意の*.auto.tfvarsまたは*.auto.tfvars.jsonファイルは、ファイル名の語句順に処理されます。
- コマンドライン上の任意-varのオプション(指定された順序で)。(これには、HCP Terraform ワークスペースによって設定された変数も含まれます。)-var-file
実際に試すとわかるのですが、.tfvars にのみ値を定義し、variables.tfなどで変数を宣言していない場合、apply時に次のようなエラーが発生します。
╷
│ Warning: Value for undeclared variable
│
│ The root module does not declare a variable named "ec2_name" but a value was found in file "terraform.tfvars". If you meant to use this value, add a "variable" block
│ to the configuration.
│
│ To silence these warnings, use TF_VAR_... environment variables to provide certain "global" settings to all configurations in your organization. To reduce the
│ verbosity of these warnings, use the -compact-warnings option.
╵
╷
│ Error: Reference to undeclared input variable
│
│ on main.tf line 75, in module "ec2":
│ 75: name = var.ec2_name
│
│ An input variable with the name "ec2_name" has not been declared. This variable can be declared with a variable "ec2_name" {} block.
╵
まとめ
.tfvars ファイルで変数を管理すること自体は理解していたのですが、
今回のような細かいところまでは把握していなかったため、良い学びのきっかけになりました。
また、普段あまり意識していない部分でも、こういった思いがけないところでハマりポイントになってしまうことがあるので、今後は注意していきたいと感じました。
以上、ありがとうございました!