Pod это минимальная единица в Kubernetes, но руками поды почти никто не создаёт. Ими управляют контроллеры: Deployment для stateless-сервисов, StatefulSet для баз, DaemonSet для агентов на каждом узле, Job и CronJob для задач.
Pod
Pod это группа контейнеров, которые всегда живут на одном узле и делят:
- сетевой namespace: один IP, общий
localhost, порты не должны пересекаться; - тома, объявленные в поде;
- жизненный цикл: под создаётся и удаляется целиком.
Обычно в поде один контейнер. Несколько бывает, когда они неразделимы: приложение и sidecar (прокси сервис-меша, сборщик логов). Не кладите в один под приложение и базу: их нельзя масштабировать и обновлять независимо.
Поды эфемерны: при пересоздании меняются имя, IP и узел. Поэтому к подам ходят через Service, а не по IP.
Init-контейнеры и sidecar
- initContainers выполняются по очереди до старта основных контейнеров и должны завершиться успешно: миграции, ожидание зависимости, подготовка файлов.
- Нативные sidecar: init-контейнер с
restartPolicy: Alwaysзапускается до основных и работает всё время жизни пода, а останавливается после них. Это решает старую проблему, когда прокси или сборщик логов останавливался раньше приложения или мешал Job завершиться.
Жизненный цикл пода
Фазы (status.phase): Pending (принят, но ещё не запущен: ждёт узла или скачивает образ), Running, Succeeded, Failed, Unknown (нет связи с узлом).
Отдельно есть состояния контейнеров: Waiting (с причиной: ContainerCreating, ImagePullBackOff, CrashLoopBackOff), Running, Terminated (с кодом выхода и причиной, например OOMKilled).
restartPolicy пода: Always (по умолчанию, для Deployment другого нет), OnFailure, Never (для Job). Упавший контейнер перезапускается в том же поде с экспоненциальной задержкой до 5 минут: это и есть CrashLoopBackOff.
Удаление пода
- Под помечается удаляемым, его убирают из EndpointSlice сервисов.
- Выполняется
preStop-хук, если есть. - Контейнерам отправляется SIGTERM.
- Через
terminationGracePeriodSeconds(по умолчанию 30) приходит SIGKILL.
Удаление из эндпоинтов и SIGTERM идут параллельно, поэтому приложение может получить ещё несколько запросов после SIGTERM. Частый приём: preStop с короткой паузой, чтобы балансировщики успели убрать под.
ReplicaSet и Deployment
ReplicaSet держит заданное число одинаковых подов по селектору меток. Deployment управляет ReplicaSet-ами и даёт обновления и откаты. Напрямую ReplicaSet почти никогда не создают.
При изменении шаблона пода (spec.template: образ, переменные, ресурсы) Deployment создаёт новый ReplicaSet и постепенно переносит реплики на него. Изменение replicas новый ReplicaSet не создаёт.
Стратегии обновления
- RollingUpdate (по умолчанию):
maxSurge(сколько подов сверх нужного числа можно поднять, по умолчанию 25%) иmaxUnavailable(сколько может отсутствовать, по умолчанию 25%).maxUnavailable: 0+maxSurge: 1даёт обновление без потери ёмкости. - Recreate: сначала удалить все старые поды, потом создать новые. Простой неизбежен, но две версии не работают одновременно (нужно, например, при несовместимых миграциях или единственном томе ReadWriteOnce).
Rolling update опирается на readiness probe: новый под считается доступным, только когда готов. Без readiness Kubernetes считает под готовым сразу после старта и может убрать старые поды раньше, чем новые реально заработают. minReadySeconds добавляет паузу, progressDeadlineSeconds задаёт, когда считать раскатку зависшей.
kubectl set image deployment/api api=registry.example.com/api:1.4.3
kubectl rollout status deployment/api
kubectl rollout history deployment/api
kubectl rollout undo deployment/api # на предыдущую версию
kubectl rollout undo deployment/api --to-revision=3
kubectl rollout restart deployment/api # пересоздать поды
kubectl scale deployment/api --replicas=5
Число хранимых старых ReplicaSet задаёт revisionHistoryLimit (по умолчанию 10).
Канареечные и blue-green выкладки в чистом Deployment делаются вручную (два Deployment и метки), удобнее через Argo Rollouts, Flagger или сервис-меш.
DaemonSet, Job, CronJob
- DaemonSet: по поду на каждом (или выбранном) узле: агенты логов и метрик, CNI, kube-proxy.
- Job: под выполняется до успешного завершения, с повторами (
backoffLimit), параллелизмом (parallelism,completions) и ограничением времени (activeDeadlineSeconds). - CronJob: создаёт Job по расписанию cron. Важные поля:
concurrencyPolicy(Forbid, чтобы запуски не накладывались),startingDeadlineSeconds,successfulJobsHistoryLimit. Время по умолчанию в часовом поясе kube-controller-manager, можно задатьtimeZone.
Частые ошибки
- Создавать голые поды: упадёт узел, под никто не пересоздаст.
- Метки шаблона не совпадают с селектором.
- Нет readiness probe, rolling update выкатывает неготовые поды.
- Ждать, что изменение ConfigMap само перезапустит поды Deployment.
- CronJob без
concurrencyPolicy: Forbidдля долгих задач.
Что спросят на собесе
- Что такое под и почему в нём бывает несколько контейнеров.
- Как работает rolling update, что значат maxSurge и maxUnavailable.
- Как откатить неудачный релиз.
- Чем Deployment отличается от StatefulSet и DaemonSet.
- Что происходит при удалении пода и как сделать graceful shutdown.