On this page
EBS vs EFS: AWS 스토리지 비교
EBS(블록 스토리지)와 EFS(네트워크 파일 시스템)를 언제 써야 하는지 정리.
마스터 노드 하나와 워커 노드 둘로 구성된 Airflow 클러스터를 굴리고 있었어요. 개발자가 마스터에서 DAG 파일을 업데이트하니까 스케줄러가 새 버전을 집어서 워커에 태스크를 보냈는데, 태스크가 실패했어요. 워커는 여전히 옛날 버전 DAG를 돌리고 있었거든요. 파일은 마스터의 로컬 디스크에는 있었는데, 워커는 자기들 사본을 따로 들고 있었고 아무도 동기화를 안 한 상태였어요.
이게 EFS가 풀어주는 정확한 문제예요. 여러 EC2 인스턴스가 같은 스토리지를 공유하는 상황이요. 그런데 EFS가 만능은 아니에요. 데이터베이스를 EFS에 올리면 성능이 끔찍해지고, GB당 비용은 EBS의 4배예요. 어떤 워크로드에 어떤 스토리지를 써야 하는지 알아두면 장애도 막고 돈도 아낄 수 있어요.
두 종류의 스토리지
큰 그림에서 EBS와 EFS는 근본적으로 다른 역할을 해요.
| 스토리지 | 타입 | 공유 가능? | 용도 |
|---|---|---|---|
| EBS | 블록(HDD/SSD에 가까움) | 안 됨(인스턴스 1개) | OS, Docker, PostgreSQL, Redis, 로그 |
| EFS | 네트워크(NFS) | 됨(여러 인스턴스 동시) | 마스터/워커 간 공유 DAG 파일 |
EBS는 컴퓨터 내부 하드 드라이브라고 보면 돼요. 빠르고, 로컬이고, 그 컴퓨터만 접근할 수 있어요. EFS는 사무실에서 다 같이 마운트하는 네트워크 드라이브에 가까워요. 어느 머신에서든 동시에 읽고 쓸 수 있지만, 네트워크를 거치는 만큼 성능 페널티가 있어요.
EBS(Elastic Block Storage)
EBS는 개별 EC2 인스턴스에 붙는 블록 레벨 스토리지 볼륨이에요. 한 볼륨은 한 인스턴스에만 속해요. 빠른 I/O가 필요하거나 본질적으로 단일 인스턴스에 묶이는 것들을 여기에 둬요. 운영 체제, 데이터베이스, 컨테이너 런타임, 로그 같은 거예요.
일반적인 크기
Airflow 배포에서 EBS 볼륨은 이렇게 잡았어요.
| 인스턴스 | EBS 크기 | 내용 |
|---|---|---|
| Master | 100 GB | PostgreSQL, Redis, Docker 이미지, 로그, OS |
| Worker | 50 GB | Docker 이미지, 태스크 아티팩트, OS |
| Bastion | 8 GB | OS만(최소) |
마스터가 가장 커요. PostgreSQL(Airflow 메타데이터), Redis(Celery 메시지 브로커), 시간이 지나면서 쌓이는 태스크 실행 로그를 다 들고 있거든요. 워커는 태스크를 돌리고 산출물을 버리는 쪽이라 더 작아도 돼요. bastion은 거의 필요 없어요. 점프 박스니까요.
EBS에 들어가는 것
마스터 노드의 실제 디스크 레이아웃이에요.
100 GB EBS Volume
│
├── /var/lib/docker/ (~30 GB)
│ ├── images/ # Docker 이미지
│ └── volumes/
│ ├── postgres-data/ # Airflow 메타데이터 DB
│ └── redis-data/ # Celery 메시지 큐
│
├── /opt/airflow/logs/ (~10-50 GB, 시간이 지나면서 증가)
│ └── dag_id/run_id/task_id/ # 태스크 실행 로그
│
└── / (root) (~10 GB)
└── 운영 체제 가장 중요한 건 Docker volumes 영역이에요. PostgreSQL이 모든 DAG run, 태스크 상태, 사용자 계정을 저장해요. Redis는 Celery 메시지 큐를 들고 있고요. 로그는 시간이 가면서 늘어나는데, rotation을 안 걸어두면 공간을 꽤 잡아먹어요.
EBS를 잃으면
마스터의 EBS 볼륨이 날아가면 거기 들어 있는 모든 것이 사라져요.
- 모든 DAG run 히스토리
- 태스크 실행 로그
- 사용자 계정과 비밀번호
- Airflow Variables와 Connections
복구하려면 EBS 스냅샷에서 되돌리거나 환경을 처음부터 다시 만들어야 해요. 그래서 마스터 노드의 EBS 자동 스냅샷은 양보할 수 없는 항목이에요. 일 단위 스냅샷에 7일 보관 정책으로 돌려요.
EFS(Elastic File System)
EFS는 여러 EC2 인스턴스가 동시에 마운트할 수 있는 매니지드 NFS 파일 시스템이에요. 모든 인스턴스가 같은 시점에 같은 파일을 봐요. 이 속성이 EFS의 가치고, EBS가 근본적으로 줄 수 없는 부분이에요.
왜 공유 파일에 EFS를 쓰는지
공유 스토리지가 없으면 일관성 악몽이 시작돼요.
시나리오: DAG 파일을 업데이트
┌─────────────┐ ┌─────────────┐
│ Master │ │ Worker │
│ my_dag.py │ │ my_dag.py │
│ (version 2) │ │ (version 1) │ ← 구버전!
│ Scheduler │ ──── task ────► │ Celery │
│ sees v2 │ │ runs v1 │ ← 잘못된 코드!
└─────────────┘ └─────────────┘
결과: 태스크 실패 또는 잘못된 로직 실행 마스터의 스케줄러가 DAG의 v2를 읽고 태스크를 돌릴 시점이라고 판단해서 워커로 보내요. 그런데 워커의 로컬 디스크엔 v1이 있어요. 코드 구조가 바뀌었으면 import 에러로 죽고, 더 나쁜 경우엔 옛 로직으로 조용히 돌아가요.
EFS를 쓰면 문제가 사라져요.
┌─────────────────┐
│ EFS │
│ my_dag.py (v2) │ ← 단일 source of truth
└────────┬────────┘
┌──────────────┴──────────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Master │ │ Worker │
│ Sees v2 │ │ Sees v2 │ ← 동일!
└─────────────┘ └─────────────┘
결과: 일관성 보장 마스터와 워커가 같은 EFS 볼륨을 /opt/airflow/dags/에 마운트해요. 파일을
업데이트하면 모든 인스턴스가 즉시 같은 버전을 봐요(NFS 캐시 propagation 시간
정도, 보통 1초 이내).
EFS에 들어가는 것
EFS (~10 GB)
└── /opt/airflow/dags/
├── example_dag.py
├── etl_pipeline.py
└── utils/
└── helpers.py DAG Python 파일만 EFS에 올라가요. 볼륨이 작은 이유는 코드가 작기 때문이에요. DAG 수십 개를 굴리는 복잡한 Airflow 배포라도 몇백 메가바이트를 넘기는 일이 드물어요.
EFS를 잃으면
EFS를 잃는 건 EBS를 잃는 것보다 훨씬 덜 치명적이에요. DAG 파일은 Git에서 몇 분 안에 다시 배포할 수 있어요. 메타데이터와 로그는 PostgreSQL과 EBS에 있으니까 히스토리 데이터도 안 잃어요.
이 비대칭이 백업 전략에서 중요해요. EBS는 자동 스냅샷이 필요해요. 잃으면 복원할 수 없는 데이터가 들어 있거든요. EFS에는 버전 컨트롤에 이미 존재하는 코드만 있으니까, 잃으면 불편하지만 복구 가능해요.
그럼 EFS만 쓰면 안 되나?
EFS가 여러 인스턴스 공유를 지원하면, 데이터베이스도 EFS에 올리고 EBS의 단일 인스턴스 제약을 그냥 피해가도 되지 않을까요?
| 항목 | EBS | EFS |
|---|---|---|
| 지연시간 | ~1ms | ~5-10ms |
| GB당 비용 | $0.08 | $0.30(4배 비쌈) |
| DB 성능 | 매우 좋음 | 안 좋음 |
| 공유 접근 | 안 됨 | 됨 |
PostgreSQL을 EFS에 올리면 5-10배 느려져요. 모든 디스크 작업이 네트워크를 타니까요. DB 워크로드는 데이터 파일, WAL 로그, 인덱스에 끊임없이 random read/write를 일으키는데, NFS는 그 모든 작업에 지연시간을 더해요. 누적 효과가 쿼리 성능에 심각하게 박혀요.
게다가 GB당 4배 더 내고 더 나쁜 성능을 받는 거예요. AWS 문서도 EFS 위에서 데이터베이스 돌리지 말라고 명시적으로 권하고 있어요. DB는 EBS, 공유 파일은 EFS — 그게 설계 경계선이에요.
비용 분석
Airflow 클러스터의 총 스토리지 비용은 그렇게 크지 않아요.
| 스토리지 | 크기 | 요금 | 월 비용 |
|---|---|---|---|
| EBS Master | 100 GB | $0.08/GB | $8.00 |
| EBS Worker | 50 GB | $0.08/GB | $4.00 |
| EFS | ~10 GB | $0.30/GB | $3.00 |
| 합계 | ~$15/월 |
스토리지는 AWS 배포에서 가장 저렴한 축이에요. 스토리지 선택을 잘못해서 생기는 진짜 비용은 월 청구서가 아니에요. 쿼리 부하를 못 받는 EFS 위 DB가 일으키는 장애나, 스냅샷 없는 EBS 볼륨이 만든 데이터 유실이 진짜 비용이에요.
정리
규칙은 단순해요.
- EBS: 단일 인스턴스 데이터. 데이터베이스, 컨테이너 런타임, 로그, 빠른 I/O가 필요한 모든 것.
- EFS: 공유 파일. 코드, 설정, 여러 인스턴스가 동시에 읽어야 하는 모든 것.
EBS는 자동 스냅샷으로 보호하세요. 복원 불가능한 데이터가 들어 있어요. EFS는 ephemeral하게 다루세요. Git에 들어 있는 코드만 들어 있으니까요. 어떤 워크로드를 EBS에 둘지 EFS에 둘지 헷갈리면 두 가지를 물어보세요. 인스턴스가 둘 이상 접근해야 하나? sub-millisecond 지연시간이 필요한가? 첫 질문이 yes면 EFS를, 두 번째 질문이 yes면 EBS를 쓰세요. 둘 다 yes면 아키텍처를 다시 생각해야 해요.