Pod
| Тип | объект API Kubernetes (core/v1) |
|---|---|
| Содержит | один или несколько контейнеров + общие тома |
| Сеть | один IP-адрес на под, общий для всех контейнеров |
| Время жизни | эфемерный, не переносится между узлами |
| Фазы | Pending, Running, Succeeded, Failed, Unknown |
| Обычно создаётся | Deployment, StatefulSet, DaemonSet, Job |
Pod (под; от англ. pod — «стручок», также «стая китов» — отсылка к логотипу Docker) — минимальная единица, которую Kubernetes размещает и запускает. Под — это группа из одного или нескольких контейнеров, которые всегда работают вместе на одном узле, разделяют сетевое пространство (один IP-адрес, общий localhost) и могут монтировать общие тома.[1] Kubernetes управляет не отдельными контейнерами, а подами: планирует, перезапускает и удаляет их целиком.
Зачем группа, а не контейнер
Под моделирует «логический хост»: процессы, которые на обычном сервере работали бы рядом и общались через localhost или общие файлы. Технически контейнеры пода делят сетевое и IPC-пространства имён, а их ресурсы находятся в общей родительской cgroup. Чаще всего в поде ровно один контейнер, но бывают и вспомогательные:
- init-контейнеры — выполняются последовательно до старта основных: дождаться базы данных, применить миграции, скачать конфигурацию.[3]
- sidecar-контейнеры — работают рядом с основным всё время его жизни: прокси service mesh, сборщик логов, обновляющий сертификаты агент. С версии 1.29 (стабильно в 1.33) их объявляют как init-контейнеры с
restartPolicy: Always, чтобы они стартовали раньше и останавливались позже основного.[4]
Пример манифеста
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
app: web
spec:
containers:
- name: app
image: ghcr.io/example/web:1.4.0
ports:
- containerPort: 8000
env:
- name: LOG_LEVEL
value: info
resources:
requests: {cpu: 250m, memory: 256Mi}
limits: {memory: 512Mi}
readinessProbe:
httpGet: {path: /healthz, port: 8000}
periodSeconds: 5
livenessProbe:
httpGet: {path: /healthz, port: 8000}
initialDelaySeconds: 10
Поля labels нужны, чтобы другие объекты находили под: Service направляет на него трафик, ReplicaSet считает реплики.
Жизненный цикл
Под проходит фазы Pending (принят, ждёт размещения или скачивания образа), Running, Succeeded или Failed (все контейнеры завершились), Unknown (узел недоступен).[2] Внутри пода kubelet следит за контейнерами и перезапускает их по политике restartPolicy (Always, OnFailure, Never) с нарастающей задержкой — отсюда знакомый статус CrashLoopBackOff.
Под эфемерен: если узел выходит из строя или под удаляют, он не «переезжает», а исчезает. Новый под — уже другой объект с другим именем и IP. Поэтому голые поды почти не создают вручную: за нужным числом реплик следят контроллеры — Deployment, StatefulSet (стабильные имена и тома), DaemonSet (по поду на узел), Job и CronJob (разовые и периодические задачи).
При удалении kubelet отправляет главному процессу контейнера SIGTERM, ждёт terminationGracePeriodSeconds (по умолчанию 30 секунд) и затем посылает SIGKILL — приложение должно корректно обрабатывать сигналы (см. Процессы и сигналы).
Пробы
Kubelet проверяет состояние контейнера тремя видами проб (HTTP-запрос, TCP-подключение, команда или gRPC):[6]
| Проба | Если не проходит |
|---|---|
startupProbe |
остальные пробы не запускаются, пока приложение стартует; при провале — перезапуск |
livenessProbe |
контейнер перезапускается |
readinessProbe |
под исключается из балансировки Service, но не перезапускается |
Типичная ошибка — делать liveness-пробу зависимой от базы данных: при сбое БД Kubernetes начнёт бесконечно перезапускать здоровые поды.
Ресурсы
requests — сколько ресурсов гарантировано; по ним планировщик выбирает узел. limits — потолок: превышение CPU приводит к троттлингу, превышение памяти — к завершению контейнера с причиной OOMKilled.[5] По соотношению requests и limits под получает класс качества обслуживания (QoS): Guaranteed, Burstable или BestEffort — он определяет порядок вытеснения при нехватке памяти на узле.
Полезные команды
kubectl get pods -o wide # статус, узел, IP
kubectl describe pod web # события: почему Pending, почему перезапуск
kubectl logs web -c app --previous # логи упавшего экземпляра
kubectl exec -it web -- sh # оболочка внутри контейнера
kubectl port-forward pod/web 8000:8000
Подробнее об утилите — в статье kubectl.