
werf — это CLI-утилита с открытым кодом для сборки приложений и их деплоя в Kubernetes. С версией v1.2 она получила множество изменений и улучшений, которые мы так тщательно тестировали и дорабатывали, что релиз долгое время — с января 2021-го — находился в статусе Early-Access. Наконец, мы рады объявить о его переводе в категорию Stable!
Для тех, кому интересен список изменений в werf v1.2 относительно v1.1, в документации проекта есть достаточно подробный changelog (а самые любопытные пользователи следили за прогрессом работы на GitHub и в Telegram-чате). Эта статья немного о другом — она представляет актуальную версию werf, рассказывая о её предназначении и основных принципах работы.
Версия 1.1 была больше похожа на конструктор (или «комбайн»), который предлагал множество вариантов реализации одного и того же, но за этим следовали и потенциальные проблемы, если пользователь не учитывал все детали выбранного подхода. werf v1.2 делает шаг в сторону систематизации и улучшения консистивности доставки, упрощая ее и делая более предсказуемой.
Что такое werf
werf — CLI-инструмент с открытым кодом для консистентной сборки и доставки приложений в Kubernetes, который может использоваться для организации полного цикла CI/CD.
Обычно, если требуется создать пайплайн сборки и деплоя приложения с Docker и Helm, инженеру приходится самостоятельно настраивать и интегрировать все компоненты системы CI/CD. Настройку детерминированного тегирования образов, связывание сборки и развертывания на уровне CI-системы, реализацию автоматической очистки образов и многое другое приходится делать вручную.
werf предлагает готовую интеграцию между всеми компонентами, задействованными в CI/CD. Пользователь получает не только полностью детерминированный, готовый конвейер для сборки и доставки приложения, но и ряд уникальных фич, которые возможны благодаря тесной интеграции между Git, Docker, Helm, CI-системой и container registry. К примеру, werf cleanup выполняет «умную» очистку container registry, которая учитывает и состояние Git-репозитория, и его историю, и текущее использование образов в кластере.
Для GitLab CI полный цикл сборки, развертывания приложения и автоматической очистки образов, ке��а и временных файлов можно реализовать в три команды:
. $(werf ci-env gitlab --as-file) # Интеграция с GitLab CI.
werf converge # Сборка и развертывание.
werf cleanup # Очистка container registry.При этом werf предоставляет пользователю возможность не только тонко настраивать вышеописанный конвейер, но и реализовывать гораздо более нестандартные схемы CI/CD. Более подробно об этом будет рассказано в разделе «Разные варианты доставки».
Гитерминизм
Что важно для воспроизводимости сборки в любом окружении? Чтобы «источник правды» был неизменным и единственным. Таким источником для werf служит Git.
Мы используем понятие гитерминизм (Git + determinism) применительно к основному режиму работы werf. Это можно перевести как «режим, детерминированный Git’ом». werf читает конфиги и файлы сборочного контекста из текущего Git-коммита, исключая внешние зависимости.
Как обеспечивается гитерминизм:
werf читает всю конфигурацию и сборочный контекст напрямую из Git;
большинство недетерминированных сущностей — например, переменные окружения и незаверсионированные файлы — по умолчанию запрещены и при деплое, и при сборке;
собираемые Docker-образы и развертываемые Kubernetes-ресурсы детерминированы Git’ом. При этом: а) werf сам управляет тегированием образов, пользователь получает уже протегированные образы; б) используется content-based-тегирование* для обеспечения оптимальных тегов с точки зрения пересборки, воспроизводимости и реализации принципа неизменяемости образов.
* Пр�� теги в werf
Если в дополнение к content-based-тегам хочется получать произвольные теги, можно использовать алиасы тегов. Если content-based-тегирование не требуется, можно экспортировать образы из экосистемы werf с помощью werf export.
Гитерминизм — это инструмент, который позволяет контролировать предсказуемость, воспроизводимость и легкость сопровождения приложения. Под детерминированностью подразумеваются фиксированные входные данные и окружение для детерминированного алгоритма: «алгоритмический процесс, который выдаёт уникальный и предопределенный результат для заданных входных данных».
Настройки по умолчанию — максимально строгие, чтобы обозначить потенциальные проблемы для пользователя и уберечь его от создания ненадежной и непредсказуемой автоматизации.
Отступление от дефолтной детерминированной конфигурации допустимо: можно работать, например, с незакоммиченными, неотслеживаемыми файлами и добавлять внешние зависимости. Но это должно быть явно указано (задекларировано) в werf_giterminism.yaml.
Стандартные технологии
werf обеспечивает интеграцию привычных для разработчика и DevOps-/SRE-инженера инструментов. Каждый из них выполняет определенную роль в CI/CD-процессе.
Технология | Функции в рамках werf |
Git | Хранение кода и конфигурации. Сборка, кеширование и очистка на основе истории и состояния Git-репозитория. |
Kubernetes | Платформа для запуска контейниризованных приложений. |
Container registry | Хранение бандлов, контейнеров, кэша и метаданных. |
Docker | Сборка и запуск образов. |
Helm | Выкат приложения. Организация конфигурации для Kubernetes: шаблонизация и параметризация, а также управление зависимостями. |
CI-система | Непрерывная интеграция кода (werf совместима с любой CI-системой, а с GitLab и GitHub Actions интегрируется одной командой). |
Docker Compose | Интеграция для локальной разработки. |
Рассмотрим чуть подробнее, как werf использует и расширяе�� Docker, Helm и container registry.
Docker
Поддерживается сборка с помощью стандартных Dockerfiles. Можно использовать уже существующие конфигурационные файлы как есть, без изменений.
Поддерживается и альтернативный синтаксис — Stapel, который полностью покрывает возможности Dockerfile-инструкций (в расширенном и более гибком варианте), а также предлагает дополнительную функциональность.
Главная особенность Stapel — тесная интеграция с Git при сборке образов. Добавление файлов может выполняться не на определённом шаге сборки, как в случае с Docker, а быть плавающим: пользователь выставляет зависимости у команд, и добавление файлов происходит оптимальным образом. В итоге время сборок значительно сокращается за счёт эффективного инкрементального изменения исходного кода из Git.
Stapel-синтаксис удобен в сопровождении за счет YAML-формата и возможностей шаблонизации.
В статье «werf vs Docker. Чем лучше собирать образы» подробно рассказано обо всех отличиях и особенностях сборки в werf.
Helm
Популярное решение для развертывания приложений в Kubernetes. werf реализует деплой, используя расширенный и улучшенный Helm (форк от upstream-проекта с некоторыми патчами от нас встроен в утилиту).
Особенности:
Обратная совместимость: чарты для Helm можно применять в werf без изменений. Используются те же Helm-шаблоны, так же организована работа с values.
Интеграция с собираемыми образами: динамически генерируемые теги образов доступны через values.
Продвинутый трекинг статуса и расширенная конфигурация выката ресурсов, отображение логов запускающихся Pod’ов — для этого мы написали отдельную Open Source-библиотеку kubedog.
Работа с секретами «из коробки».
Автоматическая установка аннотаций и лейблов в ресурсы с полезной информацией (например, ссылка на job в CI/CD-системе и Git-коммит, из которого был выкачен ресурс).
Защита от конфликтов при параллельных выкатах в один и тот же контур: выкаты могут быть с разных хостов за счет использования распределенных блокировок.
В статье «werf vs. Helm» подробно рассказано о том, как Helm интегрирован в процессы werf.
Container registry
В container registry werf хранит конечные образы, бандлы (подробнее о них — ниже), а также сборочный кэш и метаданные. Метаданные обеспечивают эффективную сборку и очистку на основе истории Git.
werf использует container registry не только как хранилище артефактов, но и как часть механизма, обеспечивающего производительность и воспроизводимость всех сборок при совместном использовании. Таким образом, с werf пользователь получает готовый к работе, гибкий, масштабируемый и производительный CI/CD — дополнительно ничего настраивать не нужно.
Поддерживаются различные схемы организации хранилища на основе нескольких типов container registry.
Разные варианты доставки
werf предлагает несколько вариантов ��остроения пайплайна. Для этого используются базовые команды, которые могут дополняться различными опциями.
Первый вариант — werf converge. Cборка образов и деплой в Kubernetes в один шаг (для пользователя). Что при этом делает werf:
анализирует текущее состояние конфигурации из Git-коммита;
дособирает и публикует недостающие образы в хранилище;
приводит состояние Kubernetes к актуальному.
Другой подход — werf bundle publish и werf bundle apply. Бандлы позволяют выкатывать приложение без доступа к Git-репозиторию, в котором приложение собирается. Как работают команды:
werf bundle publishготовит и публикует в container registry бандлы — артефакты, состоящие из собранных образов и инструкций для их развертывания;werf bundle applyвыкатывает бандл из container registry (доступ к Git-репозиторию уже не требуется, только к container registry).
Кроме того, для использования werf совместно с другими инструментами развертывания есть команды:
werf export— для сборки образов, отвязанных от werf;werf render— для сборки образов и генерации манифестов (без развертывания);werf run— для сборки образов и запуска контейнеров.
Как попробовать werf
Quickstart по началу работы с актуальной версией werf доступен на сайте проекта.
Также мы подготовили подробный онлайн-самоучитель для разработчиков на разных языках/фреймворках*, который позволит познакомиться с werf на практике, — это отличная стартовая точка, если вы заинтересовались функциональностью утилиты, но еще не пробовали ее.
* «Первые шаги» самоучителя доступны для всех фреймворков, а второй раздел в настоящий момент готов для Node.js, Laravel и Ruby on Rails.
Заключение
Несмотря на статус stable для werf v1.2, работа по расширению функциональности продолжается. Мы планируем завершить интеграцию с Buildah по следующим направлениям:
Поддержка Dockerfile (уже реализовано).
Поддержка Stapel.
Инструкции для запуска внутри Docker-контейнера (dind) и в Kubernetes.
Эффективный и версионированный кэш в container registry вместо маунтов и multistage.
Мы уже давно используем werf v1.2 в production и уверены в стабильности новой версии. Но это, конечно, не значит, что проблемы исключены. Если у вас есть вопросы про релиз или про работу werf в целом — приходите в Telegram-чат проекта; будем рады помочь!
P.S.
Читайте также в нашем блоге:
