테라폼 코드를 사용하다보면 반복되는 리소스 생성 및 리소스에 대한 관리가 필요할 때가 있다.
적은 양의 코드면 쉽게 작성이 가능 하겠지만, 몇십명 몇십개의 리소스를 관리하게 되면 각각의 리소스 생성 코드를 만드는 것은 쉽지 않은 일이다.
이를 효율적으로 사용하기 위해서 테라폼에선 반복문을 지원한다.
다음 내용을 통해서 반복문을 익히고 효율적인 테라폼 운영을 할 수 있었으면 좋겠다.
IAM 유저를 생성하려 한다. 3명의 유저를 생성 한다면 다음과 같은 코드로 생성이 가능하다
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_1" {
name = "user-2"
}
output "user_arns" {
value = [
aws_iam_user.user_1.arn,
aws_iam_user.user_2.arn,
aws_iam_user.user_3.arn,
]
}
적은 사용자를 관리 할 경우에 위와 같은 코드로 관리가 가능하지만 다수의 사용자를 관리하기는 쉽지 않다.
이를 위해서 반복문을 통해서 많은 사용자 관리를 쉽게 할 수 있다.
meta-arguments는 resource Block Body의 최상단 {count.index}를 사용하여 인덱스 정보를 가져 올 수 있다.
resource, module, data에서 사용 가능하다.
resource "aws_iam_user" "count" {
count = 3 #meta argument
name = "count-user-${count.index}"
}
output "count_user_arns" {
value = aws_iam_user.count.*.arn
}
코드로서 3명을 생성했던 것과 다르게 count를 활용하여서 쉽게 생성 및 결과를 확인 할 수 있다.
for_each 표현식을 사용하면 리스트, 집합, 맵을 사용하여 전체 리소스의 여러 복사본 또는 리소스 내 인라인 블록의 여러 복사본을 생성 할 수 있다.
기본 구문은 다음과 같다
resource "<PROVIDER>_<TYPE>" "<NAME>" {
for_each = <COLLECTION>
[CONFIG ...]
}
resource "aws_iam_user" "for_each_set" {
for_each = toset(
"for-each-set-user-1"
"for-each-set-user-2"
"for-each-set-user-3"
)
name = each.key
}
output "for_each_set_user_arns" {
value = values(aws_iam_user.for_each_set).*.arn
}
set은 List 형식으로 받기 때문에 형변환이 필요하여 toset을 사용한다.
값을 처리 하기 위해서 each, key, each.value가 생성되어서 데이터에 접근 할 수 있다.
resource "aws_iam_user" "for_each_map" {
for_each = {
cab = {
level = "low"
manager = "man1"
}
bob = {
level = "mid"
manager = "man2"
}
louis = {
level = "high"
manager = "man2"
}
}
name = each.key
tags = each.value
}
정상적으로 생성 되면 Tag Key, Tag Value 값이 생성되어서 활용 가능 하다.
리스트를 갖는 코드에서 특정 업무를 수행하기 위해서 테라폼은 for 표현식을 제공한다
count와 for-each는 data, resource, module 에서만 사용 가능한 표현식이였다면
for 표현식은 테라폼에서 expression을 사용 가능 한 모든 곳에서 사용 가능한 문법이다.
기본 구문은 다음과 같다
[for <ITEM> in <LIST> : <OUTPUT>]
[for k, v in var.map : length(k) + length(v)]
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)]
}
다른 프로그래밍에서 제공하는 3항 연산자 사용 문법에 대해서 테라폼에서도 동일 문법으로 제공해 준다.
3항 연산자를 활용해서 원하는 조건이 true일때와 false를 구분해서 리소스 배포 및 프로세스에 대해서 정의 할 수 있다.
condition ? true_val : false_val
resource "aws_iam_user_policy_attachment" "gurumee_cloudwatch_full_access" {
count = var.give_gurumee_cloudwatch_full_access ? 1 : 0
user = aws_iam_user.example.0.name
policy_arn = aws_iam_policy.cloudwatch_full_access.arn
}
resource "aws_iam_user_policy_attachment" "gurumee_cloudwatch_read_only" {
count = var.give_gurumee_cloudwatch_full_access ? 0 : 1
user = aws_iam_user.example.0.name
policy_arn = aws_iam_policy.cloudwatch_read_only.arn
}
give_gurumee_cloudwatch_full_access 변수 값에 따라서 액세스 권한을 부여하는 코드이다.
3한 연산자 표현식과 함께 if 표현식도 제공해 준다.
프로그래밍이 익숙한 사용자라면 if 조건문이 익숙할 텐데 우리가 알고 있는 조건에 해당 할 경우 정해진 코드가 실행이 되고
그 조건에 해당하지 않을 경우 종료가 실행하지 않고 지나가거나 다른 프로세스가 실행 되게 표현 할 수 있다.
%{ if <CONDITION> }<TRUEVAL>%{ endif }
%{ if <CONDITION> }<TRUEVAL>%{ else }<FALSEVAL>%{ endif }
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
}
Outputs:
for_directive = "gasida, akbun, fullmoon, "
for_directive_index = "(0) gasida, (1) akbun, (2) fullmoon, "
for_directive_index_if = <<EOT
gasida,
akbun,
fullmoon
users = [
{
name = "john"
level = 7
role = "재무"
is_developer = false
},
{
name = "alice"
level = 1
role = "인턴 개발자"
is_developer = true
},
{
name = "tony"
level = 4
role = "데브옵스"
is_developer = true
},
{
name = "cindy"
level = 9
role = "경영"
is_developer = false
},
{
name = "hoon"
level = 3
role = "마케팅"
is_developer = false
},
]
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_group" "developer" {
name = "developer"
}
resource "aws_iam_group" "employee" {
name = "employee"
}
output "groups" {
value = [
aws_iam_group.developer,
aws_iam_group.employee,
]
}
variable "users" {
type = list(any)
}
resource "aws_iam_user" "this" {
for_each = {
for user in var.users :
user.name => user
}
name = each.key
tags = {
level = each.value.level
role = each.value.role
}
}
resource "aws_iam_user_group_membership" "this" {
for_each = {
for user in var.users :
user.name => user
}
user = each.key
groups = each.value.is_developer ? [aws_iam_group.developer.name, aws_iam_group.employee.name] : [aws_iam_group.employee.name]
}
locals {
developers = [
for user in var.users :
user
if user.is_developer
]
}
resource "aws_iam_user_policy_attachment" "developer" {
for_each = {
for user in local.developers :
user.name => user
}
user = each.key
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
depends_on = [
aws_iam_user.this
]
}
output "developers" {
value = local.developers
}
output "high_level_users" {
value = [
for user in var.users :
user
if user.level > 5
]
}
테라폼에는 다양한 반복문과 조건식에 대한 표현식이 있다.
해당하는 표현식을 운영하는 사람의 편의와 필요에 맞게 익혀서 효율적인 운영 환경에 사용 되었으면 좋겠다.