Airflow 해부 (6) 운영: 컨테이너 구동, executor, 멱등성
공식 Docker Compose 기반 구동, PostgreSQL metadata DB, 규모별 executor 선택, 그리고 재시도와 backfill을 안전하게 만드는 멱등성 원칙과 운영 함정을 정리합니다.
Airflow 해부 시리즈의 6편입니다. 전체 목차는 0편에 있습니다.
컨테이너로 분리하는 이유
2편에서 가상환경 설치를 학습용까지로 제한한 이유가 운영에서 그대로 문제가 됩니다. Airflow의 수백 개 의존성이 프로젝트의 pandas, scikit-learn 버전과 충돌하기 쉽고, 업그레이드 때마다 충돌 조합이 달라집니다. 그래서 운영 관행은 Airflow를 프로젝트 환경에서 분리해 컨테이너로 돌리는 것입니다. NYC 택시 프로젝트 2편에서도 같은 이유로 컨테이너 구동을 택했습니다.
공식 Docker Compose로 시작합니다.
1
2
3
4
curl -LfO 'https://airflow.apache.org/docs/apache-airflow/stable/docker-compose.yaml'
mkdir -p ./dags ./logs ./plugins ./config
docker compose up airflow-init # DB 초기화와 계정 생성
docker compose up -d
./dags가 컨테이너 안의 DAG 폴더로 마운트됩니다. 로컬에서 파일을 수정하면 그대로 반영됩니다- 이 구성은 PostgreSQL metadata DB와 CeleryExecutor를 포함합니다. 단일 머신이면 compose 파일에서 LocalExecutor로 줄여도 됩니다
- Kubernetes 환경이라면 compose 대신 공식 Helm chart가 표준입니다
DAG가 쓰는 라이브러리(pandas 등)는 Airflow 이미지에 없을 수 있습니다. 공식 이미지를 베이스로 필요한 패키지를 추가한 커스텀 이미지를 만드는 것이 정석이고, 컨테이너에 들어가 pip install 하는 방식은 재시작하면 사라집니다.
executor 선택
| executor | 실행 위치 | 적합한 규모 |
|---|---|---|
| LocalExecutor | scheduler와 같은 머신의 프로세스 | 단일 머신, 대부분의 시작점 |
| CeleryExecutor | 별도 worker 머신들 | task를 여러 머신에 분산 |
| KubernetesExecutor | task마다 새 pod | K8s 환경, task별 자원 격리 |
선택 기준은 단순하게 잡아도 됩니다. 단일 머신에서 자원이 부족하지 않으면 LocalExecutor로 충분하고, worker를 늘려야 할 때 Celery로, 이미 Kubernetes를 운영 중이면 KubernetesExecutor로 갑니다. SQLite와 짝인 SequentialExecutor는 개발 전용이라 운영 선택지에 없습니다.
멱등성: 운영 안정성의 절반
3편의 retry와 4편의 backfill이 안전하려면 모든 task가 멱등해야 합니다. 같은 task instance를 몇 번을 다시 돌려도 결과가 같아야 한다는 조건입니다. 패턴은 세 가지로 정리됩니다.
- 덮어쓰기: 해당 logical date의 파티션(파일, 테이블 구간)을 지우고 다시 씁니다.
INSERT가 아니라DELETE 후 INSERT또는 파티션 교체입니다 - 결정적 경로: 출력 경로에 실행 시각이 아니라 logical date를 씁니다.
output_{ds}.parquet는 재실행해도 같은 파일을 갱신하지만,output_{now}.parquet는 재실행마다 새 파일을 만듭니다 - 외부 부작용 격리: 메일 발송, 결제처럼 되돌릴 수 없는 작업은 별도 task로 분리하고 재시도를 끕니다
운영 함정
- DAG 파일 상단의 무거운 코드가 scheduler를 잠식합니다. 증상은 DAG 반영 지연과 scheduler CPU 상승입니다. scheduler는 DAG 폴더를 주기적으로 재파싱하는데, top-level의 DB 접속이나 대용량 import가 파싱마다 실행되기 때문입니다. 무거운 것은 전부 task 함수 안으로 내립니다
- 로그 디스크가 조용히 찹니다. task instance마다 로그 파일이 쌓이고 기본 설정은 삭제하지 않습니다. 로그 보존 기간을 정해 정리 작업을 걸거나 원격 로그 저장(S3)을 설정합니다
- metadata DB가 비대해집니다. 오래된 task instance와 XCom 기록이 계속 쌓여 UI와 scheduler가 느려집니다.
airflow db clean명령으로 보존 기간 밖의 기록을 주기적으로 정리합니다
다음 편은 마지막으로, 이 시리즈와 MLflow 시리즈를 재학습 DAG 하나로 잇습니다.