Сначала проверьте совместимость с v2, затем изменения сборки, деплоя и очистки registry. Удалённые возможности требуют изменений до обновления; устаревшие ключи пока работают с предупреждением.
Совместимость с v2
Для параллельной работы и отката на v2 важны не только версии бинарей, но и общие конфигурация, секреты и registry:
- Конфигурация. После перехода на настройки v3 не рассчитывайте, что тот же
werf.yamlбудет работать в v2. Для отката сохраните совместимую с v2 ревизию конфигурации — см. изменения сборки. - Секреты. Старые секреты читаются в v3, но новые записи v3 не читаются старым клиентом. Обновите всех читателей до первой перезаписи; замена бинаря обратно на v2 не вернёт прежний формат — см. зашифрованные секреты.
- Registry. Общий
--repoозначает общие образы, даже при отдельном--meta-repo. До переноса метаданных остановите старые задания, а образы для отката защитите от очистки. После переноса не возвращайте cleanup v2 на этот репозиторий — см. очистку registry.
Сборка
После перехода на v3 ожидайте полную пересборку образов. Учтите её при планировании обновления.
Образы вместо artifacts
Директива artifact удалена. Замените её на image с final: false:
| Было — v2 | Стало — v3 |
|---|---|
|
|
Имена образов
Безымянные stapel-образы (image: ~) больше не поддерживаются — задайте каждому образу имя.
Имена теперь проверяются при загрузке конфигурации. Допустимы латинские буквы, цифры, _, ., - и +, а также сегменты через /. Каждый сегмент должен начинаться с буквы или цифры и заканчиваться буквой, цифрой или +. Имя modules/controller допустимо; пустое имя, пробелы, /api, api- и modules//controller вызывают ошибку конфигурации. Проверьте также имена, формируемые Go-шаблонами.
Единый from для ссылок на образы
Базовые образы и imports используют from и для внутренних, и для внешних образов. Имя образа из werf.yaml, например base, обозначает внутренний образ; ссылка с тегом или digest, например alpine:3.20, — внешний.
Ниже каждый блок — самостоятельный werf.yaml. Все образы, на которые ссылается конфигурация, объявлены в том же примере.
Базовый образ stapel
Образ app наследует образ base, объявленный выше. Замените fromImage: base на from: base:
| Было — v2 | Стало — v3 |
|---|---|
|
|
Импорт файлов из другого образа
Образ builder создаёт файл, а app копирует его до стадии setup. Замените import.image на import.from; также удалите stage, поскольку в v3 импортируется готовый образ-источник:
| Было — v2 | Стало — v3 |
|---|---|
|
|
Зависимость от образа
Образ app получает имя собранного образа backend в переменную BACKEND_IMAGE. Замените dependencies.image на dependencies.from; вложенный блок imports передаёт информацию об образе, а не копирует файлы:
| Было — v2 | Стало — v3 |
|---|---|
|
|
Ключи fromImage, import.image и dependencies.image по-прежнему работают в v3, но выводят предупреждение об устаревании. Указание одновременно старого и нового ключа — ошибка. В отличие от этих ключей, import.stage удалён.
Внешний образ с явным тегом
Внешняя ссылка в базовом from или import.from требует явного тега или digest. Например, замените неявное :latest на явное:
| Было — v2 | Стало — v3 |
|---|---|
|
|
Вместо :latest можно указать нужный тег (:TAG) или digest (@sha256:...). Внутренним именам образов из werf.yaml тег не нужен.
Билдеры и настройки образа
Ansible-билдер удалён. Перепишите шаги ansible: с использованием Shell-билдера; переименования ключа недостаточно.
Директива docker: удалена. Перенесите настройки в imageSpec.config, преобразовав имена и форматы полей. Например, для фрагмента stapel-образа:
| Было — v2 | Стало — v3 |
|---|---|
|
|
Полный набор полей описан в разделе Изменение конфигурации образов.
Импорт файлов
Кеш импорта теперь зависит от образа-источника, а не от контрольных сумм выбранных файлов, как было по умолчанию в v2. Изменение источника может вызвать пересборку образа-получателя, даже если копируемые файлы не изменились. includePaths/excludePaths по-прежнему выбирают файлы для копирования, но больше не изолируют кеш от остальных изменений источника. Если такие пересборки дороги, выделите импортируемый результат в отдельный небольшой образ.
import.stage удалён. Импорт использует готовый образ-источник, а не выбранную промежуточную стадию. Если нужно промежуточное состояние, оформите его отдельным образом. before/after по-прежнему задают момент импорта в образе-получателе.
Завершающий / в to: директив export/import теперь вызывает ошибку, кроме корневого пути to: /. Раньше werf убирал его с предупреждением, хотя пользователь мог ожидать копирование «внутрь каталога». Перед заменой to: /usr/sbin/ на to: /usr/sbin проверьте назначение:
- Если
add— каталог, его содержимое сливается вto. - Если
add— файл, он копируется внутрьto, когдаto— существующий каталог; иначеto— путь файла назначения. Чтобы результат не зависел от наличия родительского каталога, укажите полное имя файла, напримерto: /etc/app/config.yaml, и убедитесь, что по этому пути нет каталога.
Подробнее — правила пути назначения.
Зависимости стадий от Git
git.stageDependencies определяет, какие изменения файлов Git запускают пересборку стадий. В v3 отсутствие настройки и явный пустой список могут иметь разный смысл:
| Настройка | Было — v2 | Стало — v3 |
|---|---|---|
Весь блок отсутствует или задан как {} |
Прямой зависимости стадий от файлов Git нет. | Все три стадии получают **/*: учитываются все файлы git mapping с его фильтрами includePaths/excludePaths. |
| Маски стадии заданы явно | Учитываются подходящие файлы. | То же поведение. |
Для стадии явно задано [] |
Прямой зависимости от файлов Git нет. | То же поведение; стадия считается явно объявленной. |
В частично заполненном блоке пропущенные стадии до последней явно объявленной получают [], а после неё — **/*. Порядок всегда install → beforeSetup → setup, независимо от порядка ключей YAML. Правило применяется отдельно для каждого git mapping. В v2 любая пропущенная стадия не зависела от файлов Git, независимо от позиции: новые **/* после последней объявленной стадии могут добавить пересборки.
Например, задан только beforeSetup:
git:
- add: /
to: /app
stageDependencies:
beforeSetup:
- "src/**/*"
install получает [], beforeSetup — src/**/*, setup — **/*. Поэтому изменение файла вне src само по себе не запускает install или beforeSetup, но запускает setup, если у неё есть инструкции.
Если заданы install и setup:
git:
- add: /
to: /app
stageDependencies:
install:
- package-lock.json
setup:
- "src/**/*"
Пропущенный beforeSetup получает []: он находится до последней объявленной стадии setup. Пустой список тоже задаёт эту границу: при единственном beforeSetup: [] маски install и beforeSetup пусты, а setup получает **/*.
По умолчанию безопаснее: без настройки зависимостей изменения исходников запускают команды сборки заново. Сборки могут стать чаще. Чтобы сохранить отсутствие прямой Git-зависимости, задайте [] явно; чтобы стадия всегда учитывала все файлы mapping — ["**/*"]. Если задаёте маски, включите все файлы, влияющие на результат стадии.
[] отключает только прямую зависимость от файлов Git. Изменения предыдущих стадий, базового образа, команд и остальных входных данных по-прежнему могут вызвать пересборку. Маски не создают стадии без инструкций; beforeInstall в этот механизм не входит.
Непустой stageDependencies для стадии без инструкций сборки теперь вызывает ошибку вместо предупреждения. Например, этот фрагмент не пройдёт проверку при сборке:
git:
- add: /
to: /app
stageDependencies:
install:
- "src/**/*"
shell:
setup:
- cd /app && sh src/build.sh
Зависимости заданы для install, а команды есть только у setup. Если файлы src нужны для этих команд, перенесите маски из stageDependencies.install в stageDependencies.setup. Если нужна именно стадия install, добавьте инструкции shell.install; если зависимость лишняя — удалите её.
Подробнее — зависимость от изменений в Git-репозитории.
Проверка werf-giterminism.yaml
Исправьте неизвестные и опечатанные ключи в werf-giterminism.yaml: строгая проверка схемы больше не позволяет молча игнорировать их.
Какие образы собираются и выводятся
werf build и другие команды, запускающие сборку, теперь по умолчанию используют --final-images-only=true, как уже делали converge, render, export, plan, lint и bundle publish. «Сиротские» нефинальные образы, на которые не ссылается ни один финальный образ, больше не собираются по умолчанию.
werf config list также по умолчанию выводит только финальные образы; его устаревший алиас --images-only удалён.
Чтобы сохранить прежнее поведение:
werf build --final-images-only=false
werf config list --final-images-only=false
Сервер синхронизации
werf v3 больше не использует сервер синхронизации, включая публичный synchronization.werf.io. Если вы запускали собственный сервер, для v3 он больше не нужен. Отключайте его только после перехода всех клиентов, которые им пользуются; оставшимся клиентам v2 он ещё может быть нужен.
Buildah
Нативный Buildah-бэкенд перешёл с CNI/slirp4netns на netavark/pasta. До обновления подготовьте окружение в зависимости от того, как вы запускаете werf.
Официальный образ werf
Обновите контейнерный образ werf до v3, а не только бинарь внутри него. netavark уже включён в образ; для запуска werf в этом контейнере отдельно устанавливать его на хост runner не нужно.
Официальные Ubuntu-образы werf теперь основаны на Ubuntu 24.04. Если вы создаёте на их основе собственные образы, пересоберите и проверьте их.
Для rootless-сборки с настройкой сети также проверьте наличие pasta внутри контейнера при условиях, описанных ниже: одного netavark недостаточно. Если pasta отсутствует, добавьте её в свой производный образ.
Собственная установка или образ
Если вы устанавливаете werf непосредственно на хост или используете собственный контейнерный образ, убедитесь, что зависимости доступны в среде выполнения werf:
| Компонент | Где требуется |
|---|---|
netavark |
Везде, где запускается Buildah-бэкенд, включая chroot без сетевых инструкций. Без него инициализация бэкенда завершится ошибкой. |
pasta из пакета passt |
Для rootless-сборки, которая настраивает сеть. Не вызывается при network: host, network: none и в режиме chroot. |
netavark должен находиться в одном из каталогов /usr/local/libexec/podman, /usr/local/lib/podman, /usr/libexec/podman, /usr/lib/podman — поиск по $PATH не выполняется. Для pasta используются эти каталоги и $PATH.
Изменения сетевых настроек
Эти изменения действуют и внутри официального образа, и при других способах запуска.
Проверьте настройки сети. Для нестадийных Dockerfile-сборок на нативном Buildah теперь учитываются network: и --backend-network; раньше они молча игнорировались. Поддерживаются только default, host, none: bridge и имена Docker-сетей теперь вызывают ошибку.
Ограничения и совместимость:
- Для образов с
staged: trueнастройка сети уровня образа по-прежнему игнорируется; действует толькоRUN --network=конкретной инструкции. - В
native-chrootBuildah принудительно использует хостовую сеть, поэтомуnetwork: noneне обеспечивает изоляцию. - Поддержка CNI исключена при компиляции и не может быть восстановлена. slirp4netns можно вернуть на отдельном хосте через
CONTAINERS_CONF_OVERRIDE:default_rootless_network_cmd="slirp4netns"в секции[network]. - Это не миграция конфигурации системного Podman/Buildah: werf не читает и не перезаписывает
${graphroot}/defaultNetworkBackend. Если там записаноcni, значение сохраняется и продолжает влиять на системный CLI, использующий тот же graphroot.
Деплой
Перед первым werf converge проверьте werf plan: изменения values и правил исключения файлов могут повлиять на манифесты без предупреждения.
Замена удалённых команд werf helm
Команды деплоя и просмотра релизов внутри werf helm удалены. Для проектов werf используйте отдельные команды:
| Было — v2 | Стало — v3 |
|---|---|
werf helm install / werf helm upgrade |
werf converge для установки или обновления проекта |
werf helm template |
werf render |
werf helm lint |
werf lint |
werf helm list |
werf release list |
werf helm get … / werf helm status |
werf release get --release NAME --namespace NAMESPACE |
werf helm history NAME |
werf release history --release NAME --namespace NAMESPACE |
werf helm rollback NAME REVISION |
werf rollback --release NAME --namespace NAMESPACE --revision REVISION |
werf helm uninstall NAME |
werf dismiss --release NAME --namespace NAMESPACE |
werf helm test |
Используйте отдельную команду helm test; замены внутри werf нет. |
werf helm plugin |
Управляйте плагинами и запускайте их через Helm CLI напрямую; werf больше не загружает Helm-плагины. |
Это замены рабочих сценариев, а не точные алиасы. converge, render и lint работают с проектом werf, а не с позиционными аргументами Helm RELEASE CHART. Проверьте --help новой команды, явно задайте нужные release и namespace и адаптируйте скрипты разбора вывода. Например, release get --print-values включает вычисленные values в структурированный вывод, а не повторяет вывод helm get values. Для работы с отдельными Helm-чартами используйте Helm CLI напрямую.
werf helm secret и команды работы с чартами, например werf helm dependency, сохраняются; вся группа werf helm не удалена.
Values и переменные окружения
| Где | Было — v2 | Стало — v3 |
|---|---|---|
| Шаблоны основного чарта и зависимостей | .Values.global.env |
.Values.global.werf.env |
| Выбор хранилища релизов | HELM_DRIVER |
WERF_RELEASE_STORAGE |
Старый ключ .Values.global.env может превратиться в пустое значение без ошибки. Для временной совместимости можно задать WERF_LEGACY_VALUES_GLOBAL_ENV=1.
Без замены HELM_DRIVER werf использует хранилище релизов по умолчанию, а не ранее указанное этой переменной. Переменные путей Helm — HELM_CACHE_HOME, HELM_CONFIG_HOME, HELM_DATA_HOME — продолжают работать.
Чарты и бандлы
.helmignore теперь действует при чтении чарта. Исключённые файлы исчезают из сформированных манифестов и публикуемого бандла без предупреждения.
- Даже без
.helmignoreправила Helm по умолчанию исключают файлы и директории, начинающиеся с точки, непосредственно вtemplates/. Директории исключаются вместе с содержимым. **теперь вызывает ошибку, хотя раньше не оказывал эффекта.- Ведущий
!раньше не оказывал эффекта. Теперь он исключает всё, что не подошло под маску, как правило, оставляя чарт пустым. Не используйте его для отмены предыдущих исключений, как в.gitignore.
Правила для зависимых чартов зависят от способа подключения — см. Чарты и зависимости.
werf bundle publish теперь использует --helm-compatible-chart=true по умолчанию. Имя в Chart.yaml публикуемого бандла становится последним компонентом пути репозитория; меняются .Chart.Name и пути шаблонов. Чтобы сохранить имя из вашего Chart.yaml, передайте:
werf bundle publish --helm-compatible-chart=false
Режим совместимости AllowMissedSecretKeyMode из v1.2 удалён. При этом bundle publish по-прежнему не требует ключ секретов по умолчанию: значения секретов обрабатываются без расшифровки другим механизмом.
Зашифрованные секреты
Старый клиент не сможет прочитать секрет, записанный v3; возможности записать прежний формат нет. Соблюдайте порядок обновления:
- Обновите все окружения, читающие секреты репозитория, до werf v3 или nelm v2: локальные машины, CI-задачи и задачи, применяющие сохранённые deploy plans.
- Только после этого создавайте, редактируйте или ротируйте секреты. После перешифрования старый werf или nelm не должен работать с репозиторием.
| Было — v2 | Стало — v3 |
|---|---|
| Секреты в формате AES-CBC | Старые значения продолжают расшифровываться; новые записи используют новый формат. |
| Исходный YAML-тип зашифрованного значения не сохранялся | Для новых YAML-значений сохраняются тип и стиль. |
На что обратить внимание:
- Новый формат распознаёт повреждённый ciphertext и неверный ключ.
- Ciphertext целого secret-файла по-прежнему можно использовать как значение в
secret-values.yaml. - Целые secret-файлы используют формат 2, значения в
secret-values.yaml— формат 3. Автоматическое различение не даёт интерпретировать целый secret как YAML-метаданные. - Старые зашифрованные скаляры остаются строками. Чтобы восстановить число, boolean, timestamp или другой тип, введите значение заново через
werf helm secret values edit. - Комментарии у зашифрованных значений сохраняются открытым текстом. Не записывайте в них секреты.
Очистка registry
Само обновление werf не удаляет старые образы, но cleanup v3 может удалить образы v2 по политикам сохранения. Версия не даёт им отдельной защиты. Сохраните нужные для отката теги в файле --keep-list, по одному тегу стадии на строку. Не полагайтесь только на защиту Kubernetes: на образ для отката уже может не ссылаться ни один сканируемый ресурс.
Перед первой настоящей очисткой проверьте, что образы для отката не попали в список удаляемых. Используйте те же репозитории, keep-list и доступ к Kubernetes, которые будут у периодического задания:
werf cleanup --repo registry.example.com/app --dry-run --keep-list keep-list.txt
Если настроены --final-repo и --meta-repo, передайте те же значения, что и при сборке. Убедитесь, что сканирование охватывает кластеры и namespaces, использующие эти образы; --without-kube отключает защиту Kubernetes. Не используйте werf purge для удаления только образов v2: он удаляет образы проекта без политик сохранения cleanup.
Отдельный --meta-repo необязателен. Без него метаданные остаются в --repo; само обновление не требует их переноса. Если выносите метаданные существующего проекта в отдельный репозиторий:
- На время перехода приостановите периодическую очистку и старые задания v2, пишущие в тот же репозиторий.
-
Из каталога проекта перенесите накопленные метаданные до первой очистки с
--meta-repo:werf meta-repo migrate --from registry.example.com/app --to registry.example.com/app-meta - Во всех последующих командах v3, включая сборку, cleanup и purge, используйте одинаковый
--meta-repo registry.example.com/app-meta. Сами образы остаются в--repo; переносятся только метаданные. По умолчанию оригиналы удаляются после проверки копий;--remove-source=falseсохраняет их. - Повторно проверьте cleanup с
--dry-runи новым--meta-repo, затем возобновите задание очистки на v3. Не возвращайте cleanup v2 на мигрированный репозиторий: он не видит актуальные метаданные в новом месте.
Добавление --meta-repo само по себе не переносит старые метаданные. Новые записи идут в отдельный репозиторий, а оставшиеся в --repo метаданные cleanup больше не видит. Поэтому он может удалить образы, которые следовало сохранить. Защитный маркер проверяет одинаковый адрес метаданных в последующих командах, а не завершённость миграции. meta-repo detach только снимает защиту и не переносит метаданные обратно.
Подробнее — очистка container registry и отдельный репозиторий метаданных.