Search
Duplicate
📒

[Terraform] 03-3. 반복, 조건, 함수, 프로비저너

상태
완료
수업
Terraform
주제
기본개념
4 more properties
참고

반복문

NOTE
테라폼에서 반복문은 count 파라미터for-each를 사용해서 리소스, 모듈, 데이터를 반복적으로 생성 및 관리할 수 있다!
resource "local_file" "abc" { count = 5 content = "abc" filename = "${path.module}/abc${count.index}.txt" }
Bash
복사
abc0~abc4.txt 파일 생성
count : 생성할 리소스의 수를 정의한다.
count.index : 현재 리소스의 인덱스(0부터 시작)을 나타낸다.
variable "names" { type = list(string) default = [ "a", "b", "c" ] } resource "local_file" "abc" { count = length(var.names) # names의 길이 3 content = "abc" filename = "${path.module}/abc${var.names[count.index]}.txt" } resource "local_file" "def" { count = length(var.names) # names의 길이 3 content = local_file.abc[count.index].content filename = "${path.module}/def-${element(var.names, count.index)}.txt" }
Bash
복사
abc(a~c).txt, def-(a~c).txt 파일생
count의 경우 provider 블록 선언부가 포함되어 있는 경우 적용이 불가능하며, 외부 변수가 list인 경우 중간에 값이 삭제되면 중간값 뿐 아니라 이후의 정의된 리소스들도 모두 삭제되고 재생성된다.
ex) b가 제거되면, b~c의 값이 모두 제거되고 c가 재생성된다.

for-each

NOTE
for-each는 count보다 더 유연하고 복잡한 반복작업에 유용하게 사용할 수 있다!
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" }
Bash
복사
for-each 활용
for-each : 반복할 데이터(목록 또는 맵)을 정의한다.
each.key : 맵을 사용하는 경우 현재 항목의 key에 접근한다.
each.value : 맵 또는 목록을 사용하는 경우 현재 항목의 value을 나타낸다.

for

NOTE
for 구문은 리스트/맵을 기반으로 새로운 리스트/맵을 생성할 때 사용한다!
variable "names" { default = ["a", "b", "c"] } resource "local_file" "abc" { content = jsonencode([for s in var.names: upper(s)]) # ["a", "b", "c"] -> ["A", "B", "C"] filename = "${path.module}/abc.txt" }
Bash
복사
["a", "b", "c"] -> ["A", "B", "C"]
variable "names" { type = list(string) default = ["a", "b"] } output "A_upper_value" { value = [for v in var.names: upper(v)] # ["A", "B"] } output "B_index_and_value" { value = [for i, v in var.names: "${i} is ${v}"] # "0 is a", "1 is b", } output "C_make_object" { value = {for v in var.names: v => upper(v)} # "a" = "A", "b" = "B" } output "D_with_filter" { value = [for v in var.names: upper(v) if v != "a"] # ["B"] }
Bash
복사
예시 코드

dynamic

NOTE
dynamic 블록은 반복 가능한 중첩된 구조를 생성할 때 사용한다!
resource "aws_security_group" "allow_tls" { name = "allow_tls" description = "Allow TLS inbound traffic" vpc_id = "aws_vpc.main.id" ingress { description = "TLS from VPC" from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = [aws_vpc.main.cidr_block] ipv6_cidr_blocks = [aws_vpc.main.ipv6_cidr_block] } ingress { description = "HTTP" from_port = 8080 to_port = 8080 protocol = "tcp" cidr_blocks = [aws_vpc.main.cidr_block] ipv6_cidr_blocks = [aws_vpc.main.ipv6_cidr_block] } }
Bash
복사
dynamic을 사용하지 않는경우
resource "aws_security_group" "allow_tls" { name = "allow_tls" description = "Allow TLS inbound traffic" vpc_id = aws_vpc.main.id dynamic "ingress" { for_each = [ { description = "TLS from VPC", from_port = 443, to_port = 443, protocol = "tcp" }, { description = "HTTP", from_port = 8080, to_port = 8080, protocol = "tcp" } ] content { # 반복되는 내용 적용 description = ingress.value.description from_port = ingress.value.from_port to_port = ingress.value.to_port protocol = ingress.value.protocol cidr_blocks = [aws_vpc.main.cidr_block] ipv6_cidr_blocks = [aws_vpc.main.ipv6_cidr_block] } } }
Bash
복사
dynamic을 사용하는 경우

조건식

NOTE
테라폼에서 조건식은 주로 condition ? true : fale 형태로 사용되며, 특정조건에 따라 값을 반환하도록 할 때 유용하다!
# <조건 정의> ? <옳은 경우> : <틀린 경우> var.a != "" ? var.a : "default-a" # 조건신은 비교대상의 타입이 다르면 자동변환하므로 타입을 맞춰서 비교하자 var.example ? 12 : "hello" # 비권장 var.example ? "12 : "hello" # 권장
YAML
복사
variable "enable_file" { default = true } resource "local_file" "foo" { count = var.enable_file ? 1 : 0 # 파일이름이 공백이 아니면 1 content = "foo!" filename = "${path.module}/foo.bar" } output "content" { value = var.enable_file ? local_file.foo[0].content : "" # 1번째 파일의 내용이 공백인가? }
Bash
복사
예시코드

함수

NOTE
테라폼은 함수를 직접 작성할 수는 없지만, 내장된 다양한 함수를 사용할 수 있다!
resource "aws_instance" "example" { tags = { Name = format("instance-%03d", count.index) # 문자열 포맷팅 예시 } } output "subnet_id" { value = element(aws_subnet.example.*.id, 0) # 리스트에서 요소 선택 예시 } variable "user_data" { default = file("${path.module}/user_data.sh") # 파일 내용을 변수로 사용 예시 }
YAML
복사
수치함수
abs, ceil, floor, log, max, min ..
데이터와 관련된 다양한 연산을 수행한다.
문자열 함수
chomp, format, join, lower, upper, replace ..
문자열 데이터를 조작하는데 사용된다.

프로비저너

NOTE
테라폼 프로비저너는 프로바이더와 비슷하게 제공자로 해석되나, 프로바이더로 실행되지 않는 커맨드와 파일 복사 같은 역할을 수행한다.
프로비저너로 실행된 결과는 테라폼의 상태 파일과 동기화되지 않는다. (따라서 사용을 최소화하는것이 좋다.
variable "sensitive_content" { default = "secret123" sensitive = true } resource "local_file" "foo" { content = upper(var.sensitive_content) filename = "${path.module}/foo.bar" provisioner "local-exec" { command = "echo The content is ${self.content}" # 컨텐츠 출력(민감정보라 제대로 안나옴) } provisioner "local-exec" { command = "abc" # 해당 커맨드는 찾을수 없어 에러 on_failure = continue } provisioner "local-exec" { when = destroy # 파일 삭제시 발동 command = "echo the deleting filename is ${self.filename}" } }
Bash
복사
로컬 실행 프로비저너(’local-exec’)
로컬 시스템에서 명령을 실행한다.
resource "null_resource" "example1" { connection { # connection 블록으로 연결정의 type = "ssh" user = "root" password = 1234 host = "host" } provisioner "remote-exec" { inline = [ "sudo apt-get update", "sudo apt-get install -y nginx", ] } provisioner "file" { source = "conf/myapp.conf" destination = "C:/App/myapp.conf" connection { type = "winrm" user = "Administrator" password = 1234 host = "host" } } }
Bash
복사
원격 실행/파일 프로비저너는 연결할 SSH, WinRM 연결 정의가 필요하다.
원격 실행 프로비저너(’remote-exec’)
생성된 리소스에 SSH나 WinRM을 통해 연결하여 명령을 실행한다.
파일 프로비저너(’file’)
로컬 시스템에서 원격 리소스로 파일이나 디렉토리를 복사할 때 사용한다.