Helm vs Kustomize: выбор и сравнение
Helm и Kustomize — два самых популярных подхода к управлению Kubernetes manifests. Оба официально поддерживаются CNCF и встроены в основные GitOps-tools (ArgoCD, Flux). Часто их противопоставляют как “или то, или это” — но в реальности зрелые команды используют оба одновременно. Этот урок — про сравнение по ключевым аспектам, реальные критерии выбора и паттерн комбинирования.
Паттерны компоновки DE-стека в Docker Compose
Side-by-side: главное
| Аспект | Helm | Kustomize |
|---|---|---|
| Подход | Templating (Go templates) | Patches на base manifests |
| Файлы до рендера | Не валидный YAML | Всегда валидный YAML |
| Learning curve | Steeper (Sprig, helpers, _helpers.tpl) | Easier (просто YAML + kustomization.yaml) |
| Reusability | Charts via repositories | Bases можно переиспользовать (git/path) |
| Lifecycle management | Releases (история, rollback, статусы) | Stateless (нет concept of release) |
| Community charts | Огромная экосистема (Artifact Hub, Bitnami) | Меньше, но растёт |
| Conditional logic | Powerful (if/range/with + sprig) | Ограниченные (через components, alpha) |
| YAML correctness | Runtime (errors после рендера) | Compile-time (всегда valid YAML) |
| State storage | Release Secrets в кластере | Нет (only kustomization.yaml в git) |
| Inclusion в kubectl | Отдельный бинарь | Встроен (kubectl apply -k) |
| ConfigMap rollout | Через checksum/config annotation hack | Автоматически через hash suffix |
| CRDs | crds/ директория (не upgrade) | resources как обычно |
| Update strategy | upgrade с reuse/reset-values | git revert + apply |
Где побеждает Helm
1. Сложные third-party приложения
Установить Prometheus stack с alertmanager, exporters, grafana — это десятки манифестов с conditionals (включить alertmanager? scrape какие endpoints? какие dashboards?). Helm chart инкапсулирует это в helm install prometheus prometheus-community/kube-prometheus-stack -f values.yaml — пользователь меняет 20 значений в values.yaml, не понимая internal details chart-а.
Kustomize этого не может — нет conditional logic для “если включён alertmanager — добавь ServiceMonitor для него”. Пришлось бы делать множество overlays для каждой комбинации features.
2. Версионирование и распространение
helm repo add bitnami ... → команда сразу получает доступ к 100+ chart-ам. SemVer-версионирование, репозитории как стандартный механизм distribution. Можно зафиксировать --version 15.4.4 и быть уверенным, что pull в CI даст тот же результат.
Kustomize bases — это директории в git repo. Тоже работает, но менее formalized — пиннинг через ?ref=v1.0.0, нет central registry.
3. Lifecycle management
helm history web # вижу все ревизии
helm rollback web 2 # откат
helm uninstall web # cleanup всех resources
В Kustomize этого нет. Откат — git revert + apply, cleanup — kubectl delete -k <dir> (но не удалит resources, которые когда-то были, а потом убраны из kustomization).
4. helm test для smoke-тестов
Hook type test — Job, который запускается через helm test <release>. Стандартный механизм для smoke-проверки release. Kustomize такого не имеет.
Где побеждает Kustomize
1. In-house apps с multiple environments
Команда деплоит свой собственный микросервис в dev/staging/prod. Структура манифестов известна. 80% — одинаково между env, 20% — env-specific (replicas, resources, namespace). Kustomize overlays идеально для этого — никаких placeholders, копируешь только diff.
Helm для этого overkill: создавать Chart, values.yaml, разбираться с Go templates — для простых in-house apps это лишний слой.
2. ConfigMap immutability + auto-rollout
configMapGenerator создаёт ConfigMap с hash suffix. Изменение data → новое имя → автоматический rolling update Deployment-а. В Helm нужен manual hack:
spec:
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
Этот pattern — must-have, но требует disciplined adoption в каждом chart-е. Kustomize решает это by default.
3. YAML correctness и линтеры
Файлы Kustomize — валидный YAML. Можно открыть в IDE с подсветкой, прогнать через kubeval/kubeconform для validation против K8s schemas, использовать yq для query.
Helm templates — это string templating над YAML-подобным текстом. До рендеринга — не YAML. Type errors типа replicas: "{{ .Values.replicas }}" (string вместо int) — runtime errors на apply. Helm 3 добавил values.schema.json — можно валидировать values, но не сами templates.
4. GitOps-friendly
GitOps tools любят, когда git = source of truth. Kustomize fits perfectly: всё в git, никакого client-side state. ArgoCD/Flux рендерят kustomize build → applying → done. Diff между git и cluster показывается dashboard-ом.
С Helm GitOps работает, но есть две модели:
- “Helm-as-source”: ArgoCD сам запускает helm template/install — нужно managed Helm credentials, history живёт в кластере как Secrets.
- “Rendered Helm”: git хранит результат
helm template, ArgoCD просто applying — теряем helm rollback, но получаем простоту.
Combine оба: Kustomize over Helm
Реальный production-pattern: использовать Helm для third-party chart, Kustomize для env-specific overlay поверх:
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
helmCharts:
- name: nginx
repo: https://charts.bitnami.com/bitnami
version: 15.4.4
releaseName: web
namespace: production
valuesFile: values.yaml
patches:
- target:
kind: Deployment
name: web-nginx
patch: |
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: production-pool
Здесь:
- Kustomize рендерит Helm chart через
helm template. - Накладывает patches поверх rendered output.
- Финальный YAML применяется как
kubectl apply -k.
Это даёт преимущества обоих:
- Стандартизация на third-party chart (используем готовый bitnami/nginx).
- Кастомизация под наш env через patches (которых нет в values.yaml chart-а — например, nodeSelector с нашими label-ами).
GitOps: и Helm, и Kustomize нативно
ArgoCD и Flux — два самых популярных GitOps-tools. Оба поддерживают и Helm, и Kustomize:
ArgoCD
# Application с Helm
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web
spec:
source:
repoURL: https://charts.bitnami.com/bitnami
chart: nginx
targetRevision: 15.4.4
helm:
values: |
replicaCount: 3
destination:
server: https://kubernetes.default.svc
namespace: web
# Application с Kustomize
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: api
spec:
source:
repoURL: https://github.com/myorg/k8s-configs
path: overlays/prod
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: api
ArgoCD под капотом запускает helm template или kustomize build, делает server-side apply через apiserver, отслеживает drift.
Flux
# HelmRelease
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: web
spec:
chart:
spec:
chart: nginx
sourceRef:
kind: HelmRepository
name: bitnami
version: "15.4.4"
values:
replicaCount: 3
# Kustomization
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: api
spec:
path: overlays/prod
sourceRef:
kind: GitRepository
name: k8s-configs
Flux — более модульный (отдельные controllers для каждой задачи), ArgoCD — более UI-driven.
Когда что выбирать: practical guide
Helm:
- Устанавливаешь популярное third-party (Prometheus, Grafana, nginx-ingress, cert-manager, sealed-secrets).
- Нужны conditionals в манифестах (опциональный alertmanager, опциональный ingress).
- Нужен built-in lifecycle (rollback, history) на уровне инструмента.
- Команда уже знакома с Helm, есть legacy charts.
Kustomize:
- Деплоишь in-house apps с минимальными conditionals.
- Несколько environments с похожей структурой (dev/staging/prod).
- Хочешь GitOps с simple model (git = state, без client-side history).
- YAML correctness важна (auto-validation, IDE support).
- Не хочешь учить Go templates команде.
Оба:
- В GitOps setup с третьих сторон вендорят charts + накладывают env patches.
- Большая организация, разные команды могут выбирать что им удобнее.
YAML correctness — глубже
Главный killer-аргумент Kustomize: Helm templates до рендера — это string templating над YAML-подобным текстом, не YAML.
Типичные runtime errors в Helm:
# values.yaml
replicas: 3 # int
# template
replicas: "{{ .Values.replicas }}" # WRONG — quotes делают string!
Apiserver примет (StrictType disabled by default в JSON Schema validation) но Deployment broken. Или:
# template
replicas: {{ .Values.replicas | quote }} # WRONG — quote делает "3" string
Validation на K8s side detect-ит позже: “spec.replicas in body must be of type integer”. Это ошибка на runtime.
В Kustomize таких ошибок просто не существует — YAML всегда правильный, patches применяются на уже-typed values.
В Helm есть values.schema.json — JSON Schema validation для values. Но это валидирует input (значения, которые пользователь подаёт), не output (rendered manifests). Если в template ошибка с типами — schema не поможет. Используй helm template | kubeconform для post-render validation.
CKAD-перспектива
На экзамене CKAD ожидают, что ты знаешь оба:
helm install <name> <chart>— установка из chart-а (часто с уже-настроенным repo на экзамене).helm upgrade --install <name> <chart> -f values.yaml— idempotent.helm list -n <ns>— посмотреть установленные.helm uninstall <name>— удалить.kubectl apply -k <dir>— apply Kustomize overlay.- Понимание structure:
base/+overlays/<env>/для Kustomize,templates/+values.yamlдля Helm.
Создавать chart с нуля или сложные Kustomize structures — за пределами CKAD scope. Ожидается navigate существующих и базовая модификация values.
Killer-моменты
- Helm templates — НЕ валидный YAML до рендера. Type errors типа
replicas: "3"(string vs int) — runtime errors. Kustomize всегда работает с valid YAML. - ConfigMap rollout: Kustomize — автоматически через hash suffix. Helm — manual через
checksum/configannotation. Это elegantly решено в Kustomize. - State management: Helm — Release Secrets в кластере, есть
helm rollback. Kustomize — stateless, rollback черезgit revert. - GitOps tools (ArgoCD, Flux) поддерживают оба нативно. Можно даже комбинировать: Kustomize over Helm для env-specific tweaks.
- CKAD scope: пользоваться обоими. Создание чартов с нуля — за пределами.
- Reuse: Helm — через repository (центр). Kustomize — через
resources: ../../base(path) или git-ссылку.