自由気ままに書いちゃおう

好きなことをつらつらと・・・

【Terraform】(初心者向け)dynamic ブロックについて

今回はdynamicブロックについてです。

 

■はじめに

dynamicブロックの公式ページは以下です。

Dynamic Blocks - Configuration Language | Terraform | HashiCorp Developer

 

■dynamicブロックで何ができるのか?

私がdynamicブロックについて調べている際、
「繰り返し処理ができます!」という内容はたくさん見ました。

 

ただ、私は
「countやfor_eachでもできるよ」
と思ってました。

※ count/for_eachメタ引数 と dynamicブロックの違いがよくわかっていなかったので。笑

「count/for_eachではresource単位での繰り返し」ができます。
for_eachについては下記の記事を参照ください。

www.guri2o1667.work

 

では、"dynamicブロックを使う利点やユースケースは何なのか?"

答えは、

「dynamicはresourceの中のブロック単位で繰り返す」

ことができることです。

 

■本題に入る前に復習(for_each)

例えば、下記のコードの場合には、VPCが2つ作成できます。
これは前述の通り、「resource単位で繰り返し」をした結果、VPCが2つ作成されます。

locals {
  vpcs_list = ["10.20", "10.30"]
}

resource "aws_vpc" "vpc_create" {
  for_each   = toset(local.vpcs_list)
  cidr_block = "${each.key}.0.0/16"
}

■dynamicブロックを使わない場合

dynamicブロックの説明に入る前に一例ですが、SecurityGroupを作成する場合を考えてみます。
※ "aws_security_group"リソースを使う前提で記載しております。

 

インバウンドルールに80番、443番を指定する場合、以下のコードになります。

resource "aws_security_group" "allow_tls" {
  name        = "allow_tls"
  description = "Allow TLS inbound traffic"
  vpc_id      = "XXXXXX"

  ingress {
    description      = "TLS from VPC"
    from_port        = 443
    to_port          = 443
    protocol         = "tcp"
    cidr_blocks      = ["10.0.0.0/24"]
  }
 
  ingress {
    description      = "TLS from VPC"
    from_port        = 80
    to_port          = 80
    protocol         = "tcp"
    cidr_blocks      = ["10.0.0.0/24"]
  }

    egress {
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }

  tags = {
    Name = "allow_tls"
  }
}

 

name , description , vpc_id はSecurityGroupを作成する上で1回のみ指定すればよいものです。
インバウンドルールは80番、443番で絞るため、ingress{}が複数存在することになります。
この際、ingressブロック内の値を動的に変更することができれば、ingressブロックの記載は一つですみます。

■dynamicブロックを使う場合

まずは、コードから。

locals {
  inbound_ports = [80, 443]
}

resource "aws_security_group" "port_list" {
  name   = "test"
  vpc_id = aws_vpc.vpc_create.id

  dynamic "ingress" {
    for_each = toset(local.inbound_ports)

    content {
      description = "From-${ingress.key}-To-${ingress.value}"
      from_port   = ingress.key
      to_port     = ingress.key
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  }
}

 

dynamicブロックを使う場合、for_eachcontentが必須です。
for_eachでループ処理を宣言し、contentの中でingressブロック内で必要となる引数を指定します。(=dynamicブロックを使わずにSecurityGroupを設定する際に指定するingressブロックの引数のことです。)

ingressブロック内で必要な引数は以下参照ください。

Terraform Registry


for_eachを使ってはいますが、each.key , each.valueのようなeachを使った記述ではなく、dynamicを宣言したブロック名(今回の場合は dynamic "ingress" {} なのでingress)を使います。

なので、ingress.key や ingress.value を使っております。

※locals変数がリスト形式のため、key , valueはどちらを指定しても同じ値となります。

 

以下は上記コードのterraform apply実行時のログ抜粋です。

      + ingress                = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = "From-443-To-443"
              + from_port        = 443
              + ipv6_cidr_blocks =
              + prefix_list_ids  =
              + protocol         = "tcp"
              + security_groups  =
              + self             = false
              + to_port          = 443
            },
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = "From-80-To-80"
              + from_port        = 80
              + ipv6_cidr_blocks =
              + prefix_list_ids  =
              + protocol         = "tcp"
              + security_groups  =
              + self             = false
              + to_port          = 80
            },
        ]

また、AWSマネコンのSecurityGroup画面は以下です。

 

このような使い方ができるため、ブロック単位での繰り返し処理にてdynamicブロックを上手く使うことでコードの記述量を減らすことができます。

 

以上です。