- PVSM.RU - https://www.pvsm.ru -

werf [1] — наша GitOps CLI-утилита с открытым кодом для сборки и доставки приложений в Kubernetes. В релизе v1.1 [2] была представлена новая возможность в сборщике образов: тегирование образов по содержимому или content-based tagging. До сих пор типичная схема тегирования в werf предполагала тегирование Docker-образов по Git-тегу, Git-ветке или Git-коммиту. Но у всех этих схем есть недостатки, которые полностью решаются новой стратегией тегирования. Подробности о ней и чем она так хороша — под катом.
Часто встречается ситуация, когда приложение разбито на множество более-менее независимых сервисов. Релизы этих сервисов могут происходить независимо: за один раз может релизиться один или несколько сервисов, остальные при этом должны продолжать работать без каких-либо изменений. Но с точки зрения хранения кода и управления проектом удобнее держать такие сервисы приложения в едином репозитории.
Бывают ситуации, когда сервисы действительно независимы и не связаны с одним приложением. В таком случае они будут расположены в отдельных проектах и их релиз будет осуществляться через отдельные процессы CI/CD в каждом из проектов.
Однако в реальности разработчики зачастую разбивают единое приложение на несколько микросервисов, но заводить для каждого отдельный репозиторий и проект… — явный overkill. Именно про эту ситуацию и пойдет далее речь: несколько таких микросервисов лежат в едином репозитории проекта и релизы происходят через единый процесс в CI/CD.
Допустим, используется самая распространенная стратегия тегирования — tag-or-branch. Для Git-веток образы тегируются названием ветки, для одной ветки в один момент времени существует только один опубликованный образ по имени этой ветки. Для Git-тегов образы тегируются соответственно именем тега.
При создании нового Git-тега — например, при выходе новой версии — для всех образов проекта в Docker Registry будет создан новый Docker-тег:
myregistry.org/myproject/frontend:v1.1.10myregistry.org/myproject/myservice1:v1.1.10myregistry.org/myproject/myservice2:v1.1.10myregistry.org/myproject/myservice3:v1.1.10myregistry.org/myproject/myservice4:v1.1.10myregistry.org/myproject/myservice5:v1.1.10myregistry.org/myproject/database:v1.1.10
Эти новые имена образов попадают через Helm-шаблоны в конфигурацию Kubernetes. При запуске деплоя командой werf deploy происходит обновление поля image в манифестах ресурсов Kubernetes и перезапуск соответствующих ресурсов из-за изменившегося имени образа.
Проблема: в случае, когда реально с предыдущего выката (Git-тега) не изменилось содержимое образа, а лишь его Docker-тег, происходит лишний перезапуск этого приложения и, соответственно, возможен некоторый простой. Хотя не было никаких реальных причин производить этот перезапуск.
Как следствие, при текущей схеме тегирования приходится городить несколько отдельных Git-репозиториев и встает проблема организации выката этих нескольких репозиториев. В общем и целом такая схема получается перегруженной и сложной. Лучше объединять много сервисов в единый репозиторий и создавать такие Docker-теги, чтобы лишних перезапусков не было.
В werf также присутствует стратегия тегирования, связанная с Git-коммитами.
Git-commit является идентификатором содержимого Git-репозитория и зависит от истории правок файлов в Git-репозитории, поэтому кажется логичным использовать его для тегирования образов в Docker Registry.
Однако тегирование по Git-коммиту имеет те же недостатки, что и по Git-веткам или Git-тегам:
Есть и еще одна проблема, связанная со стратегией тегирования по Git-веткам.
Тегирование по имени ветки работает до тех пор, пока коммиты этой ветки собирают последовательно в хронологическом порядке.
Если в текущей схеме пользователь запустит пересборку старого коммита, связанного с некоторой веткой, то werf перетрет образ по соответствующему Docker-тегу вновь собранной версией образа для старого коммита. Использующие этот тег Deployment'ы с этого момента рискуют во время перезапуска pod'ов сделать pull другой версии образа, в результате чего наше приложение потеряет связь с CI-системой, рассинхронизируется.
Кроме того, при последовательных push’ах в одну ветку с малым промежутком времени между ними старый коммит может собраться позже, чем более новый: старая версия образа перетрет новую по тегу Git-ветки. Такие проблемы может решать CI/CD-система (например, в GitLab CI для серии коммитов запускается pipeline последнего). Однако это поддерживают не все системы и должен быть более надежный способ предотвращения столь фундаментальной проблемы.
Итак, что же такое content-based tagging — тегирование образов по содержимому.
Для создания Docker-тегов используются не примитивы Git'а (Git-ветка, Git-тег…), а контрольная сумма, связанная с:
В качестве такого тега-идентификатора выступает так называемая сигнатура стадий образа.
Каждый образ состоит из набора стадий: from, before-install, git-archive, install, imports-after-install, before-setup,… git-latest-patch и т.д. У каждой стадии есть идентификатор, отражающий ее содержимое, — сигнатура стадии (stage signature).
Финальный же образ, состоящий из этих стадий, тегируется так называемой сигнатурой набора этих стадий — stages signature, — которая является обобщающей для всех стадий образа.
У каждого образа из конфигурации werf.yaml в общем случае будет своя такая сигнатура и, соответственно, Docker-тег.
Сигнатура стадий решает все указанные проблемы:
Теперь это рекомендуемая стратегия тегирования и используется по умолчанию в werf для всех CI-систем.
Соответствующая опция появилась у команды werf publish: --tag-by-stages-signature=true|false
В CI-системе стратегия тегирования задается командой werf ci-env. Ранее для нее определялся параметр werf ci-env --tagging-strategy=tag-or-branch. Теперь, если указать werf ci-env --tagging-strategy=stages-signature или не указывать эту опцию, werf по умолчанию будет использовать стратегию тегирования stages-signature. Команда werf ci-env автоматически выставит нужные флаги для команды werf build-and-publish (или werf publish), поэтому никаких дополнительных опций для этих команд указывать не нужно.
Например, команда:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature
… может создать следующие образы:
registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386dregistry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6
Здесь 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d — это сигнатура стадий образа backend, а f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 — сигнатура стадий образа frontend.
При использовании специальных функций werf_container_image и werf_container_env в шаблонах Helm ничего менять не требуется: эти функции будут автоматически генерировать верные имена образов.
Пример конфигурации в CI-системе:
type multiwerf && source <(multiwerf use 1.1 beta)
type werf && source <(werf ci-env gitlab)
werf build-and-publish|deploy
Больше информации по настройке доступно в документации:
werf publish --tag-by-stages-signature=true|false.werf ci-env --tagging-strategy=stages-signature|tag-or-branch (если не указать, то по умолчанию будет stages-signature).WERF_TAG_GIT_COMMIT или опция werf publish --tag-git-commit COMMIT), то обязательно переключать на стратегию тегирования stages-signature.Content-based tagging решает все освещенные в статье проблемы:
Пользуйтесь! И не забывайте заглядывать к нам на GitHub [6], чтобы создать issue или найти уже существующий, поставить плюс, создать PR или просто понаблюдать за развитием проекта.
Читайте также в нашем блоге:
Автор: Timofey Kirillov
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/git/351667
Ссылки в тексте:
[1] werf: https://werf.io/
[2] релизе v1.1: https://habr.com/ru/company/flant/blog/493170/
[3] Справочник → Публикация (publish): https://ru.werf.io/v1.1/documentation/reference/publish_process.html#%D1%82%D0%B5%D0%B3%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2-%D0%BF%D0%BE-%D1%81%D0%BE%D0%B4%D0%B5%D1%80%D0%B6%D0%B8%D0%BC%D0%BE%D0%BC%D1%83
[4] Работа с CI/CD → Общие сведения → stages-signature: https://ru.werf.io/v1.1/documentation/reference/plugging_into_cicd/overview.html#stages-signature
[5] Интеграция с GitLab CI/CD → .gitlab-ci.yml: https://ru.werf.io/v1.1/documentation/guides/gitlab_ci_cd_integration.html#gitlab-ciyml
[6] GitHub: https://github.com/flant/werf
[7] Представляем werf 1.0 stable: при чём тут GitOps, статус и планы: https://habr.com/ru/company/flant/blog/481306/
[8] werf — наш инструмент для CI/CD в Kubernetes (обзор и видео доклада): https://habr.com/ru/company/flant/blog/460351/
[9] 3-way merge в werf: деплой в Kubernetes с Helm „на стероидах“: https://habr.com/ru/company/flant/blog/476646/
[10] Использование werf для выката комплексных Helm-чартов: https://habr.com/ru/company/flant/blog/468049/
[11] Поддержка monorepo и multirepo в werf и при чём здесь Docker Registry: https://habr.com/ru/company/flant/blog/465131/
[12] Собирать Docker-образы в werf теперь можно и по обычному Dockerfile: https://habr.com/ru/company/flant/blog/463613/
[13] Источник: https://habr.com/ru/post/495112/?utm_source=habrahabr&utm_medium=rss&utm_campaign=495112
Нажмите здесь для печати.