werf — это GitOps CLI-утилита с открытым кодом для сборки и доставки приложений в Kubernetes. werf поддерживает сборку образов приложения с помощью Dockerfile или собственного встроенного сборщика (на основе синтаксиса YAML, с поддержкой Ansible и инкрементальной пересборки на базе Git). Для доставки приложения используется формат конфигурации, совместимый с Helm. Код приложения, конфигурация собираемых образов и конфигурация выката приложения хранятся в одном Git-репозитории.

Долгожданный стабильный релиз 1.0 — это законченная по функциям базовая версия утилиты (точный номер версии первого стабильного релиза — это 1.0.6). В базовой версии werf поддерживает полный цикл доставки приложения и его сопровождения. Это включает в себя сборку образов приложения, деплой в Kubernetes, очистку неиспользуемых образов.

Важно, что в версии 1.0 все операции по одному проекту (build, deploy, cleanup) должны выполняться с одного хоста. Это означает, что в CI-системе должен использоваться фиксированный worker. При этом нет никаких ограничений по параллельности заданий: werf этот вопрос полностью разруливает. Также можно распределить разные проекты по разным worker’ам.

В этой приуроченной к релизу статье мы подробнее рассмотрим, что предоставляет и не предоставляет данная версия, а также наши планы на будущие версии. Но начнём мы с того, что разберёмся в понимании термина «GitOps» и роли werf в процессах непрерывной интеграции и доставки приложений (CI/CD).

Почему werf — это GitOps


Итак, что мы подразумеваем под GitOps и какие области закрывает werf?

Термин «GitOps» придумали в компании Weaveworks около 2,5 лет назад, а статью от его авторов, раскрывающую суть этого нового явления, мы не так давно переводили для блога. В нашем понимании, основная идея и основной смысл GitOps заключается в том, что Git является «единым источником истины» (single source of truth). В Git хранится:

  • код приложения;
  • все зависимости;
  • информация, как собирать контейнеры;
  • информация, как деплоить в Kubernetes;
  • и др.

А вот далее есть «нечто», которое делает так, чтобы реальность изменилась в соответствии с изменениями Git. Этот подход может быть реализован не только установкой некоторого оператора в Kubernetes, который следит за Git, но и с помощью консольной утилиты, которую можно вызывать из любой CI-системы. Более того, с нашей точки зрения, подход с CLI-утилитой не накладывает лишних ограничений: мы можем делать CI любым инструментом и с любым количеством нюансов, вызывая CLI-утилиту, которая синхронизирует «реальность» (т.е. Kubernetes) с состоянием Git.

werf предоставляет высокоуровневый CLI-интерфейс с основными командами для сборки и публикации образов, доставки приложения и очистки образов: werf build-and-publish, werf deploy, werf dismiss, werf cleanup. Предполагается, что именно эти основные команды встраиваются в ту или иную CI-систему и обеспечивают необходимую синхронизацию с реальностью. Помимо этого, werf предоставляет и низкоуровневый CLI-интерфейс для управления разными подсистемами — см. low level management commands в документации.

Не имеет значения, по push- или по pull-модели (подробнее о них читайте здесь) будет работать весь выстроенный CI/CD, потому что werf можно встроить в любую модель. При этом werf закрывает такие проблемы, как работа с отдельными низкоуровневыми утилитами вроде git, docker и kubernetes api-server, являясь «недостающей частью» для конфигурирования унифицированного CI/CD приложений.

Что такое werf 1.0 stable


1. Сборка, публикация и очистка образов


Если ваше приложение требует сборки Docker-образов, то с помощью werf 1.0 можно:

  • описать правила сборки образов (можно нескольких) в едином конфиге werf.yaml;
  • собрать образы и опубликовать в Docker Registry;
  • периодически чистить Docker Registry по настраиваемым политикам.

werf поддерживает два способа описания сборки: подключение в werf.yaml существующих Dockerfile'ов и инструкции для сборщика Stapel. Сборка с помощью Stapel имеет свои преимущества: ускорение инкрементальной пересборки при изменении кода приложения в Git, использование синтаксиса Ansible для сборки и другие. Подробнее об этом сборщике и синтаксисе можно узнать в документации, а пример его использования представлен в руководстве.

Доступны разные схемы тегирования/версионирования собираемых образов с привязкой к Git-коммитам, веткам и тегам.

Сборка образов — это опциональный этап развёртывания приложения и может быть пропущен в случае отсутствия собственных собираемых образов.

2. Хранилище стадий только на одном хосте


werf вводит такое понятие, как хранилище стадий (stages storage). Основные команды werf используют хранилище стадий следующим образом:

  • сохраняют результаты сборки — Docker-образы в хранилище стадий;
  • используют образы из хранилища стадий как кэш для пересборки и для сборки новых образов;
  • используют хранилище для получения информации о собранных образах для их дальнейшего использования (например, при доставке приложения в Kubernetes).

При развёртывании одного приложения должно быть использовано единое хранилище стадий для всех команд (сборка, публикация, очистка образов, развёртывание приложения).

В версии 1.0 в качестве хранилища стадий может выступать только локальное хранилище хоста (соответствующий параметр у команд: --stages-storage=:local). При использовании :local стадии хранятся на диске. Следствие из этого: werf 1.0 может быть использован только на одном хосте для организации развёртывания одного приложения. Этот хост должен сохранять данные между запусками команд для корректной работы werf.

В версии 1.0 отсутствует поддержка хранения стадий во внешнем хранилище, с помощью которого можно было бы организовать распределённую сборку. Однако такая функция появится в следующих версиях werf (подробнее об этом см. ниже).

3. Выкат приложения и проверка готовности


Для выката приложения пользователь описывает чарт в формате, совместимом с Helm: набор манифестов Kubernetes и параметры шаблонизации.

werf запускает приложение в Kubernetes и обеспечивает гарантию, что оно запустилось и функционирует, прежде чем завершить процесс выката приложения. Это включает в себя вывод логов компонентов и мгновенное реагирование на ошибки выката, когда что-то пошло не так — команда выката упадёт с ненулевым кодом. Таким образом, при использовании выката werf в CI/CD мы получаем адекватную обратную связь от софта: выкачено приложение или нет — и достаточно информации для отладки и исправления проблем (без необходимости запуска других утилит для поиска проблем вроде kubectl).

werf полностью совместим с уже существующими инсталляциями Helm 2, однако werf имеет ряд преимуществ перед ним. Например, в качестве механизма обновления ресурсов в Kubernetes используются патчи 3-way-merge, а также есть возможность получения обратной связи при доставке приложения в кластер. Полный список отличий описан на этой странице.

4. Связь собранных образов с процессом доставки приложения


werf интегрирует в единую систему собираемые образы, процесс их тегирования и версионирования с процессом доставки приложения в Kubernetes. Образы, которые собирает werf, можно использовать в шаблонах описания Kubernetes-ресурсов.

Именно за счёт этих функций можно говорить, что werf предоставляет более высокоуровневый интерфейс, чем Helm, Docker и другие сборщики и утилиты для деплоя в отдельности. Этот интерфейс позволяет просто интегрировать werf в любую существующую CI/CD-систему и не решать проблемы объединения всех используемых компонентов — эту задачу он берёт на себя.

5. Интеграция с существующими CI/CD-системами


В версии 1.0 доступна автоматическая интеграция только с системой GitLab CI. Для этого предусмотрена команда werf ci-env. Она получает необходимую информацию от CI/CD-системы и автоматически настраивает werf для корректной работы в CI-окружении.

Подробнее о том, как работает интеграция с любой CI/CD-системой, можно прочитать в мануалах (обзор, специфика GitLab CI, интеграция с другими системами).

6. Кроссплатформенная разработка под Linux, Windows и macOS


werf 1.0 представляет собой статически слинкованный бинарный файл, который самостоятельно работает и с Docker, и с Helm-релизами. Внешние зависимости на хост-системе:

  • локальный Docker-демон;
  • утилита Git.

werf может работать на любой из операционных систем и окружений GNU/Linux, Windows или macOS. Более того, результат сборки будет одинаков вне зависимости от используемой системы: одинаковые сигнатуры стадий кэша, одинаковое наполнение стадий вне зависимости от системы, где эту стадию собрали. Изменения в конфиге для работы в разных системах также не требуются.

Таким образом, werf 1.0 предоставляет средства кроссплатформенной сборки и доставки приложений в Kubernetes.

Здесь следует также отметить, что werf собирает стандартные Docker-образы для работы в Linux-окружении, но Windows-контейнеры в версии 1.0 не поддерживаются.

7. Покрытие функциональных возможностей тестами


На данный момент 60% кода werf покрыто интеграционными e2e-тестами и unit-тестами.

werf тестируется на всех поддерживаемых ОС (Linux, Windows и macOS) с использованием GitHub Actions для организации их запуска. Некоторые подробности о тестировании также доступны на Code Climate.

8. Версионирование werf


На данный момент, к выходу версии 1.0, в проекте было всего сделано около 700 релизов.

werf использует продвинутую систему релизов с разбиением по каналам стабильности: alpha, beta, ea (early access), stable и rock-solid. Данный пост как раз приурочен к выходу первой версии 1.0 в канале stable. Нестабильные изменения в версию сначала проходят через цепочку каналов и в итоге оказываются в rock-solid. Релизы делаются часто (порой по несколько за день) и изменения доставляются непрерывно «маленькими порциями».

Каналы стабильности и много частых релизов позволяют получить непрерывную обратную связь по новым изменениям, возможность быстро их откатить и в целом обеспечить высокую стабильность софта и при этом приемлемую скорость его развития.

Важный момент, что при переходе между версиями 1.0->1.1, 1.1->1.2 возможны такие изменения в werf, которые потребуют ручного вмешательства со стороны пользователя (это может быть скрипт миграции или просто инструкции для ручного выполнения, описанные в релизе). Обновление же версий внутри 1.0 (1.0.1, 1.0.2,… 1.0.6-alpha.1, 1.0.6-beta.2 и т.п.) гарантирует, что таких ручных изменений не потребуется.

Подробнее о backward compatibility promise можно прочитать здесь.

Дальнейшие планы


Вот как выглядят основные крупные направления работ для дальнейших версий и примерные сроки их реализации:

1. Локальная разработка и развёртывание приложений с werf


Главная цель — добиться единого унифицированного конфига для развёртывания приложений как локально, так и в production, без сложных действий, «из коробки».

От werf также требуется такой режим работы, в котором будет удобно редактировать код приложения и мгновенно получать обратную связь от работающего приложения для дебага.

Версия 1.1, январь-февраль 2020 г.

2. Content-based tagging


Тегирование образов при их публикации, основанное исключительно на содержимом этого образа. В отличие от режимов с привязкой к Git-коммитам, данный режим позволит полностью избавится от лишних пересборок. Git-commit-id не является универсальным идентификатором содержимого worktree (хотя и зависит от него).

В случае, когда код приложения не менялся, но был сделан новый коммит, текущий режим тегирования по Git-коммитам создаст образ с новым именем при его публикации. Это повлечет за собой также перевыкат ресурсов, использующих этот образ в Kubernetes. При этом содержимое самого образа не менялось.

Чтобы решить эти проблемы, werf введёт новый тип тегирования, основанный на расчётах контрольных сумм содержимого приложения, — content-based tagging.

Версия 1.1, февраль-март 2020 г.

3. Переход на Helm 3


Включает в себя переход на новую кодовую базу Helm 3 и проверенный, удобный способ миграции существующих установок.

Версия 1.1, февраль-март 2020 г.

4. Параллельная сборка образов


На данный момент werf 1.0 собирает все стадии образов и артефактов, объявленных в werf.yaml, последовательно. Требуется возможность распараллелить процесс сборки стадий.

Версия: 1.1, январь-февраль 2020 г.

5. Распределённая сборка образов


На данный момент werf 1.0 возможно использовать лишь на одном выделенном хосте (см. пункт выше про хранилище стадий только на одном хосте).

Чтобы открыть возможности распределенной сборки, когда сборка запускается на нескольких хостах и эти хосты не сохраняют свое состояние между сборками (временные runner’ы), от werf требуется реализация возможности использования Docker Registry в качестве хранилища стадий.

Ранее, когда проект werf еще назывался dapp, в нем была такая возможность. Однако мы столкнулись с рядом проблем, которые необходимо учесть при реализации этой функции в werf.

Версия 1.2: март-апрель 2020 г.

6. Jsonnet для описания конфигурации Kubernetes


werf будет поддерживать описание конфигурации для Kubernetes в формате Jsonnet. При этом werf останется совместимым с Helm и будет возможность выбора формата описания.

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

Также рассматривается возможность внедрения и других систем описания конфигурации Kubernetes (например, Kustomize).

Версия 1.1: январь-февраль 2020 г.

7. Работа внутри Kubernetes


Цель: обеспечить сборку образов и доставку приложения с использованием runner’ов в Kubernetes. Т.е. сборка новых образов, их публикация, очистка и деплой может происходить прямо из pod’ов Kubernetes.

Чтобы реализовать эту возможность, сначала требуется возможность распределенной сборки образов (см. пункт выше).

Также требуется поддержка режима работы сборщика без Docker-демона (т.е. Kaniko-подобная сборка или сборка в userspace).

werf будет поддерживать сборку в Kubernetes не только с помощью Dockerfile, но и с помощью своего сборщика Stapel с инкрементальными пересборками.

Версия 1.2: апрель-май 2020 г.

8. Другое


Также планируется:

  • обновление версии Ansible и возможность использовать разные версии Ansible;
  • поддержка Ansible-ролей;
  • поддержка произвольных сборочных стадий в Stapel (на данный момент werf поддерживает статичный набор стадий: beforeInstall, install, beforeSetup, setup);
  • улучшение синтаксиса werf.yaml, переход на configVersion: 2 (связано, в том числе, с двумя предыдущими пунктами), поддержка спецификации OpenAPI;
  • поддержка Git LFS в Stapel для хранения больших файлов в Git;
  • улучшение механизмов очистки образов (некритичные недостатки в текущей версии связаны с образами, не объявленными в конфиге werf.yaml в главной master-ветке, — эти образы будут удаляться периодической очисткой);
  • более корректная работа с shared Kubernetes namespace, когда несколько приложений деплоятся в один namespace;
  • автооткат приложения до последней рабочей версии при неудачном деплое.

Итого


Буду краток в подведении итогов. Мы:

  • долго шли к появлению версии 1.0;
  • учли много реального опыта;
  • представляем для использования проверенную утилиту со стабилизированным функционалом, проверенную десятками тысяч выкатов.

Выход версии 1.0 знаменует начало нового этапа разработки werf, в рамках которого будут добавлены принципиально новые возможности. Следите за новостями! А также присоединяйтесь к tg-каналу werf_ru, в жизни которого участвуют как непосредственные разработчики werf, так и наши инженеры, и пользователи утилиты вне компании «Флант».

P.S.


Читайте также в нашем блоге:

Комментарии (16)