인프라를 레벨업하기: Terraform의 Lifecycle Meta-arguments 마스터하기
Source: Dev.to
Introduction
AWS 챌린지의 9일 차이며, 오늘은 어제 다룬 주제인 Terraform lifecycle 메타‑인수에 대해 심화합니다. 이번 깊이 있는 탐구에서는 인프라스트럭처 코드의 가장 중요한 측면 중 하나인 리소스 라이프사이클을 제어하는 방법을 다룹니다. Terraform의 기본 동작은 많은 경우에 충분하지만, 실제 운영 환경에서는 무중단 업데이트를 구현하고, 중요한 데이터를 보호하며, 복잡한 하이브리드 관리 시나리오를 처리하기 위해 정밀한 제어가 필요합니다.
create_before_destroy – The Zero‑Downtime Hero
Terraform는 기본적으로 새 리소스를 만들기 전에 기존 리소스를 파괴합니다. 이 경우 서비스 중단이 발생할 수 있습니다. create_before_destroy = true 로 설정하면 순서가 뒤바뀝니다:
- How it works: Terraform가 먼저 새 리소스를 생성하고, 종속성을 업데이트한 뒤(예: 로드 밸런서의 타깃 그룹) 기존 리소스를 파괴합니다.
- Use case: 로드 밸런서 뒤에 있는 EC2 인스턴스나 읽기 복제본이 있는 RDS 인스턴스와 같이 무중단 배포가 필수적인 리소스에 적합합니다. 간단하고 자동화된 블루/그린 배포 전략을 가능하게 합니다.
resource "aws_instance" "blog_server" {
# ... resource arguments ...
lifecycle {
create_before_destroy = true
}
}
prevent_destroy – The Production Guardrail
이 안전 기능은 중요한 리소스(예: 프로덕션 데이터베이스 또는 민감한 S3 버킷)의 실수로 인한 삭제를 방지합니다.
- How it works:
prevent_destroy = true로 설정하면 해당 리소스를 대상으로 하는 모든terraform destroy명령이 오류와 함께 실패합니다. - Use case: RDS, 중요한 S3 버킷, ECR/EC2 키 페어와 같은 상태를 유지하는 리소스를 보호합니다. 삭제하려면 인수를 일시적으로 주석 처리하는 등 의도적인 수동 단계가 필요합니다.
resource "aws_s3_bucket" "critical_data" {
# ... arguments ...
lifecycle {
prevent_destroy = true
}
}
ignore_changes – Accepting External Management
외부 시스템이나 사람이 리소스 속성을 수정하면 Terraform가 지속적으로 변경을 되돌리려 시도하면서 드리프트가 발생할 수 있습니다.
- How it works: Terraform가 변경을 감지할 때 무시할 속성을 지정합니다.
- Use case: 자동 스케일링 정책에 의해 관리되는 Auto Scaling Group의
desired_capacity나 모니터링 에이전트가 추가한 EC2 인스턴스 태그와 같은 속성을 무시합니다.
resource "aws_autoscaling_group" "example_asg" {
# ... arguments ...
lifecycle {
ignore_changes = [
desired_capacity,
tags,
]
}
}
replace_triggered_by – Forced Replacement
다른 리소스가 변경될 때, 자체 구성은 변하지 않았더라도 종속 리소스를 교체해야 할 경우가 있습니다.
- How it works: 지정된 종속 리소스가 교체되면
replace_triggered_by를 포함한 리소스도 함께 교체됩니다. - Use case: 보안 그룹이 변경될 때마다 EC2 인스턴스를 재생성하도록 강제하여 불변 인프라 패턴을 지원합니다.
resource "aws_security_group" "app_sg" {
# ... arguments ...
}
resource "aws_instance" "app_with_sg" {
# ... arguments ...
vpc_security_group_ids = [aws_security_group.app_sg.id]
lifecycle {
replace_triggered_by = [
aws_security_group.app_sg.id,
]
}
}
Validation with precondition and postcondition
이 인수들을 사용하면 리소스 생성 전후에 조직 표준을 강제할 수 있습니다.
precondition – Pre‑Deployment Sanity Checks
- How it works: Terraform이 빌드를 시작하기 전에 반드시
true로 평가되어야 하는 조건을 정의합니다. 조건이 거짓이면 사용자 정의 오류 메시지와 함께 배포가 실패합니다. - Use case: AWS 리전이 승인된 목록에 포함되어 있는지 확인하거나, 필수 환경 변수가 존재하는지 검증합니다.
postcondition – Post‑Deployment Verification
- How it works: 리소스가 생성되거나 업데이트된 후에 실행되어 최종 속성(
self.attribute)을 검사합니다. - Use case: 중요한 태그(예:
Compliance또는Environment)가 적용됐는지 확인하거나, 모듈 출력이 예상 형식과 일치하는지 검증합니다.
resource "aws_dynamodb_table" "example" {
# ... arguments ...
precondition {
condition = contains(keys(var.resource_tags), "Environment")
error_message = "Critical table must have Environment tag for compliance!"
}
postcondition {
condition = self.billing_mode == "PAY_PER_REQUEST" || self.billing_mode == "PROVISIONED"
error_message = "Billing mode must be either PAY_PER_REQUEST or PROVISIONED!"
}
}
Key Takeaway
lifecycle 블록은 모든 리소스에 적용되는 것은 아니지만, 대규모 인프라를 관리할 때는 절대 빼놓을 수 없습니다. 적절히 사용하면 불안정하고 위험한 업데이트를 방지하고, 견고하고 협업 가능한, 규정 준수와 무중단 배포 파이프라인을 구현할 수 있습니다.