728x90
안녕하세요,
오늘은 for_each, for, dynamic 등 반복문에 대해서 살펴보도록 하겠습니다.
‘테라폼으로 시작하는 IaC’를 기준으로 내용 정리하였으며, CloudNet@의 테라폼 스터디 내용을 기반으로 하고 있습니다.
1. for_each의 주요 특징
- 반복 키(key)와 값(value)에 대한 접근:
- for_each를 사용하면 주어진 맵(map)의 각 항목 또는 집합(set)의 각 요소에 대해 반복할 수 있습니다.
- 각 반복 요소는 each.key와 each.value로 접근할 수 있습니다.
- each.key: 맵의 키(key) 또는 집합(set)의 멤버에 해당합니다.
- each.value: 맵의 값(value)에 해당하며, 집합(set)을 사용할 경우 each.key와 동일합니다.
- 타입 제한:
- for_each 표현식을 사용하면 리스트 lists, 집합 sets, 맵 maps를 사용하여 전체 리소스의 여러 복사본 또는 리소스 내 인라인 블록의 여러 복사본, 모듈의 복사본을 생성할 수 있습니다.
- 다른 타입의 데이터를 사용하려면 이를 맵 또는 집합으로 변환해야 합니다. eg., toset() 함수
- 제약 사항:
- for_each를 사용할 때 몇 가지 제약 사항이 있습니다. 예를 들어, 특정 리소스에서는 for_each를 사용할 수 없거나, 모듈 호출에서 제한이 있을 수 있습니다. 이 경우 공식 Terraform 문서나 제공된 예제를 참조하여 사용 가능 여부를 확인하는 것이 중요합니다.
- 사용 예:
- 주로 여러 리소스를 동적으로 생성할 때 for_each를 활용합니다. 예를 들어, 여러 개의 인스턴스, 데이터베이스, 스토리지 등을 일괄적으로 관리할 때 유용하게 사용됩니다.
참고 자료
코드
간단한 코드를 통해서 확인해 보겠습니다.
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_s3_bucket" "for_each_example" {
for_each = {
bucket1 = "for-each1"
bucket2 = "for-each2"
bucket3 = "for-each3"
}
bucket = each.value
}
코드 설명
- resource "aws_s3_bucket" "for_each_example"는 AWS S3 버킷을 생성하는 리소스입니다.
- for_each 매개변수는 맵(map) 형태로 정의되어 있습니다.
맵은 여러 개의 버킷을 정의하며, 각 항목은 버킷의 이름을 키(key)로, 버킷의 이름을 값(value)으로 갖습니다.
- 이때, bucket1의 이름은 "for-each1", bucket2의 이름은 "for-each2", bucket3의 이름은 "for-each3"입니다.
- bucket = each.value: 각 버킷의 이름은 each.value로 설정됩니다.
따라서 각 반복 요소에서 each.value는 버킷의 이름을 나타냅니다.
2. count의 주요 특징
지난 링크에 정리했기 때문에, 링크를 추가합니다.
https://jflip.tistory.com/114
- 고정된 개수의 리소스 생성:
- count는 정수로 지정된 값에 따라 정확히 그 수만큼의 리소스 인스턴스를 생성합니다.
- 예를 들어, count = 3으로 설정하면 세 개의 동일한 리소스가 생성됩니다.
- 리소스 이름 관리:
- 각 리소스 인스턴스는 0부터 시작하는 인덱스를 가지며, 이 인덱스를 사용하여 이름이나 속성을 고유하게 관리할 수 있습니다.
- 예를 들어, 리소스 이름을 instance-${count.index}와 같이 지정할 수 있습니다.
- 변수 사용:
- count는 변수(Variable)나 데이터 소스(Data Source)를 통해 동적으로 설정될 수 있습니다.
이를 통해 Terraform 코드를 보다 유연하게 관리할 수 있습니다. - 예를 들어, 변수로 count 값을 설정하면 여러 환경에 대응할 수 있습니다.
- count는 변수(Variable)나 데이터 소스(Data Source)를 통해 동적으로 설정될 수 있습니다.
- 제한 사항:
- count는 정수 값이어야 하며, 음수 혹은 실수는 사용할 수 없습니다.
- count 값을 동적으로 변경하거나, 생성된 리소스의 수를 후에 변경하는 것은 어렵기 때문에,
동적으로 변하는 리소스 생성에는 for_each가 더 적합할 수 있습니다.
이 내용은 공식 문서에도 정리하고 있습니다.
https://developer.hashicorp.com/terraform/language/meta-arguments/count
코드
간단한 코드를 통해서 확인해 보겠습니다.
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "example" {
count = 3
ami = "ami-0edc5427d49d09d2a"
instance_type = "t2.micro"
tags = {
Name = "instance-${count.index}"
}
}
코드 설명
- aws_instance 리소스: resource "aws_instance" "example"는 AWS EC2 인스턴스를 생성하는 리소스입니다.
- count = 3: count를 사용하여 세 개의 EC2 인스턴스를 생성합니다.
- ami = "ami-0edc5427d49d09d2a": 사용할 AMI ID를 지정합니다.
- instance_type = "t2.micro": 인스턴스 유형을 설정합니다 (여기서는 t2.micro를 사용).
- tags: 각 인스턴스에 부여할 태그를 설정합니다. 여기서는 Name 태그를 각 인덱스에 맞게 설정하여 인스턴스의 이름을 고유하게 지정합니다.
3. dynamic 블록의 주요 특징
- 동적 구성 가능:
dynamic 블록을 사용하면 Terraform 코드 내에서 동적으로 리소스 또는 모듈을 생성할 수 있습니다. 이는 정적으로 미리 정의된 수의 리소스가 아닌, 실행 시점에 결정되는 경우에 유용합니다. - 반복적 구성 처리:
for_each와 달리 dynamic은 리스트 또는 맵의 각 요소를 독립적으로 처리할 수 있습니다.
따라서 각 요소가 독립적으로 생성, 수정, 삭제될 수 있습니다. - 동적 요소의 유연한 처리:
dynamic 블록 내에서는 Terraform 표현식과 함수를 활용하여 동적 요소를 생성할 수 있습니다.
예를 들어 조건에 따라 다른 리소스를 생성하거나, 동일한 유형의 리소스를 맵핑할 수 있습니다. - 복잡한 데이터 구조 처리:
복잡한 데이터 구조를 처리할 때 dynamic 블록이 유용합니다. 예를 들어 여러 개의 중첩된 객체를 생성해야 할 때 특히 유용합니다. - 구성 단순화:
코드를 단순화하고 반복적인 부분을 줄일 수 있습니다. 예를 들어 동일한 리소스 유형을 여러 개 생성해야 할 때 효과적입니다.
일반적으로 dynamic 블록은 다음과 같이 사용할 수 있습니다.
resource "provider_resource" "name" {
name = "some_resource"
dynamic "some_setting" {
for_each = {
a_key = a_value
b_key = b_value
c_key = c_value
d_key = d_value
}
content {
key = some_setting.value
}
}
}
코드
resource "aws_security_group" "example" {
name = "example-security-group"
description = "Example security group"
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value["from_port"]
to_port = ingress.value["to_port"]
protocol = ingress.value["protocol"]
cidr_blocks = ingress.value["cidr_blocks"]
}
}
dynamic "egress" {
for_each = var.egress_rules
content {
from_port = egress.value["from_port"]
to_port = egress.value["to_port"]
protocol = egress.value["protocol"]
cidr_blocks = egress.value["cidr_blocks"]
}
}
}
variable "ingress_rules" {
default = [
{
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
},
{
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
},
]
}
variable "egress_rules" {
default = [
{
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
},
]
}
코드 설명
- ingress_rules 변수는 인바운드 규칙을 정의하며, 위의 코드 예시에서는 HTTP(포트 80)과 HTTPS(포트 443)를 허용하는 규칙이 설정되어 있습니다.
- egress_rules 변수는 아웃바운드 규칙을 정의합니다. 코드 예시에서는 모든 트래픽을 허용하는 규칙이 설정되어 있습니다.
- for_each는 var.ingress_rules 변수의 각 요소에 대해 반복하며,
- ingress.value["from_port"], ingress.value["to_port"], ingress.value["protocol"], ingress.value["cidr_blocks"]는 각 규칙의 포트 범위, 프로토콜, CIDR 블록을 설정합니다.
- for_each는 var.egress_rules 변수의 각 요소에 대해 반복합니다.
- egress.value["from_port"], egress.value["to_port"], egress.value["protocol"], egress.value["cidr_blocks"]는 각 규칙의 포트 범위, 프로토콜, CIDR 블록을 설정합니다.
728x90
반응형
'DevOps > Terraform' 카테고리의 다른 글
[Terraform] 테라폼 내장함수 사용하기 (0) | 2024.06.29 |
---|---|
[Terraform] 조건식을 활용한 태깅 (0) | 2024.06.29 |
[Terraform] cidrsubnet, cidrsubnets 함수 (0) | 2024.06.23 |
[Terraform] count 사용하기 (0) | 2024.06.23 |
[Terraform] 로컬 변수 사용하기 (0) | 2024.06.23 |