EC2 인스턴스 시작 시 스크립트 자동 실행: User Data 완전 가이드
EC2 인스턴스를 띄울 때마다 Nginx 설치, 환경 변수 설정, 애플리케이션 배포를 수동으로 반복하고 있다면, User Data를 제대로 활용하지 못하고 있는 것이다. 이 글은 EC2 User Data를 사용해 인스턴스 최초 부팅 시 셸 스크립트를 자동 실행하는 방법을 실제 운영 관점에서 정리한다.
TL;DR — EC2 User Data 핵심 요약
| 항목 | 내용 |
|---|---|
| 실행 시점 | 인스턴스 최초 부팅 시 1회 (기본값) |
| 실행 주체 | root 권한으로 실행됨 |
| 스크립트 시작 | 반드시 #!/bin/bash 또는 #!/bin/sh 포함 |
| 로그 위치 | /var/log/cloud-init-output.log |
| 콘솔 입력 위치 | 인스턴스 시작 마법사 → '고급 세부 정보' → 'User Data' |
| CLI 파라미터 | --user-data file://userdata.sh |
| 크기 제한 | 최대 16KB (일반 텍스트 기준) |
EC2 User Data가 동작하는 방식
User Data는 cloud-init 데몬이 처리한다. 인스턴스가 처음 부팅될 때 cloud-init은 EC2 인스턴스 메타데이터 서비스(IMDS)에서 User Data를 가져와 실행한다. 스크립트가 #!/bin/bash로 시작하면 셸 스크립트로 처리되고, #cloud-config로 시작하면 cloud-init 네이티브 YAML 형식으로 처리된다.
중요한 점은 기본적으로 최초 1회만 실행된다는 것이다. 인스턴스를 재시작해도 User Data는 다시 실행되지 않는다. 매 부팅마다 실행하려면 별도 설정이 필요하다.
- 인스턴스 시작: EC2가 부팅 시퀀스를 시작한다.
- IMDS 조회: cloud-init이
169.254.169.254메타데이터 엔드포인트에서 User Data를 가져온다. - 스크립트 실행: root 권한으로 셸 스크립트를 실행한다.
- 로그 기록: 모든 stdout/stderr가
/var/log/cloud-init-output.log에 기록된다. - 완료 마킹: cloud-init이 실행 완료를 기록하여 재부팅 시 재실행을 방지한다.
User Data 스크립트 작성 — Nginx 설치 예제
가장 흔한 사용 사례인 Nginx 자동 설치를 기준으로 설명한다. 스크립트는 단순해 보이지만, 실제 운영에서 자주 실수하는 지점이 몇 가지 있다.
#!/bin/bash
# 패키지 목록 업데이트 — 이 단계를 빠뜨리면 패키지를 찾지 못할 수 있음
yum update -y
# Nginx 설치 (Amazon Linux 2 기준)
amazon-linux-extras install nginx1 -y
# Nginx 시작 및 부팅 시 자동 시작 등록
systemctl start nginx
systemctl enable nginx
# 간단한 확인용 페이지 생성
echo '<h1>EC2 User Data로 배포된 서버</h1>' > /usr/share/nginx/html/index.html
Amazon Linux 2023을 사용한다면 amazon-linux-extras가 없으므로 dnf install nginx -y를 사용한다.
User Data 스크립트는 인터랙티브 프롬프트 없이 실행된다.-y플래그 없이yum install nginx를 실행하면 스크립트가 사용자 입력을 기다리다 멈춘다. 자동화 스크립트에서는 항상 비대화형 옵션을 명시해야 한다.
AWS 콘솔에서 User Data 입력하는 위치
콘솔에서 인스턴스를 시작할 때 User Data 입력 위치를 처음 찾는 사람들이 의외로 많이 헤맨다. 설정이 '고급 세부 정보' 아래 숨어 있기 때문이다.
- EC2 콘솔 → '인스턴스 시작' 클릭
- AMI, 인스턴스 유형, 키 페어, 네트워크 설정을 순서대로 구성
- 페이지 하단의 '고급 세부 정보' 섹션을 펼침
- 스크롤을 내려 '사용자 데이터' 텍스트 영역을 찾음
- 셸 스크립트를 직접 붙여넣거나 파일로 업로드
- '인스턴스 시작' 버튼 클릭
AWS CLI로 User Data 지정하기
콘솔보다 CLI가 훨씬 재현 가능하고 자동화에 적합하다. run-instances 명령어에서 --user-data 파라미터로 파일을 직접 지정한다.
aws ec2 run-instances \
--image-id ami-0c55b159cbfafe1f0 \
--instance-type t3.micro \
--key-name my-key-pair \
--security-group-ids sg-0123456789abcdef0 \
--subnet-id subnet-0123456789abcdef0 \
--user-data file://userdata.sh \
--region us-east-1
file://userdata.sh를 사용하면 AWS CLI가 파일 내용을 읽어 자동으로 Base64 인코딩을 처리한다. 스크립트를 직접 문자열로 전달하면 인코딩 오류가 발생할 수 있으므로 파일 참조 방식을 권장한다.
기존 인스턴스의 User Data 수정하기
이미 실행 중인 인스턴스의 User Data를 변경해야 하는 경우가 있다. 이 작업은 인스턴스가 중지(stopped) 상태일 때만 가능하다. 실행 중인 인스턴스에서는 수정할 수 없다.
# 1단계: 인스턴스 중지
aws ec2 stop-instances \
--instance-ids i-0123456789abcdef0 \
--region us-east-1
# 2단계: 인스턴스가 완전히 중지될 때까지 대기
aws ec2 wait instance-stopped \
--instance-ids i-0123456789abcdef0 \
--region us-east-1
# 3단계: User Data 수정
# file://를 사용하면 CLI가 파일 내용을 읽어 자동으로 Base64 인코딩을 처리함
aws ec2 modify-instance-attribute \
--instance-id i-0123456789abcdef0 \
--user-data file://userdata.sh \
--region us-east-1
# 4단계: 인스턴스 재시작
aws ec2 start-instances \
--instance-ids i-0123456789abcdef0 \
--region us-east-1
User Data를 수정해도 기본적으로 재부팅 시 스크립트가 다시 실행되지는 않는다. cloud-init이 이미 실행 완료로 마킹되어 있기 때문이다. 수정된 스크립트를 실제로 실행하려면 cloud-init 캐시를 초기화해야 한다.
실제 장애 패턴: 스크립트는 성공했는데 Nginx가 안 뜨는 경우
User Data 스크립트가 오류 없이 완료됐는데도 Nginx가 응답하지 않는 상황을 겪은 적이 있다. 콘솔에서 인스턴스 상태는 '실행 중'이고, SSH 접속도 되는데 80 포트가 막혀 있었다.
처음에는 Nginx 설치 자체가 실패했다고 판단하고 /var/log/cloud-init-output.log를 확인했다. 설치 로그는 정상이었다. systemctl status nginx도 active(running)이었다.
실제 원인은 보안 그룹이었다. 인스턴스에 연결된 보안 그룹의 인바운드 규칙에 HTTP(80) 포트가 없었다. Nginx는 정상 실행 중이었지만 트래픽이 인스턴스에 도달하지 못했던 것이다. User Data 스크립트 문제로 오해하기 쉬운 네트워크 레이어 문제였다.
보안 그룹 인바운드 규칙 확인 명령어:
aws ec2 describe-security-groups \
--group-ids sg-0123456789abcdef0 \
--query 'SecurityGroups[*].IpPermissions' \
--region us-east-1
HTTP 포트가 없다면 다음으로 추가한다:
aws ec2 authorize-security-group-ingress \
--group-id sg-0123456789abcdef0 \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0 \
--region us-east-1
스크립트 실행 결과만 보지 말고, 네트워크 레이어까지 함께 확인하는 습관이 필요하다.
User Data 디버깅 — 로그 확인 방법
스크립트가 예상대로 동작하지 않을 때 가장 먼저 봐야 할 곳은 cloud-init 로그다. SSH로 인스턴스에 접속한 후 다음 명령어로 확인한다.
# User Data 실행 전체 로그 확인
sudo cat /var/log/cloud-init-output.log
# 실시간으로 로그 모니터링 (인스턴스 시작 직후 유용)
sudo tail -f /var/log/cloud-init-output.log
# cloud-init 상태 확인
sudo cloud-init status
SSH 접속 자체가 안 되는 경우에는 EC2 콘솔에서 해당 인스턴스를 선택한 후 '작업 → 모니터링 및 문제 해결 → 시스템 로그 가져오기'로 부팅 로그를 확인할 수 있다.
IAM 권한 — User Data에서 AWS API를 호출하는 경우
User Data 스크립트에서 S3에서 파일을 다운로드하거나 Secrets Manager에서 시크릿을 가져오는 경우, 인스턴스에 IAM 역할이 연결되어 있어야 한다. 스크립트 자체에 AWS 자격증명을 하드코딩하는 것은 보안상 절대 권장하지 않는다.
🔽 S3 접근을 위한 최소 권한 IAM 정책 예제 (클릭하여 펼치기)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::my-deployment-bucket/*"
}
]
}
이 정책을 EC2 인스턴스 프로파일에 연결하면, User Data 스크립트에서 aws s3 cp s3://my-deployment-bucket/app.tar.gz .와 같이 자격증명 없이 S3에 접근할 수 있다.
EC2 User Data 관련 마무리 및 다음 단계
User Data는 단순한 초기화 스크립트 이상의 역할을 한다. Auto Scaling 그룹과 결합하면 새 인스턴스가 자동으로 애플리케이션을 배포하고 로드 밸런서에 등록되는 완전 자동화 파이프라인을 구성할 수 있다. 더 복잡한 구성 관리가 필요하다면 AWS Systems Manager나 Ansible 같은 도구와 조합하는 것을 고려할 수 있다.
다음 단계로 고려할 만한 주제:
- Launch Template에 User Data를 포함시켜 Auto Scaling 그룹과 연동
- AWS Systems Manager Run Command로 실행 중인 인스턴스에 스크립트 배포
- Secrets Manager와 연동하여 User Data에서 안전하게 시크릿 참조
공식 문서: AWS EC2 User Data 공식 문서
핵심 용어 정리
| 용어 | 설명 |
|---|---|
| User Data | EC2 인스턴스 시작 시 자동 실행되는 스크립트 또는 cloud-config 데이터 |
| cloud-init | Linux 인스턴스에서 User Data를 처리하는 초기화 데몬 |
| IMDS (Instance Metadata Service) | 인스턴스가 자신의 메타데이터와 User Data를 조회하는 내부 엔드포인트 (169.254.169.254) |
| 인스턴스 프로파일 | EC2 인스턴스에 IAM 역할을 연결하는 컨테이너 객체 |
| Launch Template | 인스턴스 시작 구성을 재사용 가능하게 저장하는 EC2 리소스. User Data 포함 가능 |
댓글
댓글 쓰기