← Kubernetes: Kustomize и Helm
6 мин · просто · Урок 2 из 9

Kustomize: трансформеры

namePrefix, labels, namespace и подмена образа: правки, которые накрывают всю группу ресурсов сразу.

Собрать манифесты в группу мало. Обычно к ним нужно применить одинаковую правку: дописать префикс ко всем именам, навесить общий label, отправить всё в другой namespace, подменить тег образа сразу везде.

Трансформер - это правило в kustomization.yaml, которое Kustomize применяет ко всем ресурсам группы при сборке. Исходные манифесты при этом не меняются ни на байт, правка живёт только в конфигурации Kustomize и появляется в отрендеренном выводе.

ПолеЧто накрываетТонкость
namePrefix, nameSuffixимена всех ресурсовссылки чинит только в известных полях
namespacenamespace всех ресурсовперебивает то, что записано в файлах
commonLabelsметаданные и селекторына живом Deployment ошибка про immutable
labelsметаданные, селекторы по выборуincludeSelectors: false селекторы не трогает
imagesимя, тег или digest образастрока образа сопоставляется буквально

namePrefix и nameSuffix

namePrefix дописывает строку в начало имени каждого ресурса, nameSuffix в конец.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml
namePrefix: prod-

Deployment web станет prod-web, Service web станет prod-web. Это нужно, когда одно приложение живёт в нескольких экземплярах в одном namespace и имена не должны сталкиваться.

Важная деталь: Kustomize не просто переименовывает объекты, он ещё чинит ссылки между ними в известных ему полях. Если Ingress ссылался на Service web, после префикса в Ingress окажется prod-web. То же самое с ConfigMap в envFrom и в томах.

namespace

Поле namespace проставляет один namespace всем ресурсам группы:

namespace: demo

После этого kubectl apply -k . уложит объекты в demo, даже если в самих файлах namespace не указан или указан другой. Удобно держать манифесты без привязки к namespace, а адрес назначения задавать конфигурацией.

Общие labels и annotations

commonLabels вешает пары ключ-значение на все объекты группы:

commonLabels:
  team: platform
  app.kubernetes.io/part-of: shop

Тут прячется главная ловушка Kustomize. commonLabels пишет label и в metadata.labels, и в селекторы: spec.selector у Deployment, spec.selector у Service, spec.template.metadata.labels у Pod-шаблона. У уже созданного Deployment селектор менять нельзя, поле неизменяемое, и API-сервер откажет с ошибкой про immutable field. На свежем ресурсе всё пройдёт нормально.

Поэтому в новых версиях Kustomize commonLabels объявлен устаревшим, а на замену пришёл блок labels, где поведение задаётся явно:

labels:
  - pairs:
      team: platform
    includeSelectors: false

С includeSelectors: false label попадёт только в метаданные и селекторы не тронет. commonLabels продолжает работать и встречается в большинстве чужих репозиториев, так что знать обе формы полезно.

Аннотации навешивает commonAnnotations. Селекторов у аннотаций нет, поэтому проблемы с неизменяемыми полями там не возникает.

Подмена образа

Блок images меняет образ контейнера, не трогая Deployment:

images:
  - name: nginx
    newTag: "1.25"

Kustomize найдёт контейнеры, у которых образ называется nginx, и поставит им тег 1.25. Можно заменить и сам образ:

images:
  - name: nginx
    newName: registry.example.com/mirror/nginx
    newTag: "1.25"
  - name: busybox
    digest: sha256:9ae97d36d26566ff84e8893c64a6dc4fe8ca6d1144bf5b87b2b85a32def253c7

digest ставится вместо тега, если нужна привязка к конкретному слепку образа. Одновременно указывать newTag и digest нельзя.

Это самый частый трансформер в реальной работе. При выкатке новой версии CI правит одну строку в kustomization.yaml вместо поиска тега по всем манифестам.

Сопоставление идёт по строке образа ровно так, как она записана в манифесте. Для docker.io/library/nginx:1.24 правило с name: nginx молча не сработает, нужно полное name: docker.io/library/nginx.

Что обычно ломается

namePrefix чинит ссылки только в тех полях, про которые Kustomize знает. Имя Service, зашитое строкой в переменную окружения или в текст ConfigMap, останется старым. Такие места приходится править патчем или брать имя из downward API.

commonLabels на живом Deployment даёт ошибку про неизменяемый селектор. Лечится либо переходом на labels с includeSelectors: false, либо пересозданием ресурса.

Порядок полей в kustomization.yaml роли не играет, а вот порядок применения трансформеров фиксирован самим Kustomize. Проверять результат надёжнее не рассуждениями, а рендером: kubectl kustomize . покажет итог целиком.

Домашка

Теорию закрепляет задание на своём кластере: 1 шаг с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.

./run.sh start k8s-kustomize-transformers     # развернуть стартовое состояние
./run.sh verify k8s-kustomize-transformers    # проверить текущий шаг

Коротко

Прошли материал до конца? Отметьте урок пройденным.