Задача 20. Обновление кластера и умирающие API

После обновления кластера пайплайн падает на манифестах, которые работали годами. Разбираем разницу между deprecated и removed, правило skew между компонентами и порядок безопасного обновления.
Опубликовано:

Задача

Кластер обновили на две минорные версии вперёд. Приложения продолжают работать, но CI/CD падает:

PLAINTEXT
error: resource mapping not found for name: "api" namespace: "prod"
from "deployment.yaml": no matches for kind "Deployment" in version "apps/v1beta2"
Нажмите, чтобы развернуть и увидеть больше

Манифест не меняли годами, и раньше он применялся без проблем.

Вопрос: что произошло и почему работающие приложения не пострадали?

Что кажется очевидным

«Обновление сломало совместимость». Формально да, но важно понять механику — она объясняет, почему предупреждения были, а их не заметили.

Как это работает на самом деле

API в Kubernetes проходят жизненный цикл, и у него две принципиально разные стадии:

Deprecated (устарел). API помечен как устаревший, но продолжает работать. При обращении возвращается предупреждение, которое kubectl печатает в stderr:

PLAINTEXT
Warning: apps/v1beta2 Deployment is deprecated in v1.16+, unavailable in v1.22+;
use apps/v1 Deployment
Нажмите, чтобы развернуть и увидеть больше

Removed (удалён). API перестаёт существовать. Запросы к нему возвращают ошибку — ровно ту, что в задаче.

Между этими стадиями обычно проходит несколько релизов, и всё это время сервер честно предупреждает. Проблема в том, что предупреждения уходят в stderr пайплайна и никто их не читает — пока не станет поздно.

Почему приложения не пострадали

Ключевой момент: API-версия — это способ представления объекта, а не способ его хранения. Объект, созданный как apps/v1beta2, хранится в etcd в единой внутренней форме и после удаления старой версии остаётся доступен через актуальную — apps/v1.

То есть уже созданные Deployment’ы продолжают работать. Ломается только применение манифестов со старым apiVersion. Именно поэтому симптом проявляется в CI, а не в проде.

Правило version skew

Компоненты кластера не обязаны иметь одинаковую версию, но допустимый разброс ограничен:

Отсюда главное правило обновления: сначала control plane, потом узлы, и строго по одной минорной версии за раз. Перепрыгивать через версии нельзя — это ломает гарантии совместимости и миграции хранимых объектов.

Ответ

API-группа apps/v1beta2 была помечена устаревшей, а затем удалена. Существующие объекты продолжили работать через актуальную версию apps/v1, но манифесты со старым apiVersion перестали применяться.

Что с этим делать

Найти проблемы заранее

BASH
# Что говорит сервер о версиях
kubectl api-resources
kubectl api-versions

# Предупреждения при применении — не игнорируйте их
kubectl apply -f manifests/ --dry-run=server 2>&1 | grep -i warn
Нажмите, чтобы развернуть и увидеть больше

Флаг --dry-run=server особенно ценен: он прогоняет манифесты через реальный API server со всеми валидациями и предупреждениями, ничего не изменяя. Хорошая практика — держать такую проверку отдельным шагом в CI.

Для планового аудита существуют специализированные инструменты (например, kubent/pluto), которые сканируют манифесты и объекты кластера на использование устаревших API и показывают, в какой версии они исчезнут.

Порядок безопасного обновления

  1. Прочитать release notes целевой версии — раздел про удалённые API и изменения поведения. Это не формальность: между минорными версиями меняются дефолты.
  2. Проверить совместимость дополнений: CNI, CSI-драйверы, ingress-контроллер, операторы, service mesh. Часто именно они, а не сам Kubernetes, определяют, когда можно обновляться.
  3. Обновить манифесты на актуальные API-версии и убедиться, что всё применяется на текущем кластере.
  4. Прогнать на тестовом кластере той же конфигурации.
  5. Обновить control plane (по одной минорной версии).
  6. Обновить узлы — по одному, через drain с уважением к PDB (см. задачу 8).
  7. Проверить: все поды поднялись, метрики в норме, ключевые сценарии работают.

Managed-кластеры

В облаках обновление control plane обычно автоматизировано, но узлы остаются вашей ответственностью: стратегия обновления пула нод, PDB, окно обслуживания. Отдельная деталь — окна автообновления: провайдер может обновить кластер сам по истечении срока поддержки версии. Если ваши манифесты не готовы, узнать об этом в момент автоматического обновления — плохой сценарий.

Профилактика

Итог серии

Двадцать задач — и почти в каждой ответ сводился к одному: декларативная простота Kubernetes скрывает механику, которая проявляется под нагрузкой и в отказах. Под Running не значит готов; удаление пода не мгновенно; requests важнее, чем кажется; namespace не изолирует ресурсы; балансировка идёт по соединениям, а не по запросам.

Если из всей серии оставить один практический вывод: задавайте requests и readinessProbe. Эти два поля прямо или косвенно участвуют в доброй половине разобранных ситуаций — от endpoints и rolling update до вытеснения и автомасштабирования.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша