Перейти к содержанию
Learning Platform
Глоссарий
Troubleshooting

Troubleshooting — Apache Airflow 2

База знаний типичных ошибок курса Apache Airflow 2.

Категория

Показано 14 из 14 ошибок

Симптомы

  • scheduler.scheduler_loop_duration метрика > 5000ms
  • Задачи долго переходят из scheduled в queued
  • UI медленно обновляется

Причина

DAG parse блокирует scheduler loop (в 2.x) Слишком много DAG файлов на медленной FS Метаданные в БД росли — индексы фрагментированы

Решение

  1. В 3.0 вынести парсинг в standalone DAG Processor (mandatory)
  2. Использовать gitSync sidecar на local SSD
  3. Increase parsing_processes до 2x vCPU
  4. Запустить VACUUM ANALYZE на task_instance, dag_run, log, xcom
  5. Очистить старую историю: airflow db clean --keep-last 28

Симптомы

  • TaskInstance в queued > 5 минут
  • Worker idle, но задачи не подбираются

Причина

Executor heartbeat миссит (Celery worker крашится) Pool slots exhausted Priority weight tasks конкурируют worker_prefetch_multiplier > 1 + long task блокирует slot Broker (Redis/RabbitMQ) недоступен

Решение

  1. Проверить celery worker logs: docker compose logs worker | grep ERROR
  2. Проверить broker connectivity: docker exec airflow-scheduler airflow celery inspect ping
  3. SELECT * FROM slot_pool WHERE used_slots = occupied_slots → exhausted
  4. Установить worker_prefetch_multiplier = 1 для long-task workloads
  5. Adopt orphans: ждать adopt_or_reset_orphaned_tasks или restart scheduler

Симптомы

  • В Postgres log: 'process X waiting for ShareLock on transaction'

Причина

HA scheduler конкурирует за critical section на slot_pool Это нормально до PR #19842 (Airflow 2.4+)

Решение

  1. Это ожидаемое поведение — игнорировать
  2. Если 2 scheduler-а часто спят (looks idle) — уменьшить scheduler_heartbeat_sec или max_dagruns_per_loop_to_schedule

Симптомы

  • Deadlocks
  • Task пропадают в queued

Причина

MariaDB < 10.6 не имеет SKIP LOCKED / NOWAIT

Решение

  1. Upgrade MariaDB до 10.6+
  2. Или мигрировать на PostgreSQL (golden path для Airflow)

Симптомы

  • Task с короткой логикой (1s работы) занимает 20+ секунд от submission до completion

Причина

Pull image занимает время K8s scheduler placement Init container Python interpreter cold start

Решение

  1. Pre-pull image на nodes через DaemonSet
  2. Minimize image size — use slim base, multi-stage build
  3. ImagePullPolicy: IfNotPresent
  4. Skip init container если возможно
  5. Для short-task — switch на CeleryExecutor через Pluggable Executors AIP-61

Симптомы

  • Pod killed reason: OOMKilled
  • Task fails with retcode 137

Причина

Worker concurrency × memory per task > pod memory limit Memory leak в user code XCom через pickle с large objects

Решение

  1. Reduce worker_concurrency
  2. Set worker_max_tasks_per_child = 100 (recycle worker)
  3. Use custom XCom backend (S3) для больших данных
  4. Set lifecycle.preStop hook для graceful flush heartbeat

Симптомы

  • TI в state=running, latest_heartbeat > scheduler_zombie_task_threshold назад

Причина

Worker OOMKilled / SIGKILL Node spot termination Network partition

Решение

  1. Ждать scheduler-зачистку (default 300s)
  2. Set retries >= 1 в задачах
  3. K8s: terminationGracePeriodSeconds: 120, pre-stop hook flush heartbeat
  4. Spot nodes: nodeAffinity на on-demand для критичных задач

Симптомы

  • DAG parse медленный
  • Vault/Secrets Backend под нагрузкой

Причина

Variable.get вызывается на уровне модуля (top-level), не внутри task

Решение

  1. Перенести Variable.get внутрь task callable
  2. [secrets] use_cache = True (в 3.x default)
  3. Использовать ENV variables для DAG-конфигов

Симптомы

  • DAG появился — сразу 730 DagRun-ов started

Причина

catchup=True по умолчанию start_date = 2 года назад

Решение

  1. Всегда catchup=False для новых DAGs
  2. При migration: airflow dags pause <dag_id> → clear → unpause
  3. Set max_active_runs_per_dag для smooth catchup

Симптомы

  • metadata DB > 100GB
  • Slow queries

Причина

log table занимает 70% (если DB log handler enabled) task_instance row count 10M+ xcom — pickled large objects task_reschedule retention отсутствует

Решение

  1. Disable DB log handler — use S3/GCS/ES remote logging
  2. airflow db clean --keep-last 28 (cron daily)
  3. pg_partman для partition log/xcom/task_instance по дате
  4. VACUUM FULL periodic
  5. Custom XCom backend (S3) для блобов

Симптомы

  • sqlalchemy errors
  • Cursor lost between transactions

Причина

PgBouncer transaction mode + Airflow server-side cursors

Решение

  1. Session mode (pool_mode = session) в PgBouncer
  2. Или tune sql_alchemy_pool* carefully
  3. Или transaction mode + sql_alchemy_pool_pre_ping = True

Симптомы

  • В полночь scheduler loop сотни ms
  • Все DAGs queue одновременно

Причина

Все DAGs с @daily расписанием на одном моменте

Решение

  1. Random schedule offsets: schedule='30 1 * * *' — разнести по часам
  2. Custom Timetable с jitter
  3. max_active_runs_per_dag = N для горизонтального ограничения

Симптомы

  • Worker slots все заняты sensor-ами
  • Real tasks ждут

Причина

@task(mode='poke') sensor с 24h timeout

Решение

  1. Switch на mode='reschedule' — освобождает slot между poke
  2. Или deferrable=True — переходит в triggerer (asyncio)
  3. 1000 deferred sensors = 1 triggerer; 1000 poke sensors = 1000 worker slots

Симптомы

  • start_date сдвигается на каждом parse
  • Backfill результаты различаются

Причина

start_date = datetime.now() — недетерминированно

Решение

  1. Hardcode: start_date = datetime(2024, 1, 1)
  2. Никогда не вызывать datetime.now() в DAG body или decorators