테라폼 함수, 표현식, 메타 인수의 이해 - AWS 규범적 지침

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

테라폼 함수, 표현식, 메타 인수의 이해

일반적인 프로그래밍 언어 대신 선언적 구성 파일을 사용하는 IaC 도구에 대한 한 가지 비판은 사용자 지정 프로그래밍 로직을 구현하기가 더 어렵다는 것입니다. Terraform 구성에서 이 문제는 함수, 표현식 및 메타 인수를 사용하여 해결됩니다.

함수

코드를 사용하여 인프라를 프로비저닝할 때의 가장 큰 장점 중 하나는 공통 워크플로를 저장하고 매번 다른 인수를 전달하여 반복해서 재사용할 수 있다는 것입니다. Terraform 함수는 AWS CloudFormation 내장 함수와 비슷하지만 구문이 프로그래밍 언어에서 함수를 호출하는 방식과 더 비슷합니다. 이 가이드의 예제에서 substr, concat, length 및 base64decode와 같은 일부 Terraform 함수를 이미 보셨을 것입니다. 내장 함수와 마찬가지로 CloudFormation Terraform에는 구성에서 사용할 수 있는 일련의 내장 함수가 있습니다. 예를 들어 특정 리소스 속성이 매우 큰 JSON 객체를 사용하므로 파일에 직접 붙여넣기에는 비효율적이면 객체를.json 파일에 넣고 Terraform 함수를 사용하여 액세스할 수 있습니다. 다음 예제에서 file 함수는 파일의 내용을 문자열 형식으로 반환한 다음 이 jsondecode 함수를 객체 유형으로 변환합니다.

resource "example_resource" "example_resource_name" { json_object = jsondecode(file("/path/to/file.json")) }

Expressions

또한 Terraform에서는 보다 전통적인 삼항 연산자 구문을 사용한다는 점을 제외하면 CloudFormation condition 함수와 유사한 조건식을 사용할 수 있습니다. 다음 예제에서 두 표현식은 완전히 동일한 결과를 반환합니다. 두 번째 예는 Terraform이 스플랫 표현식이라고 부르는 것입니다. 별표를 사용하면 Terraform이 목록을 반복하면서 각 항목의 속성만 사용하여 새 목록을 만듭니다. id

resource "example_resource" "example_resource_name" { boolean_value = var.value ? true : false numeric_value = var.value > 0 ? 1 : 0 string_value = var.value == "change_me" ? "New value" : var.value string_value_2 = var.value != "change_me" ? var.value : "New value" } There are two ways to express for loops in a Terraform configuration: resource "example_resource" "example_resource_name" { list_value = [for object in var.ids : object.id] list_value_2 = var.ids[*].id }

메타 인수

이전 코드 예제에서는 list_valuelist_value_2 인수라고 합니다. 이러한 메타 인수 중 일부는 이미 익숙할 것입니다. Terraform에는 인수처럼 작동하지만 몇 가지 추가 기능이 있는 메타 인수도 몇 개 있습니다.

다른 메타 인수를 사용하면 함수 및 표현식 기능을 리소스에 직접 추가할 수 있습니다. 예를 들어 count 메타 인수는 여러 개의 유사한 리소스를 동시에 생성하는 데 유용한 메커니즘입니다. 다음 예제는 메타 인수를 사용하지 않고 두 개의 Amazon Elastic Container Service (Amazon EKS) 클러스터를 생성하는 방법을 보여줍니다. count

resource "aws_eks_cluster" "example_0" { name = "example_0" role_arn = aws_iam_role.cluster_role.arn vpc_config { endpoint_private_access = true endpoint_public_access = true subnet_ids = var.subnet_ids[0] } } resource "aws_eks_cluster" "example_1" { name = "example_1" role_arn = aws_iam_role.cluster_role.arn vpc_config { endpoint_private_access = true endpoint_public_access = true subnet_ids = var.subnet_ids[1] } }

다음 예제는 count 메타 인수를 사용하여 두 개의 Amazon EKS 클러스터를 생성하는 방법을 보여줍니다.

resource "aws_eks_cluster" "clusters" { count = 2 name = "cluster_${count.index}" role_arn = aws_iam_role.cluster_role.arn vpc_config { endpoint_private_access = true endpoint_public_access = true subnet_ids = var.subnet_ids[count.index] } }

각 유닛에 이름을 지정하려면 에서 리소스 블록 내의 목록 인덱스에 액세스하면 됩니다. count.index 하지만 좀 더 복잡한 유사한 리소스를 여러 개 만들고 싶다면 어떻게 해야 할까요? 여기서 for_each 메타 인수가 등장합니다. for_each메타 인수는 숫자 대신 목록이나 객체를 전달한다는 점을 제외하면 매우 비슷합니다. count Terraform은 목록 또는 개체의 각 멤버에 대해 새 리소스를 만듭니다. 루프 인덱스 대신 목록의 내용에 액세스할 수 있다는 점을 제외하면 설정한 count = length(list) 경우와 비슷합니다.

이 방법은 항목 목록이나 단일 개체 모두에 적용됩니다. 다음 예제에서는 ID가 id-0 id-1 와 인 리소스 두 개를 만듭니다.

variable "ids" { default = [ { id = "id-0" }, { id = "id-1" }, ] } resource "example_resource" "example_resource_name" { # If your list fails, you might have to call "toset" on it to convert it to a set for_each = toset(var.ids) id = each.value }

다음 예시에서는 푸들 스파키를 위한 리소스와 치와와인 플러피를 위한 리소스 두 개도 생성합니다.

variable "dogs" { default = { poodle = "Sparky" chihuahua = "Fluffy" } } resource "example_resource" "example_resource_name" { for_each = var.dogs breed = each.key name = each.value }

count.index를 사용하여 루프 인덱스에 카운트 단위로 액세스할 수 있는 것처럼, for_each 루프에서도 각 객체를 사용하여 각 항목의 키와 값에 액세스할 수 있습니다. for_each는 목록과 객체를 모두 반복하기 때문에 각 키와 값을 추적하기가 약간 혼란스러울 수 있습니다. 다음 표는 for_each 메타 인수를 사용하는 다양한 방법과 각 반복에서 값을 참조하는 방법을 보여줍니다.

for_each 유형 첫 번째 반복 두 번째 반복
A
[“poodle”, “chihuahua”]
each.key = "poodle" each.value = null
each.key = "chihuahua" each.value = null
B
[ { type = "poodle", name = "Sparky" }, { type = "chihuahua", name = "Fluffy" } ]
each.key = { type = “poodle”, name = “Sparky” } each.value = null
each.key = { type = “chihuahua”, name = “Fluffy” } each.value = null
C
{ poodle = “Sparky”, chihuahua = “Fluffy” }
each.key = “poodle” each.value = “Sparky”
each.key = “chihuahua” each.value = “Fluffy”
D
{ dogs = { poodle = “Sparky”, chihuahua = “Fluffy” }, cats = { persian = “Felix”, burmese = “Morris” } }
each.key = “dogs” each.value = { poodle = “Sparky”, chihuahua = “Fluffy” }
each.key = “cats” each.value = { persian = “Felix”, burmese = “Morris” }
E
{ dogs = [ { type = “poodle”, name = “Sparky” }, { type = “chihuahua”, name = “Fluffy” } ], cats = [ { type = “persian”, name = “Felix” }, { type = “burmese”, name = “Morris” } ] }
each.key = “dogs” each.value = [ { type = “poodle”, name = “Sparky” }, { type = “chihuahua”, name = “Fluffy” } ]
each.key = “cats” each.value = [ { type = “persian”, name = “Felix” }, { type = “burmese”, name = “Morris” } ]

 

따라서 var.animals 가 E행과 같으면 다음 코드를 사용하여 동물당 하나의 리소스를 만들 수 있습니다.

resource "example_resource" "example_resource_name" { for_each = var.animals type = each.key breeds = each.value[*].type names = each.value[*].name }

또는 다음 코드를 사용하여 동물당 리소스 두 개를 만들 수도 있습니다.

resource "example_resource" "example_resource_name" { for_each = var.animals.dogs type = "dogs" breeds = each.value.type names = each.value.name } resource "example_resource" "example_resource_name" { for_each = var.animals.cats type = "cats" breeds = each.value.type names = each.value.name }