Перейти к содержанию
Learning Platform
Глоссарий Troubleshooting
Урок 18.04 · 22 мин
Средний
Kustomizekubectl apply -kbaseoverlaypatchesconfigMapGeneratorGitOps

Kustomize: альтернатива templating

Helm берёт YAML и подставляет туда переменные через Go templates. Kustomize — противоположный подход: никаких переменных, только patches на base manifests. Файлы в Kustomize-проекте — всегда valid YAML, который можно открыть в редакторе с подсветкой, прогнать через kubectl apply напрямую и понять без рендеринга. Этот урок — про философию Kustomize, его primitives и типичные паттерны.


Override-файлы: base + dev + prod конфигурации в Compose

Что такое Kustomize

Kustomize — declarative customization tool for Kubernetes. Создан Google, встроен в kubectl начиная с v1.14 (2019). Запускается через kubectl apply -k <directory> или standalone бинарь kustomize build <directory>.

Философия:

  • Никакого templating — все файлы валидный YAML.
  • Composition over inheritance — base manifests + overlay-патчи.
  • Declarativekustomization.yaml декларирует, что и как изменить, никаких императивных команд.
# kubectl-встроенный (предпочтительный для CKAD)
kubectl apply -k ./overlays/prod

# Standalone бинарь (для CI, более новые фичи)
kustomize build ./overlays/prod | kubectl apply -f -

# Render без apply (debug)
kustomize build ./overlays/prod
INFO

В kubectl встроена своя версия Kustomize, которая обычно отстаёт от standalone бинаря на 1-2 minor. Если нужны новые features (alpha-плагины, новые API) — используй standalone kustomize build. На CKAD достаточно встроенной версии.


Структура: base + overlays

Типичный layout:

myapp/
├── base/
│   ├── kustomization.yaml
│   ├── deployment.yaml
│   ├── service.yaml
│   └── configmap.yaml
└── overlays/
    ├── dev/
    │   ├── kustomization.yaml
    │   ├── deployment-patch.yaml
    │   └── config-dev.yaml
    ├── staging/
    │   ├── kustomization.yaml
    │   └── deployment-patch.yaml
    └── prod/
        ├── kustomization.yaml
        ├── deployment-patch.yaml
        └── hpa.yaml
  • base/ — общая, generic версия манифестов. Подходит для любого env (с минимальной нагрузкой).
  • overlays/<env>/ — env-специфичные изменения. Ссылаются на base и применяют patches/overrides.

base/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - deployment.yaml
  - service.yaml
  - configmap.yaml

commonLabels:
  app: myapp

commonAnnotations:
  owner: platform-team

overlays/prod/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base
  - hpa.yaml

namespace: production
namePrefix: prod-
nameSuffix: -v1

commonLabels:
  environment: production

replicas:
  - name: myapp
    count: 10

images:
  - name: myapp
    newName: registry.example.com/myapp
    newTag: v2.5.0

patches:
  - path: deployment-patch.yaml

Применение:

kubectl apply -k overlays/prod

kustomization.yaml: top-level директивы

Файл kustomization.yaml управляет тем, что Kustomize делает. Основные секции:

resources

Список файлов или директорий-ссылок:

resources:
  - deployment.yaml           # local file
  - service.yaml
  - ../base                   # parent directory как base
  - github.com/org/repo//path?ref=v1.0.0  # remote (отлично для shared bases)

Remote resources — мощный feature, но осторожно (зависимость от внешнего источника).

labels (современный способ) / commonLabels (legacy) / commonAnnotations

Добавляются ко всем resources И к их selectors:

# Современный способ (Kustomize 5.x — рекомендованный):
labels:
- includeSelectors: true        # явно: добавлять и в spec.selector.matchLabels
  pairs:
    app: myapp
    environment: production

# Legacy (всё ещё работает, но deprecated в новых версиях):
commonLabels:
  app: myapp
  environment: production

commonLabels и labels с includeSelectors: true имеют одинаковый эффект — применяют labels к metadata.labels, spec.template.metadata.labels И к spec.selector.matchLabels. Это критично: иначе Service не находит Pods после patching labels. Новые проекты пишите через labels с includeSelectors — это явно и контролируемо (можно иметь несколько групп labels с разной семантикой). commonAnnotations остаётся стандартом для annotations.

namespace / namePrefix / nameSuffix

namespace: production
namePrefix: prod-
nameSuffix: -stable

Всё резолвится в final имена ресурсов: Deployment myapp становится prod-myapp-stable в namespace production.

replicas

replicas:
  - name: myapp           # имя resource (Deployment / StatefulSet)
    count: 10

Удобный shortcut для override replicas без полного patch.

images

images:
  - name: nginx               # имя image в base manifest
    newName: registry.example.com/my-nginx  # переименовать
    newTag: 1.26               # сменить tag
  - name: myapp
    digest: sha256:abc123      # вместо tag — digest (immutable)

Kustomize ищет всех containers с image: nginx:* и заменяет.


Patches: два типа

Patches — самая мощная часть Kustomize. Они меняют что угодно в base resources.

1. Strategic Merge Patch (default)

Это native K8s формат. Указываешь только то, что меняешь, structure совпадает с original:

# overlays/prod/deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    spec:
      containers:
        - name: app
          resources:
            limits:
              cpu: 1000m
              memory: 1Gi

В kustomization.yaml:

patches:
  - path: deployment-patch.yaml

Strategic merge “умный”: для lists с merge-key (containers — merge by name) делает merge, не replace. Поэтому в patch только name: app и resources — остальные fields в container не трогаются.

2. JSON Patch (RFC 6902)

Точечные операции:

# overlays/prod/replica-patch.yaml
- op: replace
  path: /spec/replicas
  value: 10
- op: add
  path: /spec/template/spec/tolerations
  value:
    - key: dedicated
      operator: Equal
      value: prod

В kustomization.yaml:

patches:
  - target:
      kind: Deployment
      name: myapp
    path: replica-patch.yaml

Операции: add, remove, replace, move, copy, test. JSON Patch более precise но менее читаем.

Inline patches

Можно избежать отдельного файла и описать patch прямо в kustomization.yaml:

patches:
  - target:
      kind: Deployment
      name: myapp
    patch: |
      - op: replace
        path: /spec/replicas
        value: 10

Generators: ConfigMap и Secret

Уникальная фича Kustomize — генерация ConfigMap и Secret из files / literals:

# kustomization.yaml
configMapGenerator:
  - name: app-config
    literals:
      - DB_HOST=postgres.production.svc
      - LOG_LEVEL=info
  - name: nginx-config
    files:
      - configs/nginx.conf
      - configs/upstream.conf
  - name: env-config
    envs:
      - .env

secretGenerator:
  - name: db-credentials
    literals:
      - username=admin
      - password=secret123
    type: Opaque
  - name: tls-cert
    files:
      - tls.crt
      - tls.key
    type: kubernetes.io/tls

Чем эти generators лучше plain ConfigMap manifest?

  • Hash suffix: ConfigMap получает имя app-config-<hash>, где hash — это SHA256 содержимого. При изменении data — hash меняется — имя меняется — Deployment, ссылающийся на этот ConfigMap, видит новое имя — делает rolling update.
  • Автоматический rollout на изменение config. Это то, что в Helm требует checksum/config annotation hack.

Если не хочешь hash:

configMapGenerator:
  - name: app-config
    literals:
      - DB_HOST=postgres
    options:
      disableNameSuffixHash: true
TIP

Hash suffix — killer feature Kustomize. В Helm для этого паттерн с sha256sum annotation и pod template digest — Kustomize делает это автоматически и более правильно (изменилась config — новый ресурс, immutable rollout). Это основная причина выбирать Kustomize для GitOps workflows.


Practical example: dev → prod overlay

base/

base/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: app
          image: myapp:latest
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 256Mi

base/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml
commonLabels:
  app: myapp

overlays/dev/

overlays/dev/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
namespace: development
namePrefix: dev-
images:
  - name: myapp
    newTag: latest
configMapGenerator:
  - name: app-config
    literals:
      - LOG_LEVEL=debug

overlays/prod/

overlays/prod/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
  - hpa.yaml
namespace: production
namePrefix: prod-
images:
  - name: myapp
    newTag: v2.5.0
replicas:
  - name: myapp
    count: 5
patches:
  - path: prod-resources.yaml
configMapGenerator:
  - name: app-config
    literals:
      - LOG_LEVEL=info

overlays/prod/prod-resources.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    spec:
      containers:
        - name: app
          resources:
            requests:
              cpu: 500m
              memory: 512Mi
            limits:
              cpu: 2000m
              memory: 2Gi

Применение:

kubectl apply -k overlays/dev    # dev
kubectl apply -k overlays/prod   # prod
Kustomize: base + overlay flow
base/Generic версия manifests. Никаких env-specific значений — common defaults. base/kustomization.yaml перечисляет resources + commonLabels. Подходит для всех environments как foundation.
overlays/dev/Ссылается на base через resources: - ../../base. Применяет dev-specific изменения: namespace development, image tag latest, debug log level. configMapGenerator создаёт app-config-<hash>.
overlays/prod/Тот же base, но prod overrides: namespace production, image tag v2.5.0, replicas 5, increased resources. Дополнительный HPA resource. configMapGenerator с production log level.
kustomize buildkubectl apply -k overlays/prod (или kustomize build overlays/prod). Kustomize: 1. Загружает base resources. 2. Применяет все transformers (namespace, prefix, labels, images, replicas). 3. Применяет patches. 4. Генерирует ConfigMap/Secret с hash. 5. Выводит final valid YAML.
kube-apiserverПолучает уже rendered manifests как обычный kubectl apply. Никаких Kustomize-specific аннотаций или metadata — это просто YAML. Server-side apply работает нормально. Никакой client-side state как у Helm — kustomize fully stateless.
K8s resourcesFinal resources в кластере. Имена: prod-myapp, prod-app-config-abc123 (hash от content). При изменении configmap data — новый hash — новый ConfigMap — Deployment делает rolling update автоматически (ссылается на новое имя).

Stateless design: что значит для управления

Главное отличие от Helm: Kustomize stateless. Никаких Release Secrets, никакой истории, никакого kustomize uninstall.

  • Что было применено — определяется git-ом (последний kubectl apply -k коммит).
  • Удаление: kubectl delete -k overlays/prod. Удалит то, что описано в текущей версии — но если что-то было раньше и убрано, оно останется orphan.
  • Cleanup orphan: использовать kubectl prune (alpha) или labels-based delete (kubectl delete -l app=myapp).
WARNING

Stateless design Kustomize означает, что rollback — это git revert + apply. Никаких helm rollback. Это особенность GitOps-философии: git — source of truth, кластер должен совпадать с git. Tools типа ArgoCD/Flux реализуют этот flow автоматически.


kustomize edit: CLI для модификации

Standalone бинарь kustomize имеет helper-команды:

# В директории overlays/prod
kustomize edit set image myapp=myapp:v3.0.0
kustomize edit set replicas myapp=10
kustomize edit set namespace production
kustomize edit add resource hpa.yaml
kustomize edit add patch --path deployment-patch.yaml

Они модифицируют kustomization.yaml in-place. Удобно для CI: build pipeline может обновить image tag без ручного редактирования YAML.


Killer-моменты

  • Kustomize встроен в kubectlkubectl apply -k <dir> работает без отдельного бинаря. На CKAD это default.
  • Patches типа strategic merge merge-ятся по name в lists. Поэтому в patch только name: app плюс полей-для-override — остальные fields не overwritten.
  • commonLabels применяется и к selectors — критично, иначе Service ломается. Это feature, не bug.
  • configMapGenerator добавляет hash suffix — изменение config приводит к immutable rollout Deployment-а. Это elegantly решает проблему “ConfigMap update без restart”.
  • Kustomize stateless — нет releases, нет history. Rollback = git revert + apply.
  • resources: - ../../base — путь относительный, не должен начинаться с /. Можно ссылаться на git repo: github.com/org/repo//path?ref=v1.0.0.

Проверка знанийKnowledge check
В чём принципиальная разница в подходе между Helm и Kustomize?
ОтветAnswer
Helm — templating tool: берёт YAML с placeholders (типа двойных curly braces с .Values.replicaCount) и рендерит их в конкретные значения через Go templates. Файлы templates до рендеринга — не валидный YAML. Kustomize — patch-based: исходные файлы всегда валидный YAML, который можно применить напрямую. Изменения декларативные через kustomization.yaml + patches на base. Helm более powerful (conditionals, loops, sprig functions) но steeper learning curve. Kustomize простой, всегда valid YAML, native в kubectl. Helm для third-party charts (Bitnami, Prometheus), Kustomize для in-house apps с multiple environments.
Проверка знанийKnowledge check
Что делает configMapGenerator с hash suffix, и почему это elegant решение проблемы ConfigMap update?
ОтветAnswer
configMapGenerator создаёт ConfigMap с именем myconfig-<sha256hash>. Hash — от содержимого ConfigMap data. При изменении data — hash меняется — имя ConfigMap меняется. Kustomize автоматически обновляет все references на этот ConfigMap (в Deployment env, volume, etc.) на новое имя. K8s видит, что Deployment ссылается на другой ConfigMap — pod template hash меняется — rolling update. В Helm для этого нужен manual hack с checksum/config annotation. Kustomize решает elegantly: immutable resources, каждое изменение — новый ресурс, garbage collection через labels.
Проверка знанийKnowledge check
kubectl apply -k overlays/prod выдаёт ошибку 'selector matchLabels does not match labels'. В patch только labels изменили в pod template, не в matchLabels. Почему ошибка?
ОтветAnswer
K8s Deployment selector immutable после создания. Если ты в patch меняешь spec.template.metadata.labels (Pod labels), но не spec.selector.matchLabels — Deployment перестаёт находить свои Pods. Fix: использовать commonLabels в kustomization.yaml — он применяется и к labels, и к selectors одновременно. Если commonLabels недостаточно — нужно либо delete и recreate Deployment, либо use kustomize-managed deployment без selector modifications. Это feature: Kustomize commonLabels именно для этого консистентен.
Проверка знанийKnowledge check
Как сделать rollback в Kustomize, если в Helm есть helm rollback <release> <revision>?
ОтветAnswer
В Kustomize нет встроенного rollback — он stateless. Подходы: (1) Git revert + kubectl apply -k. Если git — source of truth, прошлая версия overlay — это commit назад. git revert HEAD; kubectl apply -k overlays/prod. (2) Использовать GitOps tools (ArgoCD, Flux) — у них есть rollback кнопка, который под капотом делает git revert. (3) kubectl rollout undo deployment/<name> — на уровне K8s Deployment работает независимо от Kustomize, откатит pod template. Это и есть философия Kustomize: state в git, manage через git workflow, не через client-side history как Helm.
Проверка знанийKnowledge check
resources: - github.com/example/repo//manifests?ref=v1.0.0 в kustomization.yaml. Что это делает и какие риски?
ОтветAnswer
Kustomize загружает указанную директорию из git repo на указанной revision (tag/branch/commit). Очень полезно для shared bases — команда поддерживает общий 'platform' chart, командные overlays ссылаются. Риски: (1) External dependency: если репозиторий недоступен или удалён — apply ломается. (2) Supply chain: если ?ref=main — изменения могут проникнуть незаметно. Mitigate: всегда pin на commit hash или signed tag, не branch. (3) Network на apply machine: kubectl или CI runner должен иметь network access к github. Альтернатива — git submodule с local path.

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5