Обзор
В нашей компании в производстве на постоянной основе находятся сотни моделей машинного обучения (ML) и расчетных скриптов. И наше подразделение Data Engineering поставило задачу сделать какой-нибудь CD/CD-компонент, наиболее подходящий для наших целей:
- Большое количество используемых библиотек от проекта к проекту
- Различные исполнительные платформы
- Гибкое расписание
- Уменьшение времени выхода на рынок (TTM)
- Масштабируемость и отказоустойчивость
Для достижения наших целей мы выбрали Kubernetes как лучшую систему оркестрации Docker, Airflow как один из быстро развивающихся планировщиков и Jenkins как одну из самых популярных систем непрерывной интеграции с непрерывной доставкой (CI/CD). Для некоторых задач по оптимизации мы также используем частный реестр Docker по вашему выбору (лучше всего, я думаю, Nexus или JFrog). Мы прошли две версии наших систем автоматизации ML. Первый был о контейнеризации всех приложений и сохранении образов для каждой версии каждого приложения. Не обошлось без недостатков:
- Объем памяти. Каждый контейнер занимает в среднем около 2 ГБ дискового пространства.
- Пора торговать. Нам нужно дополнительное дополнительное время для каждого запуска теста, чтобы перестроить контейнер во время разработки.
- Скорость отладки
Мы остановились на втором, о котором будет рассказано ниже.
Концепции
Создание DAG, создание модулей во время выполнения и выполнение кода непосредственно из Git.
Преимущество: устранение недостатков предыдущего подхода.
Работают две части системы:
- Генерация DAG
- выполнение DAG
Обе эти части используют шаблоны Jinja для DAG и для структур pod Kubernetes.
Генерация DAG
Генерация DAG выполняется после каждой фиксации в системе Git с помощью веб-хука. Дженкинс получает веб-перехватчик и запускает конвейер генерации DAG. Этот конвейер использует бесплатную утилиту
https://github.com/SingularBunny/render-jinja-with-yaml
для рендеринга нашего шаблона Jinja и файла конфигурации YAML.
Файлы конфигурации YAML
Эти файлы размещаются в корневом каталоге проекта в Git и описывают систему CI/CD, как следует генерировать DAG и обрабатывать код. Мы разработали две версии конфигурационных файлов: одношаговую и многошаговую.
Пошаговая настройка
Многоэтапная настройка
Шаги могут быть из разных репозиториев. Выполнение каждого шага — это независимый модуль Kubernetes. Ступени могут быть внешними DAG и преобразованы в датчики воздушного потока. На каждом шаге вы можете определить:
- базовый образ из общедоступного или частного репозитория
- команда для выполнения
- репозиторий git, ветка, ревизия с кодом для выполнения
- секреты kubernetes, карты конфигурации, пользователь, группа, пользователь контейнера синхронизации git, fsgroup, возможности
- повторные попытки воздушного потока, повторная задержка
j2 шаблон DAG
Шаблон Jinja DAG используется при генерации dag .py. Для некоторых дополнительных функций я рекомендую использовать подход динамической генерации DAG и прочитать статью Создание динамической DAG с использованием Apache Airflow от Энтони Энао.
Большинство частей шаблона являются общими для многих DAG и выглядят как обычный скрипт Python:
Аргументы по умолчанию взяты из конфигурации YAML:
Шаблон Jinja для генерации пода обычно берется из другого файла шаблона:
Макросы Jinja, которые генерируют операторы:
Макросы Jinja, которые генерируют датчики на внешних дагах:
Генерация всех шагов с использованием итерационных циклов и макросов Jinja:
Результирующий скрипт Python из рендеринга этого шаблона вы могли видеть в Приложении 1
выполнение DAG
На этом этапе DAG выполняется Airflow. Каждый оператор создает свой модуль с шаблоном Airfow с Jinja.
шаблон команды генерации пода j2
Это общий шаблон для всех шагов. И каждый шаг выполняет свою собственную команду. Шаблон выглядит как типичная команда kubectl run
с флагом --overrides
.
Он использует общедоступный контейнер Kunernetes Git-Sync для извлечения кода из репозитория и контейнера из конфигурации для выполнения. Вы можете поискать более продвинутую команду в скрипте Python из Приложения 1, а результат ее рендеринга — в Приложении 2.