Terragruntにおけるモジュール間の依存関係の書き方
Terragruntを使うと別モジュール(例:VPC)から値を引き継げるが、やり方をよく忘れるのでメモ。VPCモジュールで定義したサブネットIDやCIDRの引き渡しなど応用範囲は広い。
目次
サンプル
ディレクトリは以下の通り。本当はdev_env
という単一の環境ではなく、複数の環境を想定できるが、今回は簡略化のため単一環境で考える。
dev_env/
├── app/
│ └── terragrunt.hcl
├── vpc/
│ └── terragrunt.hcl
modules/
├── app/
│ └── main.tf
├── vpc/
│ └── main.tf
ここで、modules
以下は環境間で共通のモジュールの定義(実際のTerraformのリソース定義)、dev_env
以下は環境ごとの個別の値を表す。
ここで問題になるのは、dev_env/app
においてterragrunt apply
(またはdev_env
においてterragrunt run-all apply
)を行ったときに、dev_env/vpc
の値を引き渡せるのか?という点。
具体的なユースケースとしては、VPCやサブネットIDやCIDRなどが例。なぜなら、FargateやEC2を定義するときに、サブネットIDの指定が必要だからです。VPCの定義自体は別モジュールで行うことも多いため。
コード(modules)
モジュール側のコードは以下の通り。ただのTerraform。今回は簡略化した例でプロバイダーは使わない。
modules/app/main.tf
variable "vpc_cidr" {
description = "VPC CIDR input from dependency module"
type = string
}
output "message" {
value = "Hello ${var.vpc_cidr}!"
}
VPCのCIDRを与えて、それをHelloと表示するだけのコード。この値はTerragruntを使い、VPCのモジュールから読み取る前提。
modules/vpc/main.tf
variable "vpc_cidr_prefix" {
description = "Prefix of CIDR Value of VPC"
type = string
}
output "vpc_cidr" {
value = "${var.vpc_cidr_prefix}.0.0/20"
}
簡略化した例で、CIDRのプレフィックスをユーザーから当てて、0.0/20
を追加した文字列を出力。これはapp側の値に引き渡す前提。
コード(dev_env)
Terragruntによる環境側の設定。明示的な依存関係の定義は、dev_env/app
で行う
dev_env/app/terragrunt.hcl
terraform {
source = "../../modules/app"
}
dependency "vpc" {
config_path = "../vpc"
mock_outputs = {
vpc_cidr = "dummy-cidr"
}
}
inputs = {
vpc_cidr = dependency.vpc.outputs.vpc_cidr
}
dependency
が依存関係を定義している部分。VPC(terragrunt.hcl
のあるdev_env/vpc
)を依存モジュールとして定義し、mock_outputs
で仮の値を定義する。仮の値は、terragrunt apply
実行前のplan
の時点での値として使われる。
また、Terraformのvariable
に引き渡すために、inputs
ブロックで値の定義が必要。書き方はdependency.vpc.outputs.
で行う。inputs
ブロックは依存関係の有無関係なく、Terragruntの一般で必要。
dev_env/vpc/terragrunt.hcl
terraform {
source = "../../modules/vpc"
}
inputs = {
vpc_cidr_prefix = "172.16"
}
これは環境ごとの値172.16
をモジュールに代入しているシンプルな例。依存されている側なので、想定される挙動としては、VPC→appの順で実行される。
Terragruntの実行結果
planの結果
dev_env
ディレクトリでterragrunt run-all plan
を実行した場合
Initializing the backend...
Initializing provider plugins...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Changes to Outputs:
+ vpc_cidr = "172.16.0.0/20"
You can apply this plan to save these new output values to the Terraform
state, without changing any real infrastructure.
─────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't
guarantee to take exactly these actions if you run "terraform apply" now.
Initializing the backend...
Initializing provider plugins...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Changes to Outputs:
+ message = "Hello dummy-cidr!"
You can apply this plan to save these new output values to the Terraform
state, without changing any real infrastructure.
─────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't
guarantee to take exactly these actions if you run "terraform apply" now.
アプリ側のmessage
にはmock_outputs
の値が使われている。
applyの結果
dev_env
ディレクトリでterragrunt run-all apply
を実行した場合
Are you sure you want to run 'terragrunt apply' in each folder of the stack described above? (y/n) y
Initializing the backend...
Initializing provider plugins...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Changes to Outputs:
+ vpc_cidr = "172.16.0.0/20"
You can apply this plan to save these new output values to the Terraform
state, without changing any real infrastructure.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
vpc_cidr = "172.16.0.0/20"
Initializing the backend...
Initializing provider plugins...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Changes to Outputs:
+ message = "Hello 172.16.0.0/20!"
You can apply this plan to save these new output values to the Terraform
state, without changing any real infrastructure.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
message = "Hello 172.16.0.0/20!"
VPC側で定義したCIDRがappに引き渡されており、想定した挙動。vpcでpaln→apply、appでplan→applyとなり、依存関係を意識した実行順序になっている。
Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内
技術書コーナー
北海道の駅巡りコーナー