← Back to notes

Pod


Pod — минимальная развёртываемая единица в Kubernetes. Kubernetes управляет Pod, а не контейнерами напрямую. Pod — обёртка вокруг одного или нескольких контейнеров с общим сетевым namespace и возможностью разделять volumes.

source: kubernetes.io/docs/concepts/workloads/pods/

Single-container и multi-container Pod

Один контейнер в Pod — соотношение 1:1, типичный случай. Несколько контейнеров — когда они тесно связаны и разделяют ресурсы: паттерн sidecar (основной контейнер + вспомогательный для логирования, проксирования или синхронизации данных).

Общие ресурсы внутри Pod

Сеть: все контейнеры в Pod разделяют один сетевой namespace — обращаются друг к другу через localhost. Каждый Pod получает уникальный IP в кластере.

Хранилище: контейнеры могут монтировать общие Volume. Данные в Volume переживают перезапуск контейнера (но не удаление Pod, если Volume типа emptyDir).

Жизненный цикл Pod

source: kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/

ФазаОписание
PendingPod принят кластером, контейнеры ещё не запущены (скачивается образ, ожидается узел)
RunningPod назначен на узел, минимум один контейнер запущен
SucceededВсе контейнеры завершились успешно (exit code 0), перезапуска не будет
FailedВсе контейнеры завершились, минимум один — с ошибкой
UnknownСостояние Pod не известно (обычно проблема связи с узлом)

Pod — эфемерная сущность. При падении Pod не восстанавливается сам. За пересоздание отвечают контроллеры: Deployment, StatefulSet, DaemonSet.

Манифест Pod

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
    environment: dev
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      ports:
        - containerPort: 80
      resources:
        requests:
          cpu: 100m
          memory: 128Mi
        limits:
          cpu: 250m
          memory: 256Mi

Основные команды kubectl для Pod

# Создать Pod императивно
kubectl run nginx --image=nginx:1.27

# Создать из манифеста
kubectl apply -f pod.yaml

# Список Pod
kubectl get pods
kubectl get pods -o wide          # IP, узел, статус
kubectl get pods --show-labels

# Подробности и события
kubectl describe pod nginx-pod

# Логи
kubectl logs nginx-pod
kubectl logs nginx-pod -c sidecar  # конкретный контейнер
kubectl logs nginx-pod -f          # follow

# Выполнение команды внутри контейнера
kubectl exec -ti nginx-pod -- /bin/sh

# Проброс порта на локальную машину
kubectl port-forward nginx-pod 8080:80

# Удаление
kubectl delete pod nginx-pod
kubectl delete -f pod.yaml

Init Containers

Init-контейнеры запускаются до основных контейнеров Pod. Выполняются последовательно — каждый следующий стартует только после успешного завершения предыдущего.

source: kubernetes.io/docs/concepts/workloads/pods/init-containers/

Когда использовать:

  • Ожидание готовности внешнего сервиса (БД, API) перед стартом приложения
  • Предварительная подготовка данных или миграции схемы
  • Настройка конфигурационных файлов перед запуском
apiVersion: v1
kind: Pod
metadata:
  name: app-with-init
spec:
  initContainers:
    - name: wait-for-db
      image: busybox:1.36
      command:
        - sh
        - -c
        - |
          until nc -z postgres-service 5432; do
            echo "Waiting for database..."
            sleep 2
          done
    - name: run-migrations
      image: myapp:1.0
      command: ["./migrate", "--up"]
  containers:
    - name: app
      image: myapp:1.0
      ports:
        - containerPort: 8080

Особенности init-контейнеров:

  • Не поддерживают probes (livenessProbe, readinessProbe, startupProbe) и lifecycle
  • Завершаются до конца — не работают постоянно
  • Если init-контейнер падает, Pod перезапускает его согласно restartPolicy
  • Ресурсы: эффективный request/limit Pod — максимум из суммы основных контейнеров и самого большого init-контейнера (не сложение)

Sidecar Containers (нативные)

KEP-753: alpha 1.28, beta 1.29 (включён по умолчанию), GA 1.33. Init-контейнер с restartPolicy: Always становится sidecar-контейнером: стартует до основных, но живёт всё время жизни Pod.

source: kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/

Сравнение типов контейнеров

СвойствоInit containerSidecar containerRegular container
restartPolicyне заданAlways
ЗапускДо основных, завершаетсяДо основных, живёт постоянноОдновременно с остальными
ProbesНет (никаких)readiness, liveness, startupВсе
Влияет на Pod ReadyНетДа (через readinessProbe)Да
ЗавершениеДо запуска следующего initПосле всех основных

Пример: Fluent Bit как sidecar

apiVersion: v1
kind: Pod
metadata:
  name: app-with-sidecar
spec:
  initContainers:
    - name: log-collector
      image: fluent/fluent-bit:3.0
      restartPolicy: Always          # делает этот init-контейнер sidecar
      readinessProbe:
        httpGet:
          path: /api/v1/health
          port: 2020
      volumeMounts:
        - name: logs
          mountPath: /var/log/app
  containers:
    - name: app
      image: myapp:v1
      volumeMounts:
        - name: logs
          mountPath: /var/log/app
  volumes:
    - name: logs
      emptyDir: {}

Порядок lifecycle

  • Запуск: обычные init → sidecar (запускается и остаётся жить) → основные контейнеры
  • Завершение: основные контейнеры останавливаются первыми → sidecar завершается последним

До 1.29 logging agent (Fluent Bit, Filebeat) запускали как обычный контейнер, что создавало гонку при завершении Pod — sidecar мог упасть до того, как основной контейнер успел записать последние логи. Нативные sidecar решают эту проблему.

Типичные ошибки

Запуск Pod без контроллера в production. Pod не поднимается сам при падении узла или перезапуске. Всегда используй Deployment, StatefulSet или DaemonSet.

Образ без явного тега или с latest. Один и тот же манифест может запустить разные версии в разное время. Указывай конкретный тег или digest: nginx:1.27 или nginx@sha256:....

Один большой контейнер вместо нескольких специализированных. Соединять несвязанные задачи в одном образе — сложнее обновлять, больше поверхность атаки.

Не задавать resources.requests и resources.limits. Без requests scheduler не может правильно разместить Pod. Без limits один Pod может монополизировать ресурсы узла. Подробно — в главе 13.

Ожидать, что данные переживут удаление Pod без volume. Файловая система контейнера эфемерна. Всё, что нужно сохранить между перезапусками, должно лежать в volume.

Альтернативы

Deployment — для stateless приложений, нужны реплики и rolling update (глава 05).

StatefulSet — для stateful приложений, где важна стабильная идентичность Pod (глава 11).

Job — для разовых задач (глава 12).

CronJob — для задач по расписанию (глава 12).


01: Архитектура кластера

03: Labels, Selectors, Annotations

Pod | Aleksandr Suprun