https://github.com/idealistchanu/study-T101Study/tree/main/CHAPTER5
[GitHub - idealistchanu/study-T101Study
Contribute to idealistchanu/study-T101Study development by creating an account on GitHub.
github.com](https://github.com/idealistchanu/study-T101Study/tree/main/CHAPTER5)
테라폼은 유형을 반복 Loops, if 문 If-Statements을 사용하거나 무중단 배포를 할 수 있도록 count 메타 변수, for_each 표현식, create_before_destroy 생명 주기 블록 등 함수를 제공
- 반복문 Loops
- 조건문 Conditionals
- 무중단 배포 Zero-downtime deployment
- 테라폼의 주의 사항 Terraform gotchas
반복문
테라폼이 제공하는 반복문 구성 looping constructs
- count 매개변수 parameter : 리소스와 모듈의 반복
- for_each 표현식 expressions : 리소스 내에서 리소스 및 인라인 블록, 모듈을 반복
- for 표현식 expressions : 리스트 lists 와 맵 maps 을 반복
- for 문자열 지시어 string directive : 문자열 내에서 리스트 lists 와 맵 maps 을 반복
count 매개 변수
단점
- 인라인 블록을 반복 불가
- 목록 중간 항목을 제거시, 전체 삭제 후, 재생성
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_user" "myiam" {
count = 3
name = "$NICKNAME.${count.index}"
}
aws iam list-users | jq
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["gasida", "akbun", "fullmoon"]
}
- 테라폼에서 count 와 함께 배열 조회 구문과 length 함수를 사용해서 사용자들 생성 가능
- 배열 조회 구문 Array lookup syntax
- ARRAY[]
- 예를 들어 다음은 var.user_names 의 인덱스 1에서 요소를 찾는 방법
- var.user_names[1]
- length (내장) 함수 built-on function
- length()
- 주어진 ARRAY 의 항목 수를 반환하는 함수. 문자열 및 맵을 대상으로도 동작
- 배열 조회 구문 Array lookup syntax
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_user" "myiam" {
count = length(var.user_names)
name = var.user_names[count.index]
}
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["gasida", "akbun", "fullmoon"]
}
output "all_arns" {
value = aws_iam_user.myiam[*].arn
description = "The ARNs for all users"
}
for_each
장점
- 리스트 lists, 집합 sets, 맵 maps 를 사용하여 전체 리소스의 여러 복사본 또는 리소스 내 인라인 블록의 여러 복사본, 모듈의 복사본을 생성
- for_each 를 사용해 리소스를 맵으로 처리하면 컬렉션 중간의 항목도 안전하게 제거할 수 있어서, count 로 리소스를 배열 처리보다 이점이 큼
- 리소스 내에서 여러 개의 인라인 블록을 만들 수 있다는 점
resource "<PROVIDER>_<TYPE>" "<NAME>" {
for_each = <COLLECTION>
[CONFIG ...]
}
- COLLECTION 은 루프를 처리할 집합 sets 또는 맵 maps
- 리소스에 for_each 를 사용할 때에는 리스트는 지원하지 않습니다.
- 그리고 CONFIG 는 해당 리소스와 관련된 하나 이상의 인수로 구성되는데 CONFIG 내에서 each.key 또는 each.value 를 사용하여 COLLECTION 에서 현재 항목의 키와 값에 접근할 수 있습니다.
for_each 를 사용해 인라인 블록을 동적으로 생성하는 구문
dynamic "<VAR_NAME>" {
for_each = <COLLECTION>
content {
[CONFIG...]
}
}
dynamic "tag" {
for_each = var.custom_tags
content {
key = tag.key
value = tag.value
propagate_at_launch = true
}
}
- 여기서 VAR_NAME 은 각 ‘반복’의 값을 저장할 변수에 사용할 이름이고, COLLECTION 은 반복되는 리스트 또는 맵이며, content 블록은 각 반복에서 생성되는 항목입니다.
- content 블록 내에서 <VAR_NAME>.key 및 <VAR_NAME>.value 를 사용해 COLLECTION 에 있는 현재 항목의 키와 값에 각각 액세스할 수 있습니다.
- for_each 를 리스트와 함께 사용하는 경우 key는 인덱스가 되고 value는 해당 인덱스 목록에 있는 항목이 된다는 점을 기억합니다.
dynamic의 경우에 오류가 발생한다.

https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks
[Dynamic Blocks - Configuration Language | Terraform | HashiCorp Developer
Dynamic blocks automatically construct multi-level, nested block structures. Learn to configure dynamic blocks and understand their behavior.
developer.hashicorp.com](https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks)
for 표현식
단일 값을 생성하기 위해 반복이 필요한 경우
혹은 반복하여 단일 값을 수정해야하는 경우
[for <ITEM> in <LIST> : <OUTPUT>]
variable "names" {
description = "A list of names"
type = list(string)
default = ["gasida", "akbun", "fullmoon"]
}
output "upper_names" {
value = [for name in var.names : upper(name)]
}
output "short_upper_names" {
value = [for name in var.names : upper(name) if length(name) < 6]
}
[for <KEY>, <VALUE> in <MAP> : <OUTPUT>]
variable "names" {
description = "A list of names"
type = list(string)
default = ["gasida", "akbun", "fullmoon"]
}
output "upper_names" {
value = [for name in var.names : upper(name)]
}
output "short_upper_names" {
value = [for name in var.names : upper(name) if length(name) < 5]
}
variable "hero_thousand_faces" {
description = "map"
type = map(string)
default = {
gasida = "hero"
akbun = "love interest"
fullmoon = "mentor"
}
}
output "bios" {
value = [for name, role in var.hero_thousand_faces : "\${name} is the \${role}"]
}
# 리스트를 반복하고 맵을 출력 Loop over a list and output a map
{for <ITEM> in <LIST> : <OUTPUT_KEY> => <OUTPUT_VALUE>}
# 맵을 반복하고 리스트를 출력 Loop over a map and output a map
{for <KEY>, <VALUE> in <MAP> : <OUTPUT_KEY> => <OUTPUT_VALUE>}
문자열 지시자
- 문자열 지시자를 사용하면 문자열 보간과 유사한 구문으로 문자열 내에서 for 반복문, if문 같은 제어문을 사용할 수 있습니다.
- 다만 달러 부호와 중괄호 ${..} 대신 백분율 부호 %{}.. 를 사용한다는 차이가 있습니다.
- 테라폼은 두 가지 유형의 문자열 지시자, for 반복문과 조건문을 지원합니다.
- %{ for <ITEM> in <COLLECTION> }<BODY>%{ endfor }
- COLLECTION 은 반복할 리스트 또는 맵이고 ITEM은 COLLECTION 의 각 항목에 할당할 로컬 변수의 이름이며 BODY는 ITEM을 참조할 수 있는 각각의 반복을 렌더링하는 대상
variable "names" {
description = "Names to render"
type = list(string)
default = ["gasida", "akbun", "fullmoon"]
}
output "for_directive" {
value = "%{ for name in var.names }\${name}, %{ endfor }"
}
output "for_directive_index" {
value = "%{ for i, name in var.names }(\${i}) \${name}, %{ endfor }"
}
조건문 Conditionals
- count 매개 변수 parameter : 조건부 리소스에서 사용
- for_each 와 for 표현식 expressions : 리소스 내의 조건부 리소스 및 인라인 블록에 사용
- If 문자열 지시자 if string directive : 문자열 내의 조건문에 사용
count 매개 변수
- 리소스에 count 를 1로 설정하면 해당 리소스의 사본 하나를 얻습니다. count 를 0으로 설정하면 해당 리소스가 만들어지지 않습니다.
- 테라폼은 ? <TRUE_VAL> : <FALSE_VAL> 형식의 조건 표현식 conditional expression 을 지원합니다.
count = var.enable_autoscaling ? 1 : 0
for_each 와 for 표현식
- for_each 표현식을 빈 컬렉션으로 전달하면 0개의 리소스 또는 0개의 인라인 블록을 생성합니다.
- 비어 있지 않은 컬렉션을 전달하면 하나 이상의 리소스 또는 인라인 블록을 만듭니다.
dynamic "tag" {
for_each = {
for key, value in var.custom_tags:
key => upper(value)
if key != "Name"
}
content {
key = tag.key
value = tag.value
propagate_at_launch = true
}
}
- 중첩된 for 표현식은 일관성을 위해 var.custom_tags 를 반복하며 각 값을 대문자로 변환하고 모듈이 이미 자체 Name 태그를 설정했으므로,
- for 표현식의 조건을 사용하여 key 집합을 Name 으로 필터링합니다.
- for 표현식에서 값을 필터링하여 임의 조건부 논리를 구현할 수 있습니다.
- 리소스의 복사본을 여러 개 만들 때는 count 보다 for_each 를 사용하는 것이 더 낫지만,
- 조건 논리의 경우 비어 있지 않은 컬렉션에 for_each 를 설정하는 것보다 count 를 0 또는 1로 설정하는 것이 간단합니다.
- 즉, 리소스를 조건부로 생성할 때는 count 를 사용할 수 있지만, 그 외 모든 유형의 반복문 또는 조건문에는 for_each 를 사용합니다.
if 문자열 지시자
%{ if <CONDITION> }<TRUEVAL>%{ endif }
%{ if <CONDITION> }<TRUEVAL>%{ else }<FALSEVAL>%{ endif }
CONDITION은 boolean 으로 평가되는 표현식이고, TRUEVAL은 CONDITION이 True로 평가되면 렌더링할 표현식입니다.
variable "names" {
description = "Names to render"
type = list(string)
default = ["gasida", "akbun", "fullmoon"]
}
output "for_directive" {
value = "%{ for name in var.names }\${name}, %{ endfor }"
}
output "for_directive_index" {
value = "%{ for i, name in var.names }(\${i}) \${name}, %{ endfor }"
}
output "for_directive_index_if" {
value = <<EOF
%{ for i, name in var.names }
\${name}%{ if i < length(var.names) - 1 }, %{ endif }
%{ endfor }
EOF
}
문자열 지시자 시작에 공백이 있으며 지시자 앞에, 문자열 지시자 끝에 공객이 있으면 지시자 뒤에 물결표를 사용합니다.
output "for_directive_index_if_strip" {
value = <<EOF
%{~ for i, name in var.names ~}
\${name}%{ if i < length(var.names) - 1 }, %{ endif }
%{~ endfor ~}
EOF
}
output "for_directive_index_if_else_strip" {
value = <<EOF
%{~ for i, name in var.names ~}
\${name}%{ if i < length(var.names) - 1 }, %{ else }.%{ endif }
%{~ endfor ~}
EOF
}'Infrastructure as Code > Terraform' 카테고리의 다른 글
| [T101 Study 7주차] 프로덕션 수준의 테라폼 코드 (0) | 2022.12.11 |
|---|---|
| [T101 Study 6주차] 민감 정보 암호화 (0) | 2022.11.26 |
| [T101 Study 4주차] 모듈 (0) | 2022.11.23 |
| [T101 Study 3주차] 상태 파일 격리 방안 (2) | 2022.11.22 |
| [T101 Study 3주차] 상태 관리 (0) | 2022.11.21 |