Kubernetes
Теория: Deployment и ReplicaSet
Deployment и ReplicaSet
В предыдущем уроке мы создавали Pod вручную. Удалили — он исчез навсегда. Изменили образ — пришлось пересоздавать. Для учебных целей это работает, но в реальной системе так жить нельзя. Нужен кто-то, кто будет следить за Pod и восстанавливать его при сбоях.
Зачем нужен ReplicaSet
Представьте: ваш Pod упал из-за ошибки в коде, нехватки памяти или проблемы с нодой. Если это был единственный экземпляр приложения — сервис недоступен. Вы узнаёте об этом из алерта, заходите в кластер, разбираетесь, поднимаете заново. Минуты простоя превращаются в десятки минут.
ReplicaSet решает эту проблему. Это контроллер, который следит за количеством запущенных Pod и поддерживает его на заданном уровне. Упал один Pod — ReplicaSet создаст новый. Упала нода — Pod будут пересозданы на других нодах. Вы указываете «должно быть три экземпляра», а Kubernetes делает так, чтобы их всегда было три.
Три ключевые части:
replicas: 3— желаемое количество Pod.selector— по каким меткам ReplicaSet находит «свои» Pod. Здесь он ищет Pod с меткойapp: nginx.template— шаблон Pod, который ReplicaSet будет создавать. Это тот же манифест Pod, только безapiVersionиkind.
Применим и посмотрим:
Вы увидите три Pod с именами вида nginx-replicaset-xxxxx. Суффикс генерируется автоматически.
Теперь удалите один Pod:
ReplicaSet мгновенно создаст новый. Он постоянно сравнивает текущее состояние с желаемым и устраняет расхождения.
Проблема ReplicaSet: обновления
ReplicaSet отлично справляется с поддержанием количества Pod, но у него есть критический недостаток. Измените образ в манифесте на nginx:1.26 и примените:
Pod остались прежними. ReplicaSet не пересоздаёт существующие Pod при изменении шаблона. Он использует новый шаблон только для создания новых Pod. Чтобы обновить приложение, придётся удалять Pod вручную — ReplicaSet создаст новые уже с обновлённым образом.
Для одного-двух Pod это терпимо. Для десятков — это ручная работа с риском ошибки и простоем.
Deployment: контроллер над контроллером
Deployment решает проблему обновлений. Это объект уровнем выше, который управляет ReplicaSet. Когда вы обновляете Deployment, он создаёт новый ReplicaSet с новым шаблоном и плавно переключает Pod со старого на новый.
Структура идентична ReplicaSet, только kind: Deployment. Это не совпадение — Deployment создаёт ReplicaSet внутри себя.
Вы увидите цепочку: Deployment → ReplicaSet → Pod. Имя ReplicaSet будет содержать хеш шаблона: nginx-deployment-5d4f7b8c9.
Зафиксируем это как правило: Deployment управляет ReplicaSet, ReplicaSet управляет Pod'ами, Pod — это то, что реально запускается. Вы почти никогда не работаете с ReplicaSet напрямую и никогда не создаёте Pod вручную в production. Вы описываете Deployment, а Kubernetes выстраивает всю цепочку сам.
Как работает обновление
Теперь обновим образ:
Происходит следующее:
- Deployment создаёт новый ReplicaSet с образом
nginx:1.26. - Новый ReplicaSet начинает создавать Pod.
- Когда новый Pod готов, старый ReplicaSet уменьшает количество своих Pod на один.
- Процесс повторяется, пока все Pod не обновятся.
Ключевой момент: старый ReplicaSet остаётся в системе с нулём Pod. Это не мусор — это история. Благодаря этому работает откат:
Старый ReplicaSet хранит предыдущую конфигурацию. По умолчанию Kubernetes хранит 10 последних ревизий (настраивается через revisionHistoryLimit).
Стратегии обновления
Это частый вопрос на собеседованиях: какие стратегии обновления существуют в Kubernetes?
Recreate
Самая простая стратегия: сначала удалить все старые Pod, потом создать новые.
Плюсы: никогда не будет двух версий одновременно. Это важно, если старая и новая версия несовместимы — например, при миграции базы данных.
Минусы: полный простой. Пока старые Pod удаляются и новые запускаются, сервис недоступен.
Когда использовать: изменение схемы данных, несовместимые версии API, shared-ресурсы без поддержки конкурентного доступа.
Rolling Update
Стратегия по умолчанию. Постепенная замена Pod: создаём новый, ждём готовности, удаляем старый.
maxSurge — на сколько Pod больше желаемого количества можно создать во время обновления. Значение 1 означает: если replicas: 3, во время обновления может быть до 4 Pod.
maxUnavailable — сколько Pod может быть недоступно. Значение 1 означает: минимум 2 из 3 Pod всегда работают.
Для zero-downtime деплоя используйте maxUnavailable: 0:
Теперь Kubernetes сначала создаст новый Pod, дождётся его готовности, и только потом удалит старый. В любой момент времени работают минимум 3 Pod.
Blue/Green Deployment
Kubernetes не имеет встроенной стратегии Blue/Green, но её легко реализовать через два Deployment и переключение Service.
Идея: поднять полную копию приложения с новой версией (Green) рядом со старой (Blue). Когда Green готов и протестирован — переключить трафик одним действием.
Service направляет трафик на одну из версий:
Переключение — изменение одного лейбла в Service. Откат — обратное изменение. Минус: двойное потребление ресурсов во время деплоя.
Canary Deployment
Идея: направить небольшой процент трафика на новую версию, убедиться, что всё работает, и постепенно увеличивать долю.
Простейший вариант в Kubernetes — через количество реплик:
Service выбирает Pod по общему лейблу:
При 9 stable + 1 canary примерно 10% запросов пойдут на новую версию. Если всё хорошо — увеличиваете canary, уменьшаете stable. Если проблемы — удаляете canary.
Для точного контроля процента трафика используют service mesh (Istio, Linkerd) или ingress-контроллеры с поддержкой weighted routing.
Probes: проверки состояния контейнеров
Ещё один частый вопрос на собеседованиях: какие типы проверок есть в Kubernetes?
Kubernetes не знает, что происходит внутри контейнера. Процесс может работать, но приложение — зависнуть, уйти в deadlock, потерять соединение с базой. Без проверок Kubernetes будет считать такой Pod здоровым и отправлять на него трафик.
Liveness Probe — проверка живучести
Отвечает на вопрос: приложение ещё работает или зависло?
Если liveness probe не проходит, Kubernetes перезапускает контейнер. Это жёсткое действие — используйте с осторожностью.
initialDelaySeconds — сколько ждать после старта контейнера перед первой проверкой. periodSeconds — интервал между проверками. timeoutSeconds — таймаут на ответ. failureThreshold — сколько неудачных проверок подряд считать сбоем.
Типичная ошибка: слишком агрессивный liveness probe. Приложение стартует 30 секунд, а probe начинает проверять через 10. Контейнер не успевает подняться — probe фейлится — Kubernetes перезапускает — и так по кругу. Результат: CrashLoopBackOff.
Readiness Probe — проверка готовности
Отвечает на вопрос: приложение готово принимать трафик?
Если readiness probe не проходит, Pod исключается из Service — трафик на него не идёт. Но контейнер не перезапускается. Когда probe снова пройдёт, Pod вернётся в ротацию.
Это критически важно для Rolling Update. Без readiness probe Kubernetes создаст новый Pod и сразу начнёт отправлять на него трафик, даже если приложение ещё не готово. Со старым Pod'ом уже попрощались — в итоге часть запросов падает.
Startup Probe — проверка запуска
Отвечает на вопрос: приложение уже запустилось?
Startup probe используется для приложений с долгим стартом. Пока startup probe не пройдёт, liveness и readiness probe не запускаются.
Это позволяет дать приложению много времени на старт (здесь — до 150 секунд), но после старта использовать агрессивный liveness probe.
Типы проверок
Все три probe поддерживают три способа проверки:
-
HTTP GET — запрос на указанный путь и порт. Код 200-399 = успех.
-
TCP Socket — попытка открыть соединение. Если порт отвечает = успех.
-
Exec — выполнение команды внутри контейнера. Exit code 0 = успех.
Рекомендации по настройке probes:
- Всегда добавляйте readiness probe. Без него Rolling Update небезопасен.
- Liveness probe — только для реальных зависаний. Не проверяйте через liveness доступность внешних зависимостей. Если база недоступна, перезапуск приложения не поможет, а только создаст лишнюю нагрузку.
- Для долго стартующих приложений используйте startup probe вместо большого
initialDelaySecondsв liveness. - Endpoint для liveness должен быть лёгким — просто «я жив». Для readiness можно проверять готовность зависимостей.
Масштабирование
Изменить количество реплик можно двумя способами:
Kubernetes создаст или удалит Pod до нужного количества. Понаблюдайте за процессом в реальном времени:
Для автоматического масштабирования используется HorizontalPodAutoscaler:
Важно понимать: HPA масштабирует Deployment, а не Pod напрямую. Он изменяет поле replicas, а дальше работает обычная цепочка — ReplicaSet создаёт или удаляет Pod. Kubernetes никогда не «растягивает» существующий Pod — масштабирование всегда означает создание новых Pod или удаление лишних.
Для работы HPA нужен metrics-server в кластере.
Откат
Если новая версия сломала приложение:
Kubernetes переключит ReplicaSet — тот, что был с нулём Pod, снова станет активным.


