본문 바로가기

IaC/Terraform

[Terraform]count와 for_each를 사용하여 반복되는 resource 작성하는 방법

countfor_each와 같은 Terraform의 반복 구문을 사용하면 코드의 반복을 줄이고, 관리를 용이하게 할 수 있습니다.

단순 반복하여 작성한 Terraform resource code

# provider
provider "aws" {
    region = "ap-northeast-2"
}

# resource
resource "aws_iam_user" "user_1" {
  name = "user-1"
}

resource "aws_iam_user" "user_2" {
  name = "user-2"
}

resource "aws_iam_user" "user_3" {
  name = "user-3"
}

# output
output "user_arns" {
  value = [
    aws_iam_user.user_1.arn,
    aws_iam_user.user_2.arn,
    aws_iam_user.user_3.arn,
  ]
}

결과 - tf apply

# 중략
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Outputs:

user_arns = [
  "arn:aws:iam:::user/user-1",
  "arn:aws:iam:::user/user-2",
  "arn:aws:iam:::user/user-3",
]

count를 이용하여 resource 작성

# count를 사용하여 resource 작성
resource "aws_iam_user" "count_user" {
  count = 10

  name = "count-user-${count.index}"
}

resource, data, module 에서 모두 사용 가능합니다.

resource block 최상단에 count=num 선언을 해야합니다.

결과 - tf apply

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

# 중략
aws_iam_user.count_user[8]: Creation complete after 1s [id=count-user-8]
aws_iam_user.count_user[1]: Creation complete after 1s [id=count-user-1]
aws_iam_user.count_user[9]: Creation complete after 1s [id=count-user-9]
aws_iam_user.count_user[5]: Creation complete after 1s [id=count-user-5]
aws_iam_user.count_user[2]: Creation complete after 1s [id=count-user-2]
aws_iam_user.count_user[3]: Creation complete after 1s [id=count-user-3]
aws_iam_user.count_user[4]: Creation complete after 1s [id=count-user-4]
aws_iam_user.count_user[6]: Creation complete after 1s [id=count-user-6]
aws_iam_user.count_user[7]: Creation complete after 1s [id=count-user-7]
aws_iam_user.count_user[0]: Creation complete after 1s [id=count-user-0]

Apply complete! Resources: 10 added, 0 changed, 0 destroyed.

for_each를 이용하여 resource 작성

# for_each를 이용하여 resource 작성

## for_each_set
resource "aws_iam_user" "for_each_set" {
    ## for_each
    for_each = toset([
        "for-each-set-user-1",
        "for-each-set-user-2",
        "for-each-set-user-3"
    ])
    name = each.key
}

output "for_each_set_user_arns" {
  value = values(aws_iam_user.for_each_set).*.arn
}

for_each를 사용하면 block내에서 사용할 수 있는 reference값이 생긴다.

  • each.key
  • each.value

toset

  • set, map 지원

output

  • keys(): object의 key값만 가져온다.
  • values(): object의 value값만 가져온다.

for_each_set을 이용하여 resource 작성

## for_each_set
resource "aws_iam_user" "for_each_set" {
    name = each.key
}

set으로 작성하는 경우 each.key값만 이용하면 된다.

name = each.key

  • iam user name이 key값으로 설정된다.

결과 - tf apply

aws_iam_user.for_each_set["for-each-set-user-2"]: Creation complete after 1s [id=for-each-set-user-2]
aws_iam_user.for_each_set["for-each-set-user-1"]: Creation complete after 2s [id=for-each-set-user-1]
aws_iam_user.for_each_set["for-each-set-user-3"]: Creation complete after 2s [id=for-each-set-user-3]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

for_each_map을 이용하여 resource 작성

중괄호 안에 작성해야한다.

key값은 string이다.

map에서는 key, value 모두 쓰이므로 each.key와 each.value값을 코드에서 사용하면 된다.

## for_each_map을 이용하여 resource 작성
resource "aws_iam_user" "for_each_map" {
  for_each = {
    jeff = {
        Team = "DevOps"
        Login = "False"
        Key = "True"
    }

    jm-han = {
        Team = "System"
        Login = "True"
        Key = "True"
    }   
  }

  name = each.key
  tags = each.value
}

output "for_each_map_user_arns" {
  value = values(aws_iam_user.for_each_map).*.arn
}

결과 - tf appy

# 중략
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

for_each_map_user_arns = [
  "arn:aws:iam:::user/jeff",
  "arn:aws:iam:::user/jm-han",
]

주의 사항

tf workspace에서 관리하고 있는 목록 확인

> tf state list
aws_iam_user.count_user[0]
aws_iam_user.count_user[1]
aws_iam_user.count_user[2]
aws_iam_user.count_user[3]
aws_iam_user.count_user[4]
aws_iam_user.count_user[5]
aws_iam_user.count_user[6]
aws_iam_user.count_user[7]
aws_iam_user.count_user[8]
aws_iam_user.count_user[9]
aws_iam_user.for_each_map["jeff"]
aws_iam_user.for_each_map["jm-han"]
aws_iam_user.for_each_set["for-each-set-user-1"]
aws_iam_user.for_each_set["for-each-set-user-2"]
aws_iam_user.for_each_set["for-each-set-user-3"]
aws_iam_user.user_1
aws_iam_user.user_2
aws_iam_user.user_3

count를 사용한 리소스

예제에서 aws_iam_user.count_user[0] ~ **aws_iam_user.count_user[9]**는 count를 사용하여 생성했다.

주의점:

  • 만약 **aws_iam_user.count_user[3]**을 삭제하면 count 인덱스 4~9의 모든 리소스가 shift 됩니다. 즉, **aws_iam_user.count_user[4]**는 **aws_iam_user.count_user[3]**이 되고, 이에 따라 전체 순서가 바뀝니다.
  • 중간에 있는 index값이 삭제되는 경우 이는 기존의 리소스 삭제 및 재생성을 초래할 수 있으므로 리소스 변경 시 주의가 필요합니다.

2. for_each를 사용한 리소스

예제의 aws_iam_user.for_each_mapaws_iam_user.for_each_setfor_each를 사용하여 생성된 것으로 보입니다.

장점:

  • 만약 aws_iam_user.for_each_map["jeff"] 리소스를 삭제하더라도 다른 리소스 (aws_iam_user.for_each_map["jm-han"])에는 아무런 영향이 없습니다. 각 리소스는 키 (예: "jeff", "jm-han")에 따라 독립적으로 관리됩니다.
  • key, value로 관리하기 때문에 리소스의 추가나 삭제가 다른 리소스에 영향을 미치지 않으므로 안정적으로 리소스를 관리할 수 있습니다.

요약:

  • count를 사용할 때는 순서가 중요하며, 중간의 리소스 변경이 다른 리소스에 영향을 줄 수 있습니다. 순서와 인덱스에 주의가 필요합니다.
  • for_each는 리소스의 키에 따라 독립적으로 관리되므로, 한 리소스의 변경이 다른 리소스에 영향을 주지 않습니다. 안정적이며 예측 가능한 리소스 관리를 위해 권장됩니다.