RHEL 9 계열에 Airflow 3.3.2[1] 를 pip 로 올리고 CeleryExecutor 로 구성한다. 메타데이터 DB 는 PostgreSQL, 브로커는 Redis(Valkey) 를 쓴다. sudo 권한이 필요하다.
| 호스트 | 역할 |
|---|---|
| af01 | api-server · scheduler · dag-processor · triggerer · flower |
| af02, af03 | celery worker |
| db01 | PostgreSQL 16 · Valkey/Redis |
모든 Airflow 노드는 같은 버전 · 같은 airflow.cfg · 같은 DAG 파일을 가져야 한다. DAG 동기화(NFS · git pull · rsync)는 직접 마련한다[2].
| 항목 | 요구 |
|---|---|
| Python | 3.10 · 3.11 · 3.12 · 3.13 · 3.14 |
| 메타데이터 DB | PostgreSQL 14–18 · MySQL 8.0 · 8.4. SQLite 는 개발용 |
| 브로커 | Redis · Redis Sentinel · RabbitMQ |
| 포트 | 8080(api-server) · 5555(flower) · 5432(PostgreSQL) · 6379(Redis) |
sudo useradd -r -m -d /opt/airflow -s /bin/bash airflow
sudo mkdir -p /opt/airflow/dags /opt/airflow/logs
sudo chown -R airflow:airflow /opt/airflow
sudo dnf install -y python3.12 python3.12-devel gcc libpq-devel
sudo -u airflow python3.12 -m venv /opt/airflow/venv
constraints 파일을 반드시 준다. 없으면 의존성이 풀리지 않거나 다른 버전이 섞인다[4].
sudo -iu airflow
source /opt/airflow/venv/bin/activate
AIRFLOW_VERSION=3.3.2
PYTHON_VERSION="$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')"
CONSTRAINT_URL="https://raw.githubusercontent.com/apache/airflow/constraints-${AIRFLOW_VERSION}/constraints-${PYTHON_VERSION}.txt"
pip install --upgrade pip
pip install "apache-airflow[celery,postgres,redis]==${AIRFLOW_VERSION}" --constraint "${CONSTRAINT_URL}"
airflow version # 3.3.2
extras 는 대괄호 안에 쉼표로 나열한다. celery 는 CeleryExecutor(provider), postgres 는 psycopg2, redis 는 브로커 클라이언트다.
CREATE USER airflow WITH PASSWORD '${AIRFLOW_DB_PASSWORD}';
CREATE DATABASE airflow OWNER airflow ENCODING 'UTF8';
pg_hba.conf 에 Airflow 노드 대역을 scram-sha-256 으로 연다. Redis 는 requirepass 를 두고 Airflow 노드 대역만 bind 한다. 설치는 PostgreSQL · Valkey 를 볼 것.
AIRFLOW_HOME 을 정하고 기본 설정 파일을 만든다.
echo 'export AIRFLOW_HOME=/opt/airflow' | sudo tee /etc/profile.d/airflow.sh
export AIRFLOW_HOME=/opt/airflow
airflow config list --defaults > /opt/airflow/airflow.cfg
바꿀 항목[5].
[core]
dags_folder = /opt/airflow/dags
executor = CeleryExecutor
load_examples = False
# 워커가 태스크 상태를 보고할 API 서버. 끝의 /execution/ 까지 적는다.
execution_api_server_url = http://af01.example.com:8080/execution/
# 기본값. 다중 사용자·RBAC 가 필요하면 FAB provider 를 설치하고 FabAuthManager 로 바꾼다.
auth_manager = airflow.api_fastapi.auth.managers.simple.simple_auth_manager.SimpleAuthManager
# Simple Auth Manager 사용자. "이름:역할" 쉼표 구분. 역할은 admin · op · user · viewer
simple_auth_manager_users = admin:admin
[database]
sql_alchemy_conn = postgresql+psycopg2://airflow:${AIRFLOW_DB_PASSWORD}@db01.example.com:5432/airflow
[api]
host = 0.0.0.0
port = 8080
base_url = http://af01.example.com:8080
[api_auth]
# 모든 노드(api-server · scheduler · worker)가 같은 값을 가져야 한다. 아래 명령으로 만든다.
jwt_secret = ${JWT_SECRET}
[logging]
base_log_folder = /opt/airflow/logs
[celery]
broker_url = redis://:${REDIS_PASSWORD}@db01.example.com:6379/0
result_backend = db+postgresql://airflow:${AIRFLOW_DB_PASSWORD}@db01.example.com:5432/airflow
worker_concurrency = 16
flower_host = 0.0.0.0
flower_port = 5555
# jwt_secret 과 fernet_key 생성
python -c 'import secrets; print(secrets.token_urlsafe(48))'
python -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())'
[core] fernet_key 에 두 번째 값을 넣는다. Connection · Variable 의 비밀값이 이 키로 암호화된다 — 잃어버리면 복호화할 수 없다. 설정 파일은 chmod 600 으로 둔다.
airflow db migrate
airflow config lint
3.x 에는 airflow db init 이 없다. db migrate 가 생성과 업그레이드를 모두 한다[6].
공통 환경 파일.
sudo tee /etc/sysconfig/airflow > /dev/null <<'ENV'
AIRFLOW_HOME=/opt/airflow
PATH=/opt/airflow/venv/bin:/usr/local/bin:/usr/bin:/bin
ENV
유닛 파일 템플릿. af01 에는 api-server · scheduler · dag-processor · triggerer · celery flower, 워커 노드에는 celery worker 만 만든다.
for svc in api-server scheduler dag-processor triggerer; do
sudo tee /etc/systemd/system/airflow-${svc}.service > /dev/null <<UNIT
[Unit]
Description=Airflow ${svc}
After=network-online.target
Wants=network-online.target
[Service]
EnvironmentFile=/etc/sysconfig/airflow
User=airflow
Group=airflow
Type=simple
ExecStart=/opt/airflow/venv/bin/airflow ${svc}
Restart=on-failure
RestartSec=5
KillMode=mixed
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
UNIT
done
# af01 — flower
sudo sed 's/airflow triggerer/airflow celery flower/; s/Description=.*/Description=Airflow flower/' \
/etc/systemd/system/airflow-triggerer.service | sudo tee /etc/systemd/system/airflow-flower.service > /dev/null
# af02 · af03 — worker
sudo tee /etc/systemd/system/airflow-worker.service > /dev/null <<'UNIT'
[Unit]
Description=Airflow celery worker
After=network-online.target
Wants=network-online.target
[Service]
EnvironmentFile=/etc/sysconfig/airflow
User=airflow
Group=airflow
Type=simple
ExecStart=/opt/airflow/venv/bin/airflow celery worker
Restart=on-failure
RestartSec=5
KillMode=mixed
TimeoutStopSec=600
[Install]
WantedBy=multi-user.target
UNIT
sudo systemctl daemon-reload
# af01
sudo systemctl enable --now airflow-api-server airflow-scheduler airflow-dag-processor airflow-triggerer airflow-flower
# af02 · af03
sudo systemctl enable --now airflow-worker
워커는 TimeoutStopSec 을 길게 준다. 정지 시 실행 중인 태스크가 끝날 때까지 기다린다(airflow celery stop 과 같은 동작).
# af01
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --add-port=5555/tcp
sudo firewall-cmd --reload
# 워커는 들어오는 포트가 없다. 로그 서빙(8793)을 쓰면 연다.
systemctl status airflow-api-server airflow-scheduler airflow-dag-processor
curl -s http://af01.example.com:8080/api/v2/monitor/health | python -m json.tool
scheduler · dag_processor · triggerer 가 모두 healthy 여야 한다. 웹 UI 는 http://af01.example.com:8080/, 사용자 admin, 비밀번호는 api-server 가 처음 뜰 때 만들어 /opt/airflow/simple_auth_manager_passwords.json.generated 에 둔다[6:1].
sudo cat /opt/airflow/simple_auth_manager_passwords.json.generated
워커 등록은 flower(http://af01.example.com:5555/)에서 본다. 예제 DAG 를 하나 dags/ 에 넣고 UI 에서 트리거해 워커에서 도는지 확인한다.
airflow dags list
airflow dags trigger <dag_id>
airflow tasks states-for-dag-run <dag_id> <run_id>
airflow config lint 로 검사한다. 2.x 설정 파일을 가져왔으면 airflow config update --fix 로 옮긴다[7].최신 버전 3.3.2 — 2026-09-20 확인. https://pypi.org/project/apache-airflow/ ↩︎
Celery Executor — 2026-09-20 확인. https://airflow.apache.org/docs/apache-airflow-providers-celery/stable/celery_executor.html ↩︎
Prerequisites — 2026-09-20 확인. https://airflow.apache.org/docs/apache-airflow/stable/installation/prerequisites.html ↩︎
Installation from PyPI — 2026-09-20 확인. https://airflow.apache.org/docs/apache-airflow/stable/installation/installing-from-pypi.html ↩︎
Configuration Reference — 2026-09-20 확인. https://airflow.apache.org/docs/apache-airflow/stable/configurations-ref.html · Celery provider: https://airflow.apache.org/docs/apache-airflow-providers-celery/stable/configurations-ref.html ↩︎
Quick Start — 2026-09-20 확인. https://airflow.apache.org/docs/apache-airflow/stable/start.html ↩︎ ↩︎
Upgrading to Airflow 3 — 2026-09-20 확인. https://airflow.apache.org/docs/apache-airflow/stable/installation/upgrading_to_airflow3.html ↩︎