CFN 연동 도구
cfn-init: CloudFormation이 EC2 인스턴스에서 리소스를 초기화할 때 사용하는 헬퍼 스크립트입니다.cfn-signal: EC2 인스턴스가 성공적으로 프로비저닝되었는지를 CloudFormation에 알릴 때 사용됩니다.cfn-hup: EC2 인스턴스에서 메타데이터 변경을 감지하고 재적용하는 데 사용하는 데몬입니다.cfn-response: Lambda 함수에서 CloudFormation 커스텀 리소스에 대한 응답을 보낼 때 사용하는 모듈입니다.
사용자 데이터
EC2 인스턴스가 부팅될 때 실행되는 초기 스크립트
보통 웹 서버 설치, 설정 스크립트, 초기 파일 구성 등에 사용
CloudFormation에서 사용자 데이터 전달하는 법
필수: CloudFormation 템플릿에서 UserData는 Base64로 인코딩되어야 하므로 !Base64 사용.
예제 (YAML 형식)
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId: ami-0abcdef1234567890 # 지역에 맞는 AMI로 변경
SecurityGroupIds:
- !Ref MySecurityGroup
UserData:
Fn::Base64: !Sub |
#!/bin/bash
dnf update -y
dnf install -y httpd
systemctl enable httpd
systemctl start httpd
echo "Hello World from CloudFormation" > /var/www/html/index.html
사용자 데이터의 한계와 문제점
| 문제 | 설명 |
|---|---|
| 가독성 | 사용자 데이터에 쉘 스크립트를 직접 작성하면 길어지고 복잡해짐 |
| 유지보수 어려움 | 변경이나 상태 유지가 어려움 |
| 상태 비저장 | 인스턴스를 중지하고 다시 시작하면 사용자 데이터가 다시 실행되지 않음 |
| 상태 확인 어려움 | 성공 여부 확인이 불편하며, 로그는 직접 봐야 함 (/var/log/cloud-init-output.log) |
해결책: CloudFormation + cfn-init
MyInstance:
Type: AWS::EC2::Instance
Metadata:
AWS::CloudFormation::Init:
config:
packages:
yum:
httpd: []
files:
/var/www/html/index.html:
content: |
<h1>Hello from cfn-init</h1>
mode: '000644'
owner: root
group: root
services:
sysvinit:
httpd:
enabled: true
ensureRunning: true
Properties:
ImageId: ami-0abcdef1234567890
InstanceType: t2.micro
SecurityGroupIds:
- !Ref MySecurityGroup
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y aws-cfn-bootstrap
/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} \
--resource MyInstance --region ${AWS::Region}
Metadata에 선언된 이 부분이 cfn-init의 실행 대상 구성
| 장점 | 설명 |
|---|---|
| 💡 가독성 향상 | 구성 요소를 구조적으로 YAML로 작성 가능 |
| 🔧 복잡한 설정 관리 | 패키지 설치, 사용자 생성, 파일 배포, 서비스 실행 등 다양한 작업을 분리 가능 |
| 🧩 유연한 상태 구성 | cfn-hup과 연계하면 상태 변화 감지도 가능 |
| 📋 로그 추적 | /var/log/cfn-init.log, /var/log/cfn-init-cmd.log 등으로 명확한 로그 추적 가능 |
예시 코드: cfn-signal 포함된 템플릿
Resources:
MyInstance:
Type: AWS::EC2::Instance
Metadata:
AWS::CloudFormation::Init:
config:
packages:
yum:
httpd: []
files:
/var/www/html/index.html:
content: |
<h1>Hello from cfn-signal!</h1>
services:
sysvinit:
httpd:
enabled: true
ensureRunning: true
CreationPolicy:
ResourceSignal:
Timeout: PT2M
Count: 1
Properties:
ImageId: ami-0abcdef1234567890
InstanceType: t2.micro
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum install -y aws-cfn-bootstrap
/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} \
--resource MyInstance --region ${AWS::Region}
INIT_STATUS=$?
/opt/aws/bin/cfn-signal -e $INIT_STATUS \
--stack ${AWS::StackName} \
--resource MyInstance \
--region ${AWS::Region}
전체 프로세스
- CloudFormation 스택 생성 시작
- EC2 인스턴스가 생성되며
UserData에서cfn-init실행 cfn-init실행 결과를 변수에 저장cfn-signal로 CloudFormation의WaitCondition에 신호 전송- CloudFormation은 신호를 받아 스택 생성을 계속 진행하거나 실패로 처리
실패 원인
| 원인 | 설명 |
|---|---|
| AMI 문제 | 사용하는 AMI에 cfn-init, cfn-signal 등 부트스트랩 도구가 포함되지 않았을 수 있음 |
| 인터넷 연결 | 인스턴스가 사설 서브넷에 있고, NAT 게이트웨이 없이 외부 인터넷 접근 불가하면 cfn-signal 전송 실패 |
| 사용자 스크립트 오류 | UserData 스크립트나 cfn-init 설정 중 exit 1 등 오류 코드 반환 시 실패 |
| 롤백 설정 | 디폴트 설정은 실패 시 자동으로 인스턴스를 삭제함 → 디버깅 어려움 |
디버깅 팁: 롤백 방지
CloudFormation 스택 생성 시 “스택 실패 옵션”에서 스택 롤백 비활성화 를 반드시 체크해야 EC2 인스턴스가 삭제되지 않고 남아있어 SSH 접속 후 로그를 확인하고 문제를 추적할 수 있음.
중첩 스택(Nested Stack) vs 크로스 스택(Cross-Stack)
| 항목 | 중첩 스택 (Nested Stack) | 크로스 스택 (Cross-Stack Reference) |
|---|---|---|
| 📘 정의 | 하나의 템플릿 안에서 또 다른 스택을 포함 | 서로 다른 스택이 출력값을 공유 |
| 📦 구성 방식 | AWS::CloudFormation::Stack 리소스를 이용해 템플릿을 포함 |
Export, ImportValue를 통해 출력값을 참조 |
| ♻️ 재사용성 | 높은 수준의 구성 요소를 재사용 | 공통 리소스를 여러 스택에서 참조 |
| 🔄 업데이트 | 부모 스택을 업데이트하면 하위 스택도 자동 갱신 | 값 참조만 하므로 독립적인 업데이트 가능 |
| 🧹 삭제 시 | 부모 스택 삭제 시 함께 삭제됨 | 서로 독립적으로 삭제 가능 |
| 🧠 예시 | RDS 구성, 웹 서버 구성 등 하나의 기능 단위로 분리 | 공용 VPC, 공용 보안 그룹 등 공유 자원 구성 |
중첩 스택은 코드 재사용성과 구성 관리 측면에서 강력
크로스 스택은 자원 공유에 효과적
적절한 모듈화 전략을 사용하면 스택 유지보수가 쉬워지고 확장성도 높아짐
실습에서는 실제 웹 서버를 구성하고, 그 결과를 웹사이트로 확인함 (PHP + MySQL + httpd)
StackSet
StackSet은 하나의 CloudFormation 템플릿을 여러 계정과 여러 리전에 동시에 배포할 수 있는 기능
예를 들어, VPC 스택을 조직 전체에 동일하게 배포
| 항목 | 내용 |
|---|---|
| 🎯 목적 | 여러 계정/리전에 공통된 인프라 배포 |
| 🔐 권한 | 서비스 관리형 (AWS 자동 IAM 구성) 추천 조직 기반 StackSet은 서비스 관리형 권한을 사용하는 게 일반적 |
| 🧩 사용 조건 | AWS Organizations + 신뢰할 수 있는 액세스 활성화 |
| 🔁 자동성 | OU에 새 계정 추가 시 스택 자동 배포 |
| 👥 위임 관리 | 특정 OU 또는 계정에게 StackSet 관리 권한 위임 가능 |
CloudFormation 문제 해결
DELETE_FAILED
삭제 실패는 특정 리소스가 삭제되지 못해 스택 전체 삭제가 실패하는 경우
주요 원인:
- S3 버킷: 버킷이 비워지지 않음 → 수동 비우기 또는 Lambda + Custom Resource로 자동 비우기
- 보안 그룹: 아직 다른 리소스 (예: EC2 인스턴스)가 사용 중이라 삭제 불가
- 종속성 있는 리소스가 삭제되지 않음
DeletionPolicy: Retain설정된 리소스는 삭제되지 않음
ROLLBACK_FAILED
스택 업데이트 도중 오류가 발생했고, 롤백도 실패한 경우
주요 원인:
- 외부에서 수동 변경된 리소스
- 권한 부족
- Auto Scaling Group이 새 인스턴스를 띄우기 위한 리소스를 찾지 못함
- 외부 시스템 또는 리소스 의존성 문제
해결 팁:
- CloudFormation 콘솔에서 이벤트 로그 확인 → 오류 원인 찾기
- 수동으로 리소스를 수정하여 상태를 정상화
- CLI 또는 콘솔에서
ContinueUpdateRollback호출
StackSet 문제 해결
StackSet은 다수의 계정+리전에 동시에 배포되므로 더 복잡하고 예외 처리가 많음
주요 원인:
- IAM 권한 부족: 대상 계정에 충분한 권한이 없음
- 신뢰 관계 문제: StackSet 관리 역할과 실행 역할의 trust relationship 누락
- 리소스 이름 중복: 예: S3 버킷 이름은 글로벌 고유 →
bucket-${AWS::AccountId}같은 변수 사용 - 서비스 할당량 초과: 예: EC2 인스턴스 제한
- 스택 인스턴스 상태 불일치 → 구식(Outdated), 실패 상태
해결 팁:
- 실패한 스택 인스턴스만 다시 재배포 (
retry-stack-operation) - S3 버킷, IAM Role 등 고유해야 하는 리소스에 변수 사용
- CloudFormation StackSet 콘솔 → 인스턴스 상세 상태 확인
- StackSet 작업 시 로그 필수 확인 (실패한 지역/계정 식별)
AWS Service Catalog
조직 내 승인된 리소스 템플릿(CloudFormation)을 사용자들이 셀프서비스로 배포할 수 있도록 하는 서비스
| 구성 요소 | 설명 |
|---|---|
| 제품 (Product) | CloudFormation 템플릿으로 정의된 실제 리소스 (예: EC2, RDS 등) |
| 포트폴리오 (Portfolio) | 여러 제품들을 묶은 묶음. IAM 권한을 통해 액세스를 제어 |
| 프로비저닝된 제품 (Provisioned Product) | 사용자가 실제로 배포한 제품 인스턴스 |
| 관리자 | 템플릿 작성 및 포트폴리오 구성. IAM 역할로 통제 권한 부여 |
| 사용자 | 카탈로그에 정의된 승인된 제품만 선택 및 배포 가능 |
동작 흐름
- 관리자
- CloudFormation 템플릿 작성
- 제품 생성 (Product)
- 포트폴리오 생성 + 제품 포함
- IAM을 통해 어떤 사용자가 어떤 포트폴리오에 접근 가능한지 설정
- 사용자
- AWS 콘솔 또는 포털에서 포트폴리오 접근
- 승인된 제품 중 선택
- 파라미터 입력하고 배포
- Service Catalog는 CloudFormation 기반으로 리소스를 배포
사용 이유
| 이유 | 설명 |
|---|---|
| 표준화 | 조직에서 승인된 리소스, 네이밍, 태깅 전략 강제 |
| 보안 | 사용자는 최소한의 권한만 갖고 작업 가능 |
| 컴플라이언스 유지 | 모든 리소스는 미리 정의된 템플릿을 통해서만 생성 가능 |
| 셀프 서비스 | 사용자는 별도 교육 없이도 승인된 리소스를 배포 가능 |
| 중앙 집중식 관리 | 모든 배포 현황은 Service Catalog에서 추적 가능 |
추가 기능
StackSet 제약 조건 (StackSet Constraint)
개념:
- 제품이 CloudFormation StackSet을 통해 배포되도록 구성
- 배포 가능 지역 및 타겟 계정을 제한
- 어떤 IAM 역할을 통해 배포할지도 지정
특징: - CloudFormation 자체는 지역이나 계정에 대한 제한 기능이 없음
- Service Catalog에서 StackSet 제약 조건을 추가해야 가드레일을 설정할 수 있음
런칭 제약 조건 (Launch Constraint)
개념:
- 사용자 대신 제품을 런칭할 IAM 역할을 정의
- 사용자가 리소스(EC2, RDS 등)를 직접 생성할 권한이 없어도 제품을 실행 가능하게 해줌
특징: - IAM 역할이 제품과 연결되어 있고,
- 사용자는 그 역할로 제품만 런칭할 수 있음
- 템플릿 내부 리소스 생성 권한은 역할이 책임짐
버전 제어 및 Git 연동
개념:
- 제품 정의를 코드로 관리
- AWS CodeCommit 또는 Git 리포지토리와 동기화
- Lambda 함수를 사용해 자동 업데이트 가능
구현 방법:
- 템플릿 버전을 관리하는 YAML 파일 사용 (템플릿 ↔ 제품 매핑)
- 새 템플릿을 커밋할 때 Lambda 트리거
- Lambda가 Service Catalog API 호출하여 제품 생성 또는 업데이트
-> 제품 템플릿 표준화 + DevOps 파이프라인 통합
'Web' 카테고리의 다른 글
| 대용량 트래픽이란 몇건일까 (0) | 2025.05.01 |
|---|---|
| EKS 사용해보기 (1) | 2025.04.24 |
| Route53에서 구입한 도메인 ACM발급 실패 (0) | 2025.04.19 |
| AWS DOP - CloudFormation (2) (0) | 2025.04.17 |
| AWS DOP - CloudFormation (1) (0) | 2025.04.16 |