count
- 기본적으로 resource blockdms 실제 하나의 인프라 객체를 의미
- 유사한 객체를 여러개의 block으로 관리하지 않고 하나의 block으로 관리할 때 사용
resource "aws_instance" "server_1" {
ami = "ami-a1b2c3d4"
instance type = "t2.micro"
tags = {
Name = "Server 1"
}
}
resource "aws_instance" "server_2" {
ami = "ami-a1b2c3d4"
instance type = "t2.micro"
tags = {
Name = "Server 2"
}
}
⬇️
resource "aws_instance" "server" {
count = 2
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
tags = {
Name = "Server %{count.index}"
}
}
output "server_1" {
value = aws_instance.server[1]
}
for_each
- 값이 map, set으로 구성된 argument에 대한 처리가 필요한 경우에 사용
resource "aws_iam_user" "todd" {
name = "Todd"
}
resource "aws_iam_user" "james" {
name = "James"
}
⬇️
resource "aws_iam_user" "the-accounts" {
for_each = toset( ["Todd", "James", "Alice", "Dottie"] )
name = each.key
}
resource "azurermm_resource_group" "rg" {
for_each = {
a_group = "eastus"
another_group = "westus2"
}
name = each.key
location = each.value
}
상태 저장소 (backend)
backend란?
- terraform은 영구적인 state data 파일을 계속 관리해야함
- backend = state data 파일이 저장되는 위치
backend 종류
- local: disk(HDD, SSD). 기본 설정
- remote
- Terraform Cloud
- AWS S3
- Kubernetes secret
- Postgres DB
- Gitlab
remote backend 문제점
- S3와 같이 누구든 볼 수 있는 저장소라면 민감정보(pw, key)는 분리가 필요
- 민감정보는 환경변수로 분리하여 backend-config 옵션을 통해서 사용하는것을 권장
상태 관리
- terraform은 인프라나 설정에 대해서 무조건 state(상태)로 저장함
- state는 기본적으로 terraform.tfstate 라는 로컬 파일에 저장됨
- backend가 remote인 경우에는 환경마다 다름
- state는 terraform 으로 선언된 설정과 실제 인프라 객체를 매핑하기 위해 존재함
- 즉, state가 없으면 terraform 으로 인프라 관리를 할 수 없음
state 파일시스템 문제점
- state 파일이 저장된 위치의 성능에 따라서 terraform 성능에 영향이 발생함
- plan/apply 실행 시 매번 로컬에 저장된 state와 API로 호출된 값을 비교
- -refresh=false 옵션을 통해서 로컬에 저장된 state만으로 비교 가능
- remote backend 사용 시 환경에 따라서 추가 지연 발생 가능
S3 문제점
- 하나의 terraform module을 여러명이 관리할 때 state 파일을 공유해야함
- 하지만 S3와 같은 파일시스템을 사용할 경우에 동시에 동일한 state 파일에 접근한다면 충돌이 발생
- state 파일도 손상 및 인프라 설정 꼬임 발생
- state locking 하기 위해서는 dynamoDB 설정도 추가가 필요함
state 파일 분리
- 여러개의 환경을 관리할 때 locking이 발생하여 수정을 못하는 경우가 발생
- A가 운영환경에 배포하는 동안 locking이 발생하여 B는 개발환경 테스트가 불가능
- 환경별로 상태 파일을 분리가 필요
- 디렉토리를 분리 (환경별로 root module 생성)
- workspace 분리
리소스 강제 교체
- terraform taint / untaint
- 강제로 리소스를 재생성하는 방법
- Elastic IP 재생성, 비정상적인 리소스 처리를 위해 사용
- 현재는 deprecated 되었으며 아래 명령어로 대체됨
terraform apply -replace="aws_instance_example[0]"
workspace
- 환경에 따라서 state를 관리하고자 할 때 사용하는 기능
- workspace 별로 state가 별도로 저장됨
- 일부 backend만 multiple workspace 지원
- kubernetes
- Local
- Postgres
- Remote (Terraform Cloud)
- S3
backend
- 개인 (소규모) 프로젝트: local
- 협업이 필요하거나 팀 단위 관리가 필요한 경우: Terraform Cloud, Gitlab
- 다중 환경/계정 사용시 = 다중 workspace, S3 (+ dynamoDB)
- backend 설정에서는 표현식이나 변수 사용이 불가능하므로 단일 버킷 사용 권장
- terraform cli 옵션 중 -backend-config를 통해서 값을 바꿀 수 있음
- 다중계정으로 S3 사용 시 assume role을 통해서 다른 계정에 접근
- S3 cross account 설정을 통해서 사용할 경우, 운영계정의 access key 관리를 위한 정책이 필요
- 되도록 운영계정은 role base로 운영
workspace
- 환경 분리, 다중 계정 관리: workspace
- 다중 계정과 환경을 한번에 관리
- terraform은 동일한 환경을 재사용할 때 유리
- 테스트하기 위해서 개발환경이 있는데 개발/운영 환경이 달라진다면
- workspace를 쓰기보다는 sub(child) module로 분리
directory
- 파일은 최대한 분리
- 큰 서비스(애플리케이션)는 sub module
- module화의 장점: 개념적으로 분리하기 쉬워짐 (label name을 짧게 가능)
- sub module이 너무 커지면 프로젝트로 분리
- module 간에 output으로 참조하던 부분은 data로 처리
- sub module state import/export는 공식적인 지원 X
- 환경 (dev/prd) 별로 sub module로 나누는 방식은 권장 X