Terraform 이름 변경으로 프로덕션 데이터가 삭제된 사건이 수명 주기 관리에 대해 가르쳐 준 교훈
Source: Dev.to
위에 제공된 Source 라인 외에 번역할 텍스트가 포함되어 있지 않습니다. 번역을 원하는 본문을 제공해 주시면 한국어로 번역해 드리겠습니다.
사고 개요
It happened while I was working on a production environment.
제가 프로덕션 환경에서 작업하던 중에 발생했습니다.
I was managing a DV (data volume / database‑related resource) using Terraform. Like most production systems, the infrastructure was defined as code, and the DV was holding real data—not configuration, not metadata, but actual business data.
저는 Terraform을 사용하여 DV(데이터 볼륨 / 데이터베이스 관련 리소스)를 관리하고 있었습니다. 대부분의 프로덕션 시스템과 마찬가지로 인프라가 코드로 정의되어 있었으며, DV는 실제 데이터를 보관하고 있었습니다—구성도, 메타데이터도 아니라 실제 비즈니스 데이터였습니다.
As part of a migration and cleanup activity, I refactored my Terraform configuration. The change was simple: I renamed a few resource blocks to improve readability and structure. No values were changed. No destructive action was intended.
마이그레이션 및 정리 작업의 일환으로 Terraform 구성을 리팩터링했습니다. 변경은 간단했습니다: 가독성과 구조를 개선하기 위해 몇몇 리소스 블록의 이름을 바꿨습니다. 값은 변경되지 않았으며, 파괴적인 작업은 의도하지 않았습니다.
I ran terraform apply.
저는 terraform apply를 실행했습니다.
Result: The DV was deleted and recreated.
결과: DV가 삭제되고 다시 생성되었습니다.
Why this hit differently in production
- In dev or test environments, losing a DV is inconvenient but acceptable.
- In production, it’s a different story.
A DV is not “just infrastructure”. It holds the state of the system. Losing it means losing trust, data, and sometimes the business itself.
What bothered me the most was not the deletion—it was why it happened.
I didn’t:
- delete the resource intentionally
- change its configuration
- modify its size or type
I only changed the Terraform code structure.
Terraform interpreted that as:
“The old resource no longer exists. Create a new one.”
And from Terraform’s perspective, that interpretation was correct.
불편한 깨달음
Terraform은 의도를 이해하지 못합니다. 어떤 리소스가 “재생성해도 안전한지”와 어떤 리소스는 절대로 건드려서는 안 되는지를 알지 못합니다.
Terraform이 이해하는 것은:
- 구성
- 상태
- 라이프사이클 규칙
라이프사이클 동작을 명시적으로 정의하지 않으면, Terraform은 기본 로직을 프로덕션에서도 적용합니다.
그 깨달음은 저에게 Terraform 라이프사이클 관리를 깊이 이해하도록 만들었습니다—기능으로서가 아니라 프로덕션 안전 메커니즘으로서 말이죠.
Terraform 라이프사이클 관리란 무엇인가 (정말로)?
Terraform 라이프사이클 관리는 무언가가 변경될 때 Terraform이 어떻게 동작하는지를 제어합니다. 다음과 같은 질문에 답합니다:
- 이 리소스는 절대로 파괴되어야 할까요?
- 특정 변경을 무시해야 할까요?
- 언제 교체가 불가피한가요?
- Terraform 코드를 안전하게 리팩터링하려면 어떻게 해야 할까요?
라이프사이클 규칙은 리소스 내부의 lifecycle 블록을 사용해 정의합니다:
resource "example_resource" "demo" {
lifecycle {
# behavior rules
}
}
이 블록은 인프라를 생성하지 않습니다. Terraform의 반응을 제어합니다.
1. 교체 — Terraform이 리소스를 재구축해야 할 때
교체가 실제로 의미하는 바
교체란 Terraform이 기존 리소스를 삭제하고 새 리소스를 생성해야 함을 의미합니다.
다음과 같은 경우에 발생합니다:
- 해당 속성을 제자리에서 변경할 수 없거나,
- 클라우드 제공자가 해당 속성을 불변(immutable)으로 표시한 경우
Terraform은 여기서 우회 방법이 없습니다.
실제 프로덕션 예시 (DV / 디스크)
다음과 같이 DV를 생성합니다:
- 특정 디스크 유형
- VM에 연결
나중에 다음을 변경합니다:
- 디스크 유형
- 암호화 설정
- 연결 구성
클라우드 제공자는 이러한 변경을 제자리에서 허용하지 않습니다. Terraform plan은 다음과 같이 표시합니다:
-/+ resource will be replaced
- 기존 DV 파괴
+ 새 DV 생성
이 DV에 프로덕션 데이터가 들어 있다면, 데이터가 사라집니다.
기억해야 할 핵심 규칙
다음 한 가지 질문을 하세요: 클라우드 제공자가 이 속성을 리소스를 삭제하지 않고 업데이트할 수 있나요?
- 예 → 업데이트
- 아니오 → 교체
2. replace_triggered_by — 교체를 원할 때
때때로 교체가 필수는 아니지만 원하는 경우가 있습니다.
실제 시나리오: 보안 또는 불변성
- DV 또는 VM이 비밀에 의존
- 비밀이 변경됨
- 인프라 자체는 여전히 동작
- 하지만 깔끔한 재구축을 원함
Terraform에 명시적으로 알려줄 수 있습니다:
lifecycle {
replace_triggered_by = [
some_secret_resource
]
}
“이 종속성이 변경되면 이 리소스를 재구축합니다.”
일반적인 사용 사례:
- 불변 인프라
- 보안‑민감 시스템
- 제어된 재구축 워크플로
3. ignore_changes — 외부 시스템과의 충돌 방지
Terraform은 단일 진실 소스가 되기를 기대합니다. 실제 프로덕션에서는 이것이 거의 불가능합니다.
실제 프로덕션 예시
DV 또는 스토리지 리소스에 다음과 같은 상황이 존재합니다:
- 정책에 의해 추가된 태그
- 다른 팀이 업데이트하는 메타데이터
- 모니터링 도구가 삽입하는 값
Terraform은 이를 드리프트로 인식하고 되돌리려 하며, 실제로 문제가 없는데도 지속적인 차이가 발생합니다.
해결책: ignore_changes
lifecycle {
ignore_changes = [tags]
}
“나는 여전히 이 리소스를 관리하지만, 이 필드들은 신경 쓰지 않겠습니다.”
Terraform은 다음을 수행합니다:
- 시끄러운 플랜 표시 중지
- 외부 변경을 덮어쓰지 않음
- CI/CD 파이프라인을 안정화
중요한 주의사항
핵심 구성은 절대 무시하지 마세요.
잘못된 예:
ignore_changes = all
이렇게 하면 Terraform의 제어가 완전히 사라집니다. ignore_changes는 다음과 같은 경우에만 사용하세요:
- 변경이 자동으로 이루어짐
- 다른 시스템이 소유자임
- 되돌리는 것이 불필요하거나 해로움
4. Terraform 코드 리팩터링 — 숨겨진 프로덕션 위험
많은 프로덕션 사고가 여기서 발생합니다.
무해해 보이는 작업
가독성을 위해 리소스 블록 이름을 바꾸는 경우:
resource "example_dv" "old_name" { }
→
resource "example_dv" "new_name" { }
값은 전혀 바뀌지 않았고, DV 이름도 동일하며, 구성도 동일합니다.
Terraform이 생각하는 방식
Terraform은 리소스를 resource_type.resource_name 으로 식별합니다. 따라서 다음과 같이 인식합니다:
old_name→ 삭제 → 파괴new_name→ 새로 생성 → 생성
Terraform은 이것이 리팩터링이라는 사실을 알지 못하고, 삭제와 새로운 생성으로 처리합니다.
요점
-
Never rely on implicit behavior in production. Explicitly define lifecycle rules for any resource that must survive refactors or external changes.
→ 프로덕션에서는 절대 암시적 동작에 의존하지 마세요. 리팩터링이나 외부 변경에도 살아남아야 하는 모든 리소스에 대해 라이프사이클 규칙을 명시적으로 정의하십시오. -
Use
replace_triggered_byfor intentional rebuilds (e.g., secret rotation).
→ 의도적인 재구성을 위해replace_triggered_by를 사용하세요 (예: 비밀 회전). -
Use
ignore_changessparingly, only for fields truly owned elsewhere.
→ 실제로 다른 곳에서 관리되는 필드에 대해서만ignore_changes를 최소한으로 사용하십시오. -
When renaming resources, use the
terraform state mvcommand to tell Terraform that the underlying resource is the same:terraform state mv \ 'example_dv.old_name' \ 'example_dv.new_name'This preserves the state entry and prevents unwanted replacement.
→ 이렇게 하면 상태 엔트리를 보존하고 원하지 않는 교체를 방지합니다. -
Treat Terraform as a production safety mechanism, not just a convenience tool. Explicit lifecycle management is essential to protect critical data.
→ Terraform을 편리한 도구가 아니라 프로덕션 안전 메커니즘으로 다루세요. 명시적인 라이프사이클 관리가 중요한 데이터를 보호하는 데 필수적입니다.
결과
Destroy DV
Create new DV
프로덕션 환경에서는 이는 데이터 손실을 의미합니다.
moved Blocks — Safe Refactoring
안전하게 리팩터링하려면 Terraform state awareness를 업데이트해야 합니다.
moved {
from = example_dv.old_name
to = example_dv.new_name
}
Terraform에 다음을 알려줍니다:
“Same resource. New logical name.”
Terraform은 다음을 수행합니다:
- state 업데이트
- not 리소스 파괴
- not 리소스 재생성
다음 상황에서 필수적입니다:
- 리팩터링
- 모듈 재구성
- 계정 마이그레이션
prevent_destroy — 데이터를 어떤 대가를 치르더라도 보호
데이터를 보유하는 리소스는 삭제가 절대 우연히 일어나서는 안 됩니다.
lifecycle {
prevent_destroy = true
}
Terraform은 이제 terraform destroy를 거부합니다:
- 삭제를 시도하는 플랜은 실패합니다
- 의도적인 개입이 필요합니다
다음에 사용하세요:
- DVs
- 데이터베이스
- 상태 저장소
- 중요한 백업
create_before_destroy — 다운타임 감소 (교체가 필요할 때)
교체가 불가피할 때, 이는 영향을 줄이는 데 도움이 됩니다.
lifecycle {
create_before_destroy = true
}
Terraform은 다음을 수행합니다:
- 새 리소스를 먼저 생성합니다
- 의존성을 새 리소스로 전환합니다
- 이전 리소스를 삭제합니다
유용한 경우:
- 무상태 서비스
- 로드‑밸런싱된 워크로드
⚠️ 이름 지정이나 연결 제한 때문에 데이터 리소스에서는 항상 가능한 것은 아닙니다.
모두 합쳐 보기 — 정신 모델
Terraform 라이프사이클 관리는 한 가지 질문에 답합니다:
“변경이 발생했을 때 Terraform은 어떻게 동작해야 할까요?”
| 시나리오 | 라이프사이클 도구 |
|---|---|
| 불변 변경 | Replacement |
| 강제 재구축 | replace_triggered_by |
| 외부 드리프트 | ignore_changes |
| 리팩터링 및 이름 변경 | moved |
| 중요한 데이터 | prevent_destroy |
| 다운타임 위험 | create_before_destroy |
Final Thoughts
Terraform은 매우 강력하지만—그만큼 문자 그대로입니다.
당신이 명시적으로 방법을 알려주지 않는 한 데이터는 보호되지 않습니다.
수명주기 관리는 고급 기능이 아니라 프로덕션 요구사항이며, 특히 데이터를 보유하는 리소스에 해당합니다.
내 프로덕션 사고는 Terraform이 실패해서 발생한 것이 아니라, 수명주기를 완전히 제어하지 못했기 때문에 발생했습니다.
이 설명이 여러분이 같은 교훈을 힘들게 배우는 일을 피하는 데 도움이 되길 바랍니다.