Автоматическое именование подов Kubernetes по версии в CI/CD: практическое руководство | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Автоматическое именование подов Kubernetes по версии в CI/CD: практическое руководство

06 мая 2026 15 мин. чтения
Содержание статьи

Вы запускаете новую версию приложения в Kubernetes, но после деплоя не можете быстро найти нужный под для отладки. Вы пытаетесь откатить релиз, но kubectl показывает несколько ReplicaSet с одинаковыми именами. Эти проблемы возникают из-за статичных имён подов в CI/CD пайплайне. Решение – автоматическое включение версии сборки в идентификатор ресурса. Это руководство предоставляет готовые скрипты для GitLab CI, GitHub Actions и Jenkins, которые извлекают версию из git-тегов, package.json или pom.xml и интегрируют её в процесс деплоя. Вы получите работающие конфигурации для безопасного использования динамических имён, механизмы отката и очистки старых ресурсов.

Проблема: почему статичные имена подов мешают CI/CD

Стандартный подход с именем пода "app-name-deployment" создаёт операционные сложности при частых релизах. Команда kubectl apply обновляет существующий ресурс по его имени в кластере. Когда вы меняете только образ контейнера в манифесте Deployment, имя пода в шаблоне остаётся прежним. Kubernetes создаёт новый ReplicaSet, но поды получают те же имена в своей метаданной. Это делает невозможным параллельное существование старой и новой версии приложения для blue-green или канареечного развертывания.

Типичный сценарий: разработчик запускает пайплайн для деплоя версии 1.2.0 поверх работающей 1.1.0. При возникновении ошибки требуется откат. Инженер выполняет kubectl rollout undo deployment/myapp, но не уверен, какая именно версия теперь запущена. В логах пайплайна отображается ошибка "Error from server (AlreadyExists): pods \"myapp-pod\" already exists" при попытке запустить два процесса одновременно. Поиск конкретного пода для диагностики занимает время – нужно проверять метки или описывать каждый контейнер.

Классический подход нарушает принцип идемпотентности деплоя – возможность безопасно применять одну конфигурацию многократно. С динамическими версиями каждый деплой создаёт уникальный идентификатор, что предотвращает конфликты, но требует изменения workflow. Helm с шаблоном имени релиза частично решает проблему, но при частых обновлениях создаёт множество релизных объектов в истории.

Ограничения kubectl apply и helm upgrade при частых релизах

Инструменты orchestration не "ломаются" при работе со статичными именами – они используются не по назначению в контексте CI/CD. Команда kubectl apply сравнивает текущее состояние ресурса в кластере с предоставленным манифестом и вносит минимальные изменения. Если изменился только spec.template.spec.containers[0].image, обновляется соответствующий ReplicaSet, но имя пода в spec.template.metadata.name остаётся неизменным. Для системы это один и тот же Deployment, а не две разные версии приложения.

Helm хранит историю релизов, но имя самого релиза обычно фиксировано или генерируется на основе чарта. При обновлении с новым тегом образа Helm создаёт новую ревизию, но поды внутри Deployment всё равно получают статичные имена из шаблона. Параллельный деплой двух разных версий через Helm требует создания отдельных релизов с разными именами, что усложняет управление.

Решение: динамические имена подов на основе версии сборки

Core-идея: включать уникальный идентификатор версии в метаданные пода. Это создаёт прозрачную связь между артефактом сборки и запущенным контейнером в кластере. Вы видите версию приложения по имени пода или его меткам без дополнительных запросов к API. Архитектура пайплайна становится линейной: получить версию → подставить в манифест → применить конфигурацию.

Выгоды динамического именования:

  1. Одновременное существование версий – запуск 1.1.0 и 1.2.0 рядом для A/B-тестирования или постепенного переноса трафика.
  2. Прозрачность окружения – команда kubectl get pods сразу показывает, какая версия где работает.
  3. Упрощенный откат – переключение селектора Service на предыдущую версию без пересоздания ресурсов.
  4. Автоматическая очистка – удаление подов с устаревшими версиями по label selector.

Схематичный пайплайн:

CI/CD Pipeline:
1. Сборка → Извлечь версию (git tag / package.json / CI variable)
2. Артефакт → Подставить версию в манифест (envsubst / sed / Helm values)
3. Деплой → kubectl apply с валидацией (--dry-run)
4. Верификация → Проверить health checks нового пода
5. Очистка → Удалить ресурсы старше N дней

Стратегии формирования уникального идентификатора версии

Выбор источника версии зависит от workflow проекта:

Источник Команда/метод Плюсы Минусы Рекомендация
Git теги (semver) git describe --tags --abbrev=0 Человекочитаемость, стандарт семантического версионирования Требует дисциплины тегирования, только для релизов Для production-релизов с контролем качества
Хэш коммита git rev-parse --short HEAD Уникальность для каждого коммита, автоматическая генерация Нечитаемость (abc123def), нет информации о мажорных версиях Для dev/staging окружений, каждый коммит
Номер сборки CI $CI_PIPELINE_IID (GitLab), $GITHUB_RUN_ID Уникальность в рамках CI-системы, простой инкремент Привязка к конкретной CI, не переносимо между системами Для внутренних нужд отслеживания в одной CI
Версия из package.json/pom.xml jq -r .version package.json Синхронизация с версией пакета, один источник истины Требует обновления файла перед коммитом Для npm/Maven проектов с управлением версиями в коде

Оптимальная стратегия – комбинированный подход: "app-1.2.3-abc123def". Основная семантическая версия из тега или package.json плюс короткий хэш коммита для уникальности. Это даёт читаемость и точную идентификацию исходного кода. Для детального сравнения стратегий управления версиями в Kubernetes, включая влияние на HPA и Service Mesh, изучите практическое сравнение хранения версии в метках или в имени пода.

Практика: готовые скрипты для извлечения версии

Каждый скрипт включает проверку ошибок и fallback-механизм. Перед использованием убедитесь, что инструменты (jq, xmllint) установлены в контейнере CI/CD.

Из git-тегов (семантическое версионирование)

Скрипт для проектов с тегированием релизов:

#!/bin/bash
set -e

# Пытаемся получить последний тег
VERSION=$(git describe --tags --abbrev=0 2>/dev/null || true)

# Если тега нет, используем хэш коммита
if [ -z "$VERSION" ] || [ "$VERSION" = "" ]; then
    VERSION="untagged-$(git rev-parse --short HEAD)"
    echo "WARNING: No git tag found, using commit hash: $VERSION" >&2
else
    echo "Found version from git tag: $VERSION"
fi

# Экспортируем переменную для использования в пайплайне
export APP_VERSION="${VERSION}"
echo "APP_VERSION=$APP_VERSION" >> $GITHUB_ENV  # Для GitHub Actions
# Или для GitLab CI:
# echo "export APP_VERSION=\"$APP_VERSION\"" >> .env

# Валидация: версия не должна содержать пробелов или спецсимволов
if [[ ! "$APP_VERSION" =~ ^[a-zA-Z0-9._-]+$ ]]; then
    echo "ERROR: Invalid version format: $APP_VERSION" >&2
    exit 1
fi

Из package.json (Node.js/JavaScript проекты)

Для проектов на Node.js с версией в package.json:

#!/bin/bash
set -e

# Проверяем существование файла
if [ ! -f "package.json" ]; then
    echo "ERROR: package.json not found in current directory" >&2
    exit 1
fi

# Извлекаем версию с помощью jq (должен быть установлен)
if command -v jq &> /dev/null; then
    VERSION=$(jq -r '.version' package.json)
else
    # Fallback без jq (менее надежный)
    VERSION=$(grep -o '"version": "[^"]*"' package.json | head -1 | cut -d'"' -f4)
fi

if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then
    echo "ERROR: Could not extract version from package.json" >&2
    exit 1
fi

echo "Version from package.json: $VERSION"
export APP_VERSION="${VERSION}"

Из pom.xml (Java/Maven проекты)

Для Java/Maven проектов:

#!/bin/bash
set -e

# Проверяем существование файла
if [ ! -f "pom.xml" ]; then
    echo "ERROR: pom.xml not found in current directory" >&2
    exit 1
fi

# Способ 1: с использованием xmllint (предпочтительный)
if command -v xmllint &> /dev/null; then
    VERSION=$(xmllint --xpath '/*[local-name()="project"]/*[local-name()="version"]/text()' pom.xml 2>/dev/null || true)
fi

# Способ 2: fallback с grep/sed
if [ -z "$VERSION" ]; then
    VERSION=$(grep -o '[^<]*' pom.xml | head -1 | sed 's/\(.*\)<\/version>/\1/')
fi

# Если версия не найдена или содержит переменную Maven (${project.version})
if [ -z "$VERSION" ] || [[ "$VERSION" == \$* ]]; then
    echo "WARNING: No explicit version in pom.xml, using default"
    VERSION="1.0.0-SNAPSHOT"
fi

echo "Version from pom.xml: $VERSION"
export APP_VERSION="${VERSION}"

Из переменных окружения CI/CD

Универсальный скрипт с приоритетом источников:

#!/bin/bash
set -e

# Приоритет 1: Git tag из переменных CI
if [ -n "$CI_COMMIT_TAG" ]; then
    VERSION="$CI_COMMIT_TAG"  # GitLab CI
elif [ -n "$GITHUB_REF_NAME" ] && [[ "$GITHUB_REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+ ]]; then
    VERSION="${GITHUB_REF_NAME#v}"  # GitHub Actions tag

# Приоритет 2: Номер сборки CI
elif [ -n "$CI_PIPELINE_IID" ]; then
    VERSION="build-$CI_PIPELINE_IID"  # GitLab CI
elif [ -n "$GITHUB_RUN_ID" ]; then
    VERSION="run-$GITHUB_RUN_ID"  # GitHub Actions
elif [ -n "$BUILD_NUMBER" ]; then
    VERSION="jenkins-$BUILD_NUMBER"  # Jenkins

# Приоритет 3: Хэш коммита
elif [ -n "$CI_COMMIT_SHORT_SHA" ]; then
    VERSION="commit-$CI_COMMIT_SHORT_SHA"
elif [ -n "$GITHUB_SHA" ]; then
    SHORT_SHA="${GITHUB_SHA:0:7}"
    VERSION="commit-$SHORT_SHA"
else
    # Последний fallback
    VERSION="$(date +%Y%m%d-%H%M%S)"
    echo "WARNING: Using timestamp as version: $VERSION" >&2
fi

export APP_VERSION="${VERSION}"
echo "CI/CD version: $APP_VERSION"

Интеграция: передача версии в манифесты Kubernetes

После извлечения версии её нужно передать в манифесты для деплоя. Рассмотрим два подхода: шаблонизацию raw YAML и работу с Helm.

Шаблонизация манифестов для kubectl apply

Ключевой момент: вместо изменения metadata.name пода используйте метки (labels). Это предотвращает создание новых ReplicaSet при каждом деплое и сохраняет стабильность Service селекторов. Пример deployment.yaml с плейсхолдером:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment  # Стабильное имя Deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      version: "${APP_VERSION}"  # Селектор по версии
  template:
    metadata:
      labels:
        app: myapp
        version: "${APP_VERSION}"  # Метка версии на подах
    spec:
      containers:
      - name: myapp
        image: myregistry.com/myapp:${APP_VERSION}  # Тег образа
        ports:
        - containerPort: 8080

Скрипт подстановки с envsubst (должен быть установлен):

#!/bin/bash
set -e

# Проверяем, что переменная установлена
if [ -z "$APP_VERSION" ]; then
    echo "ERROR: APP_VERSION is not set" >&2
    exit 1
fi

# Подставляем переменные в манифест
export APP_VERSION
envsubst < deployment.yaml.template > deployment.yaml

# Валидация манифеста перед применением
kubectl apply -f deployment.yaml --dry-run=client

# Применение
kubectl apply -f deployment.yaml

# Проверка, что поды создались с правильными метками
kubectl get pods -l "app=myapp,version=${APP_VERSION}"

Альтернатива с sed для систем без envsubst:

sed "s/\$\{APP_VERSION\}/$APP_VERSION/g" deployment.yaml.template > deployment.yaml

Использование переменных в Helm Charts

Для Helm передайте версию через values или --set. Имя релиза Helm остаётся фиксированным, меняется только тег образа и метки. Пример values.yaml:

# values.yaml
image:
  repository: myregistry.com/myapp
  tag: ""  # Будет переопределено в пайплайне

labels:
  version: ""  # Для меток пода

Шаблон Deployment в templates/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
spec:
  selector:
    matchLabels:
      app: {{ .Chart.Name }}
      {{- if .Values.labels.version }}
      version: {{ .Values.labels.version | quote }}
      {{- end }}
  template:
    metadata:
      labels:
        app: {{ .Chart.Name }}
        {{- if .Values.labels.version }}
        version: {{ .Values.labels.version | quote }}
        {{- end }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

Команда деплоя в пайплайне:

helm upgrade --install myapp ./chart \
  --set "image.tag=$APP_VERSION" \
  --set "labels.version=$APP_VERSION" \
  --namespace production \
  --atomic  # Автоматический откат при ошибке

Для комплексного понимания работы с Deployment, включая стратегии обновления и настройку ресурсов, обратитесь к полному руководству по Kubernetes Deployment.

Безопасность и эксплуатация: избегаем ловушек

Динамическое именование создаёт операционные риски, которые нужно mitigate на этапе проектирования пайплайна.

Контроль уникальности и очистка старых ресурсов

Стратегии управления историей деплоев:

  1. Использование меток вместо имён подов – оставляйте metadata.name пустым или генерируемым Kubernetes. Идентификацию версии выполняйте через label version: 1.2.3. Это сохраняет стабильность Service и HorizontalPodAutoscaler.
  2. Ограничение истории ReplicaSet – настройте spec.revisionHistoryLimit в Deployment:
apiVersion: apps/v1
kind: Deployment
spec:
  revisionHistoryLimit: 3  # Хранить только 3 предыдущих ReplicaSet
  # ... остальная конфигурация
  1. Периодическая очистка устаревших ресурсов – джоба в пайплайне или CronJob в кластере:
#!/bin/bash
# Удалить поды старше 7 дней
kubectl delete pods \
  --field-selector="status.phase=Succeeded,metadata.creationTimestamp<$(date -d '7 days ago' -u +'%Y-%m-%dT%H:%M:%SZ')" \
  --namespace=production

# Удалить ReplicaSet без активных подов
kubectl delete replicasets \
  --selector="app=myapp" \
  --field-selector="status.replicas=0" \
  --namespace=production

Механизм быстрого и точного отката

С динамическими метками история ReplicaSet становится чистой и предсказуемой. Команда отката:

# Просмотреть историю деплоев
kubectl rollout history deployment/myapp-deployment

# Откат на предыдущую ревизию
kubectl rollout undo deployment/myapp-deployment

# Откат на конкретную ревизию
kubectl rollout undo deployment/myapp-deployment --to-revision=3

# Проверить, какая версия сейчас запущена
kubectl describe deployment/myapp-deployment | grep -A2 "Labels:"

При использовании меток откат сводится к обновлению селектора Service на предыдущую версию подов. Сравните с хаотичным поиском нужного ReplicaSet при статичных именах.

Обработка ошибок и валидация в пайплайне

Добавьте проверки на каждом этапе:

#!/bin/bash
set -e  # Выход при первой ошибке

# 1. Проверка переменной версии
if [ -z "$APP_VERSION" ]; then
    echo "ERROR: APP_VERSION is empty" >&2
    exit 1
fi

# 2. Валидация формата версии (опционально)
if [[ ! "$APP_VERSION" =~ ^[a-zA-Z0-9._-]+$ ]]; then
    echo "ERROR: Invalid version format: $APP_VERSION" >&2
    exit 1
fi

# 3. Dry-run перед реальным деплоем
kubectl apply -f deployment.yaml --dry-run=client --validate=true

# 4. Применение с таймаутом и проверкой готовности
kubectl apply -f deployment.yaml

# Ждём, пока все поды станут Ready
kubectl wait --for=condition=Ready pods -l "app=myapp,version=${APP_VERSION}" \
  --timeout=300s \
  --namespace=production

# 5. Проверка health checks
kubectl get pods -l "app=myapp,version=${APP_VERSION}" -o json | \
  jq '.items[] | select(.status.containerStatuses[].ready != true)' | \
  if [ -n "$(cat)" ]; then
    echo "ERROR: Not all containers are ready" >&2
    # Триггер отката
    kubectl rollout undo deployment/myapp-deployment
    exit 1
  fi

Готовые конфигурации для вашего CI/CD

Пример для GitLab CI (.gitlab-ci.yml)

stages:
  - build
  - deploy

variables:
  KUBE_NAMESPACE: production
  APP_NAME: myapp

# Этап извлечения версии
get-version:
  stage: build
  script:
    - |
      # Приоритет: тег → хэш коммита
      if [ -n "$CI_COMMIT_TAG" ]; then
        export APP_VERSION="$CI_COMMIT_TAG"
      else
        export APP_VERSION="${CI_COMMIT_SHORT_SHA}"
      fi
      echo "APP_VERSION=${APP_VERSION}" > version.env
  artifacts:
    reports:
      dotenv: version.env

deploy-to-k8s:
  stage: deploy
  image: bitnami/kubectl:latest
  dependencies:
    - get-version
  script:
    - source version.env
    # Подстановка версии в манифест
    - envsubst < deployment.yaml.template > deployment.yaml
    # Dry-run валидация
    - kubectl apply -f deployment.yaml --dry-run=client --namespace=$KUBE_NAMESPACE
    # Реальный деплой
    - kubectl apply -f deployment.yaml --namespace=$KUBE_NAMESPACE
    # Ожидание готовности
    - kubectl rollout status deployment/${APP_NAME} --namespace=$KUBE_NAMESPACE --timeout=300s
  environment:
    name: production
    url: https://myapp.example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAG
      when: manual  # Требует ручного подтверждения для production

Пример для GitHub Actions (.github/workflows/deploy.yml)

name: Deploy to Kubernetes

on:
  push:
    tags:
      - 'v*'  # Запуск на тегах v1.2.3
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      KUBE_NAMESPACE: production
      APP_NAME: myapp
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
      with:
        fetch-depth: 0  # Для работы с git тегами
    
    - name: Extract version
      id: version
      run: |
        # Из тега или хэша коммита
        if [[ "${{ github.ref }}" == refs/tags/* ]]; then
          VERSION="${GITHUB_REF#refs/tags/}"
        else
          VERSION="${GITHUB_SHA:0:7}"
        fi
        echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
        echo "APP_VERSION=${VERSION}" >> $GITHUB_ENV
    
    - name: Set up kubectl
      uses: azure/setup-kubectl@v3
      with:
        version: 'latest'
    
    - name: Configure kubeconfig
      run: |
        echo "${{ secrets.KUBECONFIG }}" > kubeconfig
        export KUBECONFIG=kubeconfig
    
    - name: Deploy to Kubernetes
      run: |
        # Подстановка версии
        export APP_VERSION="${{ env.APP_VERSION }}"
        envsubst < k8s/deployment.yaml.template > deployment.yaml
        
        # Валидация и деплой
        kubectl apply -f deployment.yaml --dry-run=client
        kubectl apply -f deployment.yaml
        
        # Проверка статуса
        kubectl rollout status deployment/${{ env.APP_NAME }} \
          --namespace=${{ env.KUBE_NAMESPACE }} \
          --timeout=5m
    
    - name: Cleanup old pods
      if: success()
      run: |
        # Удалить поды старше 1 дня
        kubectl delete pods \
          --field-selector="status.phase=Succeeded,metadata.creationTimestamp<$(date -d '1 day ago' -u +'%Y-%m-%dT%H:%M:%SZ')" \
          --namespace=${{ env.KUBE_NAMESPACE }} || true

Пример для Jenkins (Jenkinsfile, Declarative Pipeline)

pipeline {
    agent any
    
    environment {
        // Извлечение версии из git
        APP_VERSION = sh(
            script: '''
                if git describe --tags --exact-match >/dev/null 2>&1; then
                    git describe --tags --exact-match
                else
                    git rev-parse --short HEAD
                fi
            ''',
            returnStdout: true
        ).trim()
        
        KUBE_NAMESPACE = 'production'
        APP_NAME = 'myapp'
    }
    
    stages {
        stage('Build and Test') {
            steps {
                sh 'docker build -t myregistry.com/${APP_NAME}:${APP_VERSION} .'
                sh 'docker push myregistry.com/${APP_NAME}:${APP_VERSION}'
            }
        }
        
        stage('Deploy to Kubernetes') {
            steps {
                withCredentials([
                    file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')
                ]) {
                    sh '''
                        # Подготовка манифеста
                        export APP_VERSION
                        envsubst < k8s/deployment.yaml.template > deployment.yaml
                        
                        # Валидация
                        kubectl apply -f deployment.yaml --dry-run=client \
                            --namespace=${KUBE_NAMESPACE}
                        
                        # Деплой
                        kubectl apply -f deployment.yaml \
                            --namespace=${KUBE_NAMESPACE}
                        
                        # Ожидание готовности
                        kubectl rollout status deployment/${APP_NAME} \
                            --namespace=${KUBE_NAMESPACE} \
                            --timeout=300s
                    '''
                }
            }
            post {
                failure {
                    sh '''
                        # Автоматический откат при ошибке
                        kubectl rollout undo deployment/${APP_NAME} \
                            --namespace=${KUBE_NAMESPACE}
                    '''
                }
            }
        }
    }
}

Для построения комплексных CI/CD пайплайнов с поддержкой стратегий blue-green и canary развертывания изучите полное руководство по автоматизации развертывания в production.

Ответы на частые вопросы и устранение проблем

Что делать, если мой кластер не дает создавать поды с динамическими именами?

Политики безопасности (Pod Security Policies, OPA Gatekeeper, Kyverno) могут блокировать создание подов с изменяющимися именами. Решение: не меняйте metadata.name пода, оставьте его пустым или сгенерированным Kubernetes. Идентификацию версии выполняйте через метку в metadata.labels. Deployment с обновлённой меткой версии создаст новый ReplicaSet с новой версией подов, но имена подов будут сгенерированы автоматически (например, "myapp-deployment-abc123-def456"). Это обходит ограничения политик, ориентированных на статичные имена.

Если политики проверяют метки, убедитесь, что label version соответствует разрешённому формату (например, семантическому версионированию). Для enterprise-кластеров с обязательным версионированием через политики OPA ознакомьтесь с руководством по использованию меток и селекторов в Kubernetes.

Скрипт не находит версию в package.json/pom.xml

Возможные причины и решения:

  1. Файл не в корне проекта – проверьте путь: cat ./subdirectory/package.json или используйте поиск: find . -name "package.json" -type f.
  2. Невалидный JSON/XML – проверьте синтаксис: jq . package.json или xmllint --format pom.xml.
  3. Отсутствуют инструменты – установите jq или xmllint в контейнер CI/CD. Для Dockerfile: RUN apt-get update && apt-get install -y jq libxml2-utils.
  4. Версия определена через переменную – в Maven <version>${project.version}</version> требует обработки properties. Используйте: mvn help:evaluate -Dexpression=project.version -q -DforceStdout.

Как это решение работает с Service и Ingress?

Service использует селектор по меткам для нахождения подов. При изменении метки version у подов есть два подхода:

  1. Service без версии в селекторе – селектор app: myapp направляет трафик на все поды приложения независимо от версии. Подходит для одновременного запуска нескольких версий с распределением через другие механизмы (например, заголовки запросов).
  2. Service с версией в селекторе – селектор app: myapp, version: 1.2.3 направляет трафик только на конкретную версию. Для канареечного развертывания создайте второй Service с селектором на новую версию и направляйте часть трафика через Ingress.

Пример Ingress для канареечного трафика:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-service-v1-2-2  # 98% трафика
            port:
              number: 80
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-service-v1-2-3  # 2% трафика (канареечная)
            port:
              number: 80

Для выбора между GitOps и традиционным Infrastructure as Code при построении таких конфигураций изучите практическое сравнение подходов для DevOps.

Автоматическое именование подов по версии устраняет операционный хаос в CI/CD пайплайнах. Начните с простого скрипта извлечения версии из git-тега, интегрируйте его в существующий пайплайн и постепенно добавляйте валидации и механизмы очистки. Используйте метки вместо изменения имён подов для совместимости с политиками безопасности и Service. Регулярно проверяйте актуальность конфигураций – технологии CI/CD и Kubernetes активно развиваются. Для экспериментов с различными подходами к интеграции ИИ в разработку рассмотрите использование агрегатора AiTunnel, который предоставляет единый интерфейс к более чем 200 моделям нейросетей, включая GPT, Gemini и Claude, с оплатой в рублях и без необходимости VPN.

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