Шпаргалка: nelm

Nelm — движок деплоя werf нового поколения (Render → Plan → Apply, Server-Side Apply вместо 3-Way Merge). Полный разбор трёх стадий и аннотаций — M4, M7 «nelm-advanced» (полный справочник).

Самые используемые команды

1
2
3
4
5
6
7
8
nelm release install -n <ns> -r <release> <chart-dir> [--auto-rollback]  # Render+Plan+Apply одной командой
nelm release plan install -n <ns> -r <release> <chart-dir>                # только diff, без apply
nelm release uninstall -n <ns> -r <release>
nelm release list -n <ns>
nelm chart render <chart-dir> -r <release>                                 # только Render (аналог helm template)
nelm chart lint <chart-dir>
nelm chart secret key create
nelm chart secret values-file edit .helm/secret-values.yaml

Самые частые аннотации werf.io/* (полный список — ниже): werf.io/weight, werf.io/deploy-dependency-<id>, werf.io/ownership, helm.sh/resource-policy: keep, werf.io/delete-policy.


CLI: Release

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
nelm release install -n <ns> -r <release> <chart-dir>                     # Render+Plan+Apply (install/upgrade)
nelm release install -n <ns> -r <release> <chart-dir> --auto-rollback     # + автооткат при ошибке (аналог helm --atomic)
nelm release install -n <ns> -r <release> <chart-dir> --set <key>=<value> # переопределение values
nelm release plan install -n <ns> -r <release> <chart-dir>                # Render+Plan (dry-run Server-Side Apply), без Apply
nelm release plan install -n <ns> -r <release> <chart-dir> --set <key>=<value>
nelm release uninstall -n <ns> -r <release>                                # полное удаление релиза
nelm release list -n <ns>
nelm release history -n <ns> -r <release>
nelm release get -n <ns> -r <release>
nelm release rollback -n <ns> -r <release> --revision <N>

nelm release plan install показывает 100% точный diff между текущим и целевым состоянием ресурсов через dry-run Server-Side Apply — надёжнее клиентских трюков ванильного Helm.

CLI: Chart

1
2
3
4
5
6
7
8
9
nelm chart render <chart-dir> -r <release>                     # только шаблонизация (Render), аналог helm template
nelm chart render <chart-dir> -r <release> --log-level debug   # с debug-логом для dump_debug/printf_debug/...
nelm chart lint <chart-dir>                                     # синтаксис и best-practices чарта
nelm chart lint <chart-dir> --set <key>=<value>                 # lint с тестовыми values
nelm chart pack <chart-dir> -d <dist-dir>                       # упаковать чарт в .tgz
nelm chart upload <chart.tgz> oci://<registry>/charts           # опубликовать упакованный чарт в OCI-registry
nelm chart download oci://<registry>/charts/<name> --version <semver>  # скачать чарт по версии
nelm chart dependency download <chart-dir>                      # детерминированно скачать sub-charts по Chart.lock
nelm chart dependency update <chart-dir>                        # пересчитать зависимости и обновить Chart.lock

CLI: Chart secret (шифрование .helm/secret*)

1
2
3
4
5
6
7
8
export NELM_SECRET_KEY="$(nelm chart secret key create)"        # сгенерировать и сохранить ключ шифрования
nelm chart secret key rotate                                     # перешифровать все секреты новым ключом
nelm chart secret values-file edit .helm/secret-values.yaml     # интерактивная правка зашифрованного values-файла
nelm chart secret values-file encrypt <path>                     # зашифровать values-файл
nelm chart secret values-file decrypt <path>                     # расшифровать values-файл (просмотр)
nelm chart secret file edit <path>                                # интерактивная правка произвольного зашифрованного файла
nelm chart secret file encrypt <path>                              # зашифровать файл в .helm/secret/
nelm chart secret file decrypt <path>                              # расшифровать файл из .helm/secret/

NELM_SECRET_KEY — переменная окружения с ключом шифрования; без неё секреты нельзя расшифровать на стадии Render. Хранить в защищённом хранилище CI.

CLI: Repo

1
2
3
4
5
nelm repo add <alias> oci://<registry>/charts
nelm repo login oci://<registry> --username <user> --password <token>
nelm repo update
nelm repo remove <alias>
nelm repo logout <alias>

CLI: прочее

1
2
nelm version
nelm completion bash|zsh|fish|powershell

Аннотации werf.io/* и helm.sh/*: полный справочник

Ordering / dependencies (стадия Plan)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
werf.io/weight: "<N>"       # группировка порядка apply по числовому весу (меньший вес — раньше)
werf.io/deploy-dependency-<id>: "state=ready|present|absent,kind=<Kind>,name=<name>[,namespace=<ns>][,group=<g>][,version=<v>]"
# пример: ждать успешного завершения Job миграции перед Deployment
werf.io/deploy-dependency-migrate: "state=ready,kind=Job,name=db-migrate"
werf.io/deploy-dependency-migrate: "state=ready,kind=Job,name={{ .Application.Instance.Name }}-db-migrate"
werf.io/deploy-dependency-db: "state=ready,kind=StatefulSet,name=postgres"
werf.io/deploy-dependency-migrations: "state=present,kind=Job,name=db-migrate"   # present — без ожидания завершения

werf.io/delete-dependency-<id>: "state=absent,kind=<Kind>,name=<name>"           # удалить только после исчезновения другого ресурса
werf.io/delete-dependency-app: "state=absent,kind=Deployment,name=app"

# зависимость от ресурса ВНЕ текущего релиза (управляется другим оператором)
<id>.external-dependency.werf.io/resource: "<kind>[.<version>.<group>]/<name>"
<id>.external-dependency.werf.io/name: "<optional-additional-identification>"
cert.external-dependency.werf.io/resource: "certificates.v1.cert-manager.io/myapp-tls"
cert.external-dependency.werf.io/resource: "state=ready,kind=Certificate,name=app-tls,namespace=cert-manager"
tls.external-dependency.werf.io/resource: "secrets.v1/umami-tls-secret"

Lifecycle (werf.io/*, helm.sh/*)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
helm.sh/resource-policy: keep         # ресурс НЕ удаляется при uninstall / удалении из чарта (обычно на PVC)

werf.io/ownership: release             # дефолт: ресурс принадлежит одному релизу, удаляется вместе с ним
werf.io/ownership: anyone              # совместное владение — ресурс переживает uninstall одного релиза

# на какой фазе жизненного цикла ресурс рендерится/применяется
werf.io/deploy-on: pre-install | install | post-install
werf.io/deploy-on: pre-upgrade | upgrade | post-upgrade
werf.io/deploy-on: pre-rollback | rollback | post-rollback
werf.io/deploy-on: pre-uninstall | uninstall | post-uninstall
werf.io/deploy-on: "pre-install,upgrade,post-install"   # комбинация через запятую
# дефолт, если аннотация не указана:
werf.io/deploy-on: "install,upgrade,rollback"

werf.io/delete-policy: before-creation                   # удалить и пересоздать ресурс перед каждым apply
werf.io/delete-policy: before-creation-if-immutable      # пересоздание только при конфликте immutable-полей (дефолт для Job)
werf.io/delete-policy: succeeded                          # удалить ресурс после успешного деплоя
werf.io/delete-policy: failed                             # удалить ресурс при провале проверки готовности

werf.io/delete-propagation: Foreground    # каскадное удаление с ожиданием зависимых (дефолт)
werf.io/delete-propagation: Background    # удаление основного объекта без ожидания зависимых
werf.io/delete-propagation: Orphan        # зависимые объекты остаются после удаления родителя

Tracking (стадия Apply)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
werf.io/track-termination-mode: WaitUntilResourceReady   # блокировать деплой до готовности ресурса (дефолт)
werf.io/track-termination-mode: NonBlocking               # не ждать готовности ресурса

werf.io/fail-mode: FailWholeDeployProcessImmediately      # любая неудача роняет весь деплой (дефолт)
werf.io/fail-mode: IgnoreAndContinueDeployProcess          # неудача ресурса не блокирует остальной деплой

werf.io/failures-allowed-per-replica: "<N>"                # допустимое число рестартов на реплику (дефолт 1)
werf.io/no-activity-timeout: "<duration>"                  # таймаут ожидания готовности (дефолт 4m, пример 20m)
werf.io/show-service-messages: "true"                      # выводить Kubernetes Events в лог деплоя
werf.io/show-service-messages: "false"                     # не выводить (дефолт)

Log-аннотации (стадия Apply)

1
2
3
4
5
6
7
8
9
werf.io/skip-logs                                            # полностью подавить логи подов ресурса
werf.io/skip-logs-for-containers: "<container1>,<container2>" # подавить логи указанных контейнеров
werf.io/show-logs-only-for-containers: "<containers>"          # показывать логи только указанных контейнеров
werf.io/show-logs-only-for-number-of-replicas: "<N>"            # логи только от первых N реплик
werf.io/log-regex: "<regex>"                                     # показывать только строки, совпадающие с regex
werf.io/log-regex-skip: "<regex>"                                # скрывать строки, совпадающие с regex
werf.io/log-regex-skip: '.*GET /healthz.*'                        # пример: скрыть шумные health-check запросы
werf.io/log-regex-for-<container>: "<regex>"                      # regex-фильтр для конкретного контейнера (показать)
werf.io/log-regex-skip-for-<container>: "<regex>"                 # regex-фильтр для конкретного контейнера (скрыть)

Sensitive data

1
2
3
werf.io/sensitive: "true"          # скрыть diff всего ресурса в plan (для Secret это дефолт)
werf.io/sensitive-paths: "<jsonpath>,..."   # скрыть diff только указанных полей по JSONPath
werf.io/sensitive-paths: "$.spec.template.spec.containers[*].env[*].value,$.data.*"

Живая правка аннотаций (диагностика без редактирования шаблонов)

1
2
3
kubectl annotate deployment <name> -n <ns> werf.io/fail-mode=IgnoreAndContinueDeployProcess werf.io/track-termination-mode=NonBlocking --overwrite
kubectl annotate deployment <name> -n <ns> werf.io/log-regex-skip='.*GET /healthz.*' --overwrite
kubectl annotate deployment <name> -n <ns> 'werf.io/sensitive-paths=$.spec.template.spec.containers[*].env[*].value' --overwrite

Шаблонные функции Nelm/werf

{{ werf_secret_file "<path>" }}                   {{/* встраивает расшифрованный файл из .helm/secret/ */}}
{{ werf_secret_file "config.yaml" | b64enc }}     {{/* пример встраивания в Secret.data */}}

{{ dump_debug <context> }}                        {{/* выводит дерево контекста в debug-лог, не в манифест */}}
{{ dump_debug .Values.umami }}
{{ printf_debug "<format>" <args> }}               {{/* форматированный debug-вывод в лог */}}
{{ printf_debug "replicaCount: %d" .Values.replicaCount }}
{{ include_debug "<template-name>" <context> }}    {{/* debug-вариант include для именованных шаблонов */}}
{{ tpl_debug "<string-template>" <context> }}       {{/* debug-вариант tpl для строк-шаблонов */}}

{{ lookup ... }}   {{/* единственная функция Render с ограниченным доступом к кластеру (риск stale plan) */}}

Debug-функции (dump_debug, printf_debug, include_debug, tpl_debug) работают только на стадии Render и не попадают в итоговый манифест — проверяйте: nelm chart render . -r <release> --log-level debug 2>&1 | grep -c "dump_debug" должно быть 0 в манифесте.

Известные pitfalls (Server-Side Apply)

{{ .Values.foo | default <fallback> }}    {{/* защита от null — SSA трактует null как "удалить поле" */}}
{{ if .Values.foo }}...{{ end }}            {{/* условное исключение поля из манифеста при nil */}}
{{ keys <map> | sortAlpha }}                 {{/* стабильный порядок итерации по map — иначе ложные diff */}}

Недетерминированные функции ломают идемпотентность plan (каждый прогон даёт новый diff):

{{ now }}                {{/* недетерминированное время */}}
{{ randAlphaNum <N> }}   {{/* недетерминированная случайная строка */}}

Поиск проблемных мест в уже написанных шаблонах:

1
2
3
grep -rn "werf.io/" templates/ | sort                        # аудит всех Nelm-аннотаций в чарте
grep -n "lookup\|now \|randAlphaNum" templates/*.yaml         # аудит недетерминированных конструкций
grep -B2 ": null"                                              # поиск null-полей в отрендеренном манифесте

Контекст шаблонов Application (API поверхность, не CLI)

{{ .Application.Instance.Name }}                 {{/* имя инстанса Application */}}
{{ .Application.Package.Images "<image-key>" }}  {{/* образ из package.yaml */}}

Vanilla Helm — для сравнения (встречается в уроках M4 как база)

1
2
3
4
5
6
helm create <name>                                    # шаблонная структура Helm-чарта
helm template <release> <chart-dir>                    # client-side рендер без установки (аналог nelm chart render)
helm lint <chart-dir>                                    # lint ванильного Helm-чарта (аналог nelm chart lint)
helm upgrade --install --atomic --wait -n <ns> <release> <chart-dir>   # аналог nelm release install --auto-rollback
helm uninstall -n <ns> <release>                          # аналог nelm release uninstall
helm dependency build                                       # аналог nelm chart dependency download

Главное отличие: Helm 3 использует client-side 3-Way Merge (сравнение манифеста, live-состояния и последнего сохранённого релиза), Nelm — Server-Side Apply через dry-run на стороне API-сервера, что даёт 100%-точный diff даже при ручных правках kubectl edit.