こしあん
2024-12-03

Terragruntにおけるモジュール間の依存関係の書き方


11{icon} {views}

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の中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内

技術書コーナー

北海道の駅巡りコーナー


Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です