시작하며
Terraform으로 인프라를 관리하다 보면 "분명히 코드는 맞는 것 같은데 왜 안 되지?" 싶은 순간이 있습니다. 이번에는 AMI 필터링 설정 하나로 엉뚱한 이미지가 선택된 사건과, NAT Gateway와 EC2 시작 순서 때문에 SSM 연결이 안 됐던 경험을 공유해보려고 합니다.
저처럼 삽질하지 않으셨으면 하는 마음으로 정리했습니다.
문제 1: AMI 필터가 Minimal 버전을 잡아버림
문제 상황
EC2 인스턴스를 프로비저닝할 때, 항상 최신 Amazon Linux 2023 AMI를 자동으로 선택하도록 Terraform 코드를 작성했습니다.
################################################################################
# Amazon Linux 2023 AMI (최신 자동 조회)
################################################################################
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"] # ⚠️ 문제의 패턴
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
}
resource "aws_instance" "main" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = var.instance_type
subnet_id = var.private_subnet_id
vpc_security_group_ids = [var.ec2_security_group_id]
iam_instance_profile = var.ec2_instance_profile_name
monitoring = true
user_data = templatefile("${path.module}/user_data.sh.tftpl", {
project = var.project
environment = var.environment
})
root_block_device {
volume_type = "gp3"
volume_size = 30
delete_on_termination = false
tags = {
Name = "${var.project}-${var.environment}-ec2-root"
}
}
tags = {
Name = "${var.project}-${var.environment}-ec2"
}
lifecycle {
ignore_changes = [ami]
}
}
언뜻 보면 문제없어 보이지만, 실제로 이 코드를 적용했더니 의도치 않게 Minimal 버전 AMI가 선택됐습니다.
원인
al2023-ami-*-x86_64 패턴은 다음 두 가지를 모두 매칭합니다.
- al2023-ami-2023.x.x-x86_64 → 일반 버전
- al2023-ami-minimal-2023.x.x-x86_64 → Minimal 버전
most_recent = true 옵션 때문에 가장 최신 AMI가 선택되는데, 타이밍에 따라 Minimal 버전이 가장 최신으로 잡히면서 선택된 것이었습니다.
Minimal 버전은 SSM Agent를 포함한 여러 패키지가 빠져있어서, 이후 SSM 연결이나 자동화 작업에서 예상치 못한 문제가 생길 수 있습니다.
해결 방법
AMI filter의 name 패턴을 조금 더 구체적으로 수정해서 Minimal이 매칭되는 경우를 제외했습니다.
################################################################################
# Amazon Linux 2023 AMI (최신 자동 조회)
################################################################################
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-2023*-x86_64"] # ✅ 수정된 패턴
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
}
resource "aws_instance" "main" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = var.instance_type
subnet_id = var.private_subnet_id
vpc_security_group_ids = [var.ec2_security_group_id]
iam_instance_profile = var.ec2_instance_profile_name
monitoring = true
user_data = templatefile("${path.module}/user_data.sh.tftpl", {
project = var.project
environment = var.environment
})
root_block_device {
volume_type = "gp3"
volume_size = 30
delete_on_termination = false
tags = {
Name = "${var.project}-${var.environment}-ec2-root"
}
}
tags = {
Name = "${var.project}-${var.environment}-ec2"
}
lifecycle {
ignore_changes = [ami]
}
}
al2023-ami-2023* 으로 바꾸면 이름이 반드시 2023으로 시작해야 하므로 minimal이 들어간 AMI는 자연스럽게 제외됩니다.
문제 2: NAT 재생성 후 SSM 연결이 안 됨
문제 상황
비용 절약을 위해 운영 시간 외에는 EC2와 NAT Gateway를 내리도록 관리하고 있었습니다. Terraform으로 compute 모듈(EC2)과 billing 모듈(NAT Gateway)을 분리해서 관리했는데요.
어느 날 아래 순서로 인프라를 올렸더니 SSM 연결이 되지 않는 문제가 생겼습니다.
- EC2 인스턴스 실행
- NAT Gateway 생성 (terraform apply -target=module.billing)
- SSM 연결 시도 → 실패
분명히 NAT도 있고, 라우팅 테이블도 정상인데 SSM이 붙지 않았습니다. EC2를 재시작하니 바로 연결됐습니다.
원인: SSM Agent의 Backoff 메커니즘
SSM 연결 흐름은 다음과 같습니다.
EC2 부팅 → SSM Agent 자동 시작 → SSM 서비스 연결 시도
(Private Subnet이면 NAT를 통해 인터넷으로)
EC2가 먼저 부팅되면 SSM Agent가 즉시 SSM 서비스에 연결을 시도합니다. 이때 NAT가 없으면 연결에 실패하고, Agent는 Exponential Backoff 방식으로 재시도 간격을 점점 늘립니다.
처음엔 몇 초 간격으로 재시도하다가, 계속 실패하면 최대 수십 분 간격으로 늘어납니다. NAT를 나중에 올려도 Agent가 긴 대기 상태에 있어서 즉시 연결되지 않는 것이었습니다.
재시작을 하면 Agent가 새로 초기화되면서 NAT가 이미 올라가 있는 상태에서 연결을 시도하니 바로 성공하는 것이고요.
해결 방법: 시작 순서 보장
NAT Gateway를 먼저 올리고, EC2를 올려야 합니다.
# 올바른 순서
terraform apply -target=module.billing # NAT 먼저
terraform apply -target=module.compute # EC2 나중에
이 순서를 지키면 EC2 부팅 시점에 NAT가 이미 준비되어 있어서 SSM Agent가 첫 시도에 바로 연결됩니다.
main.tf에 주석으로 순서를 명시해두면 팀원 모두가 실수하지 않을 수 있습니다.
# main.tf
# ⚠️ 리소스 생성/시작 순서 주의:
# 1. module.billing (NAT Gateway) 먼저
# 2. module.compute (EC2) 나중에
# NAT 없이 EC2가 먼저 뜨면 SSM Agent backoff로 인해 연결이 지연됩니다.
배운 점
이번 경험을 통해 두 가지를 크게 느꼈습니다.
첫 번째는 와일드카드 패턴은 생각보다 넓게 매칭된다는 점입니다. *는 편리하지만, 의도하지 않은 리소스를 잡을 수 있습니다. AMI 필터처럼 most_recent와 함께 쓸 때는 특히 구체적으로 작성하는 게 안전합니다.
두 번째는 의존성이 없는 리소스도 시작 순서가 중요할 수 있다는 점입니다. Terraform은 명시적 의존성이 없으면 순서를 보장하지 않습니다. SSM Agent처럼 부팅 시 한 번만 연결을 시도하는 컴포넌트는 의존하는 인프라가 먼저 준비되어 있어야 합니다.
++ Cloudfront도 테라폼으로 운영하게되면

마지막 Pay as you go로 설정이 되는 경험을 해서 부하 테스트시 비용이 갑자기 많이 오르는 경험을 했습니다.!!
마치며
작은 설정 하나, 실행 순서 하나가 생각보다 큰 문제로 이어질 수 있다는 걸 다시 한번 느꼈습니다. 비슷한 상황에서 헤매고 계신 분들께 이 글이 도움이 됐으면 좋겠습니다.
혹시 비슷한 경험이 있거나, 더 좋은 방법을 알고 계신다면 댓글로 공유해주세요!
'Network' 카테고리의 다른 글
| 진짜 공격인 줄 알았는데 우리가 만든 장애였다 (0) | 2026.04.02 |
|---|---|
| AWS SAA-CO3 합격 후기 (0) | 2026.03.07 |
| Kind 클러스터에서 SandboxChanged 에러 해결하기: systemd와 containerd의 갈등 해소 (1) | 2026.01.20 |
| Istio로 대규모 트래픽 관리하기: 실전 적용 사례와 확장 전략 (2) | 2026.01.10 |
| EKS에서 ArgoCD로 GitOps 구축하기: 순환 의존성 해결부터 Single Sync까지 (0) | 2026.01.05 |