CertNote/ 출퇴근 학습 노트
로드맵
KOEN
CLF-C02 · FoundationalCloud Practitioner - Foundational
DVA-C02 · AssociateDeveloper - Associate
  • Week 1
    • 1.개발자 시점에서 본 AWS: 리전, 인프라, 그리고 책임의 경계
    • 2.IAM의 4대 엔터티: User, Group, Role, Policy
    • 3.STS와 정책 조건: 임시 자격증명의 깊은 세계
    • 4.AWS CLI와 SDK: 자격증명 체이닝부터 SigV4까지
    • 5.Week 1 종합: 인프라와 IAM이 만드는 신뢰의 사슬
  • Week 2
  • Week 3
  • Week 4
  • Week 5
  • Week 6
  • Week 7
  • Week 8
    • 1.CodeCommit과 CodeBuild: AWS가 그린 CI/CD의 첫 두 칸
    • 2.CodeDeploy: 배포라는 가장 위험한 순간을 안전하게
    • 3.CodePipeline: CI/CD 흐름의 지휘자
    • 4.Elastic Beanstalk: AWS가 만든 가장 친절한 PaaS
    • 5.Week 8 종합 복습: CI/CD 파이프라인을 머릿속에서 끝까지 돌려보기
  • Week 9
  • Week 10
  • Week 11
  • Week 12
  • Week 13
SAA-C03 · AssociateSolutions Architect - Associate
SOA-C02 · AssociateCloudOps Engineer - Associate
SAP-C02 · ProfessionalSolutions Architect - Professional
DOP-C02 · ProfessionalDevOps Engineer - Professional
SCS-C03 · SpecialtySecurity - Specialty
MLA-C01 · AssociateMachine Learning Engineer - Associate
AIF-C01 · FoundationalAI Practitioner - Foundational
DEA-C01 · AssociateData Engineer - Associate
MLS-C01 · SpecialtyMachine Learning - Specialty
합격 후기

© CertNote · 주간랩스

  • 소개
  • 수정 기록
  • 문의
  • 이용약관
  • 개인정보처리방침
← DVA-C02/Week 8/Day 4

기준: DVA-C02 시험 가이드·오류 제보

DVA-C02· AssociateWeek 8 · Day 4읽기 약 17분

Day 4 - Elastic Beanstalk: AWS가 만든 가장 친절한 PaaS

스타트업이 AWS를 처음 도입할 때 흔히 볼 수 있는 풍경이 있다. 개발자 두 명, 코드는 Flask 또는 Express, "일단 띄우긴 해야 하는데 ALB는 뭐고 ASG는 뭐고 IAM Role은 또 뭐야". 이런 상황을 해결하기 위해 AWS는 2011년 1월 Elastic Beanstalk를 출시했다. "코드만 zip으로 올리면 EC2·ELB·ASG·CloudWatch까지 알아서 만들어주는 PaaS"라는 약속이었다.

DVA-C02 시험에서 Beanstalk는 ECS, Lambda, App Runner와 함께 "언제 어떤 컴퓨트를 선택할지" 시나리오의 한 축으로 나온다. 특히 6가지 배포 전략의 차이, .ebextensions와 .platform의 구분, 그리고 RDS를 환경 안에 둘 때의 함정을 알아야 한다. 이번 글은 Beanstalk의 내부 구조 — 사실은 CloudFormation 위에 얹은 추상화 — 부터 시작해, 각 배포 전략이 실제로 어떻게 동작하는지를 정리한다.

Beanstalk가 풀려는 문제: Heroku식 경험을 AWS 위에

Beanstalk가 등장한 2011년은 Heroku(2007 창업, 2010 Salesforce 인수)가 PaaS 시장의 표준을 만들던 시기였다. git push heroku main 한 줄로 코드가 production에 배포되는 경험은 당시로서는 혁명적이었다. AWS는 그 경험을 자기 플랫폼 위에 가져오면서 동시에 "Heroku보다 AWS 인프라에 깊이 접근 가능하다"는 차별점을 내세웠다.

Beanstalk의 약속을 한 줄로 요약하면 "당신의 코드만 신경 쓰세요, EC2·ALB·ASG·CloudWatch·VPC는 우리가 알아서". 그러나 그 약속의 trade-off가 핵심이다 — 추상화가 잘못 새는 순간(예: 특수한 nginx 튜닝, 특정 OS 패키지 필요) Beanstalk는 갑자기 답답해진다.

Beanstalk는 EC2/ALB의 복잡성을 숨기지만, 운영 중 특수한 요구가 생기면 그 아래 layer를 직접 만져야 하고 그 순간 추상화가 깨진다. .ebextensions와 .platform이 정확히 그 "추상화의 균열"을 메우는 escape hatch다.

Beanstalk는 내부적으로 CloudFormation 스택을 생성한다. eb create 한 번이면 EC2, ALB, ASG, Security Group, IAM Role, CloudWatch Alarm 등이 정의된 CFN 템플릿이 자동 생성되고 그게 deploy된다. 즉 Beanstalk 환경 = CloudFormation 스택의 friendly UI다. 이 사실을 알면 ① 환경 삭제 시 무엇이 같이 삭제되는지 ② drift detection이 왜 가능한지 ③ Beanstalk가 만든 리소스를 CFN으로 import 가능한지를 모두 설명할 수 있다.

두 가지 환경 유형: Web vs Worker

Beanstalk 환경은 두 종류다. 같은 application 안에 둘 다 존재할 수 있고, 보통 함께 쓴다.

Web Server Environment

[Route 53 또는 Beanstalk DNS]
       │
       ▼
[Application Load Balancer]
       │
       ├── [EC2-1 (web)] ┐
       ├── [EC2-2 (web)] ├── Auto Scaling Group
       └── [EC2-N (web)] ┘
                │
                ▼
        [RDS (별도 권장)]

Worker Environment

[SQS Queue]
   │ (메시지 도착)
   ▼
[EC2 인스턴스의 SQS Daemon]
   │ (메시지를 HTTP POST로 변환)
   ▼
[애플리케이션 컨테이너 (포트 80)]

Worker 환경의 특징은 SQS Daemon이라는 별도 프로세스다. 이 daemon은 EC2 인스턴스에 미리 설치돼 있고, SQS 큐를 polling해 메시지가 오면 그것을 application의 HTTP endpoint(기본 /)에 POST로 변환해 보낸다. 즉 application은 그냥 HTTP 서버로 짜면 되고 SQS SDK를 직접 호출할 필요 없다. 이 패턴은 Heroku의 worker dyno와 같은 사상이고, "이벤트 처리와 HTTP 처리를 동일한 코드 베이스로 통일"한다는 장점이 있다.

# cron.yaml (Worker 환경에서 정기 작업)
version: 1
cron:
  - name: "daily-report"
    url: "/jobs/daily-report"
    schedule: "0 0 * * *"
  - name: "hourly-cleanup"
    url: "/jobs/cleanup"
    schedule: "0 * * * *"

SQS Daemon이 cron.yaml을 읽어 자동으로 schedule을 만들고, 시간이 되면 자기 자신의 큐에 메시지를 넣는다. 그 메시지가 다시 application HTTP로 흘러가 처리된다. 외부 cron 서비스 없이 정기 작업을 풀 수 있는 깔끔한 패턴.

Worker 환경은 ALB가 없다. SQS Daemon → EC2 local의 application으로 직접 HTTP 호출. 외부 HTTP 노출이 필요하면 Web Server Environment를 별도로 만들어야 한다. "Worker 환경에 public endpoint가 필요"라는 보기는 Web Server 환경과 혼동시키는 함정이다.

배포 전략 6종

Beanstalk의 배포 전략 표는 시험에서 중요하다. 각 전략의 "다운타임 / 배포 속도 / 비용 / 롤백 속도"를 구분할 수 있어야 한다.

전략다운타임새 인스턴스추가 비용롤백 시간적합 환경
All at once있음 (수 분)없음없음재배포 (느림)개발/저비용
Rolling없음없음없음재배포일반 production
Rolling with additional batch없음일부 추가약간 ↑재배포용량 유지 필요
Immutable없음새 ASG 통째2배 (일시)빠름 (ASG 삭제만)안전한 production
Traffic Splitting (Canary)없음새 ASG2배 (일시)자동 (CloudWatch alarm)점진적 검증
Blue/Green (수동)없음새 환경2배즉시 (URL swap)완전 분리

시나리오별 빠른 매핑은 다음과 같다.

  • "비용 최소 + 단순" → All at once
  • "일반 production" → Rolling
  • "용량 절대 안 떨어져야" → Rolling with additional batch
  • "production + 즉시 롤백" → Immutable
  • "10%만 먼저, 자동 검증" → Traffic Splitting
  • "완전히 분리된 두 환경 + 한 번에 swap" → Blue/Green

Immutable의 동작 흐름

초기:    [기존 ASG]
         [EC2 v1] [EC2 v1] [EC2 v1]   ← traffic 100%

단계 1:  [기존 ASG]              [새 임시 ASG]
         [EC2 v1] [EC2 v1] [EC2 v1]   [EC2 v2] (1개)  ← Health check 통과 대기

단계 2:                          [새 임시 ASG로 확장]
         [EC2 v1]…                    [EC2 v2] [EC2 v2] [EC2 v2]

단계 3:                          [임시 → 영구 ASG로 swap]
                                      [EC2 v2] [EC2 v2] [EC2 v2]   ← traffic 100%

단계 4:  기존 ASG 종료
                                      [EC2 v2] [EC2 v2] [EC2 v2]

Immutable의 핵심은 "단계 1에서 v2 인스턴스 1개를 먼저 띄워 health check를 통과해야 다음 단계로 진행"이라는 안전 게이트다. 만약 v2가 시작 자체가 실패하면 새 ASG가 즉시 삭제되고 기존 ASG는 그대로 — 즉 production에 영향 없음. Rolling과 결정적 차이가 여기 있다. Rolling은 기존 인스턴스를 먼저 죽이고 새 버전을 그 자리에 띄우기 때문에, 새 버전이 실패하면 그 슬롯의 용량이 사라진다.

Traffic Splitting (Canary) 동작

초기:    [ASG v1: 3대]                     트래픽 100%
         (가중치 라우팅: v1 = 100%)

단계 1:  [ASG v1: 3대] [ASG v2: 3대]      트래픽 v1 = 90%, v2 = 10%
         (지정 시간 동안 메트릭 모니터링)

성공:    [ASG v1: 0대 → 종료]
         [ASG v2: 3대]                     트래픽 100%

실패:    [ASG v2: 0대 → 종료]              자동 롤백
         [ASG v1: 3대]                     트래픽 100%

⚠️ 함정: Traffic Splitting은 Application Load Balancer의 weighted target group 기능을 활용한다. 이 기능이 없는 Classic Load Balancer로 구성된 환경에서는 동작하지 않는다. 또 Network Load Balancer로 구성된 환경도 불가. "Beanstalk + Traffic Splitting" 시나리오는 ALB를 전제로 한다.

.ebextensions vs .platform: 추상화 균열을 메우는 두 가지 방식

Beanstalk 환경 안의 EC2를 커스터마이징하려면 두 가지 방식이 있다. 시기에 따라 권장 방식이 바뀌었다.

.ebextensions (전통적, Amazon Linux 1 기반)

# .ebextensions/01_packages.config
packages:
  yum:
    git: []
    jq: []
    htop: []
 
files:
  "/etc/nginx/conf.d/custom.conf":
    mode: "000644"
    owner: root
    group: root
    content: |
      client_max_body_size 50M;
 
commands:
  01_npm_install:
    command: "npm install -g pm2"
 
container_commands:
  01_migrate:
    command: "python manage.py migrate"
    leader_only: true   # ASG 중 한 대에서만 실행 (DB 마이그레이션 등)
 
option_settings:
  aws:elasticbeanstalk:application:environment:
    DJANGO_SETTINGS: production
  aws:autoscaling:asg:
    MinSize: '2'
    MaxSize: '10'
  aws:elasticbeanstalk:environment:proxy:
    ProxyServer: nginx

.ebextensions 파일은 알파벳 순서로 실행된다. 그래서 보통 01_xxx.config, 02_xxx.config처럼 prefix로 순서를 강제한다. commands는 application 코드 압축 풀기 전에, container_commands는 압축 풀기 후에 실행된다는 차이가 있다. DB 마이그레이션처럼 application 코드가 풀려 있어야 가능한 작업은 container_commands에 두는 게 정답.

leader_only: true는 Auto Scaling Group의 인스턴스 중 정확히 한 대에서만 실행되도록 보장한다. DB 마이그레이션을 모든 인스턴스에서 동시에 실행하면 race condition이 나므로 반드시 leader_only를 써야 한다. 단, 이 옵션은 초기 배포 시점에만 leader가 결정되고 그 후 새로 추가되는 인스턴스(스케일 아웃)에서는 동작하지 않는다.

.platform (Amazon Linux 2/2023, 권장)

my-app/
  .platform/
    nginx/
      conf.d/
        custom.conf           # nginx 설정 추가 (덮어쓰지 않고 추가)
    hooks/
      prebuild/
        01_install_pkg.sh     # 코드 다운로드 후, 빌드 전
      predeploy/
        01_run_migration.sh   # 빌드 후, 배포 전
      postdeploy/
        01_warm_cache.sh      # 배포 후

Amazon Linux 2 출시(2017) 이후 AWS는 .ebextensions의 일부 기능을 폐기하고 .platform/ 디렉터리 기반으로 재설계했다. 이유는 ① 더 명확한 hook 시점 분리 ② 표준 shell script로 작성 가능 ③ nginx 설정을 통째로 덮어쓰지 않고 일부만 추가 가능. .ebextensions는 여전히 동작하지만 신규 프로젝트는 .platform이 권장. AL2 환경에서는 둘 다 같이 쓸 수도 있다.

RDS 함정: 환경 안에 두면 같이 죽는다

Beanstalk 콘솔에서 "환경 만들 때 RDS도 같이 만들기" 옵션이 있다. 편리해 보이지만 production에서는 안티패턴이다.

[Beanstalk Environment]
  ├── EC2 (web)
  ├── ALB
  ├── ASG
  └── RDS    ← 환경 삭제 시 같이 삭제!

이유는 Beanstalk가 RDS를 환경의 CloudFormation 스택에 포함시키기 때문이다. eb terminate 또는 콘솔에서 환경 삭제 시 RDS도 함께 삭제된다. 데이터가 날아간다.

⚠️ 함정: "Beanstalk 환경을 삭제했더니 production 데이터가 사라졌다"는 시나리오의 원인이 이것이다. 올바른 패턴은 RDS를 Beanstalk 외부에 별도로 생성하고, 환경 변수(DB endpoint, credentials)로만 연결하는 것. 그러면 환경을 몇 번 재생성해도 DB는 안전하다.

# .ebextensions에서 외부 RDS 연결
option_settings:
  aws:elasticbeanstalk:application:environment:
    RDS_HOSTNAME: my-prod-db.cxxxx.ap-northeast-2.rds.amazonaws.com
    RDS_PORT: '5432'
    RDS_DB_NAME: myapp
    # 비밀번호는 Secrets Manager 참조

가상의 사례로, 한 SaaS 회사가 Beanstalk 환경을 staging/prod로 분리하면서 staging 환경의 RDS를 환경 안에 같이 만들었다. staging 환경을 재생성하는 과정에서 RDS가 삭제됐고, 자동 백업 덕분에 복구는 됐지만 2시간 다운타임이 발생했다. 이후 모든 RDS를 Beanstalk 외부에 두는 정책으로 전환했다.

CLI 기반 운영: eb 명령어

# 프로젝트 초기화
eb init --platform "Python 3.11 running on 64bit Amazon Linux 2023" --region ap-northeast-2
 
# 환경 생성
eb create production-env --instance-type t3.medium --elb-type application
 
# 새 버전 배포 (현재 디렉터리의 코드를 zip으로 묶어 업로드)
eb deploy
 
# 환경 변수 설정
eb setenv DB_HOST=mydb.com LOG_LEVEL=INFO
 
# 로그 보기 (CloudWatch에서 마지막 100줄)
eb logs --all
 
# SSH 접속
eb ssh
 
# Blue/Green을 위한 URL swap
eb swap production-env --destination_name staging-env
 
# 환경 삭제 (RDS 등 모든 리소스 함께)
eb terminate production-env

다른 PaaS와의 비교

차원BeanstalkHerokuGoogle App EngineAzure App Service
호스팅 모델사용자 AWS 계정의 EC2Heroku 멀티테넌트GCP 멀티테넌트 (Standard) 또는 GCE (Flexible)Azure 멀티테넌트
가격 모델EC2/ALB/RDS 표준 가격Dyno 시간당Instance 시간당Plan 시간당
인프라 접근성풀 액세스 (EC2 SSH 가능)제한적제한적 (Standard), 풀 (Flexible)제한적
Auto-scalingASG 통합Heroku autoscaler자동자동
데이터베이스RDS 외부 권장Heroku Postgres add-onCloud SQL 분리Azure SQL 분리
Custom runtime가능 (.platform)Buildpack가능 (Flexible)가능 (Custom Container)

Heroku와 Beanstalk의 가장 큰 차이는 인프라 접근성이다. Heroku는 "어떻게 인스턴스가 동작하는지는 보지 마라"는 완전 추상화고, Beanstalk는 "원하면 SSH로 들어가서 nginx 설정 직접 만져라"는 escape hatch가 있다. 이 차이가 production에서 디버깅할 때 결정적이 된다 — Heroku에서 "왜 OOM이 나는지" 알기 어렵지만 Beanstalk에서는 eb ssh로 들어가 top을 칠 수 있다.

Beanstalk를 언제 선택해야 하는가

시나리오선택
빠른 PoC, AWS 깊이 학습 시간 없음Beanstalk
표준 웹 앱 (Django, Express, Rails) + 풀 인프라 액세스Beanstalk
Docker 컨테이너 + 마이크로서비스ECS Fargate / EKS
이벤트 기반 짧은 실행, idle 시 비용 0Lambda
컨테이너지만 Kubernetes 없이 자동 스케일 + 자동 HTTPSApp Runner
HPC, GPU, 특수 인스턴스EC2 직접

2021년 출시된 AWS App Runner는 Beanstalk의 후계자 성격이 있다. "컨테이너 이미지나 소스 코드를 주면 자동으로 build + deploy + autoscale + HTTPS까지"가 App Runner의 약속인데, Beanstalk보다 더 단순하고 컨테이너 친화적이다.

정리

Beanstalk는 "AWS의 모든 인프라 복잡성을 한 명령어로 추상화"하려는 야심 찬 시도였다. 그 약속은 대체로 잘 지켜졌지만, 추상화의 균열을 메우는 .ebextensions/.platform이 결국 필요했고, RDS 같은 stateful 리소스의 라이프사이클 관리는 여전히 사용자 책임이다.

DVA-C02 시험 대비로는 6가지 배포 전략의 trade-off, Web vs Worker 환경의 차이, 그리고 "환경 안에 RDS를 두면 안 된다"는 함정을 정확히 알아 두어야 한다.

다음 글에서는 이번 주의 마지막 — CloudFormation의 내부 동작과 SAM/CDK — 을 본다.

📝 연습 문제

선택지를 클릭하면 정답·해설이 펼쳐집니다.

문제 1

Production 환경에서 다운타임 없이 가장 빠르게 롤백 가능한 Beanstalk 배포 전략은?

문제 2

Beanstalk 환경에서 DB 마이그레이션을 인스턴스 중 한 대에서만 실행하려 한다. .ebextensions 파일에서 어떤 옵션을 써야 하는가?

문제 3

Beanstalk Web Server Environment와 Worker Environment의 차이로 옳은 것은?

문제 4

Beanstalk 환경을 생성하면서 콘솔에서 "Create new RDS DB"를 체크해 같이 만들었다. 이 환경을 eb terminate로 삭제하면 어떤 일이 일어나는가?

문제 5

Amazon Linux 2 기반 Beanstalk 환경에서 nginx의 client_max_body_size를 50MB로 늘리려 한다. 권장 방식은?

문제 6

Beanstalk Traffic Splitting 배포 전략을 사용하려고 한다. 어떤 사전 조건이 필요한가?

문제 7

Beanstalk Immutable 배포 중 새 ASG의 첫 인스턴스가 헬스 체크 통과에 실패하면?

이전CodePipeline: CI/CD 흐름의 지휘자Week 8 · Day 3다음 Week 8 종합 복습: CI/CD 파이프라인을 머릿속에서 끝까지 돌려보기Week 8 · Day 5

참고 공식 자료

  • DVA-C02 공식 시험 안내(새 탭에서 열림)
  • Amazon RDS · Aurora 공식 문서(새 탭에서 열림)
  • Amazon EC2 Auto Scaling 공식 문서(새 탭에서 열림)
  • Elastic Load Balancing 공식 문서(새 탭에서 열림)
  • Amazon EC2 공식 문서(새 탭에서 열림)
  • Amazon SQS 공식 문서(새 탭에서 열림)

이 페이지

  • Beanstalk가 풀려는 문제: Heroku식 경험을 AWS 위에
  • 두 가지 환경 유형: Web vs Worker
  • Web Server Environment
  • Worker Environment
  • 배포 전략 6종
  • Immutable의 동작 흐름
  • Traffic Splitting (Canary) 동작
  • ebextensions vs .platform: 추상화 균열을 메우는 두 가지 방식
  • ebextensions (전통적, Amazon Linux 1 기반)
  • platform (Amazon Linux 2/2023, 권장)
  • RDS 함정: 환경 안에 두면 같이 죽는다
  • CLI 기반 운영: eb 명령어
  • 다른 PaaS와의 비교
  • Beanstalk를 언제 선택해야 하는가
  • 정리
  • 연습 문제