Модуль 2.1: Поглиблене вивчення Pod'ів
Складність:
[СЕРЕДНЯ]— фундамент для всіх робочих навантаженьЧас на проходження: 40-50 хвилин
Передумови: Модуль 1.1 (Площина управління), Модуль 0.2 (Майстерність роботи з оболонкою)
Що ви зможете зробити
Розділ «Що ви зможете зробити»Після цього модуля ви зможете:
- Створювати Pod’и імперативно та декларативно із запитами ресурсів, пробами та контекстами безпеки
- Діагностувати збої Pod’ів системно для станів
Pending,ImagePullBackOff,CrashLoopBackOff, збоїв готовності таOOMKilled - Налаштовувати проби liveness, readiness та startup для застосунків із різною поведінкою запуску та залежностей
- Проєктувати багатоконтейнерні Pod’и, які доречно використовують init-контейнери, sidecar’и, спільні томи та спільну мережу
- Оцінювати політики перезапуску, фази життєвого циклу та поведінку завершення під час вибору способу відновлення робочого навантаження
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Гіпотетичний сценарій: ваша команда розгортає невеликий API за Сервісом, Деплоймент повідомляє, що розгортання завершилося, але користувачі все одно час від часу отримують збої з’єднання. kubectl get pods показує одні Pod’и як Running, деякі як CrashLoopBackOff, а один — як Running із готовністю 0/1. Виправлення полягає не в тому, щоб запам’ятати якусь одну команду; виправлення полягає в тому, щоб читати Pod як набір рішень планувальника, станів контейнерів, проб, подій, логів, мережевої поведінки та правил завершення, доки накопичені докази не вкажуть на справжню несправність.
Pod’и — це атомарна одиниця розгортання в Kubernetes. Кожен контейнер, який ви запускаєте, живе всередині Pod’а, і кожен Deployment, StatefulSet, DaemonSet та Job створює Pod’и як об’єкти виконання, що приземляються на ноди. Якщо Pod’и здаються незрозумілими, робочі навантаження вищого рівня стають оманливими, тому що контролер може виглядати справним, тоді як Pod під ним не запланований, тягне неправильний образ, не проходить пробу, працює без трафіку або перезапускається швидше, ніж застосунок встигає записати корисні логи.
Цей модуль розглядає Pod’и як операційний об’єкт, а не як форму YAML для копіювання. Ви будете швидко створювати Pod’и, перетворювати імперативні команди на маніфести, додавати межі безпеки та ресурсів, міркувати про життєвий цикл від init-контейнерів до коректного завершення та усувати поширені режими збоїв, які ви побачите на іспиті CKA та у звичайній роботі з кластером. Зрештою kubectl get pod, kubectl describe pod, kubectl logs та kubectl exec мають відчуватися як зв’язаний робочий процес, а не як чотири не пов’язані між собою команди.
Уявіть Pod як квартиру. Контейнери — це сусіди, що живуть разом у спільній квартирі: вони мають спільну адресу, той самий мережевий простір імен і, за бажання, спільне сховище, але кожен із них усе ще має власний процес та власне бачення файлової системи. Коли квартиру прибирають, усі сусіди залишають її разом; а коли один сусід уже слухає певний порт, інший сусід не може зайняти той самий порт усередині тієї ж квартири, бо мережева адреса в них спільна.
Основи Pod’ів: що Kubernetes насправді планує
Розділ «Основи Pod’ів: що Kubernetes насправді планує»Pod — це найменша придатна для розгортання одиниця в Kubernetes, але це визначення стає по-справжньому корисним лише тоді, коли ви пов’язуєте його з поведінкою планувальника та з поведінкою під час збоїв. Планувальник не розміщує окремий процес Linux на ноді; натомість він розміщує специфікацію Pod’а, а kubelet на цій ноді просить середовище виконання контейнерів створити ті контейнери, які описані в цій специфікації. Це означає, що ємність ноди, дозволи на завантаження образу, успіх init-контейнерів, проби, правила перезапуску та політика завершення — усе сходиться на межі Pod’а.
Практичний наслідок полягає в тому, що Pod є водночас обгорткою навколо контейнерів і контрактом із кластером. Специфікація каже, що має існувати, статус каже, що сталося, коли Kubernetes намагався втілити це існування, а розділ Events пояснює нещодавні рішення площини управління та kubelet. Сильна звичка налагодження Pod’ів починається з окремого читання цих трьох шарів замість того, щоб сприймати видимий стовпець STATUS як усю історію.
┌────────────────────────────────────────────────────────────────┐│ Pod ││ ││ ┌─────────────────┐ ┌─────────────────┐ ││ │ Container 1 │ │ Container 2 │ ││ │ (main app) │ │ (sidecar) │ ││ │ │ │ │ ││ │ Port 8080 │ │ Port 9090 │ ││ └─────────────────┘ └─────────────────┘ ││ │ │ ││ └──────────┬───────────┘ ││ │ ││ Shared Network Namespace ││ • Same IP address ││ • localhost communication ││ • Shared ports (can't conflict) ││ ││ Shared Volumes (optional) ││ • Mount same volume ││ • Share data between containers ││ │└────────────────────────────────────────────────────────────────┘Спільний мережевий простір імен — це особливість, яка найчастіше дивує нових операторів. Два контейнери в одному Pod’і спілкуються через localhost, але вони також конкурують за ті самі номери портів, тому що мають спільну IP-адресу Pod’а. Якщо основний застосунок слухає 8080, допоміжний контейнер у тому ж Pod’і має використовувати інший порт, тоді як інший Pod на тій самій ноді теж може слухати 8080, бо отримує іншу IP-адресу Pod’а.
| Аспект | Контейнер | Pod |
|---|---|---|
| Одиниця | Один процес | Група контейнерів |
| Мережа | Власний мережевий простір імен | Спільний мережевий простір імен |
| IP-адреса | Немає (використовує адресу Pod’а) | Одна на Pod |
| Сховище | Власна файлова система | Може мати спільні томи |
| Життєвий цикл | Керується Pod’ом | Керується Kubernetes |
Зробіть паузу й передбачте: два контейнери в одному Pod’і обидва намагаються слухати порт 8080. Що ви очікуєте побачити в логах другого контейнера, і чим відрізнявся б результат, якби ці контейнери були в окремих Pod’ах? Зробіть передбачення, перш ніж читати далі, бо саме ця ментальна модель запобігає багатьом заплутаним збоям sidecar’ів.
Pod’и існують тому, що деякі контейнери надто тісно пов’язані, щоб запускатися як окремі робочі навантаження. Збирач логів, який читає файли основного застосунку, проксі сервісної мережі, який має стояти поруч із застосунком, та init-контейнер, який готує конфігурацію перед запуском, — усе це приклади, де зв’язаність планувальника та життєвого циклу корисна. Компроміс полягає в тому, що зв’язаність також усуває незалежне масштабування, тож помічник, який потребує власного темпу розгортання чи кількості реплік, зазвичай має стати окремим робочим навантаженням.
Pod ефемерний за задумом, тому ви не повинні сприймати його ім’я, IP чи локальну файлову систему як стабільну інфраструктуру. Замінний Pod може запуститися на іншій ноді з іншим IP, а том emptyDir зникає, коли Pod прибирають. Контролери та Сервіси забезпечують стабільну поведінку на рівні над Pod’ами, але коли саме Pod дає збій, ви все одно діагностуєте сам Pod, бо це той об’єкт, що надає прямі та безпосередні докази.
Є ще одна тонка причина, чому Pod’и є правильним рівнем абстракції: вони дають змогу Kubernetes ухвалювати рішення про розміщення, використовуючи сукупну форму контейнерів, які мають працювати разом. Якщо основний контейнер потребує 200m CPU, а sidecar — 50m, слід Pod’а для планування дорівнює сумі цих запитів. Це не дає Kubernetes розмістити помічника там, де основний застосунок не може працювати, а також означає, що завеликий sidecar може заблокувати планування всього Pod’а навіть тоді, коли сам застосунок виглядає невеликим.
Межа Pod’а також визначає, як Kubernetes звітує про готовність. Pod із двома звичайними контейнерами не є повністю готовим, доки не будуть готові всі контейнери, що беруть участь у готовності, тож тихий помічник може тримати весь Pod поза ендпоінтами Сервісу. Це зазвичай бажано, коли помічник є необхідним, наприклад проксі-sidecar, але дивує, коли помічник опціональний. Якщо готовність не повинна залежати від помічника, перевірте, чи належить цей помічник до того самого Pod’а, чи його пробу слід налаштувати інакше.
Вам також слід відокремлювати ідентичність Pod’а від ідентичності застосунку. Ім’я Pod’а — корисний інструмент для налагодження, але це не довговічна адреса для клієнтів, а IP Pod’а не є стабільним ендпоінтом, який можна вшити в конфігурацію. Мітки, селектори та Сервіси утворюють стабільний шар, обернений до застосунку, над Pod’ами. Цей модуль залишається на рівні Pod’а, бо вам потрібен цей фундамент, перш ніж наступний модуль покаже, як Деплойменти та ReplicaSet’и утримують замінні Pod’и узгодженими з бажаною кількістю реплік.
Швидке створення Pod’ів без втрати контролю
Розділ «Швидке створення Pod’ів без втрати контролю»Найшвидший надійний робочий процес — згенерувати коректну вихідну точку, а потім відредагувати поля, які мають значення. Під час іспиту CKA kubectl run із --dry-run=client -o yaml дає вам коректну структуру Kubernetes без потреби пам’ятати кожне поле напам’ять. У роботі виробничого типу та сама звичка допомагає уникнути налагодження через одруківки, бо ви починаєте з форми об’єкта, створеної інструментами Kubernetes, а потім переглядаєте отриманий маніфест перед застосуванням.
# Create a simple podkubectl run nginx --image=nginx
# Create pod and expose portkubectl run nginx --image=nginx --port=80
# Create pod with labelskubectl run nginx --image=nginx --labels="app=web,env=prod"
# Create pod with environment variableskubectl run nginx --image=nginx --env="ENV=production"
# Resource requests/limits cannot be patched onto a running bare pod — its# resources are immutable. Set them in the pod spec at creation time (see the# YAML workflow below).
# Generate YAML without creating (essential for exam!)kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yamlІмперативні команди чудові для швидкості, але вони не замінюють розуміння маніфесту. Згенерований Pod без запитів ресурсів може заплануватися в слабко завантаженому тестовому кластері й не вміститися в обмеженому кластері, тоді як Pod, що використовує nginx без тегу, може пізніше завантажити інший образ, ніж той, із яким ви тренувалися. Сприймайте імперативне створення як генератор шаблонів та інструмент перевірки, а не як дозвіл припинити думати про специфікацію.
apiVersion: v1kind: Podmetadata: name: nginx labels: app: nginx env: productionspec: containers: - name: nginx image: nginx:1.25 ports: - containerPort: 80 resources: requests: memory: "64Mi" cpu: "100m" limits: memory: "128Mi" cpu: "200m"Декларативний маніфест показує операційний контракт чіткіше, ніж команда. Мітки роблять Pod вибірним для Сервісів та інших інструментів, тег образу робить поведінку під час виконання більш відтворюваною, а запити ресурсів повідомляють планувальнику, яка ємність має бути доступна, перш ніж Pod зможе приземлитися. Ліміти додають захисний бар’єр після того, як Pod стартує, але вони не замінюють запитів, бо рішення планувальника ухвалюються до того, як контейнер споживе пам’ять чи CPU.
# Apply the podkubectl apply -f pod.yamlКоли ви обслуговуєте Pod, використовуйте команди, які розкривають різні шари стану. kubectl get відповідає, чи має Kubernetes поточний об’єкт і який високорівневий статус він повідомляє, kubectl describe поєднує вибрані поля специфікації зі статусом та подіями, а kubectl get -o yaml показує повний об’єкт API. Видалення також є частиною життєвого циклу; звичайне видалення дає робочому навантаженню час на завершення роботи, тоді як примусове видалення — це інструмент усунення несправностей, який може приховати помилки завершення застосунку, якщо застосовувати його легковажно.
# List podskubectl get podskubectl get pods -o wide # Show IP and nodekubectl get pods --show-labels # Show labels
# Describe pod (detailed info)kubectl describe pod nginx
# Get pod YAMLkubectl get pod nginx -o yaml
# Delete podkubectl delete pod nginx
# Delete pod immediately (skip graceful shutdown)kubectl delete pod nginx --grace-period=0 --force
# Watch podskubectl get pods -wКонтекст безпеки — ще одне поле, яке належить до першого уроку про Pod’и, бо воно змінює те, що контейнеру дозволено робити після запуску. Pod може визначати типові значення, як-от runAsUser та fsGroup, тоді як окремий контейнер може посилити налаштування, як-от ескалацію привілеїв та файлову систему кореня з правом запису. Ці налаштування самі по собі не роблять вразливий образ безпечним, але вони зменшують шкоду, яку процес може заподіяти, коли образ чи застосунок поводяться неправильно.
apiVersion: v1kind: Podmetadata: name: sec-ctx-demospec: securityContext: runAsUser: 1000 fsGroup: 2000 containers: - name: myapp image: busybox command: [ "sh", "-c", "sleep 1h" ] securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: trueПерш ніж запустити це, який результат ви очікуєте від kubectl describe pod sec-ctx-demo, якщо образ стартує успішно, але застосунок намагається писати під /? Важливий крок міркування — відокремити запуск контейнера від поведінки застосунку: Kubernetes може коректно запустити контейнер, проте процес усе одно може дати збій, бо контекст безпеки навмисно забороняє небезпечний запис у файлову систему.
Налаштування ресурсів заслуговують на таке саме уважне читання, як і налаштування безпеки. Запит — це обіцянка планувальника: Kubernetes намагається розмістити Pod лише на ноді, яка може задовольнити запитані CPU та пам’ять. Ліміт — це межа під час виконання: контейнер може бути обмежений у CPU або вбитий за пам’ять, якщо перевищить налаштовану стелю. Багато заплутаних збоїв Pod’ів починаються, коли команди задають ліміти, не розуміючи нормального пікового споживання пам’яті, а потім тлумачать CrashLoopBackOff як помилку застосунку, навіть якщо попередній стан каже OOMKilled.
Для роботи на іспиті призвичайтеся генерувати YAML, редагувати лише потрібні поля, а потім перевіряти форму об’єкта перед застосуванням. kubectl apply --dry-run=server корисний, коли доступний, бо просить сервер API перевірити об’єкт, не зберігаючи його, тоді як kubectl diff може показати, що змінилося б для наявного об’єкта. Ці команди не є магією, але вони сповільнюють саме той клас помилок, що походять від поспішних відступів та неправильного розташування полів.
Належний обсяг YAML для Pod’а залежить від завдання. Одноразовий діагностичний Pod може бути навмисно невеликим, бо він одноразовий і створений, щоб відповісти на вузьке запитання. Pod робочого навантаження, який представляє справжній сервіс, має містити мітки, закріплений образ, ресурси, проби та позицію безпеки, що відповідає середовищу. Різниця — не церемонія; це питання того, чи зможе майбутній оператор зрозуміти намір із маніфесту замість реверс-інженерії його з поведінки кластера.
Життєвий цикл, статус і завершення
Розділ «Життєвий цикл, статус і завершення»Мова життєвого циклу Pod’а є точною, але kubectl get pods стискає кілька шарів в одну таблицю. Фаза Pod’а, як-от Pending чи Running, описує широкий стан життєвого циклу, тоді як стани контейнерів, як-от Waiting, Running та Terminated, описують окремі контейнери всередині Pod’а. Видимий стовпець STATUS може показувати причину очікування на кшталт ImagePullBackOff чи CrashLoopBackOff, тож завжди підтверджуйте деталі через describe, коли статус є частиною діагнозу.
| Фаза | Опис |
|---|---|
| Pending | Pod прийнято, очікує на планування або завантаження образів |
| Running | Pod прив’язано до ноди, принаймні один контейнер працює |
| Succeeded | Усі контейнери завершилися успішно (exit 0) |
| Failed | Усі контейнери завершилися, принаймні один із помилкою |
| Unknown | Стан Pod’а неможливо визначити (проблема зв’язку з нодою) |
| Стан | Опис |
|---|---|
| Waiting | Ще не працює (завантаження образу, застосування секретів) |
| Running | Виконується без проблем |
| Terminated | Завершив виконання (успішно або з помилкою) |
Таблиця фаз корисна, але шлях переходів важливіший під час усунення несправностей. Pending до планування зазвичай указує на ресурси, селектори нод, affinity, taints чи брак ємності для планування. Pending після планування все ще може стосуватися завантаження образів або налаштування контейнерів, а Running не доводить готовності, бо контейнер може бути живим, поки readiness-проба тримає його поза ендпоінтами Сервісу.
┌────────────────────────────────────────────────────────────────┐│ Pod Lifecycle ││ ││ Pod Created ││ │ ││ ▼ ││ ┌─────────┐ No node available ││ │ Pending │◄────────────────────────────────┐ ││ └────┬────┘ │ ││ │ Scheduled to node │ ││ ▼ │ ││ ┌─────────┐ Container crashes │ ││ │ Running │────────────────────────────────►│ ││ └────┬────┘ │ ││ │ │ ││ ├─────────────────────┐ │ ││ │ │ │ ││ ▼ ▼ │ ││ ┌───────────┐ ┌────────┐ │ ││ │ Succeeded │ │ Failed │ │ ││ │ (exit 0) │ │(exit≠0)│ │ ││ └───────────┘ └────────┘ │ ││ │└────────────────────────────────────────────────────────────────┘Найшвидші перевірки статусу мають стати м’язовою пам’яттю, бо вони відповідають на різні запитання. Звичайний get повідомляє сукупну готовність та лічильник перезапусків, describe показує події та вибрані деталі життєвого циклу, а JSONPath дає змогу витягнути саме те поле, яке вам потрібне, коли вивідна таблиця надто стиснута. Під час іспиту ці команди також заощаджують час, бо ви можете вирішити, що перевіряти далі: планування, завантаження образів, проби чи логи застосунку.
# Quick statuskubectl get pod nginx# NAME READY STATUS RESTARTS AGE# nginx 1/1 Running 0 5m
# Detailed statuskubectl describe pod nginx | grep -A10 "Status:"
# Container stateskubectl get pod nginx -o jsonpath='{.status.containerStatuses[0].state}'
# Check why a pod is pendingkubectl describe pod nginx | grep -A5 "Events:"Завершення є частиною життєвого циклу, а не запізнілою думкою. Коли ви видаляєте Pod, Kubernetes позначає його на видалення, прибирає готові ендпоінти зі звичайного трафіку Сервісу, надсилає SIGTERM контейнерам, чекає період пільгового завершення й зрештою надсилає SIGKILL, якщо процес не завершується. Типовий пільговий період — 30 секунд, що достатньо щедро для багатьох невеликих сервісів, але все ще достатньо коротко, щоб застосунки навмисно обробляли SIGTERM.
Ви можете перевизначити пільговий період під час видалення за допомогою kubectl delete pod nginx --grace-period=5, але це має бути свідомим вибором. Короткі пільгові періоди корисні для застряглих тестових Pod’ів та термінового прибирання, тоді як звичайним Pod’ам застосунку потрібно достатньо часу, щоб припинити приймати роботу, завершити запити в процесі, скинути логи та закрити з’єднання. Якщо користувачі бачать помилки під час розгортань, надто короткий або проігнорований шлях завершення є так само ймовірним, як поганий образ чи зламана readiness-проба.
apiVersion: v1kind: Podmetadata: name: restart-demospec: restartPolicy: OnFailure # Only restart if container fails containers: - name: worker image: busybox command: ["sh", "-c", "exit 1"] # Will be restartedПолітика перезапуску керує тим, що kubelet робить після завершення контейнера, і вона має відповідати формі робочого навантаження. Always — це типове значення для довготривалих сервісів, OnFailure пасує роботі до завершення, яка має повторювати ненульові виходи, а Never корисний, коли ви хочете зберегти збій для огляду. Для керованих робочих навантажень пам’ятайте, що контролери можуть створювати замінні Pod’и навіть тоді, коли окремий Pod має політику, яка не перезапускає завершений контейнер.
| Політика | Поведінка | Випадок використання |
|---|---|---|
Always (типова) | Перезапуск за будь-якого завершення | Довготривалі сервіси |
OnFailure | Перезапуск лише за ненульового виходу | Завдання, які мають повторюватися при збої |
Never | Ніколи не перезапускати | Одноразові скрипти, налагодження |
# Check restart countkubectl get pods# NAME READY STATUS RESTARTS AGE# nginx 1/1 Running 3 10m
# Describe shows restart detailskubectl describe pod nginx | grep -A5 "Last State"Зробіть паузу й передбачте: Pod із restartPolicy: Always має контейнер, що завершується з кодом 0, тоді як інший Pod із restartPolicy: OnFailure завершується з тим самим кодом. Який із них перезапуститься, і що ви очікуєте побачити в RESTARTS через кілька хвилин? Правильна відповідь показує, що ви читаєте політику, код виходу та намір робочого навантаження разом.
Діагностика життєвого циклу стає легшою, коли ви розрізняєте «об’єкт Pod існує» та «робоче навантаження обслуговує». Pod може існувати в API ще до того, як отримає ноду, бути призначеним на ноду до того, як його образ стане доступним, запустити контейнер до того, як застосунок завантажить конфігурацію, та повідомити Running до того, як готовність дозволить трафік. Кожен етап має іншого власника: планувальник, kubelet, середовище виконання контейнерів, реєстр образів, процес застосунку та налаштування проб — усі залишають докази в різних місцях.
Стовпець RESTARTS — це лічильник, а не першопричина. Лічильник перезапусків 0 усе ще може приховувати Pod, який ніколи не планувався, а високий лічильник перезапусків не каже вам, чи причина — погана команда, відсутній файл, невдала liveness-проба чи тиск на пам’ять. Поєднуйте лічильник із Last State, кодом виходу, подіями та попередніми логами. Коли ці джерела узгоджуються, ви можете виправити причину замість того, щоб сприймати сам перезапуск як проблему.
Коректне завершення також є частиною проєктування доступності. Під час видалення чи розгортання застосунок, який швидко припиняє приймати нову роботу та чисто завершує роботу в процесі, може зникнути з ендпоінтів із малим впливом на користувачів. Застосунок, який ігнорує SIGTERM чи продовжує оголошувати готовність під час завершення роботи, може створювати помилки, навіть якщо Pod зрештою завершується успішно. Тому поведінку готовності та обробку завершення слід тестувати разом, а не лише під час екстреного прибирання.
Налагодження Pod’ів від симптому до доказу
Розділ «Налагодження Pod’ів від симптому до доказу»Налагодження Pod’ів — це процес звуження. Почніть із видимого симптому, виберіть команду, що розкриває наступний шар, і не змінюйте об’єкт, доки не зрозумієте, чому він дав збій. Якщо ви залатаєте образ, видалите Pod чи розширите ліміт ресурсів надто рано, ви можете стерти докази, що відрізнили б проблему реєстру від проблеми планування або збій застосунку від перезапуску, спричиненого пробою.
Pod Problem │ ├── kubectl get pods (check STATUS) │ │ │ ├── Pending → kubectl describe (check Events) │ │ └── ImagePullBackOff, Insufficient resources, etc. │ │ │ ├── CrashLoopBackOff → kubectl logs (check app errors) │ │ └── Application crash, missing config, etc. │ │ │ └── Running but not working → kubectl exec (check inside) │ └── Network issues, wrong config, etc. │ └── kubectl describe pod (always useful)Розділ Events — це місце, де Kubernetes каже вам, що він нещодавно намагався зробити. Збій планування може згадати недостатність CPU, нестерпні taints, невідповідність node affinity чи проблему під’єднання тома. Збій образу може показати спроби завантаження, помилки автентифікації чи відсутній тег. Події не є постійними логами, тож їх найкраще використовувати рано, а потім поєднувати зі статусом Pod’а та логами застосунку.
# The trinity of debuggingkubectl get pod nginx # What's the status?kubectl describe pod nginx # What's happening? (events)kubectl logs nginx # What does the app say?
# Deeper investigationkubectl exec -it nginx -- /bin/sh # Get insidekubectl get events --sort-by='.lastTimestamp' # Recent eventskubectl top pod nginx # Resource usage (if metrics-server)Логи відповідають на інше запитання, ніж події: що сказав застосунок чи точка входу контейнера? Для Pod’а, що перезапускається, найважливішим прапорцем часто є --previous, бо поточний екземпляр контейнера може бути надто новим, щоб містити вивід збою. У багатоконтейнерних Pod’ах завжди вказуйте -c, коли неоднозначність має значення; інакше ви можете оглядати тихий sidecar, тоді як основний застосунок дає збій.
# Current logskubectl logs nginx
# Follow logs (like tail -f)kubectl logs nginx -f
# Last 100 lineskubectl logs nginx --tail=100
# Logs from last hourkubectl logs nginx --since=1h
# Logs from specific container (multi-container pod)kubectl logs nginx -c sidecar
# Previous container logs (after crash)kubectl logs nginx --previouskubectl exec призначений для огляду контейнера, що працює, а не для доведення того, що Pod справний. Він допомагає, коли Pod працює, але поведінка неправильна: файл конфігурації не змонтовано, не вдається розв’язання DNS, бракує змінної середовища процесу чи sidecar не може дістатися основного застосунку через localhost. Якщо контейнер падає надто швидко, щоб увійти до нього через exec, використовуйте логи, попередні логи, події чи ефемерний підхід до налагодження в наступних модулях усунення несправностей замість того, щоб змагатися з циклом перезапуску.
# Run a commandkubectl exec nginx -- ls /
# Interactive shell (/bin/sh works on minimal images; many images lack bash)kubectl exec -it nginx -- /bin/sh
# Specific container in multi-container podkubectl exec -it nginx -c sidecar -- /bin/sh
# Run commands without shellkubectl exec nginx -- cat /etc/nginx/nginx.confkubectl exec nginx -- envkubectl exec nginx -- ps aux| Симптом | Причина | Розв’язання |
|---|---|---|
ImagePullBackOff | Неправильне ім’я образу або немає доступу | Виправте ім’я образу, перевірте автентифікацію реєстру |
CrashLoopBackOff | Контейнер постійно падає | Перевірте логи на помилки застосунку |
Pending (немає подій) | Жодна нода не має достатньо ресурсів | Звільніть ресурси або додайте ноди |
Pending (планування) | Taints, правила affinity | Перевірте taints нод та tolerations Pod’а |
Running, але не готовий | Невдала readiness-проба | Перевірте налаштування проби та застосунок |
OOMKilled | Брак пам’яті | Збільште ліміти пам’яті |
Гіпотетичний сценарій: Pod показує Running, але Сервіс не надсилає до нього трафіку, а лог застосунку виглядає нормально. Спокуслива дія — увійти через exec у контейнер і протестувати застосунок вручну, але першою корисною підказкою зазвичай є стовпець READY та події readiness-проби в kubectl describe pod. Контейнер може бути живим і все одно виключеним з ендпоінтів, бо готовність — це сигнал маршрутизації, а не сигнал про живість процесу.
Який підхід ви б обрали тут і чому: збільшити тайм-аут liveness-проби, прибрати readiness-пробу чи спочатку перевірити шлях залежностей ендпоінта готовності? Найкраща відповідь залежить від доказів, але вам слід бути обережними щодо проб, які викликають зовнішні залежності з liveness. Збій бази даних зазвичай має зупиняти новий трафік через readiness, а не змушувати застосунок до повторних перезапусків.
Корисна послідовність налагодження — запитати: «Чи могла б ця команда взагалі відповісти на моє поточне запитання?» Якщо Pod не запланований, kubectl exec не допоможе, бо немає контейнера, до якого можна увійти. Якщо образ не вдається завантажити, логи застосунку не допоможуть, бо процес ніколи не стартував. Якщо Pod працює, але не готовий, логи можуть допомогти, але події проб та стан ендпоінтів зазвичай прямолінійніші. Ця маленька дисципліна заощаджує час під тиском іспиту й запобігає руйнівним здогадкам у реальних кластерах.
Коли події згадують недостатність ресурсів, не видаляйте одразу випадкові Pod’и, щоб звільнити місце. Спершу огляньте запитані ресурси на Pod’і, що дає збій, та доступну ємність на кандидатах-нодах, бо планувальник використовує запити, а не поточне споживання, для розміщення. Нода може виглядати тихою в миттєвому перегляді метрик і все одно бути недоступною для планування, якщо її запитану ємність уже зайнято. Ця відмінність стає важливою, коли команди надмірно запитують пам’ять чи копіюють ліміти в запити без вимірювання.
Коли логи порожні, розширте мислення замість того, щоб припускати збій системи логування. Контейнер може завершуватися до того, як застосунок ініціалізує логування, точка входу може бути неправильною, образу може бракувати очікуваної оболонки, чи контекст безпеки може блокувати запис у файлову систему, потрібний під час запуску. describe може показати команду, образ, стан та події, тоді як get pod -o yaml розкриває розв’язану специфікацію. Разом вони часто виявляють невідповідність між маніфестом, який ви мали намір створити, та контейнером, що насправді запустився.
Для багатоконтейнерних Pod’ів завжди називайте контейнер, який ви оглядаєте, коли симптом стосується конкретного процесу. Sidecar може бути справним, поки основний застосунок падає, а основний застосунок може бути справним, поки проксі-sidecar блокує трафік. Лічильник READY каже вам, скільки контейнерів готові, але стан кожного контейнера в describe каже, який саме очікує, завершений чи перезапускається. Цей поконтейнерний перегляд — різниця між швидким виправленням та оманливим сукупним статусом.
Багатоконтейнерні Pod’и, init-контейнери та спільні томи
Розділ «Багатоконтейнерні Pod’и, init-контейнери та спільні томи»Багатоконтейнерні Pod’и потужні, бо вони роблять тісну зв’язаність явною. Контейнери в одному Pod’і плануються разом, мають спільну IP-адресу Pod’а, можуть спілкуватися через localhost та можуть монтувати ті самі томи. Це ідеально для помічників, які безглузді без основного застосунку, але погано пасує незалежно масштабованим сервісам, бо Pod є одиницею масштабування.
┌────────────────────────────────────────────────────────────────┐│ Multi-Container Patterns ││ ││ Sidecar Ambassador Adapter ││ ┌──────────────────┐ ┌──────────────────┐ ┌─────────┐ ││ │ ┌────┐ ┌────┐ │ │ ┌────┐ ┌────┐ │ │┌────┐ │ ││ │ │Main│ │Log │ │ │ │Main│ │Proxy│ │ ││Main│ │ ││ │ │App │──│Ship│ │ │ │App │──│ │──┼──││App │ │ ││ │ └────┘ └────┘ │ │ └────┘ └────┘ │ │└──┬─┘ │ ││ │ Main + Helper │ │ Proxy outbound │ │ │ │ ││ └──────────────────┘ └──────────────────┘ │┌──▼──┐ │ ││ ││Adapt│ │ ││ Examples: Examples: ││Log │ │ ││ - Log collectors - Service mesh proxy │└─────┘ │ ││ - Config reloaders - Database proxy │Transform│ ││ - Git sync - Auth proxy └─────────┘ ││ │└────────────────────────────────────────────────────────────────┘Патерн sidecar тримає помічника поруч із основним застосунком на весь час життя Pod’а. Збирач логів, який читає логи застосунку зі спільного тома, є класичним прикладом, але той самий патерн з’являється в проксі, оновлювачах сертифікатів та перезавантажувачах конфігурації. Дизайн працює, коли помічника й основний застосунок слід створювати, переміщувати, перезапускати та видаляти як одне ціле.
apiVersion: v1kind: Podmetadata: name: web-with-sidecarspec: containers: # Main application container - name: web image: nginx ports: - containerPort: 80 volumeMounts: - name: logs mountPath: /var/log/nginx
# Sidecar container - ships logs - name: log-shipper image: busybox command: ["sh", "-c", "tail -F /var/log/nginx/access.log"] volumeMounts: - name: logs mountPath: /var/log/nginx
volumes: - name: logs emptyDir: {}Спільний том emptyDir у цьому Pod’і створюється, коли Pod призначається на ноду, і прибирається, коли Pod зникає. Це робить його корисним для тимчасової координації між контейнерами, як-от згенерованих файлів, відрендереної конфігурації чи логів, які споживає sidecar. Це не довговічне сховище, тож якщо вам потрібно, щоб дані пережили заміну Pod’а, вам слід перейти до патерну на основі PersistentVolume у пізнішому модулі про сховище.
Init-контейнери розв’язують іншу проблему: впорядкований запуск. Вони працюють перед контейнерами застосунку, працюють послідовно, і кожен має успішно завершитися, перш ніж стартує наступний init-контейнер чи будь-який звичайний контейнер. Це правильний інструмент для підготовки файлів, очікування на залежність чи виконання одноразового кроку налаштування, який не повинен залишатися працювати поруч із застосунком.
apiVersion: v1kind: Podmetadata: name: init-demospec: # Init containers run first, in order initContainers: - name: wait-for-db image: busybox command: ['sh', '-c', 'until nc -z db-service 5432; do echo waiting for db; sleep 2; done']
- name: init-config image: busybox command: ['sh', '-c', 'echo "config initialized" > /config/ready'] volumeMounts: - name: config mountPath: /config
# App containers start after all init containers succeed containers: - name: app image: myapp volumeMounts: - name: config mountPath: /config
volumes: - name: config emptyDir: {}| Випадок використання | Приклад |
|---|---|
| Очікування на залежність | Зачекати на готовність бази даних |
| Налаштування конфігурації | Клонувати git-репозиторій, згенерувати конфігурацію |
| Міграції бази даних | Виконати міграції перед запуском застосунку |
| Реєстрація в сервісі | Зареєструвати екземпляр у зовнішній системі |
| Завантаження ресурсів | Отримати статичні файли з S3 |
Зупиніться й подумайте: вашому вебзастосунку потрібен файл конфігурації, згенерований із шаблону перед запуском застосунку, а також потрібен помічник для відправлення логів на весь час роботи. Який патерн контейнера обслуговує кожну вимогу, і чи можуть обидва патерни з’явитися в одному Pod’і? Відповідь — так: використайте init-контейнер для завершеної роботи з налаштування та sidecar для довготривалого помічника.
Коли init-контейнер дає збій, контейнери застосунку не стартують. За типової поведінки перезапуску для Pod’ів, керованих як сервіси, kubelet повторює послідовність init, і ви побачите Pod, застряглий у стані очікування, пов’язаному з init, доки крок init не успішний або доки ви не зміните специфікацію. Це робить init-контейнери корисним захисним бар’єром для передумов, але також означає, що крихка перевірка залежностей може завадити навіть запуститися здоровому коду застосунку.
Init-контейнери мають виконувати роботу, яку безпечно повторювати. Оскільки Kubernetes може повторити їх після збою, init-контейнер, що виконує міграцію, записує зовнішній стан чи реєструється у віддаленій системі, має бути ідемпотентним або захищеним зовнішньою системою. Простий init-контейнер для рендерингу файлів природно повторюваний; міграція бази даних може потребувати інструментарію міграцій на рівні застосунку, який фіксує застосовані версії. Якщо крок налаштування не витримує повторень, він, імовірно, потребує більш явного Job чи процесу релізу.
Sidecar’и мають протилежну проблему тривалості життя. Вони продовжують працювати поруч із основним застосунком, тож мають бути достатньо дешевими, щоб існувати на кожну репліку Pod’а, та достатньо надійними, щоб не тримати Pod у заручниках. Збирач логів, який споживає забагато пам’яті, може спричинити вбивство Pod’а, навіть якщо основний застосунок ефективний, а проксі-sidecar із невдалою readiness-перевіркою може прибрати застосунок із трафіку. Помічник є частиною слід-навантаження робочого навантаження, а не безкоштовним аксесуаром.
Спільні томи — це інструмент координації, а не протокол синхронізації. Якщо один контейнер записує файл, а інший читає його, вам усе одно потрібно міркувати про час, часткові записи, дозволи та прибирання. Init-контейнери уникають багатьох проблем із часом, бо завершуються до того, як стартують контейнери застосунку, тоді як sidecar’и вимагають, щоб основний застосунок обробляв файли, які змінюються під час роботи. Саме ця відмінність пояснює, чому той самий том emptyDir може бути безпечним у патерні init та крихким у довготривалому патерні «виробник-споживач».
Коли ви обираєте між одним Pod’ом із двома контейнерами та двома Pod’ами із Сервісом, запитайте, хто володіє збоєм. Якщо збій помічника означає, що екземпляр застосунку марний, тримайте їх разом і дайте Pod’у представляти цю спільну долю. Якщо помічник може давати збій незалежно, масштабуватися незалежно чи обслуговувати кілька екземплярів застосунку, виокремте його. Kubernetes дає вам обидва інструменти, і кращий дизайн — той, чия межа збою відповідає реальній системі.
Проби, готовність та здоров’я під час виконання
Розділ «Проби, готовність та здоров’я під час виконання»Kubernetes не може автоматично знати, чи корисний ваш процес, лише тому, що він працює. Процес вебсервера може бути живим, але в дедлоку, API може віддавати лише помилки, поки прогрівається кеш, а повільний застарілий застосунок може потребувати довгого вікна запуску, перш ніж звичайні перевірки здоров’я матимуть сенс. Проби дають змогу описати ці відмінності, щоб kubelet міг перезапускати справді нездорові контейнери, а Сервіси могли маршрутизувати трафік лише до готових Pod’ів.
| Проба | Призначення | Дія при збої | Коли використовувати |
|---|---|---|---|
| Startup | Перевіряє, чи застосунок успішно запустився | Перезапускає контейнер | Для застарілих застосунків із повільним стартом, яким потрібен додатковий час на ініціалізацію без провалу liveness-перевірок. |
| Liveness | Перевіряє, чи застосунок здоровий і працює | Перезапускає контейнер | Щоб відновитися після дедлоків чи збоїв застосунку, коли процес працює, але не відповідає. |
| Readiness | Перевіряє, чи застосунок готовий приймати трафік | Прибирає Pod з ендпоінтів Сервісу | Коли застосунок працює, але тимчасово не може обслуговувати трафік (наприклад, завантажує великі кеші, втрачено з’єднання з базою даних). |
Найважливіша відмінність проб — наслідок збою. Збій liveness перезапускає контейнер, тож вона має виявляти умови, які перезапуск може правдоподібно виправити, як-от застряглий процес. Збій readiness прибирає Pod зі звичайних ендпоінтів Сервісу, тож вона має виявляти, чи може застосунок приймати трафік просто зараз. Збій startup захищає повільні старти, вимикаючи перевірки liveness та readiness, доки запуск не успішний або доки не вичерпано бюджет запуску.
Проби можуть використовувати HTTP, TCP чи виконання команди, і механізм має відповідати сигналу, який вам насправді потрібен. HTTP-ендпоінт readiness може перевірити, чи завантажив застосунок конфігурацію та відкрив необхідні пули, тоді як проба TCP-сокета лише доводить, що щось приймає з’єднання на порту. Exec-проба гнучка, але вона виконується всередині контейнера й може стати дорогою чи крихкою, якщо кожні кілька секунд викликає повільні команди.
apiVersion: v1kind: Podmetadata: name: probe-demospec: containers: - name: myapp image: nginx ports: - containerPort: 80
# 1. Startup Probe: Wait up to 300 seconds (30 * 10) for slow start startupProbe: httpGet: path: / port: 80 failureThreshold: 30 periodSeconds: 10
# 2. Liveness Probe: Restart if deadlocked livenessProbe: exec: command: - cat - /usr/share/nginx/html/index.html initialDelaySeconds: 5 periodSeconds: 5
# 3. Readiness Probe: Stop sending traffic if backend disconnected readinessProbe: tcpSocket: port: 80 initialDelaySeconds: 5 periodSeconds: 10Зробіть паузу й передбачте: якщо liveness-проба Pod’а проходить, але його readiness-проба не проходить, що покаже kubectl get pods у стовпцях READY та STATUS, і чи буде Pod перезапущено? Очікуваний результат — Pod, який залишається Running, але не повністю готовий, наприклад 0/1, і kubelet не повинен перезапускати його лише тому, що не пройшла readiness.
Налаштування проб — це балансування, а не галочка. Надто короткі тайм-аути можуть перезапускати справні, але тимчасово повільні застосунки, тоді як надто поблажливі пороги можуть залишити мертві Pod’и під трафіком або застряглі контейнери, що працюють надто довго. Під час налагодження проблеми з пробою читайте поведінку ендпоінта, тайм-аут, поріг збоїв та період разом, бо саме ці чотири значення визначають справжній бюджет збоїв.
Гіпотетичний сценарій: під час навантажувального тесту база даних сповільнюється, а ендпоінт здоров’я застосунку чекає на запит до бази даних. Якщо цей ендпоінт використовується для liveness із тайм-аутом в одну секунду, Kubernetes може повторно перезапускати застосунок, додаючи більше холодних стартів і погіршуючи тиск на базу даних. Кращий дизайн зазвичай тримає liveness зосередженою на внутрішньому здоров’ї процесу та використовує readiness, щоб зупиняти новий трафік, коли залежності тимчасово недоступні.
Startup-проби особливо корисні для застосунків, що мають довгий, але виправданий шлях ініціалізації. Без startup-проби liveness може почати судити контейнер до того, як застосунок завантажив індекси, прогрів кеші чи завершив міграції запуску. Зі startup-пробою kubelet дає застосунку окремий бюджет запуску, перш ніж liveness стане активною. Це не означає, що застосунок може стартувати вічно; це означає, що бюджет збоїв запуску є явним та окремим від звичайного здоров’я під час виконання.
Readiness має бути достатньо консервативною, щоб захистити користувачів, але не настільки широкою, щоб кожен збій залежності виснажував усю ємність. Ендпоінт readiness, що перевіряє з’єднання з базою даних, може бути доречним для шляху запитів, який завжди потребує бази даних, тоді як сервіс із деградованою, але корисною поведінкою може надавати readiness-перевірку на основі ємності локальної черги чи критичної конфігурації. Урок про Pod полягає в тому, що Kubernetes слідуватиме сигналу, який ви надаєте, тож ендпоінт має представляти те рішення про трафік, якого ви насправді хочете.
Liveness має бути дешевою, локальною та змістовною. Якщо команда проби розгалужує важкий процес кожні кілька секунд, сама перевірка здоров’я може стати навантаженням. Якщо проба перевіряє лише те, що TCP-порт відкритий, вона може пропустити дедлок застосунку. Найкращий сигнал liveness — той, що відповідає на запитання «Чи застряг цей процес так, що перезапуск, імовірно, його полагодить?», а не «Чи може кожна низхідна залежність відповісти просто зараз?».
Коли проба не проходить, оглядайте і подію Kubernetes, і ендпоінт вручну з тієї ж перспективи, якщо можливо. HTTP-ендпоінт, що працює з вашого ноутбука, може не пройти з kubelet, бо прив’язується лише до localhost усередині контейнера, потребує заголовка Host, використовує неправильний шлях чи відповідає повільніше за налаштований тайм-аут. Подія каже вам, що kubelet визнав пробу невдалою; ручне тестування допомагає пояснити, чому застосунок повівся так під цим налаштуванням проби.
Мережа Pod’ів та пряма перевірка
Розділ «Мережа Pod’ів та пряма перевірка»Kubernetes дає кожному Pod’у власну IP-адресу, а контейнери всередині Pod’а мають спільний цей IP. Ця модель простіша за мислення через порти хоста, бо Pod’и можуть спілкуватися з іншими Pod’ами напряму, тоді як контейнери в одному Pod’і використовують localhost для трафіку всередині Pod’а. Компроміс полягає в тому, що IP-адреси Pod’ів ефемерні, тож прямий доступ між Pod’ами корисний для налагодження, але Сервіси є стабільною абстракцією для звичайного трафіку.
┌────────────────────────────────────────────────────────────────┐│ Pod Networking ││ ││ Every pod gets a unique IP address ││ Containers in pod share that IP ││ Pods can communicate with all other pods (no NAT) ││ ││ ┌───────────────────────┐ ┌───────────────────────┐ ││ │ Pod A (10.244.1.5) │ │ Pod B (10.244.2.8) │ ││ │ ┌─────┐ ┌─────┐ │ │ ┌─────┐ │ ││ │ │ C1 │ │ C2 │ │ │ │ C1 │ │ ││ │ │:80 │ │:9090│ │ │ │:8080│ │ ││ │ └──┬──┘ └──┬──┘ │ │ └──┬──┘ │ ││ │ │ │ │ │ │ │ ││ │ └────┬─────┘ │ │ │ │ ││ │ │ localhost │ │ │ │ ││ └─────────┼─────────────┘ └────┼─────────────────┘ ││ │ │ ││ └───────────────────────┘ ││ Can reach each other directly ││ 10.244.1.5:80 ←→ 10.244.2.8:8080 ││ │└────────────────────────────────────────────────────────────────┘Коли ви тестуєте мережу, чітко розумійте, який шлях ви тестуєте. Sidecar, що звертається curl до localhost:80, тестує комунікацію всередині Pod’а, окремий діагностичний Pod, що звертається curl до IP Pod’а, тестує досяжність мережі Pod’ів, а клієнт, що використовує ім’я Сервісу, тестує селектор, ендпоінт та поведінку kube-proxy чи площини даних. Це різні запитання, тож не дозволяйте одному успішному curl переконати вас, що весь шлях справний.
# Containers in same pod communicate via localhost# Container 1 (nginx on port 80)# Container 2 can reach it at localhost:80
# Example: curl from sidecar to main appkubectl exec -it pod-name -c sidecar -- curl localhost:80# Get pod IPkubectl get pod nginx -o wide# NAME READY STATUS IP NODE# nginx 1/1 Running 10.244.1.5 worker-1
# Get IP with jsonpathkubectl get pod nginx -o jsonpath='{.status.podIP}'
# Get all pod IPskubectl get pods -o custom-columns='NAME:.metadata.name,IP:.status.podIP'Пряма перевірка особливо корисна, коли readiness не проходить. Якщо застосунок відповідає зсередини Pod’а, але не через Сервіс, огляньте мітки, селектори, ендпоінти та готовність. Якщо він не відповідає зсередини Pod’а, огляньте процес, порт, локальну конфігурацію та взаємодію sidecar, перш ніж звинувачувати мережу кластера. Чиста діагностична звичка — рухатися на один крок за раз замість того, щоб спершу тестувати найдовший шлях.
Мережева модель Pod’ів також пояснює, чому припущення про мережу хоста можуть бути оманливими. Порт контейнера в специфікації Pod’а документує, що контейнер має намір надати, але сам по собі він не публікує цей порт поза Pod’ом і не створює Сервіс. Сервіс вибирає Pod’и за мітками й надсилає трафік до відповідних готових ендпоінтів, тоді як прямий IP Pod’а оминає цю логіку селектора. Якщо прямий доступ до Pod’а працює, але доступ через Сервіс не вдається, ваше наступне запитання має стосуватися міток, селекторів, готовності та генерації ендпоінтів, а не слухача застосунку.
Усунення несправностей DNS дотримується того самого методу «крок за кроком». Pod може не розв’язати ім’я Сервісу, бо CoreDNS недоступний, бо запит використовує неправильний простір імен, чи бо Сервіс не існує. Тест прямого IP Pod’а повністю оминає DNS, тож він корисний для відокремлення розв’язання імен від «сирої» зв’язності. У ранньому налагодженні Pod’ів від вас не очікують опанування кожної деталі мережевого плагіна, але від вас очікують уникнення змішування DNS, вибору Сервісу, готовності та перевірок процесу всередині Pod’а в одну розпливчасту «проблему з мережею».
Контекст безпеки та мережа можуть перетинатися дрібними способами. Контейнер, що не є root, може бути неспроможним прив’язатися до привілейованого порту, а файлова система кореня лише для читання може заблокувати застосунку запис згенерованого файлу конфігурації, потрібного перед тим, як він почне слухати. Ці збої можуть виглядати як мережеві збої ззовні, бо порт ніколи не відкривається. Коли Pod не приймає трафік, огляньте логи процесу та стан контейнера, перш ніж припускати, що мережа кластера відкинула пакети.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Хороший дизайн Pod’а починається з чесної зв’язаності. Якщо контейнери мають мати спільний життєвий цикл, ділитися файлами через тимчасовий том чи спілкуватися через localhost як одне логічне ціле, патерн рівня Pod’а є доречним. Якщо їм потрібне незалежне масштабування, незалежне розгортання чи окреме володіння, втискання їх в один Pod створює операційне тертя, яке проявиться пізніше під час розгортань та інцидентів.
| Патерн | Коли використовувати | Чому працює | Міркування щодо масштабування |
|---|---|---|---|
Згенерувати YAML через --dry-run=client -o yaml | Вам потрібен швидкий, коректний стартовий маніфест | Інструменти Kubernetes створюють скелет об’єкта й зменшують синтаксичні помилки | Перегляньте та зафіксуйте остаточний YAML, коли об’єкт важливий поза швидким завданням |
| Sidecar для тісно зв’язаних помічників | Помічник має жити поруч з одним екземпляром застосунку | Спільна мережа та томи роблять координацію простою | Sidecar масштабується лише тоді, коли масштабується основний застосунок |
| Init-контейнер для впорядкованого налаштування | Налаштування має завершитися перед запуском застосунку | Init-контейнери працюють послідовно та контролюють запуск застосунку | Повільна чи крихка робота init затримує готовність Pod’а |
| Readiness для контролю трафіку | Застосунок живий, але не готовий до запитів | Ендпоінти Сервісу виключають неготові Pod’и без перезапуску | Погані readiness-перевірки можуть прибрати забагато ємності |
| Запити та ліміти ресурсів | Вам потрібне передбачуване планування та стримування | Запити спрямовують планування; ліміти обмежують споживання | Надто тісні ліміти можуть спричинити OOMKilled чи throttling |
Антипатерни зазвичай походять зі сприйняття Pod’а як маленької віртуальної машини. Pod може містити кілька контейнерів, але він усе ще призначений представляти одну придатну для розгортання одиницю, а не набір не пов’язаних між собою сервісів. Краща альтернатива майже завжди — розділити незалежні турботи на окремі робочі навантаження та з’єднати їх через Сервіси, черги чи інтерфейси сховища, що відповідають їхньому реальному життєвому циклу.
| Антипатерн | Що йде не так | Краща альтернатива |
|---|---|---|
| Розміщення не пов’язаних сервісів в одному Pod’і | Вони не можуть масштабуватися, розгортатися чи давати збій незалежно | Використовуйте окремі Деплойменти та з’єднайте через Сервіс |
Використання тегів latest | Перестворений Pod може запустити інший образ, ніж той, що тестували | Закріпіть версійний тег чи незмінний дайджест |
| Перевірка баз даних у liveness-пробах | Повільність залежності спричиняє перезапуски, що посилюють збої | Використовуйте readiness для доступності залежностей та liveness для здоров’я процесу |
| Пропуск запитів ресурсів | Планувальник не може зарезервувати реалістичну ємність | Задайте запити CPU та пам’яті на основі виміряної поведінки |
Налагодження лише через kubectl exec | Цикли збоїв та збої планування можуть не мати робочої оболонки для огляду | Почніть із get, describe, подій та логів, а exec — коли контейнер стабільний |
Таблиці патернів — це не правила для сліпого застосування; це підказки для операційної відповідності. Маленький навчальний Pod можна створити імперативно й видалити за кілька хвилин, тоді як виробниче робоче навантаження слід виражати в маніфестах під контролем версій чи в об’єктах робочих навантажень вищого рівня. Так само sidecar елегантний, коли помічник прив’язаний рівно до одного екземпляра застосунку, та незграбний, коли помічник стає спільним сервісом під виглядом помічника.
Структура для ухвалення рішень
Розділ «Структура для ухвалення рішень»Використовуйте цю структуру, коли вирішуєте, що робити з проблемою Pod’а чи дизайном Pod’а. Перше запитання — чи ви створюєте, налагоджуєте чи моделюєте зв’язаність, бо ці шляхи використовують різні докази. Робота зі створення починається з якості специфікації, налагодження починається зі статусу та подій, а рішення про зв’язаність починаються з життєвого циклу та масштабування.
Need a pod? │ ├── Quick exam or throwaway test? │ └── Use kubectl run, then generate YAML if fields need editing. │ ├── Repeatable workload definition? │ └── Write or generate YAML, pin images, add labels, resources, and probes. │ ├── Pod is not starting? │ └── Read STATUS, describe Events, then inspect image, scheduling, and init state. │ ├── Pod starts but receives no traffic? │ └── Check READY, readiness probe events, labels, selectors, and endpoints. │ └── Helper container needed? ├── Runs before app and exits? Use an init container. └── Runs beside app for its lifetime? Use a sidecar.| Рішення | Виберіть це | Коли докази показують | Стережіться |
|---|---|---|---|
| Імперативна команда | kubectl run | Вам потрібна швидкість чи згенерована стартова точка | Відсутні поля все одно треба переглянути |
| Декларативний YAML Pod’а | kubectl apply -f | Вам потрібна відтворюваність та точний контроль специфікації | Окремі Pod’и рідко є фінальним виробничим контролером |
| Init-контейнер | initContainers | Налаштування має завершитися перед запуском застосунку | Очікування залежностей можуть заблокувати весь Pod |
| Sidecar | Кілька контейнерів застосунку | Помічник має ділити життєвий цикл, мережу чи файли | Немає незалежного масштабування для помічника |
| Readiness-проба | readinessProbe | Трафік має призупинятися без перезапуску | Проба має відображати здатність обслуговувати запити |
| Liveness-проба | livenessProbe | Перезапуск, імовірно, полагодить процес | Перевірки зовнішніх залежностей можуть спричиняти шторми перезапусків |
Для іспитових завдань ця структура перетворюється на порядок дій, що заощаджує час. Згенеруйте найменший коректний об’єкт, застосуйте його, спостерігайте за статусом, а потім використовуйте найбільш конкретну команду, що відповідає на наступне запитання. Для реальних операцій той самий порядок запобігає здогадкам, бо кожна зміна прив’язана до доказів: події для планування та завантаження образів, логи для збоїв застосунку, проби для готовності та поведінки перезапуску й exec для живого огляду всередині контейнера.
Чи знали ви?
Розділ «Чи знали ви?»- Kubernetes дає Pod’у одну IP-адресу, спільну для всіх контейнерів у цьому Pod’і, ось чому два контейнери в одному Pod’і не можуть обидва прив’язатися до того самого порту на цьому IP.
- Типовий період пільгового завершення Pod’а — 30 секунд, тож застосунок, який ігнорує
SIGTERM, може виглядати нормально під час звичайної роботи й усе одно спричиняти помилки під час розгортання чи видалення. - Init-контейнери виконуються до завершення перед запуском контейнерів застосунку, і вони не використовують readiness-проб, бо їхнє завдання — завершитися, а не залишатися готовими до трафіку.
- Startup-проби додали, щоб повільно стартуючі застосунки могли отримати окремий бюджет запуску, перш ніж почнуться liveness-перевірки, що допомагає уникати перезапусків під час законної ініціалізації.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому це трапляється | Як виправити |
|---|---|---|
Використання тегу latest | Під час тестування це здається зручним, але пізніше перестворення Pod’а може завантажити інший образ. | Закріпіть тег версії, як-от nginx:1.25, чи використовуйте незмінний дайджест образу для критичних робочих навантажень. |
| Немає запитів ресурсів | Pod може працювати в тихій лабораторії, тож відсутній сигнал планування легко пропустити. | Задайте запити CPU та пам’яті, що відображають виміряні мінімальні потреби, потім свідомо додайте ліміти. |
Ігнорування подій kubectl describe | Оператори одразу переходять до логів, навіть коли контейнер ніколи не стартував. | Читайте Events про планування, завантаження образу, монтування та збої проб, перш ніж змінювати специфікацію. |
Забування --previous при циклах збоїв | Поточний перезапущений контейнер може ще не містити повідомлення про збій. | Використовуйте kubectl logs POD --previous та оглядайте Last State у describe. |
| Перевірка залежностей у liveness | Команди повторно використовують широкий ендпоінт /health для кожної проби. | Тримайте liveness зосередженою на внутрішньому здоров’ї процесу та помістіть готовність залежностей у readiness-перевірки. |
Забування -c у багатоконтейнерних Pod’ах | kubectl logs чи exec можуть за замовчуванням обрати неправильний контейнер чи попросити вас обрати. | Указуйте -c container-name, коли Pod має більше ніж один контейнер. |
| Сприйняття IP Pod’ів як стабільних | Тести прямого IP Pod’а працюють один раз, що може приховати поведінку заміни. | Використовуйте IP Pod’ів для налагодження та Сервіси для стабільного трафіку застосунку. |
| Використання примусового видалення як звичайної звички | Воно швидко очищає застряглі Pod’и, але оминає шлях завершення роботи, який вам потрібно перевірити. | Надавайте перевагу звичайному видаленню, а --grace-period=0 --force залишайте для свідомих випадків прибирання. |
Тест
Розділ «Тест»1. Ваш Pod перебуває у стані `Pending` кілька хвилин, і `kubectl logs` повертає помилку, бо жоден контейнер не стартував. Що ви перевіряєте першим і чому?
Почніть із kubectl describe pod <name> та прочитайте розділ Events, бо Pod у стані Pending може не мати контейнера, що працює, для виведення логів. Події можуть показати недостатність CPU чи пам’яті, невідповідність node affinity, нестерпні taints, проблеми з томами чи повідомлення про налаштування завантаження образу. Якщо планування не вдалося, логи застосунку нерелевантні, бо kubelet ніколи не запускав контейнер. Якщо Pod було заплановано і він чекає на завантаження образу чи роботу init, той самий вивід describe вказує вам на цей шар далі.
2. Pod показує `CrashLoopBackOff` із багатьма перезапусками після розгортання нового образу. Які команди дають найшвидші корисні докази, і що ви шукаєте?
Спершу виконайте kubectl logs <pod> --previous, бо попередній екземпляр контейнера часто містить повідомлення про збій, що зникло, коли контейнер перезапустився. Потім виконайте kubectl describe pod <pod> та огляньте Last State, код виходу, лічильник перезапусків та Events. Код виходу 137 часто вказує на тиск на пам’ять, тоді як звичайні ненульові виходи зазвичай вказують назад на команду застосунку, конфігурацію чи залежності. Вам слід уникати видалення Pod’а до збору цих доказів, бо заміна може скинути найкорисніший контекст.
3. Вашому застосунку потрібен згенерований файл конфігурації перед запуском та помічник для відправлення логів під час роботи. Як ви маєте структурувати Pod, і якої поведінки збоїв слід очікувати?
Використайте init-контейнер для генерації файлу конфігурації у спільний том, а потім запустіть основний застосунок та помічника логів як звичайні контейнери, що монтують відповідні томи. Init-контейнер виконується першим і має успішно завершитися, перш ніж стартує будь-який із контейнерів виконання. Якщо init-контейнер дає збій, Kubernetes повторює його згідно з поведінкою перезапуску Pod’а, а контейнери застосунку залишаються заблокованими. Ця структура запобігає запуску застосунку з відсутньою конфігурацією, водночас дозволяючи sidecar’у працювати весь час життя застосунку.
4. Pod перебуває у стані `Running`, але показує `0/1` у стовпці `READY`, і користувачі не можуть дістатися до нього через Сервіс. Яку область рівня Pod'а найімовірніше треба оглянути?
Огляньте readiness-пробу та шлях ендпоінта Сервісу, перш ніж припускати, що процес мертвий. Pod у стані Running із готовністю 0/1 означає, що контейнер може бути живим, поки Kubernetes вважає його неготовим до трафіку. kubectl describe pod має показати збої readiness-проби, а перевірка ендпоінтів може підтвердити, чи виключено Pod із Сервісу. Liveness — це інше: якби liveness повторно не проходила, ви б очікували перезапусків, а не лише проблему з лічильником готовності.
5. Під час сповільнення бази даних Pod'и повторно перезапускаються, бо перевірки `/health` звертаються до бази даних і налаштовані як liveness-проба. Чому це погіршує збій, і як би ви перепроєктували проби?
Liveness-проба каже kubelet перезапустити контейнер, коли ендпоінт перевищує тайм-аут, тож повільність бази даних перетворюється на перезапуски застосунку. Ці перезапуски скидають роботу в процесі, створюють холодні старти й можуть додавати більше навантаження на залежність, коли кожен Pod повторно під’єднується. Перемістіть перевірки, чутливі до залежностей, у readiness, щоб Pod припиняв отримувати новий трафік, не будучи вбитим. Тримайте liveness зосередженою на умовах, які перезапуск може полагодити, як-от внутрішній дедлок чи процес, що не може відповісти на дешеву локальну перевірку.
6. Sidecar не може під'єднатися до основного контейнера на `localhost:8080`, і обидва контейнери в одному Pod'і. Які факти про Pod спрямовують вашу діагностику?
Контейнери в одному Pod’і мають спільний мережевий простір імен, тож localhost:8080 має дістатися основного контейнера, якщо основний процес насправді слухає цей порт. Перевірте, чи основний застосунок прив’язався до іншого порту, прив’язався лише після роботи з запуску чи впав після того, як sidecar почав намагатися під’єднатися. Також підтвердьте, що немає конфлікту портів, бо два контейнери в одному Pod’і не можуть обидва прив’язатися до того самого порту на спільному IP Pod’а. kubectl logs -c, kubectl exec -c та kubectl describe pod разом відокремлюють поведінку застосунку від припущень про мережу рівня Pod’а.
7. Ви згенерували маніфест Pod'а через `kubectl run --dry-run=client -o yaml`, відредагували його, і тепер він дає збій із `ImagePullBackOff`. Що вам слід оглянути, перш ніж змінювати не пов'язані поля?
Огляньте ім’я образу, тег, шлях реєстру та події завантаження образу в kubectl describe pod. ImagePullBackOff зазвичай означає, що Kubernetes намагався завантажити образ і не зміг, бо тег не існує, реєстр недоступний чи бракує автентифікації. Запити ресурсів, проби та контекст безпеки можуть мати значення пізніше, але вони не пояснюють невдале завантаження образу до того, як контейнер стартує. Спершу виправте посилання на образ чи доступ до реєстру, а потім зачекайте, доки Pod перейде до наступного етапу життєвого циклу.
Практична вправа
Розділ «Практична вправа»Сценарій вправи: ви створите багатоконтейнерний Pod з init-контейнером, основним вебконтейнером та sidecar’ом для читання логів, потім оглянете життєвий цикл і приберете його. Мета — не лише змусити Pod працювати, а й попрактикуватися читати докази на кожному кроці. Тримайте маніфест на видноті, поки працюєте, щоб ви могли пов’язати вивід кожної команди з конкретним полем у специфікації Pod’а.
Завдання 1: Створити Pod з init-контейнером та sidecar’ом
Розділ «Завдання 1: Створити Pod з init-контейнером та sidecar’ом»cat > multi-container-pod.yaml << 'EOF'apiVersion: v1kind: Podmetadata: name: webappspec: initContainers: - name: init-setup image: busybox command: ['sh', '-c', 'echo "Init complete" > /shared/init-status.txt'] volumeMounts: - name: shared mountPath: /shared
containers: - name: web image: nginx ports: - containerPort: 80 volumeMounts: - name: shared mountPath: /usr/share/nginx/html - name: logs mountPath: /var/log/nginx
- name: log-reader image: busybox command: ['sh', '-c', 'tail -F /logs/access.log 2>/dev/null || sleep infinity'] volumeMounts: - name: logs mountPath: /logs
volumes: - name: shared emptyDir: {} - name: logs emptyDir: {}EOF
kubectl apply -f multi-container-pod.yamlНотатки до розв'язання
Маніфест використовує init-контейнер, щоб записати файл перед запуском nginx, а потім монтує той самий том shared у вебконтейнер. Він також монтує том logs і в nginx, і в sidecar log-reader, щоб помічник мав доступ до файлів, створених основним контейнером. Якщо Pod не стартує, використайте kubectl describe pod webapp, перш ніж редагувати маніфест, бо розділ Events зазвичай ідентифікує перший шар, що дав збій.
Завдання 2: Зачекати на запуск та оглянути стан init
Розділ «Завдання 2: Зачекати на запуск та оглянути стан init»# Wait for the pod to be fully readykubectl wait --for=condition=ready pod/webapp --timeout=90s
# Check init container completedkubectl describe pod webapp | grep -A10 "Init Containers"Нотатки до розв'язання
Команда wait має завершитися лише після того, як звичайні контейнери стануть готовими. Вивід describe має показати init-контейнер як успішно завершений, що підтверджує, що крок налаштування завершився перед тим, як контейнери застосунку стали активними. Якщо Pod залишається у стані init, огляньте логи init-контейнера за допомогою kubectl logs webapp -c init-setup, а потім перевірте команду, образ та монтування тома.
Завдання 3: Перевірити спільний том та бачення sidecar’а
Розділ «Завдання 3: Перевірити спільний том та бачення sidecar’а»# Init container created this filekubectl exec webapp -c web -- cat /usr/share/nginx/html/init-status.txt
# Execute command non-interactivelykubectl exec webapp -c log-reader -- ls /logsНотатки до розв'язання
Перша команда доводить, що файл, записаний init-контейнером, видимий вебконтейнеру через спільний том. Друга команда доводить, що sidecar має власну файлову систему, але може бачити змонтований каталог логів. Якщо якась із команд дає збій, уважно порівняйте імена volumeMounts та volumes, бо невідповідність у написанні змінює форму Pod’а під час виконання.
Завдання 4: Згенерувати трафік та прочитати логи
Розділ «Завдання 4: Згенерувати трафік та прочитати логи»# Get pod IPPOD_IP=$(kubectl get pod webapp -o jsonpath='{.status.podIP}')
# Generate traffic from another podkubectl run curl --image=curlimages/curl --rm -i --restart=Never -- curl -s $POD_IP
# Check sidecar saw the logkubectl logs webapp -c log-readerНотатки до розв'язання
Це завдання використовує IP Pod’а для прямого налагодження, а не для стабільного трафіку застосунку. Тимчасовий Pod із curl має дістатися nginx, а команда логів sidecar’а має показати, чи може помічник читати вивід логів зі спільного монтування. У реальному шляху сервісу ви додали б Сервіс і тестували через DNS чи IP Сервісу, але прямий доступ до Pod’а тримає цю вправу зосередженою на мережі Pod’ів та поведінці sidecar’а.
Завдання 5: Попрактикувати цілеспрямоване налагодження та прибирання
Розділ «Завдання 5: Попрактикувати цілеспрямоване налагодження та прибирання»# Logs from specific containerkubectl logs webapp -c webkubectl logs webapp -c log-reader
# View recent logskubectl logs webapp -c web --tail=10
# Cleanupkubectl delete pod webapprm multi-container-pod.yamlНотатки до розв'язання
Указування -c тримає ціль налагодження явною в багатоконтейнерному Pod’і. Прибирання використовує звичайне видалення Pod’а, щоб ви могли спостерігати коректне завершення, якщо запустите kubectl get pods -w в іншому терміналі. Примусове видалення не потрібне для цієї вправи, якщо Pod не застрягне з причин, які ви вже оглянули.
Тренувальні вправи
Розділ «Тренувальні вправи»Наступні вправи зберігають ті самі патерни команд у менших повтореннях. Використовуйте їх після основної вправи, якщо хочете практику на швидкість CKA, але зберігайте ту саму діагностичну дисципліну: генеруйте, застосовуйте, спостерігайте, оглядайте та прибирайте. Не рухайтеся швидше за вашу здатність пояснити, яке поле Pod’а чи рядок статусу доводить кожна команда.
# 1. Basic nginx podkubectl run nginx --image=nginx
# 2. Pod with labelskubectl run labeled --image=nginx --labels="app=web,tier=frontend"
# 3. Pod with portkubectl run webserver --image=nginx --port=80
# 4. Pod with environment variableskubectl run envpod --image=nginx --env="ENV=production" --env="DEBUG=false"
# 5. Pod with resource requests (set at creation via --overrides; a running# bare pod's resources are immutable, so they cannot be patched in afterward)kubectl run limited --image=nginx --overrides='{"spec":{"containers":[{"name":"limited","image":"nginx","resources":{"requests":{"cpu":"100m","memory":"128Mi"},"limits":{"cpu":"200m","memory":"256Mi"}}}]}}'
# Verify all podskubectl get pods
# Cleanupkubectl delete pod nginx labeled webserver envpod limited# Generate base YAMLkubectl run webapp --image=nginx:1.25 --port=80 --dry-run=client -o yaml > webapp.yaml
# View and verifycat webapp.yaml
# Apply itkubectl apply -f webapp.yaml
# Modify: add a labelkubectl label pod webapp tier=frontend
# Verify labelkubectl get pod webapp --show-labels
# Cleanupkubectl delete -f webapp.yamlrm webapp.yaml# Create a pod that will failkubectl run failing --image=nginx --command -- /bin/sh -c "exit 1"
# Check statuskubectl get pod failing# STATUS: CrashLoopBackOff
# Debug step 1: describekubectl describe pod failing | tail -20
# Debug step 2: logskubectl logs failing --previous
# Debug step 3: check eventskubectl get events --field-selector involvedObject.name=failing
# Cleanupkubectl delete pod failing# Create pod with sidecarcat << 'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: sidecar-demospec: containers: - name: main image: nginx volumeMounts: - name: shared mountPath: /usr/share/nginx/html - name: sidecar image: busybox command: ['sh', '-c', 'while true; do date > /html/index.html; sleep 5; done'] volumeMounts: - name: shared mountPath: /html volumes: - name: shared emptyDir: {}EOF
# Wait for readykubectl wait --for=condition=ready pod/sidecar-demo --timeout=60s
# Test - sidecar writes timestamp that nginx serveskubectl exec sidecar-demo -c main -- cat /usr/share/nginx/html/index.html
# Wait 5 seconds and check again - timestamp should changesleep 5kubectl exec sidecar-demo -c main -- cat /usr/share/nginx/html/index.html
# Cleanupkubectl delete pod sidecar-demo# Create pod with init containercat << 'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: init-demospec: initContainers: - name: init-download image: busybox command: ['sh', '-c', 'echo "Hello from init" > /work/message.txt'] volumeMounts: - name: workdir mountPath: /work containers: - name: main image: busybox command: ['sh', '-c', 'cat /work/message.txt && sleep 3600'] volumeMounts: - name: workdir mountPath: /work volumes: - name: workdir emptyDir: {}EOF
# Wait for init container and main container to be readykubectl wait --for=condition=ready pod/init-demo --timeout=60s
# Verify init workedkubectl logs init-demo
# Check init container statuskubectl describe pod init-demo | grep -A5 "Init Containers"
# Cleanupkubectl delete pod init-demo# Create two podskubectl run pod-a --image=nginx --port=80kubectl run pod-b --image=busybox --command -- sleep 3600
# Wait for readykubectl wait --for=condition=ready pod/pod-a pod/pod-b --timeout=60s
# Get pod-a IPPOD_A_IP=$(kubectl get pod pod-a -o jsonpath='{.status.podIP}')echo "Pod A IP: $POD_A_IP"
# From pod-b, reach pod-akubectl exec pod-b -- wget -qO- $POD_A_IP
# Cleanupkubectl delete pod pod-a pod-b# Create pod with wrong imagekubectl run broken --image=nginx:nonexistent-tag
# Check statuskubectl get pod broken# STATUS: ImagePullBackOff or ErrImagePull
# Diagnosekubectl describe pod broken | grep -A10 "Events"
# Fix: update the imagekubectl set image pod/broken broken=nginx:1.25
# Verify fixedkubectl get pod brokenkubectl wait --for=condition=ready pod/broken --timeout=60s
# Cleanupkubectl delete pod broken# Challenge prompt: complete this workflow without looking at the solutionkubectl run challenge --image=nginx:1.25 --labels="app=web,env=test"kubectl wait --for=condition=ready pod/challenge --timeout=60skubectl exec challenge -- sh -c 'echo "Hello" > /tmp/test.txt'kubectl get pod challenge -o widekubectl logs challenge --tail=10kubectl delete pod challenge# Challenge solution check: prove each requested result explicitlykubectl run challenge --image=nginx:1.25 --labels="app=web,env=test"kubectl wait --for=condition=ready pod/challenge --timeout=60skubectl exec challenge -- sh -c 'echo "Hello" > /tmp/test.txt'kubectl exec challenge -- cat /tmp/test.txtkubectl get pod challenge -o jsonpath='{.status.podIP}'kubectl logs challengekubectl delete pod challenge# Probe inspection drill: collect readiness and liveness evidencekubectl describe pod webapp | grep -A20 "Conditions:"kubectl describe pod webapp | grep -A20 "Events:"kubectl get pod webapp -o jsonpath='{.status.containerStatuses[*].ready}'# Lifecycle inspection drill: compare phase, container state, and restart countkubectl get pod webappkubectl get pod webapp -o jsonpath='{.status.phase}'kubectl get pod webapp -o jsonpath='{.status.containerStatuses[*].restartCount}'kubectl describe pod webapp | grep -A8 "Last State"Критерії успіху
Розділ «Критерії успіху»- Можу створювати Pod’и імперативними командами
- Можу генерувати YAML через
--dry-run=client -o yaml - Можу пояснити фази життєвого циклу Pod’а та поведінку політики перезапуску зі спостережуваного виводу
- Можу налагоджувати за допомогою
kubectl get,describe,logsтаexecу правильному порядку - Можу створювати багатоконтейнерні Pod’и з init-контейнерами, sidecar’ами та спільними томами
- Можу обирати readiness-, liveness- та startup-проби на основі наслідків збоїв
Джерела
Розділ «Джерела»- Pods — Підкріплює основи Pod’ів: Pod’и як найменша придатна для розгортання одиниця, модель з одним або кількома контейнерами, спільний мережевий простір імен, спільне сховище, co-location та абстракцію Pod’а, яку використовують контролери робочих навантажень вищого рівня.
- Deployments — Підкріплює поведінку Деплойменту, володіння Deployment-to-ReplicaSet-to-Pod, стратегію розгортання, послідовні оновлення, поведінку maxSurge/maxUnavailable, історію розгортання, паузу/відновлення та концепції відкату.
- DaemonSet — Підкріплює семантику «один Pod на ноду», автоматичне покриття доданих нод, поширені випадки використання рівня ноди, вибіркове розміщення на нодах через nodeSelector/affinity та поведінку tolerations DaemonSet.
- StatefulSets — Підкріплює стабільну ідентичність Pod’а, порядкове іменування, стабільне сховище через volumeClaimTemplates, упорядковане розгортання та послідовні оновлення, вимоги до headless-Сервісу та поведінку мережевої ідентичності DNS.
- Jobs — Підкріплює семантику виконання до завершення, backoffLimit, обмеження restartPolicy, completions, parallelism, заміну Pod’а при збої та поведінку пакетних робочих навантажень, відмінну від Деплойментів.
- Security Context — Сторінка завдання про контекст безпеки Kubernetes безпосередньо визначає поле та документує точні приклади налаштувань, використані тут.
- Pod Lifecycle — Підтримує твердження про фази Pod’а, термінологію планування/прив’язки, коректне завершення, terminationGracePeriodSeconds, виконання хука preStop під час завершення роботи та умови статусу зміни розміру Pod’а у v1.35.
- Init Containers — Підкріплює впорядкування init-контейнерів, поведінку виконання до завершення, відмінності від контейнерів застосунку та послідовність запуску Pod’а перед стартом основних контейнерів.
- Liveness, Readiness, and Startup Probes — Підкріплює семантику проб, відмінності між пробами liveness/readiness/startup та те, як kubelet реагує на невдалі проби чи утримує готовність під час запуску.
- kubectl run — Підкріплює імперативне створення Pod’а та робочий процес
--dry-run=client -o yaml, що використовується для швидкої генерації маніфесту.
Наступний модуль
Розділ «Наступний модуль»Модуль 2.2: Деплойменти та ReplicaSet’и — Послідовні оновлення, відкати та масштабування.