15장. AMI와 이미지 기반 배포
이 장에서 말하고자 하는 것
EC2를 한 대 띄울 때 우리는 다음을 선택했다.
- 운영체제
- 인스턴스 타입
- 스토리지
그런데 운영체제는 어디서 오는가?
미리 준비된 디스크 이미지에서 온다.
AMI (Amazon Machine Image)
다.
AMI는 EC2의 “디스크 + 설정 묶음” 이다.
같은 AMI로 띄우면 어디서든 같은 모양의 서버가 만들어진다.
이 장은 AMI의 구조와 운영 활용을 본다.
1. AMI는 무엇을 담고 있는가
AMI
├─ 운영체제 (Amazon Linux · Ubuntu · Windows 등)
├─ 미리 설치된 소프트웨어
├─ 디스크 스냅샷 (루트 볼륨 + 추가 볼륨)
├─ 부팅 설정
└─ 권한 정보 (누가 이 AMI를 쓸 수 있는지)
EC2를 생성할 때
"AMI ami-xxxx → 인스턴스 타입 t3.small → ..."
이 AMI가 곧 새 EC2의 출발점이다.
2. AMI의 종류
1. AWS 제공 AMI
Amazon Linux 2023, Ubuntu LTS, Windows Server 등 OS 벤더 표준 이미지.
처음 띄울 때 거의 항상 여기서 시작
2. 마켓플레이스 AMI
서드파티가 만들어 판매하는 이미지 (예: Bitnami WordPress).
3. 커뮤니티 AMI
누구나 공개한 이미지.
운영에는 절대 쓰지 않는다 — 출처 불명, 보안 위험
4. 본인의 커스텀 AMI
직접 만들어 등록한 이미지.
운영의 자리는 보통 여기
3. 왜 커스텀 AMI를 만드는가
EC2를 띄울 때마다 OS · 패치 · 에이전트 · 애플리케이션을 처음부터 깔면
- 시작이 느리다 (수 분 ~ 십수 분)
- 매번 결과가 미묘하게 다를 수 있다
- 실패 가능 지점이 많다
미리 다 준비된 AMI를 만들어 두면
- 인스턴스 시작이 빠르다 (수십 초)
- 동일한 상태로 매번 시작
- Auto Scaling이 신규 인스턴스를 즉시 합류시킬 수 있다
이 사고방식이 Immutable Infrastructure (불변 인프라) 다.
4. AMI를 만드는 두 가지 방법
1. 실행 중인 EC2에서 스냅샷
EC2를 만들고 설정한 뒤 콘솔에서 “Create Image” 클릭.
- 빠르고 단순
- 사람이 손으로 한 작업이 그대로 박힘
- 재현성이 낮다
2. 자동화된 빌드 (Packer)
HashiCorp Packer로 코드(JSON/HCL)로 정의한 AMI 빌드.
1. 임시 EC2 띄움
2. 정의된 프로비저닝 스크립트 실행 (Ansible · Shell)
3. 스냅샷 만들고 AMI로 등록
4. 임시 EC2 정리
- 재현 가능
- 코드 리뷰 가능
- CI에서 자동 빌드
운영의 자리는 거의 항상 Packer
5. 컨테이너 시대의 AMI
EC2 직접 운영에서는 AMI가 핵심이지만,
이 책의 척추(ECS Fargate) 에서는 AMI를 거의 안 만진다.
EC2 시대: AMI → EC2 → 애플리케이션 배포
컨테이너: Dockerfile → 이미지 → 컨테이너
대신
- ECS on EC2 — ECS 최적화 AMI를 쓴다 (AWS가 관리)
- 일부 데이터 / GPU 워크로드는 여전히 직접 AMI
“AMI = EC2판 컨테이너 이미지” 로 이해하면 사고방식이 자연스럽다
6. AMI 운영의 규칙
□ 베이스 OS는 AWS 공식 또는 사내 검증된 것만
□ 태그로 버전 · 빌드 시각 · 커밋 해시 박기
□ AMI 이름에 환경 · 용도 명시 (web-prod-2026-01-15-sha-abc)
□ 오래된 AMI 정기 정리 (수명 주기)
□ 리전마다 AMI ID가 다름 — 멀티 리전이면 각 리전에 복사
□ KMS 암호화 (운영 AMI는 거의 항상)
7. 우리 서비스에서
이 책의 척추는 ECS Fargate라 AMI 직접 운영은 거의 없다.
대신 다음 경우에 만난다.
- ECS on EC2 (Fargate가 아닌 클러스터)
→ ECS-Optimized AMI (AWS 제공) 사용
- 데이터/GPU 워크로드 (예: ML 학습 노드)
→ 커스텀 AMI (Packer로)
- Bastion · 운영용 워크스테이션
→ 사내 표준 AMI
8. 직접 확인해보기 — CLI
최신 Amazon Linux 2023 AMI 찾기
aws ec2 describe-images \
--owners amazon \
--filters "Name=name,Values=al2023-ami-2023.*-x86_64" \
"Name=state,Values=available" \
--query 'reverse(sort_by(Images, &CreationDate))[:1].[ImageId,Name]' \
--output table
본인 AMI 목록
aws ec2 describe-images --owners self
EC2에서 AMI 만들기
aws ec2 create-image \
--instance-id i-xxx \
--name "web-prod-2026-01-15" \
--description "build sha-abc123" \
--no-reboot
--no-reboot 는 운영 중인 인스턴스 재부팅 없이 만들지만,
파일 시스템 일관성이 살짝 약해질 수 있다.
9. 코드로는 이렇게 생겼다 — Packer + Terraform
Packer로 AMI 빌드
source "amazon-ebs" "web" {
region = "ap-northeast-2"
source_ami_filter {
filters = {
name = "al2023-ami-2023.*-x86_64"
virtualization-type = "hvm"
root-device-type = "ebs"
}
owners = ["amazon"]
most_recent = true
}
instance_type = "t3.small"
ssh_username = "ec2-user"
ami_name = "web-{{ timestamp }}"
encrypt_boot = true
kms_key_id = "alias/prod-storage"
tags = {
Name = "web"
BuildSha = "${var.git_sha}"
Environment = "prod"
}
}
build {
sources = ["source.amazon-ebs.web"]
provisioner "shell" {
inline = [
"sudo dnf update -y",
"sudo dnf install -y nginx",
"sudo systemctl enable nginx",
]
}
}
Terraform에서 AMI 사용
data "aws_ami" "web" {
most_recent = true
owners = ["self"]
filter {
name = "name"
values = ["web-*"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.web.id
instance_type = "t3.small"
subnet_id = aws_subnet.private_a.id
...
}
새 AMI가 빌드되면 다음 Terraform Apply에 자동으로 반영된다.
10. 이렇게 쓰면 망한다 — 안티패턴
안티패턴 1. 사람이 콘솔에서 EC2를 띄우고 손으로 설정
재현 불가능. 다음 사람이 같은 환경을 못 만든다.
Packer + 프로비저닝 스크립트로 코드화
안티패턴 2. AMI 이름이 “web-final-final-v2”
어느 게 진짜인지 모른다.
타임스탬프 · 커밋 해시로 자동 이름
안티패턴 3. 옛 AMI를 안 정리한다
수십 개의 옛 AMI + 스냅샷이 누적 → 청구서
AWS Backup · 수명 주기 매니저로 자동 정리
안티패턴 4. 커뮤니티 AMI를 운영에 쓴다
검증되지 않은 코드가 들어 있을 수 있다.
11. 한 줄로 정리
AMI는 EC2의 디스크 이미지이며,
Packer로 코드화해 만들면 컨테이너 이미지와 비슷한 운영이 가능하다
12. 이 장의 핵심 정리
- AMI는 EC2를 띄울 때의 OS + 디스크 + 설정 묶음이다.
- AWS 공식 AMI에서 시작하고, 커스텀이 필요하면 Packer로 코드화.
- Immutable Infrastructure — 인스턴스를 바꾸지 말고 새 AMI로 띄운다.
- ECS Fargate에서는 AMI를 거의 만지지 않는다.
- 이름 · 태그 · 정리 · 암호화가 운영의 기본이다.
- AMI는 리전마다 별도 — 멀티 리전은 복사 필요.