О бандлах и чартах
Бандл — это способ дистрибуции чарта и связанных с ним образов как единого целого.
Команда werf bundle publish собирает образы и публикует их вместе с чартом для дальнейшего развёртывания с werf. При этом для развёртывания доступ к Git-репозиторию приложения больше не потребуется.
Опубликованный чарт — обычный OCI-чарт Helm: исходный чарт как есть плюс директория .werf-data/ в его корне. В .werf-data/ хранится всё, что werf добавляет при публикации:
- собранные образы и их теги в виде служебных параметров werf;
- параметры, переданные опциями
--values,--secret-values,--set*,--set-root-json, и файлы--patches; - пользовательские и служебные аннотации и лейблы для добавления в ресурсы чарта;
- имя релиза и Namespace, вычисленные для окружения.
werf bundle apply (а также werf bundle plan и werf bundle render) использует всё это, поэтому публикация и последующее применение чарта развёртывают то же самое, что werf converge с теми же опциями. Helm, Argo CD, Flux и другие решения тоже могут установить чарт, но по умолчанию получают только собственные параметры чарта, см. Использование чарта с Helm, Argo CD и Flux.
Опубликованный бандл (чарт и связанные с ним образы) можно копировать в другой репозиторий container registry или выгружать в/из архива с помощью одной команды werf bundle copy.
Аутентификация в container registry
Перед работой с образами необходимо аутентифицироваться в container registry. Сделать это можно командой werf cr login:
werf cr login <registry url>
Например:
# Login with username and password from command line
werf cr login -u username -p password registry.example.com
# Login with token from command line
werf cr login -u username -p token registry.example.com
# Login into insecure registry (over http)
werf cr login --insecure-registry registry.example.com
В случае использования команды ci-env с поддерживаемыми CI/CD-системами аутентификация во встроенные container registry выполняется в рамках команды, поэтому использование команды werf cr login в этом случае не требуется.
Публикация бандла
Опубликовать бандл в OCI-репозиторий можно следующим способом:
-
Создайте
werf.yaml, если его ещё нет:# werf.yaml: project: mybundle configVersion: 1 -
Разместите файлы в директории основного чарта (по умолчанию
.helmв корне Git-репозитория). Публикуются все файлы директории чарта, кроме исключённых.helmignore(см. ниже). -
Следующей командой опубликуйте бандл. Соберите и опубликуйте описанные в
werf.yamlобразы (если таковые есть), затем опубликуйте содержимое.helmв виде чартаexample.org/bundles/mybundleс тегомlatest:werf bundle publish --repo example.org/bundles/mybundle
Содержимое опубликованного чарта
Директория чарта публикуется как есть: werf ничего не добавляет в values.yaml, а secret-values.yaml и директория secret/ чарта остаются на своих местах в зашифрованном виде. В Chart.yaml werf меняет только следующие поля, сохраняя остальное содержимое файла, включая комментарии и порядок ключей:
name— последний компонент пути репозитория (см. Имя и версия чарта);version— версия, полученная из тега;appVersion— только если она задана вwerf.yaml;- аннотацию
helm.sh/images— собранные werf образы и ссылки на них, добавленные к записям, которые указал автор чарта. Если имя записи автора совпадает с именем образа werf, публикация завершается ошибкой: удалите запись изChart.yamlили переименуйте образ werf.
Также werf помещает в charts/ зависимые чарты, перечисленные в Chart.lock, и собирает TypeScript-чарты.
Всё, что werf добавляет при публикации, попадает в .werf-data/:
.werf-data/
metadata.yaml # версия формата (apiVersion: v2), опции --set*, образы werf, файлы --patches, аннотации, лейблы, имя релиза и Namespace
values.yaml # файлы --values, объединённые по порядку
secret-values.yaml # файлы --secret-values, объединённые по порядку, в зашифрованном виде
extra-values.yaml # служебные параметры werf: образы, репозиторий, окружение, коммит
set-files/0, 1, ... # содержимое файлов --set-file
patches/0, 1, ... # файлы --patches
.werf-data/ всегда публикуется и сохраняется при распаковке и повторной упаковке чарта, даже если её исключает .helmignore чарта.
Примечание:
.werf-data/values.yaml, файлыset-files/и строки--set*хранятся в registry в открытом виде. Передавайте секреты только через--secret-values: werf проверяет, что все значения в этих файлах зашифрованы, и хранит их в зашифрованном виде.
Публикация нескольких бандлов из одного Git-репозитория
Разместите .helm с содержимым чарта и соответствующий ему werf.yaml в отдельную директорию для каждого бандла:
bundle1/
.helm/
templates/
# ...
werf.yaml
bundle2/
.helm/
templates/
# ...
werf.yaml
Теперь опубликуйте каждый бандл по отдельности:
cd bundle1
werf bundle publish --repo example.org/bundles/bundle1
cd ../bundle2
werf bundle publish --repo example.org/bundles/bundle2
Исключение файлов или директорий из чарта
Файл .helmignore чарта фильтрует публикуемый чарт так же, как любой чарт, который читает werf, см. Исключение файлов или директорий из чарта.
Опции --disable-default-values, --disable-default-secret-values и --no-default-patches команды werf bundle publish сохраняются в чарте: werf bundle apply тогда игнорирует values.yaml, secret-values.yaml и patches.yaml чарта, как это делает werf converge с этими опциями. Сами файлы остаются в чарте, и Helm по-прежнему использует values.yaml.
Если в директории чарта уже есть .werf-data/ с этими переключателями, например закоммиченный распакованный опубликованный чарт, werf bundle publish сохраняет их: опция со значением true устанавливает сохранённый переключатель, а неуказанная опция или опция со значением false его сохраняет. Чтобы сбросить сохранённый переключатель, удалите defaultValuesDisable или defaultSecretValuesDisable в секции values или defaultPatchesDisable из файла .werf-data/metadata.yaml чарта.
Использование произвольных тегов образов
Для использования произвольных тегов образов для бандлов необходимо задать шаблон именования с помощью опции --use-custom-tag (WERF_USE_CUSTOM_TAG).
Пример использования:
werf bundle publish --repo example.org/bundles/mybundle --use-custom-tag "%image%-my-custom-tag"
werf bundle publish отказывается публиковать чарт, если тег его версии или тег, указанный в --tag, совпадает с тегом образа werf в том же репозитории, так как публикация чарта перезаписала бы образ. В этом случае опубликуйте бандл с другим --tag или используйте другой тег образа.
Подробнее про кастомные теги можно прочитать в документации.
Имя и версия чарта
Имя чарта — всегда последний компонент пути репозитория, в который публикуется чарт: werf bundle publish --repo example.org/bundles/mybundle публикует чарт mybundle. Helm находит OCI-чарт только в репозитории, названном по имени чарта.
По умолчанию чарт публикуется с тегом latest. Указать иной тег, например, семантическую версию, можно опцией --tag:
werf bundle publish --repo example.org/bundles/mybundle --tag v1.0.0
Версия чарта определяется по тегу:
- строгая семантическая версия (
MAJOR.MINOR.PATCHс необязательными prerelease и build, с необязательным префиксомv) используется как есть, без префиксаv:v1.0.0→1.0.0; - любой другой тег (
latest, SHA коммита, имя ветки,1.2, число вроде даты или ID пайплайна) получает версию0.0.0-<unix-время>-<slug тега>, где slug — тег в нижнем регистре, в котором каждая последовательность символов, кроме букв и цифр, заменена на-:feature_Foo_1→0.0.0-<unix-время>-feature-foo-1. Если версия получилась бы длиннее 128 символов, максимальной длины тега, slug обрезается и к нему добавляется-и первые 8 шестнадцатеричных цифр SHA-256 тега.
werf публикует чарт с тегом его версии и, если он отличается, ещё и с указанным тегом, заменяя в обоих + на _, как это делает Helm: --tag 1.0.0+build.5 публикует 1.0.0_build.5. Команда выше публикует example.org/bundles/mybundle:1.0.0 и example.org/bundles/mybundle:v1.0.0, оба указывают на один и тот же чарт.
Тег, оканчивающийся на .prov, недопустим, так как такие теги адресуют файлы provenance.
Версия 0.0.0-… — это prerelease, поэтому Helm, Argo CD и Flux пропускают её при выборе версии по semver-диапазону: чтобы её выбрать, используйте диапазон вида >=0.0.0-0 или опцию Helm --devel. Две публикации с не-semver тегом в пределах одной секунды получают одинаковую версию и перезаписывают друг друга. Такие версии накапливаются в registry: очистка werf их не удаляет.
Если при публикации будет обнаружено, что в OCI-репозитории уже существует чарт с таким тегом, то чарт в репозитории будет перезаписан.
Развёртывание бандла
werf bundle apply развёртывает опубликованный чарт без доступа к Git-репозиторию приложения:
werf bundle apply --repo example.org/bundles/mybundle --tag v1.0.0
werf bundle publish и последующий werf bundle apply развёртывают то же самое, что werf converge с опциями, переданными werf bundle publish, а werf release get --print-values показывает те же параметры. Опции, переданные werf bundle apply (--values, --secret-values, --set*, --set-root-json, --patches, --add-annotation, --add-label), применяются поверх сохранённых при публикации и имеют приоритет над ними. Параметры объединяются в следующем порядке, от низшего приоритета к высшему:
values.yamlиsecret-values.yamlчарта.- Опции
--values,--secret-values,--set*и--set-root-jsonкомандыwerf bundle publish. - Служебные параметры werf, вычисленные при публикации (образы, репозиторий, окружение, коммит).
- Опции
--values,--secret-values,--set*и--set-root-jsonкомандыwerf bundle apply. - Служебные параметры werf, вычисленные при развёртывании (окружение, Namespace и другие).
Файлы --patches применяются в том же порядке: собственный patches.yaml чарта, затем файлы werf bundle publish, затем файлы werf bundle apply. Опции --disable-default-values и --disable-default-secret-values команды werf bundle apply игнорируют только values.yaml и secret-values.yaml чарта, но не параметры, сохранённые при публикации.
--secret-values команды werf bundle publish расшифровываются при развёртывании и сохраняются в релизе в расшифрованном виде, так же как werf converge сохраняет свои --secret-values, см. Секретные параметры в релизе. Для их расшифровки нужен секретный ключ, которым они были зашифрованы при публикации.
werf bundle publish сохраняет имя релиза и Namespace, вычисленные так же, как их вычисляет werf converge для указанного --env. werf bundle apply, werf bundle plan и werf bundle render используют их вместо непереданных --release и --namespace, в том числе когда не передан --env. Если вы передаёте непустой --env, отличный от использованного при публикации, сохранённые значения не используются и обязательны оба флага, --release и --namespace.
Единственное известное отличие от werf converge — .Chart.Name и .Chart.Version: при werf converge шаблоны получают имя проекта и версию из Chart.yaml (по умолчанию 1.0.0), а при werf bundle apply — имя репозитория и версию, полученную из тега. Поэтому лейбл вида helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} различается, и переход релиза с werf converge на werf bundle apply один раз перезапускает его Pod’ы.
werf converge, werf plan, werf render и werf lint тоже используют .werf-data/, если находят её в директории чарта (например, если в .helm лежит распакованный опубликованный чарт): её параметры, аннотации и лейблы применяются ниже опций команды.
Использование опубликованного чарта как зависимого
Когда werf или Nelm развёртывает чарт, который подключает опубликованный werf чарт как зависимый, параметры из .werf-data/ зависимого чарта становятся его параметрами по умолчанию, как если бы он развёртывался сам по себе с werf converge. Родительский чарт переопределяет их как обычно. Секретные параметры зависимого чарта расшифровываются секретным ключом развёртывания и, как параметры из secret-values.yaml любого зависимого чарта, сохраняются в релизе в расшифрованном виде. Его общие для релиза входные данные игнорируются с предупреждением, так как их определяет родительский чарт: аннотации и лейблы, --patches, --no-default-patches, --set-root-json, а также имя релиза и Namespace. werf bundle publish всегда сохраняет имя релиза и Namespace, поэтому развёртывание любого зависимого чарта, опубликованного werf, выводит это предупреждение.
Параметры global.*, включая global.werf.*, общие с родительским чартом, как и глобальные параметры в Helm: если родительский и зависимый чарт задают один и тот же ключ в global, зависимый чарт получает значение родительского. Параметры werf.* зависимого чарта остаются его собственными. Например, в шаблонах зависимого чарта, опубликованного с образом app:
image: {{ .Values.werf.image.app }} # образ, опубликованный с зависимым чартом
repo: {{ .Values.global.werf.repo }} # репозиторий werf-проекта родительского чарта
Изменение опубликованного чарта
Опубликованный чарт можно скачать, изменить и опубликовать снова без Git-репозитория приложения, например, с помощью CLI Nelm:
-
Скачайте и распакуйте чарт:
nelm chart download oci://example.org/bundles/mybundle --version 1.0.0 --untar -
Измените чарт:
values.yaml, секреты (nelm chart secret values-file edit mybundle/secret-values.yamlилиmybundle/.werf-data/secret-values.yaml), шаблоны или любой файл в.werf-data/. -
Упакуйте чарт и загрузите его:
nelm chart pack mybundle --set replicas=3 nelm chart upload mybundle-1.0.0.tgz oci://example.org/bundles
nelm chart pack сохраняет версию из Chart.yaml, если не передан --chart-version, и сохраняет архив в текущую директорию, если не передан --destination. Опции --values, --secret-values, --set*, --set-root-json и --patches команды nelm chart pack добавляются поверх сохранённых в .werf-data/, как если бы их дописали в конец исходной команды werf bundle publish: файлы параметров объединяются поверх сохранённых, а опции --set*, --set-root-json и --patches добавляются после сохранённых. Опции --no-default-values, --no-default-secret-values и --no-default-patches устанавливают сохранённые переключатели, но не сбрасывают их. Опция --reset-values удаляет всё сохранённое в .werf-data/ перед применением опций этой упаковки. Чтобы удалить одну сохранённую опцию, отредактируйте .werf-data/ и упакуйте чарт. При удалении сохранённого файла параметров (.werf-data/values.yaml, .werf-data/secret-values.yaml или .werf-data/extra-values.yaml) удалите и его флаг из секции values файла .werf-data/metadata.yaml (values: true, secretValues: true или extraValues: true), иначе упаковка и развёртывание чарта завершатся ошибкой вида .werf-data/metadata.yaml: values: true does not match the presence of values.yaml. Секретный ключ для nelm chart pack не нужен.
TypeScript-чарт при упаковке пересобирается, для чего нужен доступ к сети для скачивания его модулей. Чтобы вместо этого использовать собранный TypeScript-код скачанного чарта, передайте --ts-no-rebuild.
Чарт, опубликованный werf 3.12 и более ранними версиями, тоже можно переупаковать: nelm chart pack переносит его extra_annotations.json и extra_labels.json в .werf-data/, а его values.yaml, содержащий объединённые при публикации параметры, остаётся собственным values.yaml чарта.
Вместо nelm chart pack и nelm chart upload можно использовать helm package и helm push: они сохраняют .werf-data/, если её не исключает .helmignore чарта.
Изменение версии опубликованного чарта
Для изменения тега уже опубликованного чарта скопируйте бандл с новым тегом с помощью команды werf bundle copy, например:
werf bundle copy --from example.org/bundles/mybundle:v1.0.0 --to example.org/bundles/renamedbundle:v2.0.0
werf bundle copy --to REPO:TAG задаёт версию копии по TAG по тем же правилам, что и werf bundle publish, и публикует копию с тегом версии и указанным тегом. werf bundle copy --to REPO без тега сохраняет версию и тег исходного чарта. Копия называется по последнему компоненту пути целевого репозитория.
Копирование бандла в другой репозиторий
Для удобного копирования бандла в другой репозиторий имеется команда werf bundle copy. Кроме непосредственного копирования чарта и связанных с ним образов эта команда также заново формирует ссылки на образы в .werf-data/extra-values.yaml и в аннотации helm.sh/images для целевого репозитория.
Пример:
werf bundle copy --from example.org/bundles/mybundle:v1.0.0 --to other.example.org/bundles/mybundle:v1.0.0
Образы копируются по digest, мультиплатформенные образы — со всеми платформами. Образы чартов с .werf-data/, подключённых как зависимые на любом уровне вложенности, тоже копируются, а их аннотации helm.sh/images и .werf-data/extra-values.yaml переписываются для целевого репозитория. У бандла, опубликованного werf 3.12 или более ранней версией и подключённого как зависимый, нет .werf-data/: его образы не копируются, а значения не переписываются.
У бандла, опубликованного werf 3.12 или более ранней версией, нет .werf-data/: его образы берутся из значений werf.image, а значения werf.image, werf.repo и global.werf в его values.yaml переписываются для целевого репозитория.
Подписанный чарт (с provenance-файлом Helm) сохраняет подпись при копировании без изменений. Если при копировании чарт меняется, например, переписываются ссылки на образы, меняется имя или версия, подпись удаляется с предупреждением.
werf bundle apply, werf bundle plan и werf bundle render проверяют подпись бандла, скачанного из container registry, по публичным ключам из --provenance-keyring, если передан --provenance-strategy=verify (бандл без подписи вызывает ошибку) или --provenance-strategy=verify-if-possible (проверяется только подписанный бандл). werf bundle render --bundle-dir не может проверить подпись распакованного бандла и с --provenance-strategy=verify завершается ошибкой.
Экспорт бандла из container registry в архив
После публикации бандл может быть экспортирован из репозитория в локальный архив для дальнейшей дистрибуции иными способами с помощью команды werf bundle copy, например:
werf bundle copy --from example.org/bundles/mybundle:v1.0.0 --to archive:archive.tar.gz
Архив — это tar-файл, сжатый gzip, если его имя заканчивается на .gz или .tgz, с OCI image layout внутри (oci-layout, index.json, blobs/sha256/…). В нём хранятся чарт, вместе с provenance-файлом, если чарт подписан, и все образы чарта по digest:
- мультиплатформенные образы сохраняются со всеми платформами;
- non-distributable (foreign) слои образов тоже копируются в архив;
- referrers образов, например подписи и SBOM, привязанные к ним, не копируются.
werf 3.12 и более ранние версии не могут прочитать такие архивы: импортируйте их текущей версией werf.
Импорт бандла из архива в репозиторий
Экспортированный в архив бандл можно снова импортировать в тот же или другой OCI-репозиторий командой werf bundle copy, например:
werf bundle copy --from archive:archive.tar.gz --to other.example.org/bundles/mybundle:v1.0.0
После этого вновь опубликованный бандл (чарт и его образы) снова можно использовать привычными способами.
Архивы, созданные werf 3.12 и более ранними версиями (с chart.tar.gz и images/*.tar.gz внутри), по-прежнему можно импортировать. У них нет тега, поэтому без тега в --to бандл публикуется только под версией чарта.
Использование чарта с Helm, Argo CD и Flux
Helm, Argo CD и Flux устанавливают опубликованный чарт с его собственным values.yaml и параметрами, переданными им при установке. Сами они не читают .werf-data/, поэтому ссылок на образы и параметров, переданных werf bundle publish, у них нет: шаблоны, использующие .Values.werf.image.* или .Values.global.werf.images.*, получают пустые ссылки.
Примечание: в чартах, опубликованных werf 3.12 и более ранними версиями, ссылки на образы и опции
--valuesи--set*командыwerf bundle publishобъединялись вvalues.yaml. В новых чартах этого нет, поэтому для развёртывания нового чарта через Helm, Argo CD или Flux нужны файлы параметров, описанные ниже.
.werf-data/values.yaml (--values команды werf bundle publish) и .werf-data/extra-values.yaml (ссылки на образы и другие служебные параметры werf) — обычные YAML-файлы внутри чарта, поэтому их можно передать как файлы параметров. werf bundle publish всегда создаёт .werf-data/extra-values.yaml, а .werf-data/values.yaml — только если получает --values: либо перечислите только те файлы, которые есть в чарте, либо разрешите Flux и Argo CD пропускать отсутствующие файлы, как показано ниже.
Flux, HelmRelease, чарт которого берётся из HelmRepository типа oci:
spec:
chart:
spec:
chart: mybundle
sourceRef:
kind: HelmRepository
name: bundles
valuesFiles:
- values.yaml
- .werf-data/values.yaml
- .werf-data/extra-values.yaml
ignoreMissingValuesFiles: true
valuesFiles заменяет список файлов параметров по умолчанию, поэтому values.yaml нужно указать первым.
Argo CD, пути указываются относительно корня чарта:
spec:
source:
repoURL: example.org/bundles
chart: mybundle
targetRevision: 1.0.0
helm:
valueFiles:
- .werf-data/values.yaml
- .werf-data/extra-values.yaml
ignoreMissingValueFiles: true
Argo CD скачивает чарт из container registry, только если репозиторий (example.org/bundles) зарегистрирован в Argo CD как Helm-репозиторий с enableOCI: "true", например, в Secret репозитория с type: helm.
Даже с этими файлами параметров в Helm, Argo CD и Flux недоступно следующее:
- опции
--set*командыwerf bundle publish; - секреты: Helm не может расшифровать
secret-values.yaml,.werf-data/secret-values.yamlи файлыsecret/, а шаблоны, вызывающиеwerf_secret_file, завершаются ошибкой; - аннотации и лейблы
werf bundle publish; --disable-default-valuesкомандыwerf bundle publish: Helm по-прежнему используетvalues.yamlчарта;- ресурсы, генерируемые TypeScript: Helm не выполняет
ts/; - всё из
.werf-data/, если опубликованный werf чарт — зависимый чарт чарта, развёртываемого через Helm, Argo CD или Flux.
Helm помещает .werf-data/ в .Files и сохраняет её в релизе вместе с остальным чартом (.werf-data/secret-values.yaml остаётся зашифрованным). Шаблоны, читающие все файлы чарта, например через .Files.Glob "**", получают и файлы .werf-data/.
Совместимость с другими версиями werf и Nelm
Чарты, опубликованные werf 3.12 и более ранними версиями, текущая версия werf развёртывает без изменений.
Текущий формат чарта (apiVersion: v2 в .werf-data/metadata.yaml) требует werf v3 или Nelm v2 с поддержкой .werf-data/. Релизы werf v2 и Nelm v1, включающие проверку (werf/werf#8141, werf/nelm#808), отказываются развёртывать такой чарт, а также чарт, подключающий его как зависимый. Релизы werf v2 и Nelm v1 без этой проверки, werf 3.12 и более ранние версии, а также версии Nelm v2 без поддержки .werf-data/ не отказываются: они развёртывают чарт только с его собственными параметрами, без ссылок на образы, параметров, секретов, аннотаций и лейблов werf bundle publish.
Container registries, поддерживающие публикацию бандлов
Для публикации бандлов требуется container registry, поддерживающий спецификацию OCI (Open Container Initiative). Список наиболее популярных container registries, совместимость с которыми была проверена:
| Container registry | Поддерживает публикацию бандлов |
|---|---|
| AWS ECR | + |
| Azure CR | + |
| Docker Hub | + |
| GCR | + |
| GitHub Packages | + |
| GitLab Registry | + |
| Harbor | + |
| JFrog Artifactory | + |
| Yandex container registry | + |
| Nexus | + |
| Quay | - |