Terraform S3 백엔드, 이제 DynamoDB 없이 락 걸자
오늘 알게 된 건데, 아직도 dynamodb_table을 백엔드에 박아둔 프로젝트가 팀 내에 꽤 남아있더라. Terraform 1.11에서 dynamodb_table, dynamodb_endpoint, endpoints.dynamodb 인자가 전부 deprecated 마크가 붙었고, HashiCorp 공식 문서에서도 "future minor version에서 제거된다"고 못 박아 뒀다. 1.12에서는 아직 안 지웠지만, 언제 사라질지 모르니 미리 정리해두는 게 낫다.
핵심은 use_lockfile = true 하나다. 2024년 말 1.10에서 실험 기능으로 들어왔던 게 이제는 안정 궤도에 올랐고, S3의 conditional write(PutObject If-None-Match) 덕분에 별도 DB 없이 락 파일 하나로 동시성 제어가 된다.
마이그레이션 순서
바로 DynamoDB를 빼면 진행 중이던 다른 사람 apply가 락을 못 잡고 이상하게 꼬일 수 있다. 그래서 나는 항상 두 단계로 나눈다.
먼저 두 옵션을 동시에 켜서 배포한다:
terraform {
backend "s3" {
bucket = "my-tfstate"
key = "prod/network.tfstate"
region = "ap-northeast-2"
dynamodb_table = "tf-lock" # 아직 둔다
use_lockfile = true # 새로 추가
encrypt = true
}
}
이 상태로 최소 하루 정도 팀 전체 apply가 정상 동작하는지 지켜본다. 그러고 나서 dynamodb_table 라인을 지우고 terraform init -migrate-state. 마지막에 DynamoDB 테이블 자체를 지운다. 순서 바꾸면 안 된다.
확인 팁
락이 실제로 걸리는지 궁금하면 apply 도중에 S3 버킷을 뒤져보면 된다. key와 같은 경로에 .tflock 오브젝트가 잠깐 생겼다 사라진다.
aws s3 ls s3://my-tfstate/prod/ | grep tflock
# prod/network.tfstate.tflock ← apply 중일 때만 보임
혹시 apply가 강제 종료돼서 lockfile이 남았다면 terraform force-unlock <LOCK_ID>로 지우면 된다. DynamoDB 시절과 명령어는 똑같다.
한 가지 놓치기 쉬운 부분. 버킷 정책에 s3:PutObject만 있고 s3:DeleteObject가 빠져 있으면 락 해제가 안 된다. 우리 팀도 스테이징에서 한 번 걸렸다. IAM 정책 다시 훑어보자.
DynamoDB 없앨 뒤로 비용은 뭐 얼마 안 되지만(월 몇 달러 수준), 관리 리소스가 하나 줄어드는 게 더 크다. state 하나 저장하려고 DynamoDB 테이블 프로비저닝하고 IAM 붙이고 하던 게 없어진다.