About/IaC

[Terraform] count 문법 (Meta-Agument)

김징어 2022. 6. 11. 12:45

Terraform을 사용하면서 여러 개의 리소스를 생성해야하는 경우가 있습니다. 예를 들어 3개의 IAM User를 생성해야하는 경우 다음과 같이 Terraform 코드를 작성할 수 있다.

provider "aws" {
	region = "ap-northeast-2"
}

resource "aws_iam_user" "user_1" {
  name = "user-1"
}

resource "aws_iam_user" "user_2" {
  name = "user-2"
}

resource "aws_iam_user" "user_3" {
  name = "user-3"
}

 

하지만 생성해야하는 리소스의 수가 100, 1000개 등으로 많아질 경우에 Terraform 코드가 너무 길어질 수 있으며 소스코드가 복잡해지고 수정이 어려워집니다.

이 때 Terraform의 countfor_each와 같은 모듈을 사용하여 반복적으로 리소스를 생성할 수 있습니다.

Count Meta Argument


https://www.terraform.io/language/meta-arguments/count

 

The count Meta-Argument - Configuration Language | Terraform by HashiCorp

Count helps you efficiently manage nearly identical infrastructure resources without writing a separate block for each one.

www.terraform.io

count는 Terraform 0.13에서 추가되었으며 이전 버전에서는 리소스와 함께만 사용할 수 있습니다.

공식문서에서 count에 대한 설명은 다음과 같습니다.

리소스 또는 모듈 블록에 값이 정수인 count 인수가 포함된 경우 Terraform은 그만큼 많은 인스턴스를 생성합니다.

Basic Syntax


count 메타 인수는 정수를 허용하고 리소스 또는 모듈의 많은 인스턴스를 만듭니다. 각 인스턴스에는 연결된 고유한 인프라 개체가 있으며 구성이 적용될 때 각각 별도로 생성, 업데이트 또는 소멸됩니다.

또한 count는 meta argument로 소스코드는 resource body의 최상단에 위치하도록 함

resource "aws_instance" "server" {
  count = 4 # create four similar EC2 instances

  ami           = "ami-0225bc2990c54ce9a" # Ubuntu
  instance_type = "t2.micro"

  tags = {
    Name = "Server ${count.index}"
  }
}

 

The Count Object

In blocks where count is set, an additional count object is available in expressions, so you can modify the configuration of each instance. This object has one attribute:

count가 설정된 블록에서 count 객체를 사용할 수 있고, count 객체를 이용하여 각 인스턴스의 구성을 수정할 수 있습니다. 이 객체에는 하나의 속성이 있습니다.

  • count.index — 인스턴스에 해당하는 고유한 인덱스 번호(0부터 시작).
  tags = {
    Name = "Server ${count.index}"
  }

 

위의 예시에서 인스턴스의 Name tag에 count.index 속성을 사용하였고, count=4 이므로 count.index는 0~3의 값을 가집니다.
따라서 생성되는 인스턴스의 Name 태그를 출력해보면 다음과 같습니다.

Changes to Outputs:
  + server-name = [
      + "Server 0",
      + "Server 1",
      + "Server 2",
      + "Server 3",
    ]

 

Referring to Instances

count가 설정되면 Terraform은 블록 자체와 블록과 연결된 여러 리소스 또는 모듈 인스턴스를 구별합니다. 인스턴스는 0부터 시작하는 인덱스 번호로 식별됩니다. 

예를 들어 Output을 통해서 Server Name을 출력할 때 다음과 같이 인스턴스를 참조할 수 있습니다.

# index 0번 인스턴스의 Name tag
output server-name0 {
  value = aws_instance.server[0].tags.Name
}

# index 1번 인스턴스의 Name tag
output server-name1 {
  value = aws_instance.server[1].tags.Name
}

# count로 생성한 모든 인스턴스의 Name tag
output server-name-all {
  value = aws_instance.server.*.tags.Name
}

 

Output은 다음과 같습니다.

Changes to Outputs:
  + server-name-all = [
      + "Server 0",
      + "Server 1",
      + "Server 2",
      + "Server 3",
    ]
  + server-name0    = "Server 0"
  + server-name1    = "Server 1"

 

Count Module 사용시 주의할 점

count 모듈을 사용할 때도 주의할 점이 있습니다. 

예를 들어 다음과 같이 회사의 직원에 대해 AWS IAM 계정을 100개 생성하는 코드가 있다고 가정합니다.

provider "aws" {
	region = "ap-northeast-2"
}

resource "aws_iam_user" "count" {
  count = 100
  name = "count-user-${count.index}" # count-user-0 ~ count-user-99
}

 

총 100개의 IAM User 계정을 쉽게 생성하였는데 만약에 50번의 IAM User에 해당하는 직원이 퇴사를 해서 해당 IAM User의 계정을 삭제해야하는 경우를 생각해보면 문제가 조금 복잡해질 수 있습니다. 직원이 99명이 되었기에 count=99가 될 것이고, 직원에 대한 Index들이 바뀌게 되어 문제가 생길 수 있습니다.(직원의 IAM User가 삭제된다던가, 직원들의 Index가 잘못 할당된다던가..)

따라서 index로 리소스를 구분하여도 상관이 없을 때 count 를 사용하는 것이 좋을 것 같습니다. 예를 들면 로드밸런서로 트래픽을 분산할 EC2 인스턴스를 생성할 때는 server0, server1 등 번호를 사용해도 문제가 되지 않을 것 같습니다.

그렇다면 위와 같은 경우에는 어떻게 100명의 IAM User를 생성하는 것이 좋을까요?

이 때 Terraform의 for_each 라는 Meta-Argument를 적절하게 사용할 수 있습니다. 다음 포스팅에서 이에 관해 다루어 보도록 하겠습니다.


Terraform Meta Argument 중 count에 대하여 알아보았습니다.