본문 바로가기
  • lakescript
스터디 이야기/Terraform

[T101] 2-4. Terraform - 반복문(count)

by lakescript 2024. 6. 22.
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_iam_user" "example" {
  name = "neo"
}

 

더보기

이 스터디는 CloudNet@에서 진행하는 T101 스터디를 참여하면서 공부하는 내용을 기록하는 블로그 포스팅입니다.

CloudNet@에서 제공해주는 자료들과 테라폼으로 시작하는 IaC 를 바탕으로 작성되었습니다.

 
 

반복문

list 형태의 값 목록이나  Key-Value 형태의 문자열 집합인 데이터가 있는 경우 동일한 내용에 대해 테라폼 구성 정의를 반복적으로 하지 않고 관리할 수 있습니다. 

Count

resource 또는 module 블록에 count 값이 정수인 인수가 포함된 경우 선언된 정수 값만큼 리소스나 모듈을 생성하게 됩니다. count에서 생성되는 참조값은 count.index이며, 반복하는 경우 0부터 1씩 증가해 index가 부여됩니다. 
 

resource "local_file" "abc" {
  count		 = 5
  content	 = "abc"
  filename	 = "${path.module}/abc.txt"
}

 
위와 같은 코드를 작성한 후 terraform apply를 실행합니다.
 

 
의도대로라면 5개의 파일이 생성되어야 하지만 파일명에는 변함이 없기 때문에 결과적으로 하나의 파일만 존재하게 됩니다. (하나의 파일을 5번 수정하는 결과) count를 사용하는 경우 반복되는 정의로 인해 문제가 되는 값이 있는지 주의해야 합니다.
 

resource "local_file" "abc" {
  count		 = 5
  content	 = "abc"
  filename	 = "${path.moudle}/abc${count.index}.txt"
}

 
위와 같이 filename에 count.index를 넣어 파일을 생성하는 방식으로 코드를 수정하고 terraform apply를 실행합니다.
 

 
파일명이 count.index로 생성되기 때문에 5개의 파일이 생성되는 것을 확인하실 수 있습니다.
 
하지만 여러 resource나 module의 count로 지정되는 수량이 동일해야 하는 상황이 있습니다. 이 경우 count에 부여되는 정수 값을 외부 변수에 식별되도록 구성할 수 있습니다. 

variable "names" {
  type	 	= list(string)
  default 	= ["a", "b", "c"]
}

resource "local_file" "abc" {
  count 	= length(var.names)
  content 	= "abc"
  # index 활용
  filename 	= "${path.module}/abc-${var.names[count.index]}.txt"
}

resource "local_file" "def" {
  count = length(var.names)
  content = local_file.abc[count.index].content
  # element 활용
  filename = "${path.module}/def-${element(var.names, count.index)}.txt"
}

 
local_file.abc와 local_file.def는 var.names에 선언되는 값에 영향을 받아 동일한 개수 만큼 생성하게 됩니다. local_file.def의 경우 local_file.abc와 개수가 같아야 content에 선언되는 인수 값에 오류가 없을 것이므로 서로 참조되는 리소스와 모듈의 반복된 정의에 대해 공통적으로 영향을 주는 변수로 관리(variable 활용)할 수 있습니다.
 

count로 생성되는 리소스의 경우 <리소스 타입>.<이름>.[<인덱스 번호>], 모듈의 경우 module.<module 이름>[<인덱스 번호>]로 해당 리소스의 값이 참조 됩니다.

 
 
모듈 내에 count 적용이 불가능한 선언이 있으므로 주의해야 합니다. 

  • provide 블록 선언부가 포함되어 있는 경우에는 count 적용이 불가능
  • 외부 변수가 list 타입인 경우 중간에 값이 삭제되면 인덱스가 줄어들어 의도했던 중간 값에 대한 리소스만 삭제되는 것이 아니라 이후의 정의돈 리소스들도 삭제되고 재생성

list 형태의 값 변경

배열 중간 값을 변경할 때 의도하지 않은 결과 발생하니 유의 하셔야 합니다.
variable "names" {
  type = list(string)
  default = ["a", "c"]
}

resource "local_file" "abc" {
  count 	= length(var.names)
  content 	= "abc"
  # index 활용
  filename 	= "${path.module}/abc-${var.names[count.index]}.txt"
}

resource "local_file" "def" {
  count = length(var.names)
  content = local_file.abc[count.index].content
  # element 활용
  filename = "${path.module}/def-${element(var.names, count.index)}.txt"
}

 
위에서 작성했었던 main.tf 코드에서 변수를 수정하고, terraform plan를 수행하면 index 번호 1과 2에 해당하는 리소스 4개가 삭제되고 2개를 새로 만드는 것을 확인하실 수 있습니다. 

 
list 형태의 배열 중간 값 하나의 삭제로 2개의 리소스가 영향을 받는 결과를 확인하실 수 있습니다. 즉, count 사용 시 목록 중간 항목을 제거하면 테라폼은 해당 항목 뒤에 있는 모든 리소스를 삭제한 다음 해당 리소스를 처음부터 다시 만들게 됩니다.
 

실습 - IAM 사용자 생성하기

count를 활용하여 IAM 사용자 생성하는 실습을 진행해보도록 하겠습니다.

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

resource "aws_iam_user" "example" {
  name = "lake"
  count = 3
}

 
위와 같이 count를 resource 내에 지정하여 terraform plan을 실행해보겠습니다. 

plan 결과로는 3개가 생성된다(3 to add)로 표기되지만 name이 "lake" 하나이기 때문에 3번 덧붙여 생성되게 됩니다.

terraform apply 실행 시 lake already exists 라는 오류 문장을 확인 가능합니다.
 
그렇다면 어떻게 count를 정의하고 그 갯수만큼 resource를 생성할 수 있을까요?
 

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

resource "aws_iam_user" "example" {
  name = "lake-${count.index}"
  count = 3
}

이렇게 name에 ${count.index}를 넣어주어 count의 index마다 이름을 지정되게 설정합니다.

그 후 terraform apply를 실행하게되면 위의 사진에서 보이시는 것 처럼 lake-0, lake-1, lake-2count.index에 맞게 resource가 생성된 것을 확인하실 수 있습니다.

aws iam list-users | jq

의도한 대로 생성된 것인지 확인하기 위해 aws cli 명령어를 통해 확인해보도록 하겠습니다.

 
정상적으로 lake-0, lake-1, lake-2의 IAM User가 생성된 것을 확인하실 수 있습니다.