이 스터디는 CloudNet@에서 진행하는 T101 스터디를 참여하면서 공부하는 내용을 기록하는 블로그 포스팅입니다.
CloudNet@에서 제공해주는 자료들과 테라폼으로 시작하는 IaC 를 바탕으로 작성되었습니다.
반복문
for_each
리소스 또는 모듈 블록에서 for_each에 입력된 데이터 형태가 map 또는 set이면, 선언된 key 값 개수만큼 리소스를 생성합니다. 즉, for_each 표현식을 사용하면 집합(sets), 맵(maps)을 사용하여 전체 리소스의 여러 복사본 또는 리소스 내 인라인 블록의 여러 복사본, 모듈의 복사본을 생성 할 수 있습니다.
map
resource "azurerm_resource_group" "rg" {
for_each = tomap({
a_group = "eastus"
another_group = "westus2"
})
name = each.key
location = each.value
}
set
resource "aws_iam_user" "the-accounts" {
for_each = toset(["Todd", "James", "Alice", "Dottie"])
name = each.key
}
실습
resource "local_file" "abc" {
for_each = {
a = "content a"
b = "content b"
}
content = each.value
filename = "${path.module}/${each.key}.txt
}
위의 코드와 같이 main.tf 파일을 수정하여 terraform init & apply --auto-approve를 실행합니다.
2개의 resouece가 생성되었다고 결과를 반환해주는 것을 확인하실 수 있습니다.
이처럼 for_each 구문에 있는 값처럼 2개의 파일이 생성되고 각각 내용이 작성되었습니다.
for_each가 설정된 블록에서는 each 속성을 사용하여 구성을 수정할 수 있습니다.
- each.key : 이 인스턴스에 해당하는 map 타입의 key 값
- each.value : 이 인스턴스에 해당하는 map타입의 value 값
생성되는 resource의 경우 <리소스 타입>.<이름>.[<key>], module의 경우 module.<이름>[<key>]로 해당하는 리소스의 값을 참조합니다. 이 참조 방식을 통해 리소스간 종속성을 정의하기도 하고 변수로 다른 리소스에서 사용하거나 출력을 위한 결과값으로 사용합니다.
variable "names" {
default = {
a = "content a"
b = "content b"
c = "content c"
}
}
resource "local_file" "abc" {
for_each = var.names
content = each.value
filename = "${path.module}/abc-${each.key}.txt"
}
resource "local_file" "def" {
for_each = local_file.abc
content = each.value.content
filename = "${path.module}/def-${each.key}.txt"
}
위와 같이 코드를 작성하여 terraform apply를 실행해보겠습니다. 그전에 잠깐 코드를 살펴보면 local_file.abc는 변수의 map 형태의 값을 참조하고, local_file.def의 경우 local_file.abc의 결과가 map으로 반환되므로 다시 for_each 구문을 사용할 수 있습니다.
for_each 를 사용한 후에는 하나의 resource 또는 count 를 사용한 것과 같은 리소스 배열이 되는 것이 아니리 리소스 맵이 됩니다.
variable "names" {
default = {
a = "content a"
c = "content c"
}
}
resource "local_file" "abc" {
for_each = var.names
content = each.value
filename = "${path.module}/abc-${each.key}.txt"
}
resource "local_file" "def" {
for_each = local_file.abc
content = each.value.content
filename = "${path.module}/def-${each.key}.txt"
}
key 값은 count의 index와 달리 고유하므로 중간에 값을 삭제한 후 다시 적용해도 삭제한 값에 대해서만 리소스를 삭제합니다. 그것을 확인해보기 위해 위와 같이 main.tf 파일을 수정한 후 terraform apply를 실행해보겠습니다.
결과 값에 2 destoryed가 반환되는데, map 형태의 중간 값을 삭제했을 때 local_file.abc와 local_file.def 리소스에 각각 하나씩 영향을 받는다는 결과를 확인하실 수 있습니다.
resource "local_file" "abc" {
for_each = toset(["a", "b", "c"])
content = "abc"
filename = "${path.module}/abc-${each.key}.txt"
}
이때, key에 해당하는 리소스만 영향을 받아 삭제가 됩니다. 위의 코드처럼 index에 영향을 받지 않도록 구성하려면 list 대신 set을 활용하여 중간 값의 삭제로 인해 다른 리소스가 삭제되는 것을 방지할 수 있습니다. 즉, for_each 를 사용해 리소스를 맵으로 처리하면 컬렉션 중간의 항목도 안전하게 제거할 수 있어서, count 로 리소스를 배열 처리보다 이점이 큽니다.
count VS for_each
count
count 는 index 로 몇번에 어떤 내용이 있는지를 알 수 없기 때문에 중간 리소스 삭제나 추가 시 문제가 발생할 수 있습니다.
resource "local_file" "abc" {
count = 3
content = "This is filename abc${count.index}.txt"
filename = "${path.module}/abc${count.index}.txt"
}
위와 같이 main.tf 를 작성한 후 terraform apply를 진행합니다.
{
"version": 4,
"terraform_version": "0.14.11",
"serial": 1,
"lineage": "b029fb2c-2c27-fe96-dae3-1552c8efdcfd",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "local_file",
"name": "abc",
"provider": "provider[\"registry.terraform.io/hashicorp/local\"]",
"instances": [
{
"index_key": 0,
"schema_version": 0,
...
"sensitive_attributes": []
},
{
"index_key": 1,
"schema_version": 0,
...
"sensitive_attributes": []
},
{
"index_key": 2,
"schema_version": 0,
...
"sensitive_attributes": []
}
]
}
]
}
그 후 생성되는 terraform.tfstate 파일을 확인해보면 위와 같이 index_key가 부여되어 리소스가 생성된 것을 확인하실 수 있습니다.
for_each
key 값은 count의 index와는 달리 고유하므로 중간에 값을 삭제한 후 다시 적용해도 삭제한 값에 대해서만 리소스를 삭제합니다.
resource "local_file" "abc" {
for_each = toset(["a", "b", "c"])
content = "This is filename abc-${each.key}.txt"
filename = "${path.module}/abc${each.key}.txt"
}
위와 같이 main.tf 파일을 수정한 후 terraform apply를 진행합니다.
{
"version": 4,
"terraform_version": "0.14.11",
"serial": 8,
"lineage": "b029fb2c-2c27-fe96-dae3-1552c8efdcfd",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "local_file",
"name": "abc",
"provider": "provider[\"registry.terraform.io/hashicorp/local\"]",
"instances": [
{
"index_key": "a",
"schema_version": 0,
...
"sensitive_attributes": []
},
{
"index_key": "b",
"schema_version": 0,
...
"sensitive_attributes": []
},
{
"index_key": "c",
"schema_version": 0,
...
"sensitive_attributes": []
}
]
}
]
}
그 후 생성되는 terraform.tfstate 파일을 확인해보면 위와 같이 index_key가 for_each의 값으로 부여되어 리소스가 생성된 것을 확인하실 수 있습니다.
'스터디 이야기 > Terraform' 카테고리의 다른 글
[T101] 3-3. Terraform - 반복문(dynamic) (0) | 2024.06.26 |
---|---|
[T101] 3-2. Terraform - 반복문 (for) (0) | 2024.06.24 |
[T101] 2-4. Terraform - 반복문(count) (0) | 2024.06.22 |
[T101] 2-3. Terraform - local & output (0) | 2024.06.18 |