Airflow docker-compose.yaml 알아보기

ohyujeong·2023년 6월 6일
0

Airflow

목록 보기
3/6
post-thumbnail

Airflow를 설치하는 방법은 다양한데, 그 중 간단하게 로컬에서 Airflow를 실행하기에는 Docker를 이용하는 것이 적절하다고 한다. 아래 공식문서를 통해서 Docker로 Airflow를 설치했는데 설정파일인 docker-compose.yaml 파일 내용이 이해가 잘 안가서 정리해보았다.

Docker 기반 Airflow 설치 공식문서
https://airflow.apache.org/docs/apache-airflow/stable/howto/docker-compose/index.html

YAML

먼저 설정파일의 확장자명인 yaml 에 대해 알아보자면, YAML Ain't Markup Language 의 약자로 사람이 읽을 수 있는 데이터 직렬화 언어로서 구성파일 작성에 자주 사용된다. 최근 사용되는 대부분의 설정파일이 yaml 형식으로 작성되고 있다.

들여쓰기로 계층구조를 표현하여 가독성이 좋고 여러 데이터 유형을 지원하거나 상속/참조가 가능하기 때문에 다양한 용도로 유연하게 활용될 수 있다. 특히 구성 파일, CI/CD 설정, RESTful API에서 데이터 전송 및 구조화된 문서 등에 널리 사용되고 있다.

Docker compose

Docker Compose 는 여러 개의 독립적인 Docker 컨테이너를 정의하고 관리하기 위한 도구이다. Docker Compose 사용을 통해 하나의 호스트에서 여러 컨테이너로 구성된 애플리케이션을 간단한 명령어로 쉽게 실행할 수 있다.

이 도구의 설정파일이 docker-compose.yaml 이고, 서비스, 네트워크, 볼륨 등의 정보가 포함된다. 이 파일에 컨테이너(Service로 정의됨)를 명시하고, 컨테이너의 관계와 의존성, 환경 변수, 포트 매핑, 볼륨 마운트 등을 어떻게 사용할 것인지 작성한다.

이 포스팅을 통해 공식문서에서 제공한 Docker에서 Airflow를 실행할 때 사용되는 docker-compose.yaml 파일을 좀 자세하게 알아보고자 한다. 아래 커맨드로 설정파일을 받을 수 있다.

curl -LfO 'https://airflow.apache.org/docs/apache-airflow/2.6.1/docker-compose.yaml'

Airflow docker-compose.yaml

구성

version

version: "3.8"

Docker Compose 파일 버전정보를 명시한다. 버전에 따라 사용 가능한 기능과 문법이 달라진다. 현재 기준으로 3.8 이 가장 최신 버전이고, 버전 3에서는 servicedeploy 필드를 사용하여 스웜 모드에서 배포 관련 설정을 지정할 수 있다. (버전 2에서는 불가능)

services

services:
  postgres:
    image: postgres:13
    environment:
      POSTGRES_USER: airflow
      POSTGRES_PASSWORD: airflow
      POSTGRES_DB: airflow
    volumes:
      - postgres-db-volume:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "airflow"]
      interval: 10s
      retries: 5
      start_period: 5s
    restart: always

애플리케이션에서 실행될 서비스들을 정의한다. 하나의 서비스를 하나의 컨테이너라고 생각하면 된다. 각 서비스는 이름을 가지며, 해당 서비스에 대한 설정을 포함한다. 위의 예시에서 postfres 는 서비스의 이름이고, image 는 해당 Docker이미지를 사용하겠다는 것을 의미한다. (버전 13의 postgres Docker이미지를 사용하겠다!) 이 외에도 포트를 매핑하거나 환경변수를 설정하는 작업들을 서비스에 맞게 작성하면 된다.

volumes

volumes:
  postgres-db-volume:
  # 정의된 내용 없음

데이터를 저장하고 컨테이너 간에 공유하기 위한 볼륨을 정의한다. 위의 예시에서 postgres-db-volume 은 볼륨의 이름이다. 현재 볼륨의 이름만 설정하고 볼륨을 정의하는 부분이 없는데, 이럴 경우 Docker는 postgres-db-volume이라는 이름의 볼륨을 호스트 시스템의 파일시스템 특정 경로에 자동으로 생성한다.
찾고자 한다면 docker volume inspect postgres-db-volume 명령어를 사용하면 된다.
위의 명령을 실행하면 볼륨에 대한 세부 정보가 표시되고, 그 중 Mountpoint 필드에서 마운트 경로를 확인할 수 있다.

이렇게 설정된 postgres-db-volumeservices-postgres-volumes 에 사용된다.

Airflow services

services:
  postgres: ...
  redis: ...
  airflow-webserver: ...
  airflow-scheduler: ...
  airflow-worker: ...
  airflow-triggerer: ...
  airflow-init: ...
  airflow-cli: ...
  flower: ...

설정 파일에는 총 9개의 Airflow 관련 서비스들이 정의되어 있는데, 그 중 airflow-init 은 처음 Airflow 컨테이너가 시작될 때 실행되어 초기 설정 및 리소스 체크 등을 수행한다.

flower 는 Airflow의 작업 및 작업자(worker) 상태를 모니터링하기 위한 시각적인 웹 기반 인터페이스로, 아래 명령어로 별도로 서비스를 활성화하고 포트를 지정하면 사용할 수 있다.

docker compose --profile flower up

따라서 처음 실행하는 것이 아니라면 아래와 같이 컨테이너가 실행된다. (airflow-init 은 실행되지 않음)

postgres

postgres 서비스는 Airflow에서 사용되는 PostgreSQL 데이터베이스를 실행하는 역할을 한다.

redis

redis 는 인메모리 데이터 구조 저장소로서, 다양한 데이터 유형을 지원하고 메모리 내에서 빠른 데이터 액세스를 가능하게 한다. Airflow에서는 Redis를 메시지 브로커로 사용하여 작업 실행에 필요한 메시지 전달과 상태 관리를 처리한다.

airflow-webserver

airflow-webserver 는 Airflow UI를 제공하며, 워크플로우와 관련된 다양한 작업을 수행할 수 있는 사용자 인터페이스를 제공한다. 웹 브라우저를 통해 접속할 수 있으며(localhost:8080), 워크플로우의 상태, 로그, 스케줄 등을 모니터링하고 관리할 수 있다.

airflow-scheduler

airflow-scheduler 는 정의된 작업(DAG)들을 주기적으로 실행하고, 작업 간의 의존성을 관리하여 워크플로우를 자동으로 조정한다. 설정된 주기에 따라 작업들을 실행하고, 작업의 실행 결과를 추적하고 관리한다.

airflow-worker

airflow-workerscheduler 로부터 할당받은 작업(DAG)들을 비동기적으로 실행한다. 워커는 분산 작업 실행을 위해 Celery Executor를 사용하며(Executor 변경 가능, LocalExecutor로 설정 시 작업을 병렬로 실행하지 않고 순차적으로 처리함), 설정된 작업을 가져와 실행하고 작업의 실행 결과를 보고한다.

airflow-triggerer

airflow-triggerer 는 예약된 작업(DAG)을 트리거하고 실행을 시작하는 역할을 한다. 작업이 특정 조건에 따라 실행되도록 예약하고, scheduler 에게 작업 실행을 요청한다.


Anchor 기능

앵커는 YAML 문서 내에서 재사용 가능한 값을 정의하기 위해 사용된다. 반복되는 설정을 간소화하고 가독성을 높인다. 어떤 변수에 값을 저장하는 것이라고 생각하면 편할 것 같다.

&앵커이름 형식으로 Docker 이미지, 환경 변수, 볼륨, 사용자 및 서비스를 선언한 앵커이름을 통해 사용할 수 있다.

Anchor 정의

x-airflow-common: &airflow-common # anchor 
  image: ${AIRFLOW_IMAGE_NAME:-apache/airflow:2.6.1}
  # build: . # image 설정이 지정되지 않은 경우에 사용, 현재 디렉토리에 있는 Dockerfile을 사용하여 이미지를 빌드하고 해당 이미지를 서비스에 사용함
  environment:
    &airflow-common-env # anchor 
    AIRFLOW__CORE__EXECUTOR: CeleryExecutor # LocalExecutor로 설정 시 작업을 병렬로 실행하지 않고 순차적으로 처리함
    AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: postgresql+psycopg2://airflow:airflow@postgres/airflow
    AIRFLOW__CORE__SQL_ALCHEMY_CONN: postgresql+psycopg2://airflow:airflow@postgres/airflow
    AIRFLOW__CELERY__RESULT_BACKEND: db+postgresql://airflow:airflow@postgres/airflow
    AIRFLOW__CELERY__BROKER_URL: redis://:@redis:6379/0
    AIRFLOW__CORE__FERNET_KEY: ""
    AIRFLOW__CORE__DAGS_ARE_PAUSED_AT_CREATION: "true"
    AIRFLOW__CORE__LOAD_EXAMPLES: "true"
    AIRFLOW__API__AUTH_BACKENDS: "airflow.api.auth.backend.basic_auth,airflow.api.auth.backend.session"
    AIRFLOW__SCHEDULER__ENABLE_HEALTH_CHECK: "true"
    _PIP_ADDITIONAL_REQUIREMENTS: ${_PIP_ADDITIONAL_REQUIREMENTS:-}
  volumes:
    - ${AIRFLOW_PROJ_DIR:-.}/dags:/opt/airflow/dags
    - ${AIRFLOW_PROJ_DIR:-.}/logs:/opt/airflow/logs
    - ${AIRFLOW_PROJ_DIR:-.}/config:/opt/airflow/config
    - ${AIRFLOW_PROJ_DIR:-.}/plugins:/opt/airflow/plugins
    - ${AIRFLOW_PROJ_DIR:-.}/outputs:/opt/airflow/outputs
  # Airflow 컨테이너 내에서 실행되는 사용자를 지정
  user: "${AIRFLOW_UID:-50000}:0"
  depends_on: # Airflow 서비스가 시작되기 전에 Redis와 PostgreSQL 서비스가 준비되어야 함을 의미함
    &airflow-common-depends-on 
    redis:
      condition: service_healthy
    postgres:
      condition: service_healthy
      

Anchor 사용

*앵커이름 형식으로 정의한 Anchor를 사용할 수 있다.

   airflow-scheduler:
    <<: *airflow-common
    command: scheduler
    healthcheck:
      test: ["CMD", "curl", "--fail", "http://localhost:8974/health"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 30s
    restart: always
    depends_on:
      <<: *airflow-common-depends-on
      airflow-init:
        condition: service_completed_successfully

<<: *airflow-common 에서 << 는 병합을 나타낸다. 즉, airflow-common 의 내용과 airflow-scheduler 에 설정한 내용을 합친다고 생각하면 된다.

환경변수 사용

  volumes:
    - ${AIRFLOW_PROJ_DIR:-.}/dags:/opt/airflow/dags
    - ${AIRFLOW_PROJ_DIR:-.}/logs:/opt/airflow/logs
    - ${AIRFLOW_PROJ_DIR:-.}/config:/opt/airflow/config
    - ${AIRFLOW_PROJ_DIR:-.}/plugins:/opt/airflow/plugins
    - ${AIRFLOW_PROJ_DIR:-.}/outputs:/opt/airflow/outputs

여기서 ${AIRFLOW_PROJ_DIR:-.} 은 환경 변수 AIRFLOW_PROJ_DIR 의 값을 사용하되, 값이 설정되어 있지 않은 경우 기본값으로 현재 디렉토리(.)을 사용한다는 의미이다.
마찬가지로 user: "${AIRFLOW_UID:-50000}:0" 의 경우에서도 AIRFLOW_UID 환경변수가 없다면 500000 과 매핑한다.

종속성 설정

depends_on 속성으로 아래 옵션을 선택하여 종속성을 설정한다.

  • service_healthy : 종속성 서비스의 건강 상태를 확인한다. 종속성 서비스가 실행 중이고 정상적인 상태이면 서비스가 시작된다.
  • service_started : 종속성 서비스의 시작 상태를 확인한다. 종속성 서비스가 실행되기 시작하면 서비스가 시작된다.
  • service_completed_successfully : 종속성 서비스의 실행이 성공적으로 완료되었는지 확인한다. 종속성 서비스가 정상적으로 실행되고 완료된 경우에만 서비스가 시작된다.
  • service_failed : 종속성 서비스의 실패 상태를 확인한다. 종속성 서비스가 실패한 경우 서비스가 시작되지 않는다.
x-airflow-common: &airflow-common # anchor 
...
  depends_on: &airflow-common-depends-on # anchor 
    redis:
      condition: service_healthy
    postgres:
      condition: service_healthy

이 부분에서는 Airflow 서비스가 시작되기 전에 Redis와 PostgreSQL 서비스의 건강상태를 확인(health check)하여 정상적 상태이면 서비스가 시작되는 종속성을 설정하고 있다.

Port 설정

port 노출

  redis:
    image: redis:latest
    expose:
      - 6379
    ...

expose 값을 설정하여 컨테이너 내에서 다른 컨테이너가 해당 포트에 접근할 수 있도록 포트를 공개한다. 호스트 머신에서 접근하게 하려면 ports 설정으로 포트 매핑이 필요하다.

port 매핑

  airflow-webserver:
    <<: *airflow-common
    command: webserver
    ports:
      - "8080:8080"
    ...

ports 설정은 Docker Compose에서 컨테이너의 포트를 호스트의 포트와 연결한다. 컨테이너 내의 서비스 포트를 호스트에 노출시켜 외부에서 해당 포트를 통해 컨테이너에 접근할 수 있도록 해준다.

<호스트 포트>:<컨테이너 포트> 형태로 호스트와 컨테이너의 포트를 매핑하면 되고, 호스트 포트와 컨테이너 포트는 서로 다를 수도 있고, 같을 수도 있다. 여러 포트의 매핑이 가능하다.

정리하자면 expose 설정은 컨테이너 간 통신을 위한 내부 포트 공개에 사용되지만, 외부에서 컨테이너에 접근하기 위해서는 ports 설정을 사용해야 한다.

profile
거친 돌이 다듬어져 조각이 되듯

0개의 댓글