Модуль 3 / 19
Pod: устройство, жизненный цикл и диагностика
Содержание
1. Цели модуля
После модуля вы сможете объяснить жизненный цикл Pod и контейнеров, отличить phase от готовности, применить init container и emptyDir, выполнить корректное завершение и диагностировать ImagePullBackOff.
- Pod как одноразовая единица выполнения
- Pod Conditions и containerStatuses
- restartPolicy и CrashLoopBackOff
- graceful termination и evidence-first диагностика
2. Теория: Pod как единица выполнения
Pod — минимальная планируемая единица Kubernetes. Все контейнеры Pod назначаются на один Node, совместно используют network namespace и взаимодействуют через localhost. Общими становятся только явно подключённые volumes.
Pod обычно создаёт контроллер. При замене новый экземпляр получает другой UID и IP, поэтому приложение не должно зависеть от локальной идентичности Pod.
3. Теория: Phase, Conditions и состояния контейнера
status.phase показывает грубую фазу Pending, Running, Succeeded, Failed или Unknown, но не доказывает готовность приложения. Сопоставляйте phase, Pod Conditions и status.containerStatuses.
- Waiting содержит reason, например ImagePullBackOff
- Running означает запущенный процесс, но не гарантирует Ready
- Terminated содержит exitCode, signal и reason
- restartCount считает перезапуски контейнера в том же Pod
4. Теория: Init containers и volumes
Init containers выполняются последовательно и должны успешно завершиться до запуска app containers. Они подходят для подготовки файлов и одноразовых проверок зависимостей; бесконечный init container навсегда задержит запуск Pod.
emptyDir создаётся для Pod и переживает перезапуски контейнеров, но удаляется вместе с Pod. Он подходит для временного обмена данными, а не постоянного хранения.
5. Теория: перезапуск и завершение
restartPolicy принимает Always, OnFailure или Never. CrashLoopBackOff — экспоненциальная задержка повторных запусков, а не отдельная phase. Перезапуск контейнера сохраняет UID Pod; eviction или замена контроллером создаёт новый Pod.
При удалении kubelet запускает preStop, отправляет процессу PID 1 сигнал TERM и ждёт terminationGracePeriodSeconds. После истечения срока процессы останавливаются принудительно.
6. Методические указания
- Всегда указывайте namespace и имя контейнера в многоконтейнерном Pod
- Наблюдайте phase, Conditions, containerStatuses и Events вместе
- Используйте logs --previous только для предыдущего экземпляра перезапущенного контейнера
- Не считайте Running эквивалентом Ready
- Не используйте kubectl delete --force как штатный способ остановки
7. Лабораторная работа: полный жизненный цикл
Сохраните манифест как pod-lifecycle.yaml. Init container подготовит страницу в emptyDir, а nginx прочитает её.
apiVersion: v1
kind: Namespace
metadata: {name: lab-pods}
---
apiVersion: v1
kind: Pod
metadata: {name: lifecycle-demo, namespace: lab-pods}
spec:
terminationGracePeriodSeconds: 20
initContainers:
- name: prepare
image: busybox:1.37.0
command: ["sh", "-c", "printf 'ready from init container\n' > /work/index.html"]
volumeMounts: [{name: content, mountPath: /work}]
containers:
- name: web
image: nginx:1.28-alpine
lifecycle: {preStop: {exec: {command: ["sh", "-c", "sleep 5"]}}}
volumeMounts: [{name: content, mountPath: /usr/share/nginx/html, readOnly: true}]
volumes: [{name: content, emptyDir: {}}kubectl apply -f pod-lifecycle.yaml
kubectl wait -n lab-pods --for=condition=Ready pod/lifecycle-demo --timeout=120s
kubectl exec -n lab-pods lifecycle-demo -c web -- wget -qO- http://127.0.0.1
kubectl logs lifecycle-demo -n lab-pods -c prepare
kubectl delete pod lifecycle-demo -n lab-pods --wait=truekubectl get pod lifecycle-demo -n lab-pods -w
kubectl get pod lifecycle-demo -n lab-pods -o jsonpath='{.status.phase}{"\n"}'
kubectl get pod lifecycle-demo -n lab-pods -o jsonpath='{range .status.conditions[*]}{.type}{"="}{.status}{"\n"}{end}'
kubectl get pod lifecycle-demo -n lab-pods -o jsonpath='{range .status.containerStatuses[*]}{.name}{" ready="}{.ready}{" restarts="}{.restartCount}{"\n"}{end}'
kubectl describe pod lifecycle-demo -n lab-pods
kubectl events -n lab-pods --for pod/lifecycle-demoКритерий: init container завершился с exitCode 0, web имеет ready=true, HTTP возвращает ready from init container, а обычное удаление соблюдает grace period.
8. Диагностика: ImagePullBackOff
Сохраните манифест как pod-broken-image.yaml. Неправильный tag намеренно создаёт ErrImagePull, а затем ImagePullBackOff.
apiVersion: v1
kind: Pod
metadata: {name: broken-image, namespace: lab-pods}
spec:
containers: [{name: web, image: "nginx:does-not-exist"}]Команда wait ожидаемо завершится по timeout. Соберите reason и Warning Events до исправления image.
kubectl apply -f pod-broken-image.yaml
kubectl wait -n lab-pods --for=condition=Ready pod/broken-image --timeout=30s
kubectl describe pod broken-image -n lab-pods
kubectl events -n lab-pods --for pod/broken-image --types=Warning
kubectl set image pod/broken-image web=nginx:1.28-alpine -n lab-pods
kubectl wait -n lab-pods --for=condition=Ready pod/broken-image --timeout=120s
kubectl delete namespace lab-podsАлгоритм: context и namespace → Pod Conditions → containerStatuses.state.waiting.reason → Events → проверка image и доступа к registry → минимальное исправление.
9. Контроль и шпаргалка
- Почему Running не означает Ready?
- Что переживает перезапуск контейнера, но не удаление Pod?
- Чем restart отличается от replacement?
- Когда доступен logs --previous?
- Почему preStop не заменяет обработку SIGTERM?
Модуль освоен, если вы определяете состояние каждого контейнера без догадок, объясняете новый UID после замены и восстанавливаете Pod из ImagePullBackOff на основании evidence.
PDF для работы офлайн
Скачайте оформленную версию модуля для чтения без подключения к сети.