Terraform State 잠금과 충돌 운영

Terraform
요약 다이어그램(직접 생성). 본문 내용은 공식 문서 근거 기반입니다.

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) 장애 재현-해결

재현 시나리오

  1. 동일 workspace/state에 대해 파이프라인 A와 B가 동시에 terraform apply 실행
  2. A가 잠금을 획득
  3. B는 lock 획득 실패 오류로 중단

해결 절차

  1. CI에서 동일 state 대상 작업을 직렬화합니다.
  2. backend 잠금 기능이 활성화되어 있는지 점검합니다.
  3. 장시간 점유가 반복되면 state 분리(서비스/환경 단위)를 검토합니다.
  4. 실제 고아 잠금(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) 관련 글

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux