Планируем и запускаем дата-конвейеры с Apache AirFlow и Dagster

Автор Категория ,
Планируем и запускаем дата-конвейеры с Apache AirFlow и Dagster

Продолжая сравнивать Apache AirFlow с Dagster, сегодня рассмотрим особенности развертывания и эксплуатации этих оркестраторов ETL-процессов и конвейеров обработки данных. Читайте далее о плюсах изоляции процессов, отделения системных служб от пользовательского кода, сложностях планирования и запуска задач, а также способах их решения с помощью современных инструментов дата-инженера.

В изолятор: как развернуть и выполнить Big Data Pipeline, не мешая другим

Помимо базовых возможностей планирования и запуска batch-процессов по расписанию, оркестратор должен быть надежной, многопользовательской платформой, которая позволяет различным командам надежно разворачивать необходимые им системы независимо друг от друга. Таким образом, в крупной Big Data инфраструктуре оркестратор, такой как Apache AirFlow, Dagster или другие аналоги (Luigi, Argo, MLFlow и KubeFlow), о которых мы писали здесь, становится многопользовательской и мульти-инструментальной платформой, которая должна масштабироваться технически и организационно. Требования и особенности работы одной команды к этой среде не должны влиять на других участников. Также должна быть защита от сбоев, чтобы ошибки отдельных пользователей, команд или приложений не привели к остановке всего оркестратора. За это отвечает изоляция процессов, которая реализована в AirFlow и Dagster по-разному.

Архитектура Airflow состоит из множества компонентов, включая:

  • централизованный планировщик, отвечающий за планирование запусков и задач;
  • веб-сервер;
  • набор worker’ов для обработки задач.

Планировщики и worker’ы загружают и обрабатывают все цепочки задач (DAG, Directed Acyclic Graph) с частым интервалом, по умолчанию равным 1 минуте. При этом все пользовательские DAG’и и компоненты Airflow существуют в одном процессе Python, что имеет ряд недостатков [1]:

  • сложные зависимости, включая связи между пакетами, должны существовать в одной среде Python. Но разным командам обычно нужны различные пакеты, версии пакетов или версии Python. Облегчить процесс управления этим множеством пакетов можно через их публикацию в виде общедоступных провайдеров, что предоставляет 2-я версия фреймворка. Однако, данный способ увеличивает накладные расходы на дата-инженерию и усложняет процесс обновления операторов Airflow и самой платформы.
  • хрупкость системы – ошибки DAG’а одной команды в production-среде, могут вывести из строя всю платформу. Аналогично, падение скорости разработки DAG’ов снизит производительность планирования задач для всех задач и команд.
  • монолитное развертывание несмотря на перераспределение пакетов и механизм провайдеров во 2-ой версии фреймворка, о чем мы писали здесь, все команды в экземпляре Airflow должны развертываться монолитно. Это вызывает проблемы с надежностью, т.к. процессы Airflow могут оценивать эти файлы во время неатомарного обновления, например, операции git или команды rsync. Пользователи вынуждены приостанавливать процессы планировщика, обновлять код, а затем возобновлять планирование, что снижает скорость работы и усложняет процессы развертывания.

Таким образом, команда дата-инженеров должна выбирать между управлением одним хрупким и трудно масштабируемым экземпляром Airflow, множеством экземпляров или детальным структурированием всех DAG’ов, чтобы вывести из процесса всю бизнес-логику и инфраструктуру. Это можно реализовать, совмещая AirFlow с Kubernetes. Помимо непосредственного запуска оркестратора на платформе управления контейнерами, для вывода всех пользовательских вычислений из процесса управления конвейером можно использовать только операторы Kubernetes [2]. Но это предполагает игнорирование экосистемы встроенных операторов и интеграций AirFlow, а также меняет ее на более сложную локальную среду разработки, вводя вводит жесткую зависимость от Kubernetes.

При использовании нескольких экземпляров AirFlow можно централизованно управлять ими или делегировать операционную нагрузку профильным командам. Но это увеличивает организационную сложность системы и допускает разрозненные зависимости между конвейерами разных командам.

В отличие от AirFlow, в Dagster системные и пользовательские процессы четко разделены. Системные процессы (веб-сервер и службы) не загружают написанный пользователем код в память, а конвейеры, ресурсы и другие определения сгруппированы в репозитории и доступны через API. Это дает следующие преимущества [1]:

  • изолированные зависимости позволяют разным командам использовать различные пакеты и избежать технических проблем, таких как завышенные размеры Docker-образов, неразрешимые конфликты и несоответствие версий пакетов и языка Python. Кроме того, пользовательские зависимости отделены от зависимостей компонентов самой системы Dagster.
  • Надежность – изоляция процессов предохраняет от ошибок, вызванных действиями одной из инженерных командозначает более надежную систему. Даже критический сбой или приостановка разработки конвейера не повлияют на общесистемные операции.
  • Независимое атомарное развертывание – когда пользователи Dagster обновляют код, они обновляют репозиторий без перезапуска системных процессов, что более надежно, чем постоянная перезагрузка кода.

3 отличия Airflow и Dagster в планировании и запуске задач

В Airflow за политику выполнения задач отвечают исполнители (executors), которые действуют на уровне экземпляра, что ограничивает их гибкость. Они должны постоянно загружать все задачи из всех работающих DAG’ов. Больше DAG, задач и запусков означает больше рабочих узлов (worker’ов), каждый из которых должен обрабатывать больше данных. Это узкое место масштабируемости и точка отказа. Также в AirFlow нет возможности изолировать выполнение на уровне выполнения.

В Dagster системный демон отвечает за планирование запусков, а не задач, что позволяет использовать преимущества многоуровневого разделения. В этом подходе запуски Dagster управляются с помощью одноцелевых вычислительных ресурсов, таких как процессы или Kubernetes Jobs, отвечающих за планирование задач. Каждый из этих ресурсов может выбрать собственную политику планирования задач и использует преимущества полностью эластичных вычислений в общедоступных облаках. Таким образом, гибкое планирование задач в Dagster позволяет выполнять развертывание с учетом потребностей пользователей, настраивая параллелизм на нужном им уровне без сложного управления централизованной инфраструктурой.

Также стоит сказать про планирование запусков на основе событий, например, запуск задачу/конвейера при обновлении корзины в AWS S3 независимо от временного расписания, такого как ежедневно в 10:00. За это в AirFlow отвечают датчик или сенсор – особый вид операторов, цель которого в ожидании определенного триггера, например, успешного завершения внешней задачи. Она может работать вечно, но существует в DAG’е, который требует расписания, основанного на времени, например, ежедневно. Моделировать частоту обновления состояния, от которого зависит сенсор, с расписанием включающего DAG’а неудобно. Например, ежедневный запуск ожидает события от корзины AWS S3, которая может обновляться дважды в день. Сообщать время выполнения нецелесообразно, т.к. сенсор просто ждет возникновения события, а не выполняет вычисления. Кроме того, несмотря на нововведения Apache AirFlow 2.0 под названием «умный датчик» (Smart Sensor), цель которого оптимизировать использование ресурсов, датчики занимают слот в рабочем пуле, потребляя ЦП и память. Чтобы сократить потребление ресурсов, умные датчики объединяются в другом процессе. Но запуск этого специализированного процесса также увеличивает операционные издержки.

В Dagster за планирование запуска отвечает отдельная системная служба. С учетом заданных пользователем расписаний и датчиков она решает, когда запустить задачу, запускает ее и распределяет всю остальную обработку. Этот демон также унифицирует обработку расписаний и датчиков, основанных на событиях, вызывает определенные пользователем расписания и датчики во внешнем процессе и вычисляет запуски, которые должны существовать. Он сравнивает желаемые запуски с существующими и вычисляет, что именно запускается. Таким образом, управление расписанием запусков становится проще и стабильнее. А гибкость обеспечивается возможностью настраивать расписания не только в cron-выражениях, а через веб-GUI, чтобы, например, не запускать конвейер в дни, выходные или праздничные для конкретной страны.

Благодаря такому разделению подход Dagster более отказоустойчив, чем в AirFlow: демон вызывает весь определенный пользователем код вне процесса, а пользователи не могут остановить системные службы. Кроме того, в Dagster реализуется унификация расписаний на основе времени и событий: датчики являются аналогами расписаний, а не бесконечно выполняемыми задачами в рамках расписания, основанного на времени, как в Airflow.

Разумеется, описанные преимущества Dagster не отменяют достоинств AirFlow, а показывают выигрыш использования методологически зрелых решений в конкретной технической реализации. С учетом тренда развития AirFlow можно сделать вывод, что некоторые из описанных подходов будут внедрены в этом batch-оркестраторе в ближайшем будущем, чтобы сделать его удобнее для дата-инженеров. Об особенностях AirFlow и Dagster с точки зрения мониторинга и отладки запущенных data pipeline’ов мы поговорим в следующей статье.

Узнайте больше про применение Apache AirFlow для разработки сложных конвейеров аналитики больших данных с Hadoop и Spark на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:

Источники

  1. https://medium.com/dagster-io/moving-past-airflow-why-dagster-is-the-next-generation-data-orchestrator-e5d297447189
  2. https://medium.com/bluecore-engineering/were-all-using-airflow-wrong-and-how-to-fix-it-a56f14cb0753