[IaC] Terraform State: backend, locking, drift, import
terraform.tfstate, S3 backend, state locking, DynamoDB lock, drift detection, terraform import, state rm
정의
Terraform State = 코드 (의도) vs 실제 인프라 매핑. JSON 파일. 모든 Terraform 작업의 핵심. plan, apply, destroy 모두 state 를 기반으로 diff 계산.
사용 상황
| 상황 | Terraform State 주요 고려사항 |
|---|---|
| 팀 협업 | Remote backend 필수 (S3/TFC), local file 금지 |
| 여러 환경 분리 | Workspace 또는 별도 backend key |
| 기존 인프라 도입 | terraform import 로 state 등록 |
| 인프라 드리프트 감지 | terraform plan -refresh-only 정기 실행 |
| 대규모 모노리식 state | 레이어별 state 분할 전략 |
| Secret 관리 | output sensitive + aws-secrets-manager 또는 Vault |
State 가 하는 일
flowchart LR
Code["main.tf<br/>(의도)"] --> Plan
State["terraform.tfstate<br/>(알려진 실제)"] --> Plan
Real["AWS 실제"] --> Refresh
Refresh --> State
Plan --> Diff[Diff]
Diff --> Apply[apply]
Apply --> Real
Apply --> State
| 역할 | 의미 |
|---|---|
| Mapping | resource 이름 ↔ AWS ARN/ID |
| Metadata | 의존성 그래프, 버전 정보 |
| Performance | refresh 캐시 (매번 AWS API 호출 안 해도 됨) |
| Sensitive | output value 보관 (평문) |
State 파일 내부 구조
{
"version": 4,
"terraform_version": "1.8.0",
"serial": 42,
"lineage": "550e8400-...",
"outputs": {
"vpc_id": {
"value": "vpc-0abc123",
"type": "string",
"sensitive": false
}
},
"resources": [
{
"mode": "managed",
"type": "aws_s3_bucket",
"name": "data",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"id": "my-data-bucket",
"bucket": "my-data-bucket",
"region": "us-east-1"
}
}
]
}
]
}
serial: apply 마다 증가. 충돌 감지.lineage: state 파일 고유 ID. 다른 state 교체 방지.sensitive출력값도 JSON 에 평문 저장. Backend 암호화 필수.
Backend 종류
flowchart TB
B[Backend]
B --> Local[local file<br/>팀 사용 금지]
B --> S3["S3 + DynamoDB lock<br/>(AWS 표준)"]
B --> TFC["Terraform Cloud / HCP Terraform"]
B --> GCS[GCS]
B --> Azure[Azure Blob]
B --> Consul[Consul]
S3 + DynamoDB (AWS 표준)
terraform {
backend "s3" {
bucket = "my-tf-state"
key = "prod/web/terraform.tfstate"
region = "us-east-1"
encrypt = true
kms_key_id = "arn:aws:kms:us-east-1:123:key/..."
dynamodb_table = "tf-lock"
}
}
| 컴포넌트 | 역할 |
|---|---|
| S3 bucket | state 저장 + versioning 활성화 |
| KMS | server-side 암호화 |
| DynamoDB | distributed lock (conditional write) |
State Locking
sequenceDiagram
Dev1->>Lock: acquire (DynamoDB CAS)
Lock-->>Dev1: OK
Dev1->>State: write
Dev2->>Lock: acquire
Lock-->>Dev2: 이미 잠겨있음
Dev1->>Lock: release
Dev2->>Lock: acquire
Lock-->>Dev2: OK
동시 apply 충돌 방지. DynamoDB 의 conditional write (CAS: Compare-And-Swap).
Lock 강제 해제 (비정상 종료 후):
terraform force-unlock LOCK_ID
Drift Detection
# 코드 변경 없이 실제 vs state 차이만 확인
terraform plan -refresh-only
| 상황 | 원인 | 대응 |
|---|---|---|
| state < 실제 | 콘솔 직접 수정 | terraform refresh + 코드 반영 |
| state > 실제 | 수동 삭제 | terraform state rm 후 재적용 |
| 정기 감지 | 드리프트 자동화 | CI 에서 plan -refresh-only 스케줄링 |
Prod 수동 변경 감지. 정기 drift check 는 CI 파이프라인에 포함.
State 분할 전략
flowchart TD
Mono["모노리식 State<br/>(모든 리소스 한 파일)"]
Split["레이어별 State 분할"]
Mono --> Split
Split --> Net["network/<br/>VPC, Subnet, Route"]
Split --> Compute["compute/<br/>EKS, EC2, ASG"]
Split --> App["app/<br/>Lambda, RDS, ElastiCache"]
Split --> Shared["shared/<br/>IAM, KMS, ECR"]
| 레이어 | 예시 리소스 | 변경 빈도 |
|---|---|---|
| network | VPC, Subnet, Route Table | 매우 낮음 |
| shared | IAM Role, KMS Key, ECR | 낮음 |
| compute | EKS, EC2, Auto Scaling | 중간 |
| app | Lambda, RDS, ElastiCache | 높음 |
분할 이점: plan 시간 단축, 블라스트 반경 감소, 팀별 소유권 분리.
분할 방법: terraform_remote_state 로 다른 state 의 output 참조.
data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "my-tf-state"
key = "prod/network/terraform.tfstate"
region = "us-east-1"
}
}
resource "aws_eks_cluster" "main" {
vpc_config {
subnet_ids = data.terraform_remote_state.network.outputs.private_subnet_ids
}
}
State 조작 명령
terraform state list # 모든 리소스 목록
terraform state show aws_s3_bucket.data # 단일 리소스 상세
terraform state mv old.name new.name # rename (리팩토링 시)
terraform state rm aws_s3_bucket.old # state 에서만 제거 (AWS 실제 리소스 남음)
terraform state pull > backup.tfstate # state 다운로드 (백업)
terraform state push backup.tfstate # state 업로드 (위험, 수동)
terraform import aws_instance.web i-1234abcd # 기존 리소스를 state 에 등록
CAUTION
state push 는 serial 번호 역전 방지 없이 덮어씀. 잘못된 state 로 인프라 삭제 위험.
Import (기존 리소스 등록)
CLI import (Terraform 1.5+)
import {
to = aws_s3_bucket.legacy
id = "my-legacy-bucket"
}
resource "aws_s3_bucket" "legacy" {
bucket = "my-legacy-bucket"
}
# 코드 자동 생성
terraform plan -generate-config-out=generated.tf
terraform apply
구버전 CLI import
terraform import aws_s3_bucket.legacy my-legacy-bucket
코드는 직접 작성. import 후 terraform plan 으로 drift 없는지 확인.
Workspace (환경 분리)
terraform workspace new prod
terraform workspace new staging
terraform workspace select prod
terraform workspace list
locals {
env = terraform.workspace # "prod" / "staging"
}
resource "aws_instance" "web" {
instance_type = local.env == "prod" ? "c5.xlarge" : "t3.small"
}
한 backend 에 여러 state 관리. 단, separate backend (별도 S3 key) 가 더 안전. Workspace 는 동일 AWS 계정에서 사용 → 실수로 Prod 에 staging 적용 위험.
Terragrunt 연계
Terraform 의 DRY wrapper. 여러 환경/레이어의 중복 backend 설정 제거.
# terragrunt.hcl
remote_state {
backend = "s3"
config = {
bucket = "my-tf-state-${get_aws_account_id()}"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "tf-lock"
}
}
environments/
prod/
network/ ← terragrunt.hcl 상속
compute/
app/
staging/
network/
compute/
CI/CD 연계
| 단계 | 명령 | 설명 |
|---|---|---|
| PR | terraform plan | diff 리뷰, 변경 범위 확인 |
| Merge | terraform apply -auto-approve | 자동 적용 |
| 정기 | terraform plan -refresh-only | drift 감지 |
| 공유 | plan 결과를 PR comment 로 | Atlantis / Spacelift / TFC |
Atlantis 나 Terraform Cloud 는 PR 이벤트에 plan 자동 실행 + 승인 후 apply.
State 의 위험
WARNING
- State 의 secret 평문 =
terraform output의 password 등 그대로. 접근 제한 + KMS + IAM. - 수동 state 편집 = 형식 깨짐 위험. 반드시
terraform state명령 사용. - State 손실 = 추적 불가 (코드와 실제 매핑 소실). S3 versioning + 정기 백업.
- 여러 사람 동시 apply = lock 없으면 state 깨짐. DynamoDB lock 필수.
- Local backend 를 팀이 공유 = git 에 state 올리면 secret 노출 + 충돌. Remote backend 전환.
관련 위키
- terraform
- aws-s3
- aws-kms
- aws-iam
- aws-cloudtrail (state 변경 감사)
이 글의 용어 (6개)
- [AWS] CloudTrail (API Activity Logging)cloud
- 정의 AWS CloudTrail 은 AWS 계정의 API 호출 및 사용자 활동을 기록 하는 감사 로깅 서비스입니다. "누가, 언제, 어디서, 어떤 API 를, 어떤 리소스에 대해…
- [AWS] IAM: User, Role, Policy, STScloud
- 정의 IAM (Identity and Access Management) = AWS 의 권한 관리 전부. User, Group, Role, Policy 로 구성. "누가 어떤 리소…
- [AWS] KMS: 암호화 키 관리, envelope encryptioncloud
- 정의 KMS (Key Management Service) = 암호화 키 중앙 관리. envelope encryption + IAM 통합 + 감사 로그. 키 종류 | 종류 | 의미…
- [AWS] S3: object storage, storage classes, lifecyclecloud
- 정의 S3 = AWS 의 object storage. bucket + key + object. 11 9's durability (99.999999999%), 무한 확장. 2026…
- [AWS] Secrets Manager + Parameter Storecloud
- 정의 AWS Secrets Manager = 회전이 필요한 비밀 (DB 패스워드, API key) 을 안전하게 저장/관리하는 서비스. Lambda 기반 자동 회전과 암호화 내장.…
- [IaC] Terraform: HCL, provider, statecloud
- 정의 Terraform = 선언적 인프라 코드. HCL (HashiCorp Configuration Language) 로 리소스 정의 → AWS/GCP/Azure 등 provid…
💬 댓글