Перейти к содержанию

Kubernetes: новая версия API, rollout и rollback

У «Площадки» уже есть две копии API, Service, probes и требования ресурсов. Теперь рассмотрим замену кода. Цель урока — подготовить собственный образ следующей версии, проследить постепенное обновление и понять, что именно возвращает rollback. Откат Deployment полезен, но он не восстанавливает автоматически внешние данные, изменённые секреты или удалённый образ.

Работа относится к локальной лаборатории. Автор не создавал образ версии 2, не запускал rollout и не выполнял rollback. В наборе остаются полные исходники версии 1 и инструкция следующего изменения. Все выводы о числе копий и HTTP-ответах ниже обозначают ожидаемое состояние.

Новый образ должен означать новый код

В исходном api/server.mjs массив lessons содержит две записи. Для версии 2 читатель добавляет третью запись, не меняя форму ответа. Например, полный новый массив:

const lessons = [
  { id: 'http', title: 'HTTP и границы приложения' },
  { id: 'containers', title: 'Контейнеры веб-проекта' },
  { id: 'kubernetes', title: 'Управление копиями API' },
];

Это замена конкретного определения в существующем полном файле. Остальные обработчики остаются прежними. Такой выпуск совместим с frontend: он всё ещё перебирает data.lessons и показывает названия. Мы изменяем содержание каталога, а не сразу схему ответа, маршруты и конфигурацию.

Будущая сборка получает отдельный локальный тег:

docker build -t ploshchadka-api:2 ./api
kind load docker-image ploshchadka-api:2 --name ploshchadka

Не пересобирайте ploshchadka-api:1 как новый выпуск. При использовании одного тега уже запущенные процессы могут продолжать старое содержимое, а новые получать другое. Тогда декларация с одинаковым именем образа перестаёт описывать одинаковый код. В реальном registry предпочтительно использовать проверяемые неизменяемые артефакты; локальный учебный тег показывает ту же необходимость различать версии.

Политика imagePullPolicy: Never сохраняется. Значит, новый образ должен быть доступен runtime kind до обновления Deployment. Если пропустить загрузку, новая копия не стартует, хотя старая продолжит обслуживать запросы. Ошибка подготовки образа не является признаком несовместимого HTTP-контракта.

Стратегия и промежуточное состояние

Изменим поле image в полном 07-resources.yaml для API на ploshchadka-api:2 и применим файл. Такое изменение сохраняет конфигурацию, probes и ресурсы в одном обозримом источнике. Для краткой демонстрации существует и команда kubectl set image, но после неё декларацию на диске необходимо согласовать с выбранным выпуском.

У API заданы maxUnavailable: 0 и maxSurge: 1. Deployment может добавить одну копию новой версии и ждать её готовности, сохраняя старые. Затем количество старых сокращается, а новых увеличивается. В разные моменты Service может направлять запросы к двум версиям, поэтому совместимость ответа особенно важна.

Если новая версия уберёт поле lessons, web начнёт ошибаться только на части запросов в переходный период. Зелёная readiness не предотвратит этого, потому что она проверяет готовность процесса, а не договорённость JSON-схемы. Для рабочего продукта изменение контракта планируют отдельно и сохраняют совместимость старых и новых участников.

Дополнительный Pod требует ресурсов. Если узел не вмещает surge-копию, rollout может остановиться при работающих старых экземплярах. Это отличается от ситуации, когда новая копия размещена, но её startupProbe не проходит. Один и тот же симптом «не завершилось обновление» требует разных решений в зависимости от состояния конкретного Pod.

Наблюдение обновления

Будущие команды:

kubectl --context kind-ploshchadka apply -f manifests/07-resources.yaml
kubectl --context kind-ploshchadka -n ploshchadka rollout status deployment/api
kubectl --context kind-ploshchadka -n ploshchadka rollout history deployment/api
kubectl --context kind-ploshchadka -n ploshchadka get replicasets -l app=api

В ожидаемом исправном состоянии новая ReplicaSet получает две доступные копии, а прежняя — ноль активных. История ревизий Deployment относится к изменениям Pod template. Изменение количества replicas само по себе не означает новую версию программы. Поэтому номер ревизии не следует использовать вместо версии продукта без дополнительного описания.

Параметр progressDeadlineSeconds: 120 ограничивает время ожидания прогресса для состояния Deployment. Он не означает, что Kubernetes автоматически выполнит предметный rollback ровно через две минуты. Решение об откате и его выполнение остаются отдельным действием. Состояние проблемы нужно прочитать и объяснить до смены версии.

Через страницу «Площадки» после завершённого обновления ожидается третий урок. Пока старые и новые экземпляры сосуществуют, пользователь может видеть два или три пункта. Это допустимая особенность нашего изменения данных. Если продукт требует атомарной смены каталога для всех пользователей, хранение списка в образе и такой rollout не обеспечивают нужную гарантию.

Для диагностики сопоставляйте фактический image Pod с декларацией и ответом API. APP_VERSION из ConfigMap в нашем наборе пока остаётся строкой 1; без отдельного изменения она не станет 2 вслед за образом. Это специально показывает ограничение переменной окружения как идентификатора кода. Третья запись и image здесь надёжнее описывают подготовленный выпуск.

Граница rollback

Параметр revisionHistoryLimit сохраняет ограниченное число прежних ReplicaSet для истории. Он не является бесконечным архивом всех выпусков. Для долговременного восстановления нужны отдельно сохранённые декларации и артефакты; доступность конкретной ревизии проверяют перед выбором отката.

Для будущего отката читатель может использовать:

kubectl --context kind-ploshchadka -n ploshchadka rollout undo deployment/api
kubectl --context kind-ploshchadka -n ploshchadka rollout status deployment/api

Deployment возвращает прежний Pod template из сохранённой ревизии. Runtime должен по-прежнему иметь соответствующий образ. Если локальный образ был удалён, запись ревизии не содержит его слои и не создаст программу заново. Аналогично registry производственной системы должен сохранять используемые артефакты на срок возможного отката.

ConfigMap api-config и Secret api-demo-secret не входят своим содержимым в ревизию Pod template. При ссылке на то же имя старая программа может получить новое значение. Поэтому перед откатом нужно знать совместимую конфигурацию. Версионированные имена объектов помогают выражать связь выпуска и параметров, но требуют собственного жизненного цикла и аккуратной очистки.

Откат кода не отменяет совершённые операции с базой или файлами. Если новая версия изменила формат данных необратимо, прежний образ может оказаться неспособным их читать. Наш основной API не записывает данные, поэтому этот риск вынесен за пределы демонстрации. В реальном проекте обратимость миграций и стратегия совместимости должны обсуждаться вместе с rollout.

Модель ревизий и обновления описана в документации Deployment. Практический результат урока — набор условий осмысленного отката: прежний образ существует, его конфигурация известна, данные совместимы, а декларация на диске соответствует выбранному состоянию. Далее добавим журналы и масштабирование, чтобы новые копии можно было сопровождать по наблюдаемым признакам.

Оглавление серии