← 학습 카테고리

Learn

Airflow

151개 모듈 · 현재 25번째

Airflow 모듈 25/151 airflow-learn-25

커스텀 실행기 작성하기 — BaseExecutor 인터페이스

Apache Airflow Official Documentation (in-repo snapshot) — Apache Software Foundation core-concepts/executor/index.rst - Writing Your Own Executor (Workloads, BaseExecutor Methods, Compatibility Attributes, CLI, Logging)

이 모듈을 다 읽으면

  • Workload 개념이 무엇을 나타내는지 설명할 수 있다
  • BaseExecutor를 상속할 때 반드시 구현해야 하는 메서드와 선택적으로 구현하는 메서드를 구분할 수 있다
  • Compatibility Attributes가 왜 필요한지 설명할 수 있다

모든 Airflow 실행기는 공통 인터페이스 BaseExecutor를 구현해 pluggable하게 동작한다. 이 모듈은 실행기가 다루는 실행 단위인 Workload, 오버라이드 없이도 쓸 수 있는 헬퍼 메서드, 반드시 구현해야 하는 메서드(sync/execute_async/_process_workloads), 그리고 실행기의 지원 기능을 코어에 알리는 Compatibility Attributes를 다룬다.

Workload — 실행기가 다루는 실행 단위

Executor 맥락에서 Workload란 실행기의 기본 실행 단위다. 워커에서 실행기가 실행하는 하나의 개별 연산이나 작업을 나타내며, 예를 들어 워커에서 실행되는 Airflow 태스크에 담긴 사용자 코드를 실행하는 것도 하나의 workload다. 대표 예시인 ExecuteTask는 토큰, TaskInstanceDTO(태스크 ID, Dag ID, run ID, 시도 횟수, Dag 버전 ID, map_index, pool_slots, queue, priority_weight, executor_config 등), Dag 상대 경로, Dag 번들 정보, 로그 경로를 담아 워커에 전달된다.

핵심 포인트

  • Workload는 실행기가 워커에서 실행하는 최소 단위의 작업(예: ExecuteTask)을 표현하는 객체다
  • ExecuteTask는 TaskInstanceDTO, Dag 상대 경로, Dag 번들 정보, 로그 경로 등을 담아 워커에 전달한다

BaseExecutor의 주요 헬퍼 메서드 (오버라이드 불필요)

다음 메서드들은 커스텀 실행기를 만들 때 오버라이드할 필요는 없지만 알아두면 유용하다. heartbeat는 Airflow 스케줄러 Job 루프가 주기적으로 호출하는 메서드로, 스케줄러와 실행기가 상호작용하는 주요 지점 중 하나다. 일부 메트릭을 갱신하고, 새로 큐잉된 태스크의 실행을 트리거하며, 실행 중/완료된 태스크의 상태를 갱신한다. queue_workload는 Airflow 실행기가 실행할 태스크를 넘겨받기 위해 호출하는 메서드로, BaseExecutor는 이 workload들을 실행기 내부의 큐잉된 workload 목록에 추가하기만 하며 저장소에 있는 모든 실행기가 이 메서드를 사용한다. get_event_buffer는 스케줄러가 실행기가 실행 중인 TaskInstance들의 현재 상태를 가져올 때 호출한다. has_task는 스케줄러가 특정 태스크 인스턴스가 이미 실행기에 큐잉/실행 중인지 판단할 때 쓴다. send_callback은 실행기에 설정된 싱크로 콜백을 보낸다.

핵심 포인트

  • heartbeat는 스케줄러 Job 루프가 주기적으로 호출하며 메트릭 갱신, 큐잉된 워크로드 실행 트리거, 실행/완료 상태 갱신을 담당한다
  • queue_workload는 모든 실행기가 공통으로 쓰는, 워크로드를 내부 큐에 추가하는 메서드다

필수 구현 메서드: sync, execute_async, _process_workloads

실행기가 Airflow에서 지원되려면 최소한 다음 메서드를 오버라이드해야 한다. sync는 실행기 heartbeat 동안 주기적으로 호출되며, 실행기가 알고 있는 태스크들의 상태를 갱신하도록 구현한다. 선택적으로 스케줄러로부터 받은 큐잉된 태스크를 실행 시도하는 로직도 여기 둘 수 있다. execute_async는 workload를 비동기로 실행하는 메서드로, (몇 단계를 거쳐) 스케줄러가 주기적으로 실행하는 실행기 heartbeat 동안 호출된다. 실제로는 실행기에 따라 내부/외부 태스크 큐에 넣기만 하는 경우가 많지만(예: KubernetesExecutor), 태스크를 직접 실행할 수도 있다(예: LocalExecutor). _process_workloads는 queue_workload로 큐잉된 workload 목록을 처리하는 메서드로, heartbeat 동안 호출되며 실행기가 workload 실행을 어떻게 다룰지(워커에 큐잉, 외부 시스템에 제출 등)를 정의한다.

핵심 포인트

  • sync, execute_async, _process_workloads 세 메서드는 실행기를 만들 때 반드시 오버라이드해야 한다
  • execute_async는 실행기에 따라 단순히 큐에 넣기만 할 수도(KubernetesExecutor), 직접 실행할 수도 있다(LocalExecutor)

선택적 인터페이스와 호환성 속성(Compatibility Attributes)

다음 메서드들은 오버라이드가 필수는 아니지만, 구현하면 실행기에 강력한 기능과 안정성을 더할 수 있다. start는 스케줄러 Job이 실행기 객체를 초기화한 후 호출하며, 실행기에 필요한 추가 설정을 여기서 완료할 수 있다. end는 스케줄러 Job이 종료(teardown)될 때 호출되며, 실행 중인 작업을 마무리하기 위한 동기적 정리 작업을 여기서 수행한다. terminate는 더 강제적으로 실행기를 멈추며, 완료를 동기적으로 기다리는 대신 진행 중인 태스크까지 죽이거나 멈춘다. try_adopt_task_instances는 (죽은 스케줄러 Job에서 남겨진 등) 버려진 태스크들을 실행기가 인수하거나 다르게 처리하도록 넘겨주는 메서드로, 인수할 수 없는 태스크는 반환해야 한다(BaseExecutor의 기본 구현은 모든 태스크를 인수 불가능한 것으로 가정). get_cli_commands는 실행기가 사용자에게 CLI 명령을 제공할 수 있게 한다. get_task_log는 실행기가 Airflow 태스크 로그에 포함될 로그 메시지를 제공할 수 있게 한다.

BaseExecutor 클래스 인터페이스에는 Airflow 코어 코드가 실행기의 지원 기능을 판단하는 데 쓰는 호환성 속성(Compatibility Attributes) 집합이 있다. 커스텀 실행기를 만들 때는 이를 용도에 맞게 정확히 설정해야 한다. supports_pickling은 실행 전 파일시스템에서 Dag 정의를 읽는 대신 DB에서 피클링된 Dag를 읽어올 수 있는지 여부다. sentry_integration은 Sentry를 지원한다면 통합을 만드는 콜러블의 import 경로를 지정한다(예: CeleryExecutor는 이를 sentry_sdk.integrations.celery.CeleryIntegration으로 설정). is_local은 실행기가 원격인지 로컬인지를 나타낸다. is_single_threaded는 실행기가 단일 스레드인지를 나타내며 특히 어떤 데이터베이스 백엔드를 지원하는지와 직결된다 — 단일 스레드 실행기는 SQLite를 포함해 어떤 백엔드로도 실행할 수 있다. is_production은 해당 실행기를 프로덕션 목적으로 써야 하는지를 나타내며, 비프로덕션 실행기를 쓰면 사용자에게 UI 메시지가 표시된다. serve_logs는 실행기가 로그 서빙을 지원하는지 여부다.

Airflow 3.2.0부터는 auth manager나 executor 같은 코어 확장 요소를 관리하는 provider 레벨 CLI 명령을 쓸 수 있는데, 불필요할 때 무거운 임포트를 피해 CLI 시작 시간을 줄일 수 있다. 새 실행기를 만들거나 기존 실행기를 갱신할 때는 모듈 레벨에서 비용이 큰 연산/코드를 임포트·실행하지 않도록 주의해야 한다 — 실행기 클래스는 여러 곳에서 임포트되므로, 임포트가 느리면 Airflow 환경 성능, 특히 CLI 명령 성능에 부정적 영향을 준다.

핵심 포인트

  • try_adopt_task_instances로 죽은 스케줄러가 남긴 태스크를 인수할 수 있으며, 기본 구현은 아무것도 인수하지 않는다고 가정한다
  • is_single_threaded 속성은 SQLite 같은 DB 백엔드 지원 여부와 직결된다
  • is_production=False인 실행기를 쓰면 UI에 비프로덕션 경고가 표시된다
  • 실행기 클래스는 여러 곳에서 임포트되므로 모듈 레벨에서 무거운 연산을 하면 CLI 성능이 나빠진다