[Terraform] for_each 문법 및 사용 예시(Meta Argument)
이전 포스팅에서 Terraform의 count 문법에 대하여 알아보았습니다.
2022.06.11 - [About/DevOps] - [Terraform] Meta-Agument - count
테라폼에서 여러 리소스를 한 번에 생성하는 방법으로는 count와 for_each가 있는데 이번 포스팅에서 for_each에 대하여 다루어 보도록 하겠습니다. 자세한 정보는 Terraform 공식 문서에서 확인할 수 있습니다.
https://www.terraform.io/language/meta-arguments/for_each
for_each
for_each는 Terraform 언어에서 정의한 메타 인수입니다. 모듈 및 모든 리소스 유형과 함께 사용할 수 있습니다. 우선
Terraform의 Map과 Set 변수에 대하여 알아야합니다.
- set : 유일한 값의 요소들로 이루어진 list
- [1, 2, 3]
- map : Key-Value 형식의 데이터
- { k : v, k2 : v2 }
- key 값은 string이여야함
Terraform은 해당 Map 또는 Set 의 각 구성원에 대해 하나의 인스턴스를 생성합니다.
Basic Syntax
for_each는 Terraform 언어에서 정의한 메타 인수입니다. 모듈 및 모든 리소스 유형과 함께 사용할 수 있습니다.
for_each 메타 인수는 Map 또는 String Set 를 허용하고 해당 또는 세트의 각 항목에 대한 인스턴스를 생성합니다. 각 인스턴스에는 연결된 고유한 인프라 개체가 있으며 구성이 적용될 때 각각 별도로 생성, 업데이트 또는 소멸됩니다.
예시 - Map을 사용한 for_each
resource "azurerm_resource_group" "rg" {
for_each = {
a_group = "eastus"
another_group = "westus2"
}
name = each.key
location = each.value
}
예시 - Set을 사용한 for_each
resource "aws_iam_user" "the-accounts" {
for_each = toset( ["Todd", "James", "Alice", "Dottie"] )
name = each.key
}
each Object
for_each가 설정된 블록에서는 표현식에서 각 개체를 추가로 사용할 수 있으므로 각 인스턴스의 구성을 수정할 수 있습니다. 이 개체에는 두 가지 속성이 있습니다.
- each.key — 인스턴스에 해당하는 Map의 Key(또는 Set의 Value)입니다.
- each.value — 인스턴스에 해당하는 Map의 Value니다. (Set의 경우 each.key와 동일)
for_each 예시
for_each - set 자료형 사용 예시
for_each를 이용해서 AWS에서 IAM User 를 여러 개 생성해보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_user" "for_each_set" {
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
}
|
cs |
- 6번 라인 : toset() 함수를 통해서 리스트 자료형을 set으로 변경합니다.
- 7~9번 라인 : IAM User의 name에 사용할 값입니다.
- 12번 라인 : each.key를 이용하여 set의 데이터를 가져옵니다. set이기 때문에 each.value를 이용해도 상관없습니다.
- 13번 라인 : for_each는 map형태로 참조됩니다. 따라서 values() 함수를 이용하여 값만 가져오도록 하여 생성된 리소스의 모든 arn을 출력합니다.
위의 코드를 이용해 Terraform apply를 통해 적용한 결과는 다음과 같습니다.
Outputs:
for_each_set_user_arns = [
"arn:aws:iam::536887461755:user/for-each-set-user-1",
"arn:aws:iam::536887461755:user/for-each-set-user-2",
"arn:aws:iam::536887461755:user/for-each-set-user-3",
]
또한 AWS Management Console에 접속해서 생성된 IAM User를 확인할 수 있습니다.
for_each - map 자료형 예시
이번에는 set이 아닌 map 자료형을 통해 리소스를 생성해보도록 하겠습니다. 이전과 동일하게 AWS에서 IAM User를 생성합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_user" "for_each_map" {
for_each = {
alice = {
level = "low"
manager = "mhmhm3"
}
bob = {
level = "mid"
manager = "wlghks5"
}
jh = {
level = "high"
manager = "mcc32"
}
}
name = each.key
tags = each.value
}
output "for_each_map_user_arns" {
value = values(aws_iam_user.for_each_map).*.arn
}
|
cs |
- 6번 라인 : map자료형은 toset()과 같은 함수 필요 없이 {}를 통해서 바로 생성할 수 있습니다.
- 7~18번 라인 : IAM User의 생성에 사용할 정보를 정의합니다. map이기 때문에 key = value 형태로 정의합니다.
- 21~22번 라인 : IAM User의 name은 map의 key 값, 그리고 tags에는 map의 Value를 사용합니다.
위의 코드를 이용해 Terraform apply를 통해 적용하고 AWS Management Console에 접속해서 생성된 IAM User와 태그를 확인할 수 있습니다.
$ terraform state list
aws_iam_user.for_each_map["alice"]
aws_iam_user.for_each_map["bob"]
aws_iam_user.for_each_map["jh"]
Map 자료형은 key-value 형식으로 관리되기 때문에 좀 더 유리할 수 있습니다. 또한 이전에 count에서 발생할 수 있는 문제가 발생하지 않습니다. 예를들어 중간에 bob이 퇴사를 한다고 하더라도 bob에 대한 value만 삭제하면 되므로 문제가 생기지 않습니다.
Terraform의 for_each에 대하여 알아보았습니다.
참고
https://www.terraform.io/language/meta-arguments/for_each
https://fastcampus.co.kr/dev_online_awsdevops