14 min read

Airflow install using docker-compose on mac-mini by kr

1. Airflow란?

Apache Airflow는 워크플로우를 작성하고 실행하는 오픈소스 도구로, 데이터 파이프라인 자동화 및 스케줄링을 위한 강력한 기능을 제공합니다. DAG(Directed Acyclic Graph)를 사용하여 작업을 정의하고 실행할 수 있으며, UI를 통해 작업 상태를 쉽게 모니터링할 수 있습니다.

  • 제가 가장 선호하는 기능은 로그(log)와 코드(code)를 공유할 수 있는 점입니다.
    • 스케줄링 기능은 Cron과 비슷하지만, 실행 결과와 로그(log)를 웹(Web)에서 바로 확인할 수 있다는 점이 가장 마음에 듭니다.
    • web ui 를 통해서 코드를 바로 보아서, 공유 확인이 편한 것또한 강점으로 생각합니다.
    • backfill 기능이 강력하다고 알려져 있으나, 저는 딱히 backfill 기능을 사용해 본적은 없습니다.
      • 회사에서 backfill은 아니고, task clear 로 기존 작업을 덮어 씀 --> execute_date 설정 필요

2. Mac Mini 환경 설정

Airflow를 Docker Compose로 실행하기 위해 Mac Mini에서 필요한 환경을 먼저 설정합니다.

2.1 필수 소프트웨어 설치

Mac에서 Airflow를 실행하려면 다음이 필요합니다:

  • DockerDocker Compose (Homebrew를 이용하여 설치 가능)
  • Python 3 (Airflow 설정을 위해 필요)
    • 저는 python은 pyenv를 통해서 실행합니다.
    • airflow는 docker를 이용해서 작업하기 때문에, 실행을 위해서 python은 따로 설치할 필요는 없습니다.
      • 그러나 dag를 짤때에는 airflow package가 있어야지, 코드 작성이 편해집니다.

설치가 되어 있지 않다면, Homebrew를 이용하여 다음과 같이 설치합니다:

brew install --cask docker
brew install python

Docker 설치 후, Docker Desktop을 실행하여 정상적으로 동작하는지 확인합니다.

3. Airflow Docker Compose 설치 및 실행

3.1 Airflow 공식 Docker Compose 파일 다운로드

Airflow 공식 GitHub에서 Docker Compose 파일을 가져옵니다.

mkdir airflow && cd airflow
curl -LfO 'https://airflow.apache.org/docs/apache-airflow/2.10.3/docker-compose.yaml'

최신 버전

curl -LfO 'https://airflow.apache.org/docs/apache-airflow/stable/docker-compose.yaml'
    • 저는 이전에 다운 받은 docker-compose를 구글 클라우드에 백업을 해놓아서, 해당 파일을 저렇게 받은 것이라고 확답은 하지 못합니다. --> chat gpt가 저렇게 하라고 공유 해줌
    • 참고로 저는 아래와 같은 것은 docker가 아닌 실제로 설치 하여 사용하고 있습니다.
      • PostgreSQL
      • Redis
    • 실제 설치된 것을 사용하기에 docker-compose의 services: 의 postgres와 redis 부분은 전부 주석처리 합니다.

참고로 이건 예전에 받은 것이라서 정확하지는 않습니다.

environment: &airflow-common-env
	AIRFLOW__CORE__EXECUTOR: CeleryExecutor
	AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: postgresql+psycopg2://id:password!@localhost/airflow_db?sslmode=disable
	AIRFLOW__CELERY__RESULT_BACKEND: db+postgresql://id:password!@localhost/airflow_db
	AIRFLOW__CELERY__BROKER_URL: redis://:@localshot:6379/0
	AIRFLOW__CORE__FERNET_KEY: ""
	AIRFLOW__CORE__DAGS_ARE_PAUSED_AT_CREATION: "true"
	AIRFLOW__CORE__LOAD_EXAMPLES: "false"
	AIRFLOW__API__AUTH_BACKENDS: "airflow.api.auth.backend.basic_auth,airflow.api.auth.backend.session"
	# yamllint disable rule:line-length
	# Use simple http server on scheduler for health checks
	# See https://airflow.apache.org/docs/apache-airflow/stable/administration-and-deployment/logging-monitoring/check-health.html#scheduler-health-check-server
	# yamllint enable rule:line-length
	AIRFLOW__SCHEDULER__ENABLE_HEALTH_CHECK: "true"
	# WARNING: Use _PIP_ADDITIONAL_REQUIREMENTS option ONLY for a quick checks
	# for other purpose (development, test and especially production usage) build/extend Airflow image.
	_PIP_ADDITIONAL_REQUIREMENTS: ${_PIP_ADDITIONAL_REQUIREMENTS:-}
services:
	# postgres:
	# #image: postgres:13
	# image: busybox
	# # environment:
	# # POSTGRES_USER: airflow
	# # POSTGRES_PASSWORD: airflow
	# # POSTGRES_DB: airflow
	# # volumes:
	# # - postgres-db-volume:/var/lib/postgresql/data
	# healthcheck:
	# test: ["CMD", "pg_isready", "-h", "192.168.0.1", "-U", "admin"]
	# interval: 10s
	# retries: 5
	# start_period: 5s
	# # restart: always
	# command: ["sleep", "infinity"]
	
	# redis:
	# # Redis is limited to 7.2-bookworm due to licencing change
	# # https://redis.io/blog/redis-adopts-dual-source-available-licensing/
	# # image: redis:7.2-bookworm
	# # image: redis:7.2-bookworm
	# image: busybox
	# # expose:
	# # - 6379
	# healthcheck:
	# test: ["CMD", "redis-cli", "-h", "192.168.0.2", "ping"]
	# interval: 10s
	# timeout: 30s
	# retries: 50
	# start_period: 30s
	# # restart: always
	# command: ["sleep", "infinity"]
	
	airflow-webserver:

3.2 환경 변수 설정

Airflow에서 사용할 .env 파일을 생성하여 기본 설정을 추가합니다.

echo -e "AIRFLOW_UID=$(id -u)\nAIRFLOW_GID=0" > .env
  • Mac에서는 파일 권한 문제를 피하기 위해 AIRFLOW_GID=0으로설정하는 것이 권장됩니다 라고 합니다.. by chatgpt
  • 저는 .env 파일에 GID를 넣지를 않았습니다. 저는 아래과 같이 airflow의 폴더 구조를 정의 하였습니다.
    • 아래에서 /path/to/airflow/project 는 아래의 dags, logs 등의 폴더구조가 있는 곳입니다.
AIRFLOW_PROJ_DIR=/path/to/airflow/project/airflow
  • 파일 구조
├── .env
└── docker-compose.yaml

3.3 폴더 구조 생성

Airflow 실행을 위해 필요한 폴더를 생성합니다.

mkdir -p dags logs plugins
  • 폴더 구조
    • 참고로 config 안에는 아무것도 없습니다.
.
├── config
├── dags
├── logs
└── plugins

3.4 Docker 컨테이너 실행

다음 명령어를 실행하여 Airflow 컨테이너를 시작합니다.

docker-compose up -d

Airflow의 모든 서비스(Webserver, Scheduler 등)가 실행되면, UI에 접속할 수 있습니다.

3.5 Web UI 접속 확인

브라우저에서 http://localhost:8080으로 접속하여 Airflow UI가 정상적으로 실행되는지 확인합니다. 기본 로그인 정보는 다음과 같습니다:

  • Username: airflow
  • Password: airflow

4. 간단한 DAG 실행 테스트

4.1 기본 제공 DAG 활성화

Airflow에서는 기본으로 제공되는 예제 DAG가 비활성화되어 있습니다. airflow.cfg 파일을 수정하여 활성화할 수 있습니다.

docker-compose exec webserver airflow config set core load_examples True
  • 참고로 저는 예제 dag를 비 활성화 했습니다. 그리고 docker-compose의 명령어로 한게 아니고, docker-compose.yml에 직접 넣어서 했습니다.
    • AIRFLOW__CORE__LOAD_EXAMPLES: "false" 를 검색하시면 됩니다.
    • 처음에는 예제로 확인을 하려고 했는데, log가 장난아니게 쌓여 버려서 삭제를 했습니다.
    • 저는 airflow 를 동작시킬때 log 처리가 가장 힘들었습니다 --> 굉장히 많이 쌓임

4.2 예제 DAG 실행

Airflow UI에서 DAGs 페이지로 이동한 후, example_bash_operator DAG를 실행하여 정상적으로 동작하는지 확인합니다.

5. Mac 환경에서의 최적화 및 문제 해결

5.1 컨테이너 리소스 제한 설정

Mac 환경에서는 Docker가 과도한 리소스를 사용하지 않도록 설정하는 것이 중요합니다. Docker Desktop에서 Preferences > Resources에서 CPU 및 RAM을 조정할 수 있습니다.

  • 저는 Disk usage도 잘 지정하라고 이야기 하고 싶습니다. Disk usage가 맥에서 시스템 데이터로 잡히게 되는데, 이게 아마 비례해서 크기가 줄었다가 늘어났다 하는것 같습니다 --> 예측
    • 줄어드는 건 문제가 아닌데, 늘어날때 잡은 크기에 비례를 하는데 시스템 데이터로 잡혀서 컨트롤이 불가능 합니다.
    • 저는 늘어날때 디스크 용량을 100% 사용하여, 몇번 크래시가 발행했고(다행히 껏다 키면 다시 정상화 됨), 그래서 2번 정도 리셋했습니다.
    • 저는 아래의 설정에서 작업한것이 아니고, 로그를 실제 찾아봐서 삭제하는 dag를 만들었습니다.
    • airflow.cfg 파일에서 로그 유지 기간 설정
    • 혹은 docker-compose.yml에서 AIRFLOW__LOGGING__LOGGING_LEVEL을 조절하는 방법.

로그 관련 chat gpt의 추천

[core]
base_log_folder = /path/to/logs
logging_level = INFO
log_retention_days = 7

5.2 포트 충돌 문제 해결

기본적으로 Airflow는 8080 포트를 사용하지만, 다른 프로세스에서 이미 사용 중일 경우 변경해야 합니다. docker-compose.yaml에서 다음과 같이 수정합니다:

  webserver:
    ports:
      - "9090:8080"

이후, http://localhost:9090에서 UI를 확인할 수 있습니다.

5.3 볼륨 권한 문제 해결

Mac 환경에서는 볼륨 마운트 시 권한 문제가 발생할 수 있습니다. docker-compose.yaml에서 volumes 섹션을 확인하고, 필요 시 chmod 명령을 사용하여 적절한 권한을 부여합니다.

5.4 여러 개의 DAG 동시 실행 및 최적화

  • 여러 DAG를 동시에 실행하려면 airflow.cfg에서 max_active_runs_per_dag 값을 증가시켜야 합니다.
  • 특정 DAG 간 의존성이 있다면 TriggerDagRunOperator를 사용하여 순차 실행을 조정할 수 있습니다.
  • DAG 실행 시 과부하 방지를 위해 concurrencydag_concurrency 값을 적절히 조정해야 합니다.
concurrency = 8
dag_concurrency = 4

이 설정을 통해 각 DAG가 최대 4개씩 동시에 실행될 수 있으며, 전체적으로는 8개의 태스크가 동시 실행됩니다.

6. 결론

이 글에서는 Mac Mini에서 Docker Compose를 이용해 Airflow를 설치하고 실행하는 과정을 다뤘습니다. 기본 DAG 실행을 통해 정상 동작 여부를 확인하고, Mac 환경에서 발생할 수 있는 몇 가지 문제 해결 방법도 소개했습니다.

Airflow를 활용하여 보다 복잡한 데이터 파이프라인을 구축할 수 있으며, 이후에는 외부 데이터 소스 연동, 사용자 정의 Operator 추가, Kubernetes Executor 사용과 같은 고급 기능을 실험해볼 수 있습니다.

참고 사항 : Backfill

Airflow의 Backfill 기능은 과거의 특정 기간 동안 실행되지 않은 DAG 실행을 보충하는 기능입니다. 주로 DAG가 추가되거나 수정된 후, 과거 데이터를 다시 처리할 필요가 있을 때 사용됩니다.

🔹 Backfill의 개념

  • Airflow는 DAG의 실행 날짜(execution_date)를 기준으로 실행됩니다.
  • 특정 기간 동안 DAG 실행이 누락되었거나, 새로운 DAG를 추가했을 때 과거 데이터를 처리하려면 backfill 기능을 사용합니다.
  • Backfill은 DAG의 스케줄에 따라 과거 날짜로 실행되며, 해당 기간 동안 실행되지 않은 태스크들을 보완합니다.

🔹 Backfill 실행 방법

Airflow CLI를 사용하여 특정 DAG의 과거 실행을 강제 수행할 수 있습니다.

airflow dags backfill -s 2024-02-01 -e 2024-02-10 my_dag_id
  • -s 2024-02-01: 시작 날짜 (Start Date)
  • -e 2024-02-10: 종료 날짜 (End Date)
  • my_dag_id: 실행할 DAG ID

위 명령어는 my_dag_id DAG를 2024년 2월 1일부터 2024년 2월 10일까지 실행합니다.

🔹 Backfill 사용 시 주의점

    • DAG 정의에서 catchup=False로 설정된 경우, backfill이 자동으로 실행되지 않습니다.
    • Backfill을 수행하려면 DAG의 catchup 설정을 True로 변경해야 합니다.
    • 백필 작업이 많은 경우, 병렬 실행을 설정하여 빠르게 처리할 수 있습니다.
    • airflow.cfg에서 parallelismmax_active_runs_per_dag 값을 조정하여 최적화할 수 있습니다.
  1. 리소스 사용량 고려
    • Backfill은 과거의 여러 DAG 실행을 동시에 수행하기 때문에, CPU/메모리 사용량이 증가할 수 있습니다.
    • Scheduler 및 Worker 노드의 성능을 고려하여 적절한 설정을 해야 합니다.

병렬 실행 최적화

parallelism = 10 
max_active_runs_per_dag = 5

catchup 설정 확인

dag = DAG(
    'my_dag',
    default_args=default_args,
    schedule_interval='@daily',
    catchup=True  # 과거 실행을 허용
)

🔹 Backfill을 활용하는 경우

✅ 새로운 DAG 추가 후 과거 데이터 처리
✅ DAG 수정 후 과거 데이터에 대해 동일한 논리를 적용할 때
✅ 특정 기간 동안 DAG이 정상적으로 실행되지 않았을 경우 재실행

참고사항 : Executor

Airflow의 Executor

Airflow의 Executor는 태스크를 실행하는 방식을 결정하는 중요한 구성 요소입니다. Airflow에서 지원하는 주요 Executor 유형은 다음과 같습니다:

  • 참고로 저는 Home server 에서 설치 하기 때문에 Celery가 아닌 LocalExecutor나 StandaloneExecutor 면 될 것 같은데 테스틑 한다고 Celery를 적용 했습니다
  1. SequentialExecutor
    • 한 번에 하나의 태스크만 실행 가능
    • SQLite와 함께 사용할 때 기본 Executor
    • 작은 테스트 환경에서만 사용 추천
  2. LocalExecutor
    • 여러 태스크를 병렬로 실행 가능
    • 단일 머신에서 실행되며, multiprocessing을 사용
    • 개발 환경 또는 소규모 프로덕션 환경에 적합
  3. CeleryExecutor
    • 여러 워커 노드에서 태스크를 병렬로 실행 가능
    • 메시지 브로커(Redis, RabbitMQ 등)와 Celery를 사용
    • 대규모 분산 환경에서 적합
  4. KubernetesExecutor
    • 태스크마다 개별적인 Kubernetes Pod에서 실행
    • 리소스 격리 및 확장성 우수
    • 클라우드 환경에서 최적
  5. DaskExecutor
    • Dask를 이용한 분산 실행
    • 동적 스케일링 및 병렬 처리를 지원
  6. StandaloneExecutor (Airflow 2.7 이상)
    • LocalExecutor와 유사하지만 설정이 간단
    • airflow standalone 명령으로 손쉽게 실행 가능

참고사항 : Flower

Flower란? (Airflow에서의 역할)

Flower는 Celery 작업을 모니터링할 수 있는 웹 기반 대시보드입니다. Airflow에서 CeleryExecutor를 사용할 때 워커 상태 및 태스크 실행 상태를 쉽게 확인할 수 있습니다.

Flower의 주요 기능

  • 현재 실행 중인 Celery 태스크 모니터링
  • 각 Celery 워커의 상태 확인
  • 태스크 재시도 및 취소 기능
  • 실행 로그 및 작업 큐 확인 가능

Airflow에서 Flower 실행하는 방법

CeleryExecutor를 사용하는 경우, 아래 명령어로 Flower UI를 실행할 수 있습니다:

airflow celery flower

그런데 docker-compose에는 아래와 같이 적혀 있습니다.

# You can enable flower by adding "--profile flower" option e.g. docker-compose --profile flower up
# or by explicitly targeted on the command line e.g. docker-compose up flower.

실행 후, 브라우저에서 http://localhost:5555에 접속하면 Flower UI를 통해 Celery 작업을 모니터링할 수 있습니다.

  • 저는 실행을 해보지 않았습니다.

참고사항 : Using Airflow cli with docker-compose

현재 docker-compose.yamlairflow-cli 서비스에는 profiles: - debug가 지정되어 있으므로, 해당 컨테이너는 docker-compose --profile debug up을 실행해야 활성화됩니다.
즉, docker-compose up만 실행하면 airflow-cli는 뜨지 않고, --profile debug 옵션을 추가해야 실행됩니다.

또한, Airflow 명령어(airflow dags list 등)를 실행하려면 airflow-cli 컨테이너 내부에서 실행해야 합니다.
이를 위해 다음과 같이 실행하면 됩니다:

docker-compose run --rm airflow-cli airflow dags list

이 명령어는 airflow-cli 컨테이너를 실행하고, 명령어가 끝나면 컨테이너가 자동 종료됩니다.
만약 컨테이너 내부에서 계속 작업하려면:

docker-compose run --rm airflow-cli bash

이렇게 하면 CLI가 실행된 컨테이너 내부로 들어가서 원하는 Airflow 명령어를 실행할 수 있습니다.

참고사항 : Disk usage 문제 해결 방안

  • Docker의 볼륨을 정리하는 명령어 추가:
docker system prune -a --volumes
  • Airflow 로그 디렉토리를 주기적으로 정리하는 크론 작업 추가:
find /path/to/airflow/logs -type f -mtime +7 -delete
  • 컨테이너 재시작 자동화
    • docker-compose up -dlaunchctl 혹은 cron을 이용하여 자동화.