Шаблоны Application рендерятся и разворачиваются с помощью Nelm. Nelm расширяет стандартное поведение Helm аннотациями, управляющими порядком деплоя, жизненным циклом ресурсов, трекингом готовности и выводом логов. На этой странице описаны все аннотации, доступные в шаблонах Application.
Стадии деплоя
Nelm обрабатывает деплой в три стадии. Разные группы аннотаций влияют на разные стадии.
1. Render
Шаблоны вычисляются с текущими values. Доступ к кластеру не нужен (кроме lookup). На этой стадии:
werf.io/deploy-onуправляет включением ресурса в результат рендера для текущего типа операции (install,upgradeи т. д.).- Выполняются шаблонные функции (
werf_secret_file,dump_debugи др.). - Расшифровываются
secret-values.yamlи файлы изsecret/.
2. Plan
Nelm подключается к кластеру, читает текущее состояние ресурсов и запускает dry-run Server-Side Apply для вычисления точного diff. Затем строит DAG операций — какие ресурсы создать, обновить или удалить и в каком порядке.
На этой стадии:
- Аннотации порядка и зависимостей (
werf.io/weight,werf.io/deploy-dependency-*,*.external-dependency.werf.io/*) формируют DAG. - Аннотации жизненного цикла (
werf.io/ownership,werf.io/delete-policy,werf.io/delete-propagation) определяют, какие операции попадут в план.
Dry-run SSA означает, что diff вычисляет API server — defaulting, admission-плагины и мутирующие webhook’и применяются корректно.
3. Apply
Выполняется DAG: ресурсы создаются, обновляются или удаляются в порядке зависимостей, с параллелизмом там, где зависимостей нет. Трекинг готовности и стриминг логов выполняются параллельно.
На этой стадии:
- Аннотации трекинга (
werf.io/track-termination-mode,werf.io/fail-mode,werf.io/failures-allowed-per-replica,werf.io/no-activity-timeout) управляют ожиданием. - Аннотации логов управляют выводом во время деплоя.
Типичные задачи
1. Job, которая должна запуститься перед основным приложением
Классический сценарий: миграция БД перед запуском приложения.
apiVersion: batch/v1
kind: Job
metadata:
name: {{.Application.Instance.Name}}-db-migrate
annotations:
werf.io/delete-policy: before-creation
spec: ...
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{.Application.Instance.Name}}-app
annotations:
werf.io/deploy-dependency-migrate: state=ready,kind=Job,name=db-migrate
spec: ...
before-creation гарантирует пересоздание Job при каждом деплое (иначе Kubernetes откажет в обновлении иммутабельных полей Job). Deployment ждёт ready — то есть успешного завершения Job.
2. Сохранение ресурса при удалении или uninstall
Сценарий: PVC с данными БД, который не должен удаляться при uninstall Application.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{.Application.Instance.Name}}-postgres-data
annotations:
helm.sh/resource-policy: keep
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 50Gi
storageClassName: gp3
helm.sh/resource-policy: keep предотвращает удаление PVC при uninstall или удалении из чарта. От d8 k delete pvc не защищает — для этого используйте persistentVolumeReclaimPolicy: Retain на StorageClass.
3. Ресурс, общий между релизами
TLS-секрет, используемый несколькими чартами, не должен исчезать при uninstall любого из них.
apiVersion: v1
kind: Secret
metadata:
name: {{.Application.Instance.Name}}-shared-tls
annotations:
werf.io/ownership: anyone
type: kubernetes.io/tls
data: ...
anyone сообщает Nelm, что он не единственный владелец ресурса, поэтому Nelm пропускает удаление при uninstall.
4. Зависимость от ресурса, созданного оператором
Деплой только после выпуска сертификата cert-manager:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{.Application.Instance.Name}}-app
annotations:
cert.external-dependency.werf.io/resource: certificates.v1.cert-manager.io/myapp-tls
spec: ...
Nelm дождётся состояния present и ready у Certificate, прежде чем создавать Deployment.
5. Некритичный компонент, не роняющий весь деплой
DaemonSet с метриками, чья недоступность не должна блокировать релиз:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: {{.Application.Instance.Name}}-metrics-agent
annotations:
werf.io/fail-mode: IgnoreAndContinueDeployProcess
werf.io/track-termination-mode: NonBlocking
spec: ...
Nelm не будет ждать готовности и не упадёт по таймауту.
6. Ресурс, рендерящийся только при первой установке
Init Job, нужная только при install, не при upgrade:
apiVersion: batch/v1
kind: Job
metadata:
name: {{.Application.Instance.Name}}-init-data
annotations:
werf.io/deploy-on: install
werf.io/ownership: anyone # КРИТИЧНО
spec: ...
Без werf.io/ownership: anyone при upgrade ресурс рендерится как отсутствующий, и владеющий релиз его удалит. anyone предотвращает это.
7. Медленно стартующий ресурс с большим образом
StatefulSet с большим Docker-образом (ML-модели, Elasticsearch с предзагруженными индексами):
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: elasticsearch
annotations:
werf.io/no-activity-timeout: 20m
werf.io/failures-allowed-per-replica: "3"
werf.io/show-service-messages: "true"
spec: ...
no-activity-timeout: 20m— 20 минут без событий, прежде чем Nelm считает это таймаутом. Используйте для медленного image pull или долгой инициализации.failures-allowed-per-replica: "3"— допускает до 3 перезапусков на реплику перед объявлением ошибки. Используйте для нестабильных зависимостей при инициализации.show-service-messages: "true"— выводить Kubernetes Events в лог деплоя (полезно для диагностикиImagePullBackOff, ошибок планирования, OOM).
Порядок и зависимости
Веса
werf.io/weight группирует ресурсы: одинаковые веса деплоятся параллельно; разные — последовательно в порядке возрастания.
metadata:
annotations:
werf.io/weight: "-10" # Деплоится раньше ресурсов с весом по умолчанию (0)
Прямые зависимости
werf.io/deploy-dependency-<id> ждёт, пока конкретный ресурс в том же релизе достигнет указанного состояния, прежде чем деплоить аннотированный ресурс.
metadata:
annotations:
werf.io/deploy-dependency-db: state=ready,kind=StatefulSet,name=postgres
werf.io/deploy-dependency-migrations: state=present,kind=Job,name=db-migrate
Состояния зависимости:
ready— ресурс в готовом состоянии (например, у Deployment сошлисьavailableReplicas == replicas).present— ресурс существует в кластере.
Полный формат:
werf.io/deploy-dependency-<id>: state=ready|present[,name=<name>][,namespace=<namespace>][,kind=<kind>][,group=<group>][,version=<version>]
Аннотация не работает, если ресурс-зависимость находится в другой стадии деплоя (pre/main/post). Порядок между стадиями уже обеспечивает сама последовательность стадий.
Внешние зависимости
<id>.external-dependency.werf.io/resource ждёт ресурс вне релиза (созданный оператором или другим релизом):
metadata:
annotations:
cert.external-dependency.werf.io/resource: certificates.v1.cert-manager.io/myapp-tls
cert.external-dependency.werf.io/name: myapp-production # Неймспейс внешнего ресурса
Полный формат:
<id>.external-dependency.werf.io/resource: <kind>[.<version>.<group>]/<name>
Зависимости при удалении
werf.io/delete-dependency-<id> — аннотированный ресурс будет удалён только после того, как указанный ресурс станет absent:
metadata:
annotations:
werf.io/delete-dependency-app: state=absent,kind=Deployment,name=app
Аннотации жизненного цикла
helm.sh/resource-policy
keep — не удалять ресурс при uninstall или удалении из чарта. Ресурс продолжает обновляться при install/upgrade, пока рендерится.
werf.io/ownership
release(по умолчанию для обычных ресурсов) — ресурс удаляется при uninstall и при отсутствии в чарте. Применяются release metadata-аннотации.anyone(по умолчанию для хуков и CRD изcrds/) — ресурс не удаляется при uninstall. Release metadata-аннотации не применяются.
Используйте anyone для ресурсов, общих между релизами, или для ресурсов, которые должны переживать свой релиз (init Job с werf.io/deploy-on: install).
werf.io/deploy-on
Управляет тем, в каких операциях жизненного цикла рендерится ресурс.
werf.io/deploy-on: pre-install,upgrade,post-install
Допустимые значения: pre-install, install, post-install, pre-upgrade, upgrade, post-upgrade, pre-rollback, rollback, post-rollback, pre-uninstall, uninstall, post-uninstall. По умолчанию: install,upgrade,rollback.
Если ресурс рендерится для install, но не для upgrade, и у него werf.io/ownership: release — ресурс будет удалён при upgrade, так как он отсутствует в upgrade-рендере. Установите werf.io/ownership: anyone, чтобы это предотвратить.
werf.io/delete-policy
Управляет тем, когда ресурс удаляется относительно операции apply.
| Значение | Когда |
|---|---|
before-creation |
Всегда пересоздавать перед apply |
before-creation-if-immutable |
Пересоздавать только при ошибке «поле иммутабельно» (по умолчанию для Job) |
succeeded |
Удалить после успешного деплоя |
failed |
Удалить при провале readiness-чека |
Значения можно комбинировать через запятую: before-creation,succeeded.
werf.io/delete-propagation
Стратегия каскадного удаления в Kubernetes.
| Значение | Поведение |
|---|---|
Foreground (по умолчанию) |
Ждать удаления зависимых объектов |
Background |
Удалить ресурс сразу; зависимые удаляются асинхронно |
Orphan |
Удалить ресурс; зависимые оставить |
Аннотации трекинга
| Аннотация | По умолчанию | Описание |
|---|---|---|
werf.io/track-termination-mode |
WaitUntilResourceReady |
WaitUntilResourceReady или NonBlocking |
werf.io/fail-mode |
FailWholeDeployProcessImmediately |
FailWholeDeployProcessImmediately или IgnoreAndContinueDeployProcess |
werf.io/failures-allowed-per-replica |
1 |
Число перезапусков на реплику до объявления ошибки |
werf.io/no-activity-timeout |
4m |
Go duration; таймаут при отсутствии событий или изменений статуса |
werf.io/show-service-messages |
false |
Показывать Kubernetes Events в выводе деплоя |
Аннотации логов
| Аннотация | По умолчанию | Описание |
|---|---|---|
werf.io/skip-logs |
false |
Скрыть все логи подов |
werf.io/skip-logs-for-containers |
— | Список контейнеров через запятую для скрытия |
werf.io/show-logs-only-for-containers |
— | Список контейнеров через запятую; показывать только для них |
werf.io/show-logs-only-for-number-of-replicas |
1 |
Показывать логи только для первых N реплик |
werf.io/log-regex |
— | RE2-паттерн; показывать только совпадающие строки |
werf.io/log-regex-skip |
— | RE2-паттерн; скрывать совпадающие строки |
werf.io/log-regex-for-<container> |
— | Per-container RE2-фильтр на показ |
werf.io/log-regex-skip-for-<container> |
— | Per-container RE2-фильтр на скрытие |
Шаблонные функции
werf_secret_file
Встроить расшифрованное содержимое файла из директории secret/:
data:
config.yaml: {{ werf_secret_file "config.yaml" | b64enc }}
Файлы в secret/ хранятся зашифрованными (AES-128-CBC, ключ из NELM_SECRET_KEY). При рендере расшифровываются в памяти. Используйте для сертификатов, приватных ключей и больших конфигов, которые неудобно хранить в secret-values.yaml.
dump_debug, printf_debug, include_debug, tpl_debug
Функции отладочного вывода, которые пишут в логи, не влияя на результат рендера. Активируются только при debug log-level.
{{ dump_debug $ }}
{{ printf_debug "replicaCount: %d" .Values.replicaCount }}
{{ include_debug "myapp.labels" . | nindent 4 }}
{{ tpl_debug "{{ .Values.template }}" . }}
Известные подводные камни
-
null-значения и SSA. Server-Side Apply часто падает на полях со значениемnull. Если.Values.fooравноnil, в манифесте появитсяfoo: null. Решение: guard-условия{{ if .Values.foo }}или использованиеdefault. -
Время выполнения
lookup. Если ресурсы кластера изменились между стадиями Plan и Apply, отрендеренный план может быть устаревшим. Избегайтеlookupдля критичной логики — передавайте данные через values. -
Недетерминированные функции.
now,randAlphaNumи итерация по map с непостоянным порядком ключей дают разный результат при каждом вызове. С замораживанием плана это может создавать ложные diff’ы. -
werf.io/deploy-dependency-*и стадии. Аннотация не работает через стадии деплоя (pre/main/post). Порядок между стадиями обеспечивается самой последовательностью стадий.