Airflow를 처음 구성할 때는 메타 DB로 SQLite를 사용했다.
설정이 간단했고, 빠르게 환경을 띄울 수 있었기 때문이다.
초기에는 DAG 수도 적고 실행 빈도도 낮아 큰 문제를 느끼지 못했다.
하지만 DAG 수가 늘고, 실행 빈도가 증가하면서 다음과 같은 문제가 반복적으로 발생했다.
처음에는 작업 코드의 문제라고 생각했다.
하지만 동일한 코드라도 DAG가 겹쳐 실행되는 상황에서만 문제가 발생했다.
이 시점부터 Airflow를 단순한 실험 도구가 아니라
운영 환경에서 신뢰하고 사용해야 하는 스케줄러로 쓰고 있다는 신호라고 판단했고,
가장 먼저 메타 DB부터 정리하기로 했다.
Airflow의 메타 DB에는 다음과 같은 컴포넌트들이 동시에 접근한다.
이 컴포넌트들은 지속적으로 다음 작업을 수행한다.
SQLite는 파일 기반 DB이며 single-writer 모델을 가진다.
즉, 여러 프로세스가 동시에 상태를 기록하는 Airflow 구조와는 맞지 않는다.
그 결과 write lock 경합이 발생했고,
Scheduler heartbeat가 실패하면서 프로세스가 종료되는 현상이 반복되었다.
해결 방향은 단순했다.
회사에서 이미 표준 DB로 MySQL을 사용하고 있었기 때문에,
추가적인 운영 부담 없이 MySQL을 메타 DB로 선택했다.
메타 DB 이관을 위해 최소한의 구성으로 docker-compose를 구성했다.
mysql:
image:mysql:8.0
container_name:mysql
restart:unless-stopped
environment:
MYSQL_ROOT_PASSWORD:rootpw
MYSQL_DATABASE:airflow
MYSQL_USER:airflow
MYSQL_PASSWORD:airflowpw
ports:
-"3306:3306"
volumes:
-./mysql:/var/lib/mysql
airflow-webserver:
image:airflow-webserver:2.8
depends_on:
-mysql
environment:
-AIRFLOW__CORE__EXECUTOR=LocalExecutor
-AIRFLOW__DATABASE__SQL_ALCHEMY_CONN=mysql+mysqlconnector://airflow:airflowpw@mysql:3306/airflow
-AIRFLOW__CORE__LOAD_EXAMPLES=False
command:airflowwebserver
핵심 설정은 한 줄이다.
AIRFLOW__DATABASE__SQL_ALCHEMY_CONN
SQLite 대신 MySQL을 메타 DB로 사용하도록 지정한다.
airflow-scheduler:
image:airflow-scheduler:2.8
depends_on:
-mysql
environment:
-AIRFLOW__CORE__EXECUTOR=LocalExecutor
-AIRFLOW__DATABASE__SQL_ALCHEMY_CONN=mysql+mysqlconnector://airflow:airflowpw@mysql:3306/airflow
command:airflowscheduler
Webserver와 Scheduler가 동일한 메타 DB를 바라보도록 설정했다.
메타 DB를 MySQL로 전환한 이후 다음과 같은 변화가 있었다.
즉, 성능 튜닝이 아니라 안정성 문제가 해결되었다.
이 작업을 통해 명확히 느낀 점은 다음이다.
Airflow를 “돌아가게 만드는 것”과
“안정적으로 운영하는 것”은 완전히 다른 문제였다.
이후에는 데이터 처리 파이프라인 자체에서도
재실행과 멱등성을 고려한 구조를 설계하게 되었고,
그 내용은 별도의 글로 정리할 예정이다.
Airflow 운영에서 메타 DB는 옵션이 아니라 전제 조건이다.