Контроль версий ресурсов Kubernetes через Kustomize: патчи и компоненты | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Контроль версий ресурсов Kubernetes через Kustomize: патчи и компоненты

06 мая 2026 8 мин. чтения

Проблема: почему ручное версионирование ресурсов Kubernetes не масштабируется

DevOps-инженер в микросервисной архитектуре сталкивается с десятками, а иногда сотнями YAML-манифестов. Каждый сервис - это Deployment, Service, ConfigMap. Когда приходит время обновить версию приложения, нужно вручную отредактировать метки, имена ресурсов или контейнерные образы в каждом файле. Для 5 сервисов это полчаса работы. Для 15 - полдня, с высоким риском опечатки или пропуска критического ресурса.

Ручное управление версиями создаёт три ключевых риска:

  • Человеческий фактор. Ошибка в имени пода или метке версии приводит к рассинхронизации сервисов. Frontend v1.2 может начать запрашивать несуществующий backend v1.1.
  • Сложность отката. Определить, какая версия каждого микросервиса работала в кластере неделю назад, без автоматизированного подхода почти невозможно. Нужно рыться в истории git или логах CI/CD.
  • Невозможность централизованного контроля. Изменение политики именования - например, перейти с суффикса -v1.2.3 на -release-1.2.3 - потребует правки всех манифестов в проекте.

Как отсутствие централизованного контроля версий усложняет жизнь DevOps-инженеру

Рассмотрим реальный кейс из практики. В продакшн-среде упала критическая функциональность оплаты. Логи показали ошибки взаимодействия между сервисом payment-service и user-service. Выяснилось, что при деплое обновили образ контейнера для payment-service до версии 2.1.0, но забыли обновить ожидаемую версию user-service в его конфигурации. Сервис payment-service v2.1.0 вызывал устаревший API user-service v1.5.0. На поиск и исправление этой рассинхронизации ушло более двух часов простоя.

Альтернатива - написание bash- или Python-скриптов для пакетного обновления версий во всех YAML-файлах. Но такие скрипты тоже содержат логику, которую нужно поддерживать, тестировать и которые могут сломаться при изменении структуры манифестов.

Решение: Kustomize патч для автоматического добавления суффикса версии

Kustomize решает проблему через декларативные патчи. Вы определяете желаемое состояние - «ко всем именам ресурсов добавить суффикс версии» - в отдельном файле kustomization.yaml. Инструмент применяет это правило ко всем базовым манифестам, генерируя финальные конфигурации для kubectl apply. Это готовое, проверенное на практике решение.

Основной файл kustomization.yaml с патчем выглядит так:

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

# 1. Указываем базовые манифесты
resources:
  - deployment.yaml
  - service.yaml

# 2. Задаём общий суффикс для имён всех ресурсов
nameSuffix: -$(cat version.txt)

# 3. Определяем патч для добавления метки версии в Pod template
patchesStrategicMerge:
  - patch-version-label.yaml

Патч patch-version-label.yaml - это strategic merge patch, который добавляет метку в спецификацию пода:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/version: $(cat version.txt)

Рядом с kustomization.yaml создайте файл version.txt с содержимым, например, v1.2.3. При запуске kustomize build . или kubectl apply -k . Kustomize прочитает значение из файла и подставит его.

До применения патча: Под в манифесте назван my-app.
После применения патча: Имя пода становится my-app-v1.2.3, а в его метках появляется app.kubernetes.io/version: v1.2.3. Это изменение касается всех ресурсов, перечисленных в секции resources.

Пример kustomization.yaml с патчем для добавления версии из version.txt

Приведём полный листинг рабочего примера для одного сервиса. Базовая структура проекта:

my-service/
├── deployment.yaml
├── service.yaml
├── kustomization.yaml
├── patch-version-label.yaml
└── version.txt

Содержимое deployment.yaml (базовый манифест):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-service
  template:
    metadata:
      labels:
        app: my-service
    spec:
      containers:
      - name: app
        image: myregistry.com/my-service:latest
        ports:
        - containerPort: 8080

После обработки Kustomize сгенерирует манифест, где имя Deployment станет my-service-v1.2.3, а в Pod template добавится метка версии. Это решение готово к копированию и адаптации.

Альтернатива: использование переменной окружения для динамического задания версии

Подход с файлом version.txt обеспечивает воспроизводимость - версия зафиксирована в репозитории. Однако в CI/CD-пайплайнах часто удобнее передавать версию через переменные окружения.

Kustomize поддерживает это через shell-переменные. Модифицируем kustomization.yaml:

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

resources:
  - deployment.yaml

nameSuffix: -${KUSTOMIZE_VERSION_SUFFIX}

patchesStrategicMerge:
  - patch-version-label.yaml

Патч также использует переменную:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/version: ${KUSTOMIZE_VERSION_SUFFIX}

Теперь перед вызовом kustomize build нужно экспортировать переменную:

export KUSTOMIZE_VERSION_SUFFIX="v1.2.3"
kustomize build .
# или сразу apply с флагом -k
kubectl apply -k .

Плюс подхода с env var - возможность менять версию без коммита в git, что удобно для тестовых сборок из feature-веток. Плюс файла version.txt - явность и контроль через код.

Безопасность и надёжность: почему этот подход не сломает ваше production-окружение

Kustomize работает как препроцессор конфигураций. Он не изменяет ваши исходные YAML-файлы в resources, а создаёт в памяти модифицированную версию, которую передаёт kubectl. Исходные манифесты остаются нетронутыми и служат источником истины. Риск их случайного повреждения отсутствует.

Команда kubectl apply -k идемпотентна. Повторный запуск с теми же входными данными не создаст дубликатов ресурсов, а лишь убедится, что текущее состояние кластера соответствует желаемому. Это фундаментальный принцип Kubernetes, на котором строится GitOps.

Интеграция с GitOps-методологией становится прямой. Версия приложения контролируется через git - либо в файле version.txt, либо в переменной окружения, заданной в конфигурации CI/CD (которая тоже хранится в репозитории). Каждый деплой соответствует конкретному коммиту с известным хешем и тегом. В случае проблемы вы всегда можете откатиться к предыдущему коммиту и переприменить всю конфигурацию целиком, получив точное состояние кластера на момент прошлого стабильного релиза.

Как Kustomize + kubectl apply -k обеспечивают согласованность обновлений в микросервисных приложениях

Представьте проект с 15 микросервисами. В классическом сценарии вам нужно обновить версию в 15 Deployment, 15 Service, возможно, ConfigMap. С Kustomize вы структурируете проект так:

project-root/
├── version.txt                    # Единый файл версии для всех сервисов
├── base/
│   ├── service-a/
│   │   ├── deployment.yaml
│   │   └── kustomization.yaml
│   └── service-b/
│       ├── deployment.yaml
│       └── kustomization.yaml
└── overlays/
    └── production/
        ├── kustomization.yaml    # Указывает на все базы и задаёт общие патчи
        └── patch-version.yaml

В корневом kustomization.yaml для production вы задаёте общий nameSuffix и патчи. Применяя kubectl apply -k overlays/production, вы одновременно и атомарно обновляете все 15 сервисов одной версией. Это исключает рассинхронизацию, как в кейсе с payment-service и user-service.

Для глубокого понимания основ, без которых сложно работать с патчами, изучите полное руководство по Kubernetes Deployment. Там разобраны стратегии обновлений, проверки жизнеспособности и управление ресурсами - критичные знания для production.

Продвинутая техника: Kustomize Components для повторного использования логики версионирования

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

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

Создание компонента версионирования: step-by-step инструкция

1. Создайте структуру директорий проекта:

my-project/
├── base/
│   ├── service-a/
│   │   └── deployment.yaml
│   └── service-b/
│       └── deployment.yaml
├── components/
│   └── versioning/           # Наш компонент
│       ├── kustomization.yaml
│       └── patch-version.yaml
└── overlays/
    └── production/
        └── kustomization.yaml # Подключает компонент

2. Определите компонент components/versioning/kustomization.yaml:

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

# Патч, добавляющий метку версии и модифицирующий имя
patchesStrategicMerge:
  - patch-version.yaml

# Общий суффикс для имён
nameSuffix: -${VERSION}

# Объявляем переменную, которую нужно передать
vars:
- name: VERSION
  objref:
    kind: ConfigMap
    name: version-config
    apiVersion: v1
  fieldref:
    fieldpath: data.version

3. В overlays/production/kustomization.yaml подключите компонент и задайте версию:

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

resources:
  - ../../base/service-a
  - ../../base/service-b

components:
  - ../../components/versioning  # Подключение компонента

configMapGenerator:
- name: version-config
  literals:
    - version=v1.5.0            # Версия задаётся здесь, в одном месте

Теперь логика версионирования инкапсулирована в компоненте. Изменение в components/versioning/patch-version.yaml автоматически применится ко всем сервисам (service-a, service-b и любым другим), которые подключают этот компонент. Чтобы управлять версиями в CI/CD, смотрите готовые скрипты в руководстве по автоматическому именованию подов в пайплайне.

Интеграция в GitOps-пайплайн и проверка на совместимость

Для внедрения в существующий процесс CI/CD добавьте этап, который устанавливает версию и применяет конфигурацию через Kustomize. Пример для GitHub Actions:

name: Deploy to Kubernetes
on:
  push:
    tags:
      - 'v*'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Extract version from tag
        id: get_version
        run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

      - name: Deploy with Kustomize
        run: |
          cd overlays/production
          # Передаём версию через переменную окружения
          export KUSTOMIZE_VERSION_SUFFIX=${{ steps.get_version.outputs.VERSION }}
          kubectl apply -k .

Версионная совместимость. Примеры в этой статье работают с:

  • kubectl версии 1.20 и выше (встроенная поддержка -k флага).
  • Kustomize v4.0.0+ (встроен в kubectl) или standalone версии v4+.

Используйте синтаксис patchesStrategicMerge и nameSuffix, который стабилен и поддерживается во всех актуальных версиях. Избегайте экспериментальных фич типа patchesJson6902 для критичных продакшн-процессов, если не уверены в их поддержке вашим CI.

Потенциальные проблемы и их решение:

  • Конфликты имён. nameSuffix изменяет имя ресурса. Убедитесь, что Service селекторы и Ingress правила ссылаются на правильные имена подов после применения суффикса.
  • Custom Resource Definitions (CRD). Kustomize может применять патчи к CRD, но убедитесь, что патч соответствует схеме вашего CRD.
  • Порядок применения. Kustomize применяет трансформации в определённом порядке. Если поведение отличается от ожидаемого, проверьте документацию по порядку трансформаций.

Для комплексной автоматизации всего процесса развёртывания, включая стратегии Blue-Green и Canary, изучите полное руководство по CI/CD в 2026 году. Правильно настроенный пайплайн снижает риски и ускоряет доставку изменений.

Этот подход с Kustomize патчами и компонентами даёт DevOps-инженерам конкретный инструмент для решения проблемы контроля версий. Он масштабируется от одного сервиса до сотен, интегрируется в GitOps и делает процесс деплоя предсказуемым. Чтобы глубже погрузиться в тему именования и мониторинга, прочтите статью о том, как именование подов с версией ускоряет диагностику инцидентов.

Для тех, кто работает со StatefulSets или сложными сценариями деплоя нескольких версий одновременно, полезным будет практическое руководство по шаблонам именования подов с версиями.

Если вам нужен единый доступ к различным AI-моделям для автоматизации написания скриптов или документации, обратите внимание на сервис AiTunnel. Это агрегатор API, который позволяет работать с GPT, Gemini, Claude и другими моделями через единый интерфейс без необходимости настройки VPN, с оплатой в рублях.

Поделиться:
Сохранить гайд? В закладки браузера