
Terraform 심화: State 잠금과 동시 실행 충돌 운영
1) 버전 기준
- Terraform 릴리즈 기준: v1.14.5 (2026-02-11, GitHub Releases)
- 공식 문서 기준: State, Backends, State Locking
2) 핵심 개념
Terraform은 상태 파일(state)을 기준으로 실제 인프라와 선언된 구성을 동기화합니다. 공식 문서에서 state 잠금(locking)은 동일 상태에 대한 동시 변경을 방지하기 위한 핵심 안전장치로 설명됩니다.
- 원격 백엔드(예: S3, HCP Terraform 등)는 잠금 기능을 통해 동시 apply를 제어합니다.
- 잠금 획득 실패 시 Terraform은 apply를 중단하여 상태 손상을 방지합니다.
- 잠금 예외 상황에서는 공식 절차(강제 잠금 해제 등)를 매우 신중하게 적용해야 합니다.
3) 트레이드오프
- 강한 잠금 정책: 상태 일관성은 높아지지만 파이프라인 대기시간이 증가합니다.
- 잠금 우회 시도: 속도는 빨라질 수 있으나 state 손상 위험이 커집니다.
- 단일 state 집중: 관리 단순성은 있으나 팀/서비스 규모가 커지면 병목이 발생합니다.
4) 장애 재현-해결
재현 시나리오
- 동일 workspace/state에 대해 파이프라인 A와 B가 동시에
terraform apply실행 - A가 잠금을 획득
- B는 lock 획득 실패 오류로 중단
해결 절차
- CI에서 동일 state 대상 작업을 직렬화합니다.
- backend 잠금 기능이 활성화되어 있는지 점검합니다.
- 장시간 점유가 반복되면 state 분리(서비스/환경 단위)를 검토합니다.
- 실제 고아 잠금(stale lock)만 공식 지침에 따라 해제합니다.
5) 체크리스트
- [ ] 원격 backend와 잠금 기능이 활성화되어 있는가?
- [ ] 동일 state 대상 apply가 직렬 실행되는가?
- [ ] force-unlock 실행 기준과 승인 절차가 있는가?
- [ ] state 파일 분리 기준(서비스/환경/팀)이 정해져 있는가?
- [ ] 잠금 실패 로그를 운영 지표로 수집하는가?
6) 공식 링크
- Terraform State Overview: https://developer.hashicorp.com/terraform/language/state
- State Locking: https://developer.hashicorp.com/terraform/language/state/locking
- Terraform Backends: https://developer.hashicorp.com/terraform/language/backend
- Terraform Releases: https://github.com/hashicorp/terraform/releases
7) 실전: S3 Backend + DynamoDB 잠금 설정
AWS에서 가장 널리 쓰이는 원격 백엔드 구성입니다. S3에 상태 파일을 저장하고, DynamoDB 테이블로 잠금을 관리합니다.
# backend.tf
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/network/terraform.tfstate"
region = "ap-northeast-2"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
# DynamoDB 잠금 테이블 생성 (한 번만 실행)
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
tags = {
Purpose = "Terraform State Locking"
}
}
8) 고아 잠금(Stale Lock) 진단 및 해제
CI/CD 파이프라인이 비정상 종료되면 잠금이 남아있을 수 있습니다. 이때 무조건 force-unlock 하지 말고 반드시 원인을 확인한 뒤 해제해야 합니다.
# 1. 잠금 상태 확인 — 에러 메시지에 Lock ID가 표시됨
terraform plan
# Error: Error acquiring the state lock
# Lock Info:
# ID: a1b2c3d4-e5f6-...
# Path: terraform.tfstate
# Operation: OperationTypeApply
# Who: runner@ci-node-3
# Created: 2026-02-27 10:15:30 UTC
# 2. 해당 CI 작업이 실제로 종료되었는지 확인
# (다른 팀원이 apply 중일 수 있음!)
# 3. 확인 후 강제 해제
terraform force-unlock a1b2c3d4-e5f6-...
# 4. DynamoDB에서 직접 확인 (필요시)
aws dynamodb get-item
--table-name terraform-locks
--key '{"LockID":{"S":"my-terraform-state/prod/network/terraform.tfstate"}}'
9) State 분리 전략: 모놀리스 vs 서비스별
팀이 커지면 단일 state 파일은 병목이 됩니다. 서비스/계층별로 state를 분리하면 동시 작업이 가능해지고, blast radius(장애 영향 범위)도 줄어듭니다.
| 전략 | 장점 | 단점 |
|---|---|---|
| 단일 State | 간단, 리소스 간 참조 용이 | 동시 작업 불가, plan 느림 |
| 환경별 분리 | dev/staging/prod 독립 배포 | 환경 간 참조 시 data source 필요 |
| 서비스별 분리 | 팀 병렬 작업, blast radius 최소 | data source/output 연결 복잡 |
# 서비스별 분리 시 다른 state 참조 방법
data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "my-terraform-state"
key = "prod/network/terraform.tfstate"
region = "ap-northeast-2"
}
}
# 네트워크 state에서 VPC ID 참조
resource "aws_instance" "app" {
subnet_id = data.terraform_remote_state.network.outputs.private_subnet_id
# ...
}
10) 관련 글
- Terraform Variables 가이드 — state와 함께 변수 관리 전략을 잡으면 인프라 코드 품질이 올라갑니다.
- Terraform lifecycle 가이드 — prevent_destroy와 create_before_destroy로 state 변경 시 리소스 보호 전략을 세우세요.
- Terraform Modules 가이드 — 모듈 단위로 state를 분리하는 실전 패턴을 다룹니다.