데이터베이스 백엔드 설정하기

데이터베이스 백엔드 설정하기 (Set up a Database Backend)

Airflow가 메타데이터를 저장하는 데 사용하는 데이터베이스 백엔드를 설정하는 방법을 설명하는 문서예요. PostgreSQL·MySQL·SQLite의 지원 버전과 데이터베이스 URI 설정, 각 데이터베이스 생성 절차, 데이터베이스 초기화, 그리고 모니터링·유지보수 고려 사항까지 살펴볼게요.

출처: 문서

본문

Airflow는 SqlAlchemy로 메타데이터와 상호작용하도록 만들어졌어요.

아래 문서는 데이터베이스 엔진 구성, Airflow와 함께 사용하기 위한 구성의 필요한 변경, 그리고 이 데이터베이스에 연결하기 위한 Airflow 구성의 변경을 설명해요.

데이터베이스 백엔드 고르기 (Choosing database backend)

Airflow를 진짜로 사용해 보려면 PostgreSQL이나 MySQL에 데이터베이스 백엔드를 설정하는 것을 고려해야 해요. 기본적으로 Airflow는 개발 목적으로만 의도된 SQLite를 사용해요.

Airflow는 다음 데이터베이스 엔진 버전을 지원하므로 자신의 버전을 확인해 두세요. 오래된 버전은 일부 SQL 문을 지원하지 않을 수 있어요.

  • PostgreSQL: 13, 14, 15, 16, 17
  • MySQL: 8.0, 8.4, Innovation
  • SQLite: 3.15.0+

스케줄러를 두 개 이상 실행할 계획이라면 추가 요구사항을 충족해야 해요. 자세한 내용은 Scheduler HA Database Requirements를 참고하세요.

경고 (Warning)

MariaDB와 MySQL 사이에 큰 유사점이 있음에도 불구하고, 우리는 MariaDB를 Airflow의 백엔드로 지원하지 않아요. MariaDB와 MySQL 사이에는 (예: 인덱스 처리) 알려진 문제가 있고 우리는 마이그레이션 스크립트나 애플리케이션 실행을 MariaDB에서 테스트하지 않아요. MariaDB를 Airflow에 사용한 사람들이 있었고 그게 운영상 많은 골칫거리를 일으킨다는 것을 알고 있으므로, MariaDB를 백엔드로 사용하려는 시도는 강력히 만류하며, MariaDB를 사용해 보려고 한 사용자 수가 매우 적어 커뮤니티 지원도 기대할 수 없어요.

데이터베이스 URI (Database URI)

Airflow는 데이터베이스에 연결하기 위해 SQLAlchemy를 사용하며, 데이터베이스 URL을 구성해야 해요. [database] 섹션의 sql_alchemy_conn 옵션에서 할 수 있어요. AIRFLOW__DATABASE__SQL_ALCHEMY_CONN 환경 변수로 구성하는 것도 흔해요.

참고 (Note)

설정에 대한 자세한 내용은 Setting Configuration Options을 참고하세요.

현재 값을 확인하려면 아래처럼 airflow config get-value database sql_alchemy_conn 명령을 사용할 수 있어요.

$ airflow config get-value database sql_alchemy_conn
sqlite:////tmp/airflow/airflow.db

정확한 형식 설명은 SQLAlchemy 문서인 Database Urls에 설명되어 있어요. 아래에 몇 가지 예시도 보여줄게요.

SQLite 데이터베이스 설정하기 (Setting up a SQLite Database)

SQLite 데이터베이스는 데이터베이스 서버가 필요 없으므로(데이터베이스는 로컬 파일에 저장됨) 개발 목적으로 Airflow를 실행하는 데 사용할 수 있어요. SQLite 데이터베이스 사용에는 온라인에서 쉽게 찾을 수 있는 많은 제한이 있고, 프로덕션에는 절대 사용하면 안 돼요.

Airflow 2.0+를 실행하려면 최소 sqlite3 버전이 필요해요 — 최소 버전은 3.15.0이에요. 일부 오래된 시스템은 기본적으로 이전 버전의 sqlite가 설치되어 있어서, 그 시스템에서는 SQLite를 수동으로 3.15.0 이상으로 업그레이드해야 해요. 참고로 이는 python library 버전이 아니라 업그레이드해야 할 SQLite 시스템 수준 애플리케이션이에요. SQLite가 설치되는 방식은 여러 가지가 있으며, SQLite 공식 웹사이트와 사용 중인 운영체제 배포판 관련 문서에서 정보를 찾을 수 있어요.

트러블슈팅 (Troubleshooting)

때때로 SQLite를 더 높은 버전으로 업그레이드하고 로컬 python이 더 높은 버전을 보고해도, Airflow가 사용하는 python 인터프리터는 Airflow를 시작하는 데 사용되는 python 인터프리터에 설정된 LD_LIBRARY_PATH에 있는 이전 버전을 여전히 사용할 수 있어요.

인터프리터가 사용하는 버전을 다음 체크로 확인할 수 있어요:

[Breeze:3.10.19] root@b8a8e73caa2c:/opt/airflow# python
Python 3.8.10 (default, Mar 15 2022, 12:22:08)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlite3
>>> sqlite3.sqlite_version
'3.27.2'
>>>

다만 Airflow 배포를 위한 환경 변수를 설정하면 어떤 SQLite 라이브러리가 먼저 발견되는지 바뀔 수 있으므로, "충분히 높은" 버전의 SQLite가 시스템에 설치된 유일한 버전인지 확인하고 싶을 거예요.

sqlite 데이터베이스의 예시 URI:

sqlite:////home/airflow/airflow.db

AmazonLinux AMI나 컨테이너 이미지에서 SQLite 업그레이드하기 (Upgrading SQLite on AmazonLinux AMI or Container Image)

AmazonLinux SQLite는 소스 repo를 사용하면 v3.7까지만 업그레이드할 수 있어요. Airflow는 v3.15 이상을 요구해요. 최신 SQLite3로 기본 이미지(또는 AMI)를 설정하려면 다음 지침을 사용하세요.

전제 조건: 업그레이드 과정을 진행하려면 wget, tar, gzip, gcc, make, expect가 필요해요.

yum -y install wget tar gzip gcc make expect

https://sqlite.org/에서 소스를 다운로드하고 로컬에서 make하고 설치해요.

wget https://www.sqlite.org/src/tarball/sqlite.tar.gz
tar xzf sqlite.tar.gz
cd sqlite/
export CFLAGS="-DSQLITE_ENABLE_FTS3 \
    -DSQLITE_ENABLE_FTS3_PARENTHESIS \
    -DSQLITE_ENABLE_FTS4 \
    -DSQLITE_ENABLE_FTS5 \
    -DSQLITE_ENABLE_JSON1 \
    -DSQLITE_ENABLE_LOAD_EXTENSION \
    -DSQLITE_ENABLE_RTREE \
    -DSQLITE_ENABLE_STAT4 \
    -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT \
    -DSQLITE_SOUNDEX \
    -DSQLITE_TEMP_STORE=3 \
    -DSQLITE_USE_URI \
    -O2 \
    -fPIC"
export PREFIX="/usr/local"
LIBS="-lm" ./configure --disable-tcl --enable-shared --enable-tempstore=always --prefix="$PREFIX"
make
make install

설치 후 /usr/local/lib를 라이브러리 경로에 추가해요.

export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

PostgreSQL 데이터베이스 설정하기 (Setting up a PostgreSQL Database)

Airflow가 이 데이터베이스에 접근하는 데 사용할 데이터베이스와 데이터베이스 사용자를 만들어야 해요. 아래 예시에서는 airflow_db 데이터베이스와 username airflow_user·password airflow_pass인 사용자가 만들어져요.

CREATE DATABASE airflow_db;
CREATE USER airflow_user WITH PASSWORD 'airflow_pass';
GRANT ALL PRIVILEGES ON DATABASE airflow_db TO airflow_user;

-- PostgreSQL 15 requires additional privileges:
-- Note: Connect to the airflow_db database before running the following GRANT statement
-- You can do this in psql with: \c airflow_db
GRANT ALL ON SCHEMA public TO airflow_user;

참고 (Note)

데이터베이스는 UTF-8 문자 집합을 사용해야 해요.

Postgres pg_hba.conf를 업데이트해 airflow 사용자를 데이터베이스 접근 제어 목록에 추가하고, 변경 사항을 로드하기 위해 데이터베이스 구성을 리로드해야 할 수도 있어요. 자세한 내용은 Postgres 문서의 The pg_hba.conf File을 참고하세요.

경고 (Warning)

SQLAlchemy 1.4.0+를 사용할 때 sql_alchemy_conn의 데이터베이스로 postgresql://를 사용해야 해요. SQLAlchemy 이전 버전에서는 postgres://를 사용할 수 있었지만, SQLAlchemy 1.4.0+에서 사용하면 다음과 같은 결과가 생겨요:

>       raise exc.NoSuchModuleError(
            "Can't load plugin: %s:%s" % (self.group, name)
        )
E       sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:postgres

URL 프리픽스를 즉시 변경할 수 없다면 SQLAlchemy 1.3으로 Airflow가 계속 동작하고 SQLAlchemy를 다운그레이드할 수 있지만, 프리픽스를 업데이트하는 것을 권장해요.

자세한 내용은 SQLAlchemy Changelog에서 확인할 수 있어요.

psycopg2 드라이버를 사용하고 SqlAlchemy connection 문자열에 지정하는 것을 권장해요.

postgresql+psycopg2://<user>:<password>@<host>/<db>

또한 SqlAlchemy는 데이터베이스 URI에서 특정 스키마를 대상으로 하는 방법을 노출하지 않으므로, public 스키마가 Postgres 사용자의 search_path에 있는지 확인해야 해요.

Airflow용 새 Postgres 계정을 만들었다면:

  • 새 Postgres 사용자의 기본 search_path는 "$user", public이므로 변경이 필요 없어요.

커스텀 search_path를 가진 기존 Postgres 사용자를 사용한다면, search_path는 다음 명령으로 변경할 수 있어요:

ALTER USER airflow_user SET search_path = public;

PostgreSQL connection 설정에 대한 자세한 내용은 SQLAlchemy 문서의 PostgreSQL dialect을 참고하세요.

참고 (Note)

Airflow는 특히 고성능 설정에서 메타데이터 데이터베이스에 많은 연결을 여는 것으로 알려져 있어요. Postgres에서 각 연결은 새 프로세스를 만들기 때문에 많은 연결이 열리면 Postgres가 리소스를 많이 먹게 되어 리소스 사용에 문제가 될 수 있어요. 따라서 모든 Postgres 프로덕션 설치에서 PGBouncer를 데이터베이스 프록시로 사용하는 것을 권장해요. PGBouncer는 여러 컴포넌트의 연결 풀링을 처리할 수 있고, 잠재적으로 불안정한 연결의 원격 데이터베이스가 있는 경우 일시적 네트워크 문제에 대해 DB 연결성을 훨씬 더 탄력적으로 만들어 줘요. PGBouncer 배포의 예시 구현은 Helm Chart for Apache Airflow에서 찾을 수 있는데, 불리언 플래그 하나로 사전 구성된 PGBouncer 인스턴스를 활성화할 수 있어요. 공식 Helm Chart를 사용하지 않더라도 우리가 거기서 취한 접근 방식을 살펴보고 자신의 배포를 준비할 때 영감으로 사용할 수 있어요.

Helm Chart production guide도 참고하세요.

참고 (Note)

Azure Postgresql, CloudSQL, Amazon RDS 같은 관리형 Postgres의 경우 connection 파라미터에서 keepalives_idle을 사용하고 유휴 시간보다 작게 설정해야 해요. 이러한 서비스는 일정 시간 비활성(보통 300초) 후 유휴 연결을 닫아 The error: psycopg2.operationalerror: SSL SYSCALL error: EOF detected 오류가 발생하기 때문이에요. keepalive 설정은 [database] 섹션의 sql_alchemy_connect_args 구성 파라미터 Configuration Reference로 변경할 수 있어요. 예를 들어 local_settings.py에서 args를 구성할 수 있고 sql_alchemy_connect_args는 구성 파라미터를 저장하는 딕셔너리의 전체 import 경로여야 해요. Postgres Keepalives에 대해 읽을 수 있어요. 문제를 고치는 것으로 관찰된 keepalives의 예시 설정:

keepalive_kwargs = {
    "keepalives": 1,
    "keepalives_idle": 30,
    "keepalives_interval": 5,
    "keepalives_count": 5,
}

그런 다음 airflow_local_settings.py에 두었다면 구성 import 경로는:

sql_alchemy_connect_args = airflow_local_settings.keepalive_kwargs

로컬 설정 구성 방법에 대한 자세한 내용은 Configuring local settings를 참고하세요.

MySQL 데이터베이스 설정하기 (Setting up a MySQL Database)

Airflow가 이 데이터베이스에 접근하는 데 사용할 데이터베이스와 데이터베이스 사용자를 만들어야 해요. 아래 예시에서는 airflow_db 데이터베이스와 username airflow_user·password airflow_pass인 사용자가 만들어져요.

CREATE DATABASE airflow_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'airflow_user' IDENTIFIED BY 'airflow_pass';
GRANT ALL PRIVILEGES ON airflow_db.* TO 'airflow_user';

참고 (Note)

데이터베이스는 UTF-8 문자 집합을 사용해야 해요. 알아야 할 작은 주의 사항이 있는데, 최신 MySQL 버전의 utf8은 사실 utf8mb4라서 Airflow 인덱스가 너무 커지게 해요 (https://github.com/apache/airflow/pull/17603#issuecomment-901121618 참고). 따라서 Airflow 2.2부터 모든 MySQL 데이터베이스는 (오버라이드하지 않는 한) sql_engine_collation_for_ids가 자동으로 utf8mb3_bin으로 설정돼요. 이는 Airflow 데이터베이스의 id 필드에 대한 콜레이션 id 혼합을 초래할 수 있지만, Airflow의 모든 관련 ID는 ASCII 문자만 사용하므로 부정적인 결과는 없어요.

우리는 MySQL의 더 엄격한 ANSI SQL 설정에 의존해 합리적인 기본값을 갖습니다. my.cnf 파일의 [mysqld] 섹션 아래에 explicit_defaults_for_timestamp=1 옵션을 지정했는지 확인하세요. mysqld 실행 파일에 전달되는 --explicit-defaults-for-timestamp 스위치로도 이 옵션을 활성화할 수 있어요.

mysqlclient 드라이버를 사용하고 SqlAlchemy connection 문자열에 지정하는 것을 권장해요.

mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>

중요 (Important)

MySQL 백엔드의 통합은 Apache Airflow의 지속적 통합(CI) 과정에서 mysqlclient 드라이버로만 검증됐어요.

다른 드라이버를 사용하려면 SqlAlchemy connection의 다운로드·설정에 대한 자세한 내용은 SQLAlchemy 문서의 MySQL Dialect을 방문하세요.

추가로 MySQL의 인코딩에 특히 주의해야 해요. utf8mb4 문자 집합이 MySQL에서 점점 더 인기 있지만(실제로 utf8mb4는 MySQL 8.0의 기본 문자 집합이 됨), utf8mb4 인코딩을 사용하려면 Airflow 2+에서 추가 설정이 필요해요 (#7570](https://github.com/apache/airflow/pull/7570)에서 자세히 보기). 문자 집합으로 utf8mb4를 사용한다면 sql_engine_collation_for_ids=utf8mb3_bin도 설정해야 해요.

참고 (Note)

엄격 모드에서 MySQL은 0000-00-00을 유효한 날짜로 허용하지 않아요. 그러면 경우에 따라 (일부 Airflow 테이블은 타임스탬프 필드 기본값으로 0000-00-00 00:00:00을 사용합니다) "Invalid default value for 'end_date'" 같은 오류가 발생할 수 있어요. 이 오류를 피하려면 MySQL 서버에서 NO_ZERO_DATE 모드를 비활성화할 수 있어요. 비활성화하는 방법은 https://stackoverflow.com/questions/9192027/invalid-default-value-for-create-date-timestamp-field를 읽어보세요. 자세한 내용은 SQL Mode - NO_ZERO_DATE를 참고하세요.

MsSQL 데이터베이스

경고 (Warning)

논의투표 과정 후, Airflow의 PMC 멤버와 Committers는 MsSQL을 지원되는 Database Backend로 더 이상 유지보수하지 않기로 결정했습니다.

Airflow 2.9.0부터 Airflow Database Backend에 대한 MsSQL 지원이 제거됐어요. 이것은 기존 providers(operators와 hooks)에는 영향을 미치지 않고, Dags는 여전히 MsSQL의 데이터에 접근·처리할 수 있어요. 다만 더 사용하면 Airflow의 핵심 기능을 사용할 수 없게 만드는 오류가 발생할 수 있어요.

MsSQL Server에서 마이그레이션하기 (Migrating off MsSQL Server)

Airflow 2.9.0에서 MSSQL 지원이 종료됐으므로, 마이그레이션 스크립트가 Airflow 2.7.x나 2.8.x에서 SQL-Server에서 벗어나는 데 도움이 될 수 있어요. 마이그레이션 스크립트는 airflow-mssql-migration repo on GitHub에서 사용할 수 있어요.

마이그레이션 스크립트는 지원과 보증 없이 제공된다는 점을 참고하세요.

기타 구성 옵션 (Other configuration options)

SQLAlchemy 동작을 구성하는 더 많은 구성 옵션이 있어요. 자세한 내용은 [database] 섹션의 sqlalchemy_* 옵션에 대한 reference documentation을 참고하세요.

예를 들어 Airflow가 필요한 테이블을 만들 데이터베이스 스키마를 지정할 수 있어요. PostgreSQL 데이터베이스의 airflow 스키마에 Airflow가 테이블을 설치하길 원한다면 다음 환경 변수를 지정해요:

export AIRFLOW__DATABASE__SQL_ALCHEMY_CONN="postgresql://postgres@localhost:5432/my_database?options=-csearch_path%3Dairflow"
export AIRFLOW__DATABASE__SQL_ALCHEMY_SCHEMA="airflow"

SQL_ALCHEMY_CONN 데이터베이스 URL 끝의 search_path를 참고하세요.

데이터베이스 초기화 (Initialize the database)

데이터베이스를 구성하고 Airflow 구성에서 연결한 후에는 데이터베이스 스키마를 만들어야 해요.

airflow db migrate

Airflow에서 데이터베이스 모니터링과 유지보수 (Database Monitoring and Maintenance in Airflow)

Airflow는 태스크 스케줄링과 실행을 위해 관계형 메타데이터 데이터베이스를 광범위하게 활용해요. 이 데이터베이스의 모니터링과 적절한 구성은 최적의 Airflow 성능에 매우 중요해요.

핵심 우려 사항 (Key Concerns)

  1. 성능 영향 (Performance Impact) — 길거나 과도한 쿼리는 Airflow의 기능에 크게 영향을 줄 수 있어요. 이는 워크플로우 특성, 최적화 부족, 코드 버그로 인해 발생할 수 있어요.
  2. 데이터베이스 통계 (Database Statistics) — 종종 오래된 데이터 통계로 인한 데이터베이스 엔진의 잘못된 최적화 결정이 성능을 저하시킬 수 있어요.

책임 (Responsibilities)

Airflow 환경에서 데이터베이스 모니터링·유지보수의 책임은 자체 관리 데이터베이스와 Airflow 인스턴스를 사용하는지, 아니면 관리형 서비스를 선택하는지에 따라 달라져요.

자체 관리 환경 (Self-Managed Environments) — 데이터베이스와 Airflow가 모두 자체 관리되는 설정에서는 Deployment Manager가 데이터베이스 설정·구성·유지보수를 담당해요. 여기에는 성능 모니터링, 백업 관리, 주기적 정리, Airflow와의 최적 동작 보장이 포함돼요.

관리형 서비스 (Managed Services):

  • 관리형 데이터베이스 서비스 (Managed Database Services) — 관리형 DB 서비스를 사용할 때는 백업, 패칭, 기본 모니터링 같은 많은 유지보수 작업이 provider에 의해 처리돼요. 하지만 Deployment Manager는 여전히 Airflow의 구성과 자신의 워크플로우에 특화된 성능 설정 최적화를 감독하고, 주기적 정리를 관리하며 Airflow와의 최적 동작을 위해 DB를 모니터링해야 해요.
  • 관리형 Airflow 서비스 (Managed Airflow Services) — 관리형 Airflow 서비스를 사용하면 그 서비스 provider가 Airflow와 그 데이터베이스의 구성·유지보수를 책임져요. 하지만 Deployment Manager는 서비스 구성과 협력해 사이징과 워크플로우 요구사항이 관리형 서비스의 사이징·구성과 일치하도록 해야 해요.

모니터링 측면 (Monitoring Aspects)

정기 모니터링에는 다음이 포함되어야 해요:

  • CPU, I/O, 메모리 사용.
  • 쿼리 빈도와 개수.
  • 느리거나 오래 실행되는 쿼리의 식별과 로깅.
  • 비효율적인 쿼리 실행 계획 감지.
  • 디스크 스왑 대 메모리 사용, 캐시 스왑 빈도 분석.

도구와 전략 (Tools and Strategies)

  • Airflow는 데이터베이스 모니터링을 위한 직접적인 도구를 제공하지 않아요.
  • 서버 측 모니터링과 로깅을 사용해 메트릭을 얻어요.
  • 정의된 임계값에 기반한 오래 실행되는 쿼리 추적을 활성화해요.
  • 유지보수를 위해 house-keeping 작업(예: ANALYZE SQL 명령)을 정기적으로 실행해요.

데이터베이스 정리 도구 (Database Cleaning Tools)

  • Airflow DB Clean Command — 데이터베이스의 관리·정리에 airflow db clean 명령을 활용해요.
  • airflow.utils.db_cleanup의 Python 메서드 — 이 모듈은 데이터베이스 정리·유지보수를 위한 추가 Python 메서드를 제공해 특정 요구에 더 세밀한 제어와 커스터마이징을 제공해요.

권장 사항 (Recommendations)

  • 사전 모니터링 (Proactive Monitoring) — 성능에 큰 영향을 주지 않고 프로덕션에서 모니터링·로깅을 구현해요.
  • 데이터베이스별 지침 (Database-Specific Guidance) — 특정 모니터링 설정 지침은 선택한 데이터베이스의 문서를 참고하세요.
  • 관리형 데이터베이스 서비스 (Managed Database Services) — 데이터베이스 provider에서 자동 유지보수 작업이 가능한지 확인해요.

SQLAlchemy 로깅 (SQLAlchemy Logging)

상세한 쿼리 분석을 위해 SQLAlchemy 클라이언트 로깅을 활성화해요(SQLAlchemy 엔진 구성에서 echo=True).

  • 이 방법은 더 침습적이고 Airflow의 클라이언트 측 성능에 영향을 줄 수 있어요.
  • 특히 바쁜 Airflow 환경에서 많은 로그를 생성해요.
  • 스테이징 시스템 같은 비프로덕션 환경에 적합해요.

SQLAlchemy logging documentation에서 설명하듯이 echo=True를 sqlalchemy 엔진 구성으로 할 수 있어요.

echo 인자를 True로 설정하려면 sql_alchemy_engine_args 구성 파라미터를 사용해요.

주의 (Caution)

  • 광범위한 로깅을 활성화할 때 Airflow의 성능과 시스템 리소스에 미치는 영향에 주의하세요.
  • 프로덕션 환경에서는 성능 간섭을 최소화하기 위해 클라이언트 측 로깅보다 서버 측 모니터링을 선호하세요.

다음은 무엇인가요? (What's next?)

기본적으로 Airflow는 LocalExecutor를 사용해요. 더 나은 성능을 위해 다른 executor를 구성하는 것을 고려해 보세요.

더 알아보기 (Learn more)