Модуль 1.5: Поди
Складність:
[СЕРЕДНЯ]— базова концепція ресурсу.Час на проходження: 45–55 хвилин.
Передумови: Модулі 1.1–1.4, особливо об’єкти API та концепції площини управління.
Що ви зможете зробити
Розділ «Що ви зможете зробити»Після завершення цього модуля ви зможете пов’язувати рішення щодо проєктування Подів із конкретними рішеннями про діагностику, розгортання та власність замість того, щоб сприймати Поди як анонімні контейнери.
- Діагностувати проблеми життєвого циклу Пода, інтерпретуючи фазу, умови, події, перезапуски та статус контейнерів.
- Проєктувати одноконтейнерні та багатоконтейнерні патерни Подів, які коректно використовують спільну мережу та сховище.
- Оцінювати, коли окремий Под є хибним інструментом, а власником Пода має стати Деплоймент, Job чи DaemonSet.
- Впроваджувати маніфест Пода для Kubernetes 1.35+ із мітками, портами, ресурсами та томами, що відповідають задуму робочого навантаження.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»У лютому 2017 року GitLab.com зазнав інциденту з робочою базою даних, який став публічним, тому що команда детально задокументувала відновлення. Збій не був спричинений Подами Kubernetes, але урок безпосередньо стосується експлуатації Kubernetes: системи стають крихкими, коли інженери плутають тимчасові одиниці виконання з тривалою власністю над сервісом. Процес, контейнер або Под можуть зникнути швидше, ніж устигнуть пояснити вплив на бізнес, і коли платформа не має контролера, що підтримує бажаний стан, кожен перезапуск перетворюється на ручну вправу з відновлення.
А тепер уявіть той самий патерн усередині кластера Kubernetes під час релізу платіжного сервісу. Розробник створює один Под для гарячого виправлення, бо це швидко; Под отримує реальний трафік через імпровізований селектор, і застосунок працює достатньо довго, щоб усі переключилися на інше. За кілька годин вузол виводиться на обслуговування, Под зникає, і сервіс не повертається, тому що жоден Деплоймент, ReplicaSet, Job чи DaemonSet ним не володіє. Розбір інциденту не каже «Kubernetes відмовив»; він каже, що команда розгорнула хибну абстракцію та пропустила ту частину Kubernetes, яка безперервно узгоджує бажаний стан.
Поди — це місце, де кожне робоче навантаження Kubernetes стає конкретним. Деплойменти, StatefulSets, Jobs, CronJobs та DaemonSets усі створюють Поди, тому що зрештою саме kubelet запускає контейнери на вузлах, приєднує томи, налаштовує мережеву взаємодію та повідомляє статус через об’єкти Подів. Якщо ви вмієте добре читати Под, ви можете діагностувати, чому робоче навантаження перебуває в очікуванні, чому відсутній трафік, чому перемістилися логи, чому сайдкар не може побачити файл або чому застосунок зі статусом «Running» усе ще недоступний. Цей модуль обережно й послідовно вибудовує цю навичку: спершу модель Пода, потім мережа та сховище, потім життєвий цикл, а потім межа рішення між прямими Подами та робочими навантаженнями під керуванням контролерів.
Межа Пода: одна одиниця планування, спільний контекст
Розділ «Межа Пода: одна одиниця планування, спільний контекст»Под — це найменша придатна до розгортання та планування одиниця в Kubernetes, але це речення приховує найважливішу частину дизайну. Kubernetes не планує окремі контейнери напряму, тому що контейнерам інколи потрібен спільний контекст, сильніший за «два процеси випадково існують в одному кластері». Под дає Kubernetes єдиний об’єкт, який можна розмістити на одному вузлі, призначити йому одну мережеву ідентичність, приєднати до тих самих томів та спостерігати як одну одиницю бажаного стану виконання.
┌─────────────────────────────────────────────────────────────┐│ WHAT IS A POD? │├─────────────────────────────────────────────────────────────┤│ ││ A Pod is: ││ • A group of one or more containers ││ • The atomic unit of scheduling ││ • Containers that share storage and network ││ ││ ┌─────────────────────────────────────────────────────┐ ││ │ POD │ ││ │ ┌───────────────────────────────────────────────┐ │ ││ │ │ Shared Network Namespace │ │ ││ │ │ • All containers share same IP │ │ ││ │ │ • Containers communicate via localhost │ │ ││ │ └───────────────────────────────────────────────┘ │ ││ │ │ ││ │ ┌─────────────┐ ┌─────────────┐ │ ││ │ │ Container 1 │ │ Container 2 │ │ ││ │ │ (app) │ │ (sidecar) │ │ ││ │ └─────────────┘ └─────────────┘ │ ││ │ │ ││ │ ┌───────────────────────────────────────────────┐ │ ││ │ │ Shared Storage (Volumes) │ │ ││ │ │ • Both containers can access same files │ │ ││ │ └───────────────────────────────────────────────┘ │ ││ └─────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────┘Аналогія з квартирою корисна, бо вона відокремлює ідентичність контейнера від спільної адреси Пода. Контейнер схожий на людину зі своєю роботою та звичками, тоді як Под — це квартира, де ці люди живуть разом. Вони мають спільну адресу на вулиці, можуть розмовляти через кімнату, не виходячи до публічного вестибюля, і можуть мати спільну кухню, де файли з’являються для кожного, кому дозволено нею користуватися. Таке спільне облаштування потужне, коли контейнери тісно пов’язані, і дороге, коли їм слід масштабуватися або відмовляти незалежно.
┌─────────────────────────────────────────────────────────────┐│ POD vs CONTAINER │├─────────────────────────────────────────────────────────────┤│ ││ Container: Pod: ││ ───────────────────────────────────────────────────────── ││ • Single process • One or more containers ││ • Runtime concept • Kubernetes concept ││ • No shared context • Shared network/storage ││ • Isolated • Co-located ││ ││ Analogy: ││ ───────────────────────────────────────────────────────── ││ Container = Person ││ Pod = Apartment where people live together ││ ││ People in the same apartment: ││ • Share the same address (IP) ││ • Share kitchen and bathroom (volumes) ││ • Can talk directly (localhost) ││ │└─────────────────────────────────────────────────────────────┘Саме тому «Под дорівнює контейнер» — приваблива, але неповна спрощена модель. Багато Подів містять рівно один контейнер застосунку, тож цей спрощений підхід працює протягом першого тижня навчання. Він ламається тієї миті, коли ви додаєте init-контейнер, проксі сервісної мережі (service mesh), збирача логів, адаптер метрик або спільний том. Об’єкт Пода — це те, що Kubernetes планує та відстежує; контейнер — це одне середовище процесу всередині цього об’єкта. Ця відмінність пояснює, чому k get pods показує стан Пода, тоді як k describe pod і k logs часто вимагають вибрати конкретний контейнер усередині Пода.
До кінця цього модуля припустіть, що поширений псевдонім оболонки alias k=kubectl налаштовано перед першою командою. Документація Kubernetes та робочі інструкції часто використовують повну назву kubectl для ясності, але цей курс після одноразового знайомства з псевдонімом використовує k, щоб команди залишалися читабельними. Псевдонім не змінює поведінки; він лише скорочує клієнтську команду, яка спілкується з API-сервером Kubernetes.
alias k=kubectlk version --clientЗупиніться й передбачте: якби Kubernetes планував контейнери напряму, а не Поди, що сталося б із двома допоміжними контейнерами, які мають завжди опинятися на одному вузлі та мати спільні файли? Планувальнику знадобилася б друга абстракція, щоб виразити «розмісти їх разом», а операторам — ще одне місце для огляду їхньої сукупної поведінки мережі та томів. Под розв’язує це, роблячи спільне розміщення частиною об’єкта API, а не нечіткою домовленістю у скриптах розгортання.
Межа Пода — це також перше місце, де початківці зустрічають компроміси Kubernetes. Розміщення двох контейнерів в одному Поді дає їм швидку комунікацію через localhost та спільні файли, але також пов’язує їхнє планування, час життя й масштабування. Якщо один помічник має працювати поруч із кожною реплікою застосунку, така зв’язаність коректна. Якщо ж помічник насправді є спільною базою даних, кешем чи чергою, ця зв’язаність зазвичай хибна, тому що кожна репліка застосунку тягнула б за собою окрему копію цієї залежності зі станом.
Одноконтейнерні Поди: форма за замовчуванням
Розділ «Одноконтейнерні Поди: форма за замовчуванням»Більшість Подів у кластерах застосунків містять один основний контейнер, тому що про більшість сервісів найлегше міркувати, коли кожна репліка має одну головну відповідальність. Реплика вебсервера API, репліка обробника черги чи репліка сервера статичних файлів зазвичай потребує власного образу, оточення, портів, запитів ресурсів та проб. Kubernetes усе одно загортає цей один контейнер у Под, тому що Под надає розміщення на вузлі, мережеву ідентичність, монтування томів та статус життєвого циклу, що використовуються рештою площини управління.
┌─────────────────────────────────────────────────────────────┐│ SINGLE-CONTAINER POD │├─────────────────────────────────────────────────────────────┤│ ││ ┌─────────────────────────────────────────────────────┐ ││ │ POD │ ││ │ ┌─────────────────────────────────────────────┐ │ ││ │ │ Main Application Container │ │ ││ │ │ (e.g., nginx) │ │ ││ │ └─────────────────────────────────────────────┘ │ ││ └─────────────────────────────────────────────────────┘ ││ ││ This is the most common pattern: ││ • One container per Pod ││ • Simple to manage ││ • Each Pod runs one instance of your app ││ ││ "One-container-per-Pod" is the standard use case ││ │└─────────────────────────────────────────────────────────────┘Одноконтейнерний Под не є слабшою концепцією за багатоконтейнерний Под. Це просто найекономніший вираз робочого навантаження. Ви все одно отримуєте мітки для вибірки, запити ресурсів для планування, поведінку політики перезапуску, контекст безпеки, конфігурацію завантаження образу, ідентичність сервісного акаунта, проєктовану конфігурацію та монтування томів. Ключова думка в тому, що Kubernetes тримає деталі середовища виконання контейнера за стабільним об’єктом API, що дозволяє контролерам і Сервісам міркувати про екземпляри робочого навантаження, не залежачи від внутрішніх особливостей Docker, containerd чи CRI-O.
Коли пізніше в курсі ви створюватимете Деплоймент, ви напишете шаблон Пода всередині специфікації Деплойменту. Цей шаблон — не декоративний YAML; це креслення, яке контролер ReplicaSet використовує щоразу, коли йому потрібен ще один Под. Якщо вузол відмовляє, контролер не воскрешає той самий об’єкт Пода. Він створює замінний Под за шаблоном, із новою ідентичністю, новим UID і часто новим IP. Сприйняття Подів як замінних реплік — один із тих ментальних зсувів, що відрізняють експлуатацію Kubernetes від традиційного адміністрування серверів.
Наведена нижче концептуальна специфікація Пода навмисно невелика, але вона охоплює частини, які вам слід розпізнавати для KCNA та для реальної діагностики. Метадані дають Поду ім’я та мітки, spec.containers описує те, що має виконуватися, ports документує очікувані порти контейнера, resources дає планувальнику та kubelet запобіжники, а volumes визначає спільне сховище, яке контейнери можуть монтувати. Вам не потрібно запам’ятовувати кожне поле, але ви маєте вміти вказати на зламаний маніфест Пода й запитати, який розділ керує спостережуваною поведінкою.
# Pod Specification - Key PartsapiVersion: v1kind: Podmetadata: name: my-pod # Pod name labels: # Labels for selection app: webspec: containers: # List of containers - name: app # Container name image: nginx:1.25 # Container image ports: # Exposed ports - containerPort: 80 resources: # Resource limits limits: memory: "128Mi" cpu: "500m" volumes: # Shared storage - name: data emptyDir: {}Маніфест вище — також корисний діагностичний контрольний список. Якщо Под ніколи не планується, перевірте запити ресурсів, селектори вузлів, толерації, спорідненість та квоту, перш ніж розглядати код застосунку. Якщо Под планується, але контейнер не може запуститися, перевірте назву образу, облікові дані для завантаження образу, команду, аргументи, оточення, змонтовану конфігурацію та посилання на томи. Якщо контейнер запускається, але сервіс не має ендпоінтів, перевірте мітки, проби готовності та селектор Сервісу. Под — це не весь застосунок, але це найчесніше місце, щоб побачити, чи репліка застосунку насправді існує.
Перш ніж запустити це, який вивід ви очікуєте від окремого Пода, що має один контейнер і жодного Сервісу? Вам слід очікувати, що k get pod покаже Под, а k get pod -o wide покаже внутрішньокластерний IP, але не варто очікувати стабільної зовнішньої адреси. IP Пода — це деталь реалізації однієї репліки, а не тривалий контракт для клієнтів. Сервіси, Інгрес та ресурси Gateway API існують саме тому, що клієнтам потрібен стабільний спосіб знаходити змінні Поди.
k run pod-demo --image=nginx:1.25 --restart=Never --port=80k get pod pod-demo -o widek describe pod pod-demok delete pod pod-demoНаведена вище команда корисна для навчання та швидких експериментів, а не як патерн виробничого розгортання. Окремий Под не має контролера, що підтримує кількість реплік, не має стратегії плавного оновлення та автоматичної заміни після видалення. Kubernetes може перезапускати контейнери всередині того самого Пода відповідно до політики перезапуску Пода, поки Под залишається на вузлі, але якщо об’єкт Пода видалено або вузол зникає, прямий Под не має власника вищого рівня, який би його відтворив. Саме тому правильне виробниче питання рідко звучить як «як мені створити Под?», а частіше — «який контролер має володіти цим шаблоном Пода?».
Багатоконтейнерні Поди: сайдкари, амбасадори та адаптери
Розділ «Багатоконтейнерні Поди: сайдкари, амбасадори та адаптери»Багатоконтейнерні Поди існують для контейнерів, що утворюють одну тісно пов’язану одиницю роботи. Важливою є не фраза «кілька контейнерів»; важлива фраза «тісно пов’язані». Контейнери в одному Поді мають спільний мережевий простір імен, можуть мати спільні томи, плануються разом і зазвичай створюються та видаляються разом. Це робить патерн цінним для допоміжних обов’язків, невіддільних від однієї репліки застосунку, але робить патерн ризикованим для залежностей, що заслуговують на незалежне масштабування, незалежне оновлення чи незалежне збереження стану.
┌─────────────────────────────────────────────────────────────┐│ MULTI-CONTAINER PATTERNS │├─────────────────────────────────────────────────────────────┤│ ││ SIDECAR PATTERN ││ ───────────────────────────────────────────────────────── ││ ┌─────────────────────────────────────────────────────┐ ││ │ POD │ ││ │ ┌─────────────────┐ ┌─────────────────┐ │ ││ │ │ Main App │ │ Log Shipper │ │ ││ │ │ (writes logs) │─→│ (reads logs) │ │ ││ │ └─────────────────┘ └─────────────────┘ │ ││ │ └────────────┘ │ ││ │ Shared volume │ ││ └─────────────────────────────────────────────────────┘ ││ Example: Main app + Fluentd sidecar for logging ││ ││ AMBASSADOR PATTERN ││ ───────────────────────────────────────────────────────── ││ ┌─────────────────────────────────────────────────────┐ ││ │ POD │ ││ │ ┌─────────────────┐ ┌─────────────────┐ │ ││ │ │ Main App │ │ Proxy │ │ ││ │ │ (localhost) │─→│ (outbound) │─→ External│ ││ │ └─────────────────┘ └─────────────────┘ │ ││ └─────────────────────────────────────────────────────┘ ││ Example: App + Envoy proxy for service mesh ││ ││ ADAPTER PATTERN ││ ───────────────────────────────────────────────────────── ││ ┌─────────────────────────────────────────────────────┐ ││ │ POD │ ││ │ ┌─────────────────┐ ┌─────────────────┐ │ ││ │ │ Main App │ │ Adapter │ │ ││ │ │ (custom format)│─→│(standard format)│─→ Monitor │ ││ │ └─────────────────┘ └─────────────────┘ │ ││ └─────────────────────────────────────────────────────┘ ││ Example: App + Prometheus exporter adapter ││ │└─────────────────────────────────────────────────────────────┘Патерн сайдкара (sidecar) найлегше обґрунтувати, тому що помічник існує, щоб розширити основний контейнер, не змінюючи основний образ. Збирач логів може читати спільний файловий том, перезавантажувач конфігурації може стежити за проєктованими даними ConfigMap, а проксі сервісної мережі може перехоплювати локальний трафік. Застосунок залишається зосередженим на бізнес-логіці, тоді як сайдкар обробляє наскрізну відповідальність. Компроміс — це операційна зв’язаність: кожна репліка тепер споживає ресурси для обох контейнерів, а зламаний сайдкар може зробити справну репліку застосунку неготовою чи галасливою.
Патерн амбасадора (ambassador) розміщує проксі поруч із застосунком, тож застосунок звертається до localhost, а проксі обробляє деталі зовнішнього з’єднання. Це було поширеним до того, як сервісні мережі стали мейнстрімом, і залишається корисним, коли одному процесу потрібен вузький мережевий помічник із тим самим життєвим циклом. Патерн адаптера (adapter) нормалізує вивід основного застосунку, наприклад перетворюючи власний формат метрик на щось, що система моніторингу може зчитувати. Обидва патерни корисні лише тоді, коли помічник є частиною тієї самої поведінки на рівні репліки, а не коли він є загальним спільним сервісом.
Зупиніться й подумайте: у патерні сайдкара контейнер-збирач логів працює поруч з основним застосунком. Чому помістити їх в один Под, а не в окремі Поди? Відповідь — не «бо Kubernetes це підтримує». Відповідь у тому, що сайдкар у тому ж Поді може читати той самий шлях тому й координуватися із застосунком через localhost, не винаходячи систему мережевого спільного доступу до файлів чи другий механізм виявлення. Якщо окремим Подам потрібні ті самі дані, ви вже проєктуєте розподілене сховище та виявлення сервісів, а це більша проблема, ніж збирання логів.
Найпоширеніша помилка — використовувати багатоконтейнерний Под як невелику приватну групу серверів. Наприклад, розміщення контейнера API та кешу Redis в одному Поді може здаватися ефективним, тому що API може дістатися до Redis через localhost. Це також означає, що кожна репліка API несе власний кеш, Redis не може масштабуватися чи оновлюватися незалежно, а персистентні дані заплутуються з ритмом розгортання застосунку. Якщо Redis є реальною сервісною залежністю, запустіть його через власний контролер і відкрийте через Сервіс. Якщо ж це одноразовий помічник на репліку, тоді патерн «в одному Поді» може бути доречним.
Init-контейнери — це пов’язана, але окрема функція Пода. Вони виконуються до завершення перед запуском контейнерів застосунку та корисні для завдань налаштування, як-от очікування на залежність, генерація файлу чи підготовка дозволів. Вони не є тривалими сайдкарами, і їх не слід використовувати, щоб приховати крихкі припущення про запуск. Якщо застосунок не може запуститися, поки не завершиться міграція бази даних, це заслуговує на явний дизайн розгортання, а не на init-контейнер, який тихо зациклюється назавжди й залишає Под у непридатному стані очікування.
Який підхід ви обрали б тут і чому: експортер метрик, який читає локальний Unix-сокет, створений застосунком, чи спільна база даних Postgres, яку використовує кожна репліка застосунку? Експортер — сильний кандидат на сайдкар, бо він прив’язаний до межі локального процесу однієї репліки. База даних не є кандидатом на сайдкар, тому що це сервіс зі станом із власними потребами доступності, резервного копіювання, масштабування та оновлення. Це питання — серцевина проєктування багатоконтейнерних Подів: розміщуйте разом те, що невіддільне, відокремлюйте те, що має власний життєвий цикл.
Мережа та сховище Пода: один IP, багато портів, спільні томи
Розділ «Мережа та сховище Пода: один IP, багато портів, спільні томи»Кожен Под отримує власний мережевий простір імен і зазвичай одну маршрутизовану кластерну IP-адресу. Контейнери всередині цього Пода спільно використовують простір імен, що означає, що вони бачать ті самі мережеві інтерфейси та можуть дістатися одне до одного через localhost на різних портах. Ззовні Пода інші Поди не адресують окремі контейнери; вони адресують IP Пода та порт. Саме тому два контейнери в одному Поді не можуть обидва прив’язатися до того самого порту на тому самому інтерфейсі, так само як два процеси на одному хості Linux не можуть обидва слухати 0.0.0.0:8080.
┌─────────────────────────────────────────────────────────────┐│ POD NETWORKING │├─────────────────────────────────────────────────────────────┤│ ││ Each Pod gets: ││ • Its own unique IP address ││ • Can be reached directly by other Pods ││ • Containers in Pod share this IP ││ ││ ┌─────────────────────────────────────────────────────┐ ││ │ POD (IP: 10.1.1.5) │ ││ │ ┌────────────┐ ┌────────────┐ │ ││ │ │Container A │ │Container B │ │ ││ │ │ Port 80 │ │ Port 8080 │ │ ││ │ └────────────┘ └────────────┘ │ ││ │ │ │ │ ││ │ └────────┬─────────┘ │ ││ │ │ │ ││ │ localhost:80 localhost:8080 │ ││ │ (within Pod) (within Pod) │ ││ └─────────────────────────────────────────────────────┘ ││ │ ││ 10.1.1.5:80 10.1.1.5:8080 ││ (from outside Pod) ││ ││ Within Pod: Use localhost ││ Between Pods: Use Pod IP ││ │└─────────────────────────────────────────────────────────────┘Мережева модель Пода навмисно простіша за традиційну мережу хостів. Kubernetes очікує, що кожен Под зможе спілкуватися з кожним іншим Подом без трансляції мережевих адрес усередині кластера, хоча мережеві політики та хмарна маршрутизація визначають, що насправді дозволено в конкретному середовищі. Практичний результат у тому, що автори застосунків можуть мислити категоріями IP Подів та Сервісів замість ручного зіставлення портів хоста. Операційний результат у тому, що IP Подів є одноразовими, тож стабільний клієнтський трафік має проходити через Сервіс, Інгрес, Gateway або інший продуманий рівень маршрутизації.
Сховище дотримується того самого патерну «спільний контекст, одноразовий Под». Под може визначати томи, а контейнери можуть монтувати ці томи за шляхами всередині своїх файлових систем. Том emptyDir створюється, коли Под призначається вузлу, і видаляється, коли Под прибирається з цього вузла, що робить його корисним для тимчасового простору та обміну файлами в межах одного Пода. Персистентне сховище використовує PersistentVolumeClaim та класи сховища, але Под усе одно монтує claim як том. Под — це місце, де сховище приєднується до запущеної репліки, а не місце, де слід приховувати тривалу власність застосунку.
Невелика довідкова таблиця допомагає зберегти точність порівняння контейнерів, уникаючи хибного мислення «або-або». Контейнери — це одиниці виконання, Поди — одиниці API Kubernetes, а контролери — менеджери бажаного стану, які створюють і замінюють Поди. Під час діагностики визначте, який рівень володіє симптомом, перш ніж щось змінювати. Збій контейнера може потребувати виправлень образу чи команди, збій планування Пода може потребувати виправлень ресурсів чи розміщення, а проблема розгортання Деплойменту може потребувати виправлень шаблону чи стратегії.
| Концепція | Сфера | Спільний контекст | Операційне питання |
|---|---|---|---|
| Контейнер | Одне середовище процесу | Спільне лише те, що надає Под | Чому цей процес запустився, зупинився чи відмовив? |
| Под | Одна планована одиниця Kubernetes | Мережевий простір імен та обрані томи | Чому ця репліка запланувалася, запустилася чи стала готовою? |
| Контролер | Бажаний стан над багатьма Подами | Шаблон Пода та цикл узгодження | Чому очікувані репліки відсутні чи не оновлені? |
| Сервіс | Стабільний доступ до обраних Подів | Віртуальний IP чи DNS-ім’я над ендпоінтами | Чому клієнти можуть чи не можуть дістатися справних реплік? |
Таблиця помилок початківців компактна, тому що ці чотири відмінності — мінімум концептуальних пасток. У зрілому кластері ті самі непорозуміння проявляються в дорожчих формах: дашборди, які сигналізують про статус контейнера, але ігнорують готовність Пода; скрипти, які звертаються до IP Подів напряму; та плани розгортання, що сприймають один замінний Под так, ніби це та сама машина, яка повертається в роботу. Тримайте таблицю поруч, діагностуючи пояснення початківця чи опис інциденту.
| Помилка | Чому це шкодить | Правильне розуміння |
|---|---|---|
| «Под = Контейнер» | Втрачена абстракція Пода | Под містить контейнер(и) |
| «Поди мають кілька IP» | Нерозуміння мережі | Один IP на Под, спільний для контейнерів |
| «Створюй Поди напряму» | Немає стійкості | Натомість використовуй Деплойменти |
| «Поди зберігаються після видалення» | Сприйняття як ВМ | Поди ефемерні |
Мережа та сховище також пояснюють, чому має значення готовність. Под може мати IP до того, як застосунок безпечно отримувати трафік, а контейнер може мати змонтований том до того, як дані всередині нього будуть готові. Проби готовності (readiness) дають Kubernetes специфічну для навантаження відповідь на питання «чи має цей Под отримувати трафік зараз?». Проби живучості (liveness) відповідають на інше питання: «чи слід перезапустити цей контейнер, бо він здається застряглим?». Проби запуску (startup) захищають застосунки з повільним стартом від убивства, перш ніж вони матимуть справедливий шанс ініціалізуватися. Жодна з цих проб не змінює того, чим є Под, але вони роблять статус Пода кориснішим для контролерів та маршрутизаторів трафіку.
Життєвий цикл Пода: від планування до завершення
Розділ «Життєвий цикл Пода: від планування до завершення»Діагностика життєвого циклу Пода починається з фаз, але фази — лише зовнішня оболонка істини. Под може бути Pending, Running, Succeeded, Failed чи Unknown, проте причина за цією фазою живе в умовах, станах контейнерів, подіях та власності контролера. KCNA очікує, що ви розпізнаєте базові фази, тоді як реальна експлуатація вимагає пов’язати фазу з наступною діагностичною командою. Звичка, яку треба виробити, проста: прочитайте фазу, а тоді одразу запитайте, який компонент відповідає за перехід, що не стався.
┌─────────────────────────────────────────────────────────────┐│ POD LIFECYCLE PHASES │├─────────────────────────────────────────────────────────────┤│ ││ Pending ──────→ Running ──────→ Succeeded/Failed ││ ││ PENDING: ││ • Pod accepted but not running yet ││ • Waiting for scheduling ││ • Waiting for image pull ││ ││ RUNNING: ││ • Pod bound to a node ││ • At least one container running ││ • Or starting/restarting ││ ││ SUCCEEDED: ││ • All containers terminated successfully ││ • Won't be restarted ││ • Common for Jobs ││ ││ FAILED: ││ • All containers terminated ││ • At least one failed (non-zero exit) ││ ││ UNKNOWN: ││ • Cannot get Pod state ││ • Usually communication error ││ │└─────────────────────────────────────────────────────────────┘Pending означає, що API-сервер прийняв об’єкт Пода, але Под не повністю запущений на вузлі. Це може означати, що планувальник ще не знайшов вузла, тому що запити ресурсів завеликі, селектори вузлів не збігаються, толерації не покривають taint-и, або квоти блокують допуск. Це також може означати, що Под уже призначено вузлу, але образ контейнера все ще завантажується. Це різні проблеми, тож корисна робоча інструкція не зупиняється на «Pending». Вона читає k describe pod, перевіряє події та визначає, який саме компонент є поточним блокувальником: планувальник, kubelet, середовище виконання контейнерів, реєстр образів чи рівень допуску.
Running означає, що Под прив’язаний до вузла й щонайменше один контейнер запущений або в процесі запуску чи перезапуску. Це не гарантує, що застосунок справний, доступний чи готовий до трафіку. Под може бути Running, поки його єдиний контейнер циклічно падає, поки сайдкар справний, а основний застосунок зламаний, або поки готовність хибна, бо застосунок не прогрів свої кеші. Саме тому виробничі дашборди, що сприймають Running як «добре», створюють сліпі зони. Для доступності сервісу готовність та членство в ендпоінтах зазвичай важать більше за широку фазу Пода.
Succeeded та Failed найбільше важать для скінченних навантажень, як-от Jobs, одноразові завдання обслуговування та пакетна обробка. Под Деплойменту зазвичай не має завершуватися у Succeeded, бо вебсервер має продовжувати працювати. Проте Под Job має завершитися у Succeeded, коли всі контейнери завершуються з кодом виходу нуль. Якщо Под Job неодноразово відмовляє, питання не «як мені втримати цей Под живим?», а «чому це скінченне завдання виходить із ненульовим кодом, і що далі робить політика повторів контролера Job?». Фаза Пода каже вам, що сталося з однією спробою; контролер каже, що буде далі.
Unknown — це симптом комунікації, а не діагноз застосунку. Площина управління не може визначити стан Пода, часто тому, що вузол недосяжний або kubelet припинив звітувати. Під час відмов вузлів саме тут відмінність між Подом та його власником стає операційно важливою. Прямо створений Под може залишатися в заплутаному стані до прибирання, тоді як навантаження під керуванням контролера може створити замінні Поди деінде відповідно до своєї логіки узгодження та правил порушення роботи.
Практичний потік діагностики починається з широкого переліку, переходить до детального опису, а потім перевіряє логи та події. Використовуйте k get pod -o wide, щоб дізнатися вузол, IP, готовність, перезапуски та вік. Використовуйте k describe pod, щоб побачити умови, стани контейнерів, повідомлення про завантаження образу, події планування та помилки монтування томів. Використовуйте k logs для виводу застосунку й додавайте -c <container>, коли Под має більше одного контейнера. Якщо контейнер перезапустився, k logs --previous часто дає єдину підказку від процесу, що відмовив.
k get pods -o widek describe pod pod-demok logs pod-demok logs pod-demo -c app --previousГіпотетичний сценарій: колись команда платформи гналася за «мережевим збоєм», бо клієнти бачили періодичні відповіді 503 після релізу. Усі Поди показували Running, що затримало розслідування. Справжньою проблемою була проба готовності, що вказувала на поверхневий TCP-порт замість ендпоінта здоров’я застосунку, тож Поди потрапляли до Сервісу, перш ніж завантажувався їхній кеш залежностей. Виправленням була не зміна мережі; це була краща проба готовності та політика розгортання, що поважала прогрів застосунку. Фаза Пода була технічно правдивою й операційно недостатньою.
Найкорисніше питання під час роботи з життєвим циклом — «хто може зробити цю зміну стану?». Планувальник може розмістити Под в очікуванні на вузлі, kubelet може запускати контейнери та звітувати про статус, середовище виконання контейнерів може завантажувати й запускати образи, застосунок може проходити чи не проходити проби, а контролери можуть створювати замінні Поди. Людина з k delete pod може змусити контролер створити нову репліку, але це допомагає лише тоді, коли власник і шаблон коректні. Видалення окремого Пода — це не зцілення; це усунення.
Власність над Подом: прямі Поди проти Деплойментів, Jobs та DaemonSets
Розділ «Власність над Подом: прямі Поди проти Деплойментів, Jobs та DaemonSets»Емпіричне правило навмисно різке: майже ніколи не створюйте Поди напряму для виробничих сервісів. Прямі Поди корисні для навчання, усунення несправностей та короткочасних експериментів, бо вони відкривають сирий об’єкт без машинерії контролерів. Виробничі навантаження потребують власності над бажаним станом. Деплоймент підтримує реплікований бездержавний сервіс, Job керує скінченною роботою, CronJob планує повторювану скінченну роботу, DaemonSet запускає один Под на обраному вузлі, а StatefulSet керує репліками зі станом, що мають стабільні ідентичності. Усі ці контролери створюють Поди, але вони відповідають на різні операційні питання.
┌─────────────────────────────────────────────────────────────┐│ POD vs DEPLOYMENT │├─────────────────────────────────────────────────────────────┤│ ││ Creating a Pod directly: ││ • Pod dies → It's gone ││ • No automatic restart ││ • No scaling ││ • Manual management ││ ││ Using a Deployment: ││ • Deployment manages Pods ││ • Pod dies → Deployment creates new one ││ • Easy scaling (replicas: 3) ││ • Rolling updates ││ ││ Rule of thumb: ││ ───────────────────────────────────────────────────────── ││ Almost NEVER create Pods directly ││ Use Deployments, Jobs, DaemonSets instead ││ │└─────────────────────────────────────────────────────────────┘Ця відмінність не академічна, бо кожен контролер кодує обіцянку відновлення. Деплоймент каже: «тримай доступними стільки реплік цього шаблону Пода й розгортай зміни шаблону поступово». Job каже: «виконуй це завдання, доки потрібні завершення не вдадуться або політика повторів не скаже зупинитися». DaemonSet каже: «забезпеч, щоб кожен відповідний вузол мав копію». Прямий Под не каже майже нічого з цього. Він записує інструкцію запустити контейнери як одну плановану одиницю, і щойно цей об’єкт зникає, Kubernetes не має бажаного стану вищого рівня для відновлення.
Оцінюючи, чи прийнятний окремий Под, запитайте, що має статися після відмови, видалення, розгортання, зміни масштабу та обслуговування вузла. Якщо відповідь містить «має з’явитися ще одна копія», «трафік має продовжувати текти», «мені потрібно кілька реплік» чи «мені потрібна історія розгортань», відповідь — не прямий Под. Якщо відповідь — «мені треба один раз відтворити проблему запуску контейнера», «мені треба тимчасовий мережевий тест» чи «я вивчаю поля у специфікації Пода», прямий Под може бути доречним. Інструмент не заборонено; він вузький.
Власність у Kubernetes також впливає на те, як ви інтерпретуєте мітки. Сервіс вибирає Поди за мітками, а не за іменами контролерів, тож прямий Под із відповідними мітками може випадково отримати виробничий трафік, якщо він поділяє селектори з реальним застосунком. Це одна з причин, чому тимчасові Поди мають використовувати чітко ізольовані мітки та простори імен. Мітки потужні, бо вони відв’язують маршрутизацію трафіку від імен об’єктів, але та сама відв’язаність може спрямувати трафік до хибної репліки, якщо ви недбало скопіюєте мітки з шаблону Деплойменту в експериментальний Под.
Зв’язок життєвого циклу між Деплойментом, ReplicaSet та Подом важитиме більше в наступному модулі, але концепція потрібна вам уже зараз. Деплоймент володіє ReplicaSet, а ReplicaSet володіє Подами, створеними з конкретного шаблону Пода. Під час плавного оновлення Деплоймент створює новий ReplicaSet і поступово переміщує репліки зі старого шаблону на новий. Под — це видимий об’єкт виконання, але посилання на власника (owner references) кажуть вам, який контролер відреагує, якщо цей Под зникне. У роботі з інцидентами перевірка OwnerReferences часто є різницею між безпечним видаленням та збоєм сервісу.
Якщо ви не впевнені, чи Под створено напряму, чи ним керує контролер, перевірте його власника. k get pod <name> -o yaml показує метадані, включно з посиланнями на власника, коли вони є. Под під керуванням Деплойменту зазвичай показує власника-ReplicaSet, а ReplicaSet, своєю чергою, належить Деплойменту. Прямий Под не має такого ланцюга. Ця відсутність — попередження для тривалих сервісів, бо немає контролера, який чекатиме, щоб замінити його після видалення чи втрати вузла.
k get pod pod-demo -o yamlk get pod pod-demo -o jsonpath='{.metadata.ownerReferences[0].kind}{"\n"}'Розбір прикладу: читати Под, як робочу інструкцію
Розділ «Розбір прикладу: читати Под, як робочу інструкцію»Сильна звичка з усунення несправностей Подів — читати ззовні всередину. Почніть із власника, бо власність каже вам, чи Под має бути замінений, повторений чи залишений у спокої. Потім прочитайте розміщення, бо призначення вузла каже вам, чи планувальник уже ухвалив рішення. Потім прочитайте стани контейнерів, бо саме там kubelet та середовище виконання контейнерів звітують про образ, команду, перезапуск та поведінку виходу. Нарешті прочитайте логи застосунку, бо логи пояснюють, що робив процес після того, як Kubernetes успішно передав йому середовище виконання.
Припустімо, платіжний обробник має один Под у стані CrashLoopBackOff, тоді як Деплоймент усе ще показує бажану кількість реплік. Перший корисний висновок — що контролер виконує свою роботу: у нього є Под, а kubelet неодноразово намагається запустити контейнер. Другий корисний висновок — що видалення Пода може створити заміну з тим самим зламаним шаблоном. Кращою першою дією є прочитати попередні логи контейнера та стан завершення, а потім вирішити, чи хибним є образ, команда, оточення, змонтований Secret чи конфігурація застосунку.
Тепер припустімо, що інший Под перебуває у стані Pending і не має призначеного вузла. Логи не допоможуть, бо жоден контейнер не запустився. Корисні докази живуть у подіях та обмеженнях планування: недостатньо пам’яті, непокриті taint-и, спорідненість вузла, що не відповідає жодному вузлу, відсутній PersistentVolume чи квота простору імен, що блокує запит. Перезбірка образу — марна праця в цій ситуації, бо процес застосунку не мав шансу запуститися. Це той вид відмінностей, який сценарії KCNA перевіряють опосередковано: правильний наступний крок залежить від того, який рівень володіє поточним станом.
Нарешті припустімо, що Под перебуває у Running, усі контейнери показують нуль перезапусків, а Сервіс усе одно не надсилає трафіку. Це не суперечність. Сервіс може вибирати мітки, яких Под не має, проба готовності може провалюватися, або контролер EndpointSlice може коректно виключати Под, бо він не готовий. Робоча інструкція має порівняти мітки, умови готовності та ендпоінти, перш ніж міняти образ контейнера. У Kubernetes доступність — це ланцюг об’єктів, і Под — лише одна ланка в цьому ланцюзі.
Цей розбір прикладу також пояснює, чому одна команда рідко доводить усю історію. k get pods — це зведення, а не діагноз. k describe pod додає події та умови, але може бути галасливим та історичним. k logs бачить лише вивід контейнера, а не рішення планувальника. Вивід YAML розкриває власність та точні поля специфікації, але може приховувати людську оповідь усередині сотень рядків. Досвідчені оператори переходять між цими виглядами, бо кожен відповідає на інше питання про той самий Под.
Остання дисципліна — відокремлювати спостереження від ремонту. Якщо контролер володіє Подом, а шаблон хибний, виправте шаблон контролера, а не латайте один замінний Под вручну. Якщо прямий Под існує лише для лабораторної роботи, його видалення може бути чистим скиданням. Якщо прямий Под несе виробничий трафік, видалення може бути збоєм. Та сама команда API може бути нешкідливою, корисною чи руйнівною залежно від власності, міток та маршрутизації трафіку, і саме тому грамотність щодо Подів важить ще до того, як ви потягнетеся за швидкими виправленнями.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Патерни допомагають обрати форму Пода, що відповідає операційній поведінці, якої ви насправді хочете. Той самий YAML може виглядати нешкідливо під час огляду й усе одно кодувати хибний життєвий цикл. Хороше проєктування Подів починається з рішення про те, які контейнери мають бути розміщені разом, які ресурси мають бути спільними, які залежності потребують незалежного контролю та який контролер має володіти поведінкою заміни. Наведені нижче патерни менше про запам’ятовування назв і більше про вироблення судження, щоб пояснити свій вибір під час інциденту чи огляду дизайну.
| Патерн | Коли застосовувати | Чому це працює | Міркування щодо масштабування |
|---|---|---|---|
| Один контейнер застосунку | Реплика бездержавного сервісу, обробник чи простий допоміжний процес | Тримає кожен Под зосередженим на одному основному процесі та одній моделі здоров’я | Масштабуйте репліки через Деплоймент, Job чи іншого власника |
| Помічник-сайдкар | Логування, проксі мережі, локальний експортер метрик чи помічник конфігурації, прив’язаний до кожної репліки | Поділяє localhost та томи, не змінюючи основний образ | Кожна репліка платить за CPU та пам’ять помічника |
| Налаштування через init-контейнер | Одноразова підготовка перед запуском контейнерів застосунку | Відокремлює логіку налаштування від тривалого образу застосунку | Тривалі очікування init затримують готовність і можуть приховувати проблеми залежностей |
| Шаблон Пода під контролером | Будь-яке виробниче навантаження, що має передбачувано відновлюватися, масштабуватися чи оновлюватися | Дозволяє контролерам узгоджувати бажаний стан після втрати Пода | Обирайте Деплоймент, Job, DaemonSet чи StatefulSet за поведінкою навантаження |
Антипатерни зазвичай постають із зручності під тиском. Прямий Под швидший за написання Деплойменту, база даних у тому ж Поді здається простішою за створення Сервісу, а копіювання міток із виробництва робить тестовий трафік легким. Ці скорочення небезпечні, бо вони розмивають межі власності. Kubernetes дає гострі інструменти для розміщення, ідентичності та вибірки, тож невелика помилка в YAML може змінити, хто отримує трафік, хто володіє відновленням і де живе стан.
| Антипатерн | Що йде не так | Краща альтернатива |
|---|---|---|
| Прямий Под для виробничого вебсервісу | Втрата Пода стає втратою сервісу, бо жоден контролер його не відтворює | Використовуйте Деплоймент із репліками та пробами |
| База даних у кожному Поді застосунку | Стан масштабується з репліками застосунку, а оновлення заплутуються | Запустіть базу даних як власний керований сервіс чи StatefulSet |
| Сайдкар для непов’язаної спільної залежності | Незалежний сервіс стає прив’язаним до життєвого циклу одного застосунку | Відкрийте залежність через Сервіс |
| Повторне використання виробничих міток на тестових Подах | Сервіси можуть надсилати реальний трафік до експериментів | Використовуйте ізольовані простори імен та мітки |
| Сприйняття Running як справного | Трафік може дістатися застосунку, що живий, але не готовий | Свідомо налаштуйте проби готовності, живучості та запуску |
Повторюваний патерн — спершу намалювати життєвий цикл. Якщо два процеси мають запускатися разом, поділяти файли та зникати разом, межа Пода може бути доречною. Якщо двом компонентам потрібна різна кількість реплік, вікна оновлення, термін зберігання даних чи команди-власники, помістіть їх за мережевий контракт замість того, щоб втискати в один Под. Kubernetes робить обидва варіанти можливими, тож робота інженера — зробити зв’язаність явною, перш ніж платформа нав’яже її вам.
Фреймворк ухвалення рішень
Розділ «Фреймворк ухвалення рішень»Використовуйте цей фреймворк ухвалення рішень, коли ви оглядаєте дизайн Пода, діагностуєте навантаження, що відмовило, чи відповідаєте на сценарій у стилі KCNA. Почніть із бізнес-поведінки, а потім зіставте її з власністю Kubernetes. Не починайте з «скільки контейнерів я можу втиснути в один Под?», бо це питання оптимізує форму YAML замість операційної коректності. Краще питання — «що Kubernetes має зберігати, замінювати, масштабувати та відкривати?».
Need to run workload? │ ├─ One-time or finite task? │ ├─ Yes → Job or CronJob owns the Pod template │ └─ No │ ├─ Long-running stateless service? │ ├─ Yes → Deployment owns replicated Pods │ └─ No │ ├─ One Pod on each selected node? │ ├─ Yes → DaemonSet owns Pods │ └─ No │ ├─ Stable identity or ordered stateful replicas? │ ├─ Yes → StatefulSet owns Pods │ └─ No │ └─ Temporary experiment or diagnostic? ├─ Yes → Direct Pod may be acceptable └─ No → Revisit workload requirementsДругий шар фреймворку вирішує, чи має Под містити один контейнер, чи кілька. Почніть з одного основного контейнера, бо він дає вам найчіткішу модель здоров’я, ресурсів, логів та розгортання. Додавайте сайдкар лише тоді, коли помічник має поділяти ту саму межу мережі чи сховища на рівні Пода, що й кожна репліка. Додавайте init-контейнер лише тоді, коли налаштування скінченне, детерміноване та безпечне для повторення. Якщо ви не можете пояснити спільну межу одним реченням, компоненти, ймовірно, належать до окремих Подів.
| Рішення | Обирайте це | Уникайте цього |
|---|---|---|
| Виробничий бездержавний API | Деплоймент з одним основним контейнером на Под | Прямий Под, скопійований із діагностичної команди |
| Збирач лог-файлів на репліку | Сайдкар зі спільним томом | Окремий Под, що зчитує файли вузла з широкими дозволами |
| Генерація файлів під час запуску | Init-контейнер, що пише у спільний том | Образ застосунку, роздутий специфічними для кластера скриптами налаштування |
| Спільний кеш чи база даних | Окремий контролер та Сервіс | Той самий Под, що й кожна репліка застосунку |
| Вузловий агент рівня кластера | DaemonSet | Вручну створений Под на обраних вузлах |
| Одноразовий ремонт даних | Job із явною поведінкою завершення | Тривалий Деплоймент, що одразу виходить |
Застосуйте фреймворк до прикладу з Redis у тесті. Якщо Redis — реальний кеш, спільний для кількох реплік застосунку, він має власний життєвий цикл і не повинен бути в тому самому Поді, що й застосунок. Якщо кожна репліка застосунку потребує крихітного одноразового локального кешу, дійсного лише для цієї репліки, помічник у тому ж Поді може мати сенс. Технічна різниця не «Redis особливий»; різниця в тому, чи залежність є одноразовою на репліку, чи спільною та незалежно експлуатованою.
Фреймворк стає кориснішим, коли ви пишете причину поруч із YAML. Коментар до огляду на кшталт «сайдкар поділяє emptyDir із застосунком, тож кожна репліка відвантажує власний локальний лог-файл» — чіткий та перевірний. Коментар на кшталт «Redis у Поді, бо localhost швидший» — це попередження, бо він оптимізує один шлях з’єднання, ігноруючи життєвий цикл і стан. Хороший дизайн Kubernetes фіксує, чому один компонент поділяє межу Пода, чому інший компонент отримує межу Сервісу й чому контролер володіє поведінкою заміни. Ці причини допомагають майбутнім операторам діагностувати систему, не перевідкриваючи дизайн із розкиданих маніфестів.
В екзаменаційних сценаріях стежте за дієсловами, що передбачають власність. «Масштабувати», «розгорнути», «замінити», «запустити на кожному вузлі», «завершити один раз» та «планувати щоночі» — це слова контролера, а не прямого Пода. Стежте за фразами, що передбачають спільний контекст, як-от «той самий локальний файл», «той самий мережевий простір імен», «проксі через localhost» чи «помічник на репліку». Ці фрази вказують на рішення щодо складу Пода. Якщо питання змішує два, спершу вирішіть власність, а потім склад. Добре спроєктований Деплоймент усе ще може мати поганий сайдкар, але ідеальний сайдкар усередині прямого виробничого Пода все одно залишає сервіс без семантики заміни.
Чи знали ви?
Розділ «Чи знали ви?»-
Поди ефемерні — їх спроєктовано бути одноразовими. Коли Под помирає, він зникає назавжди, і навіть заміна з тим самим згенерованим іменем є новим об’єктом із новим UID.
-
Контейнер pause — кожен Под має прихований контейнер «pause» (пісочниця), що утримує мережеві простори імен. Контейнери застосунку приєднуються до його простору імен, щоб поділяти IP Пода та localhost.
-
IP Пода внутрішній — IP Подів маршрутизуються лише в межах кластерної мережі. Ви не можете дістатися до них ззовні кластера без Сервісу, Інгресу, Gateway, port-forward чи іншого механізму відкриття.
-
Поди мають унікальні імена — у межах простору імен імена Подів мають бути унікальними. Контролери зазвичай додають згенеровані суфікси, як-от
nginx-7b8d6c-xk4dz, тож замінні Поди не вдають із себе той самий об’єкт.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому вона трапляється | Як її виправити |
|---|---|---|
| Сприйняття Пода як тривалого сервера | Традиційна експлуатація привчила команди ремонтувати іменовані машини на місці | Сприймайте Поди як замінні репліки й вкладайте тривалу поведінку в контролери, томи та Сервіси |
| Створення прямого Пода для виробничого сервісу | k run швидкий і дає миттєвий зворотний зв’язок під час експериментів | Використовуйте Деплоймент чи інший контролер, щоб Поди, які відмовили чи були видалені, відтворювалися |
Припущення, що Running означає готовність до трафіку | Фаза Пода видима, проста й легко виноситься на дашборд | Перевіряйте готовність, членство в ендпоінтах, стани контейнерів, перезапуски та логи застосунку |
| Розміщення спільних баз даних у Подах застосунку | Localhost здається простішим за виявлення через Сервіс | Запускайте залежності зі станом із власним життєвим циклом, сховищем, резервними копіями та мережевим контрактом |
| Забування, що контейнери в Поді поділяють один IP | Люди уявляють кожен контейнер як крихітну ВМ із власною адресою | Використовуйте різні порти на localhost усередині Пода й той самий IP Пода ззовні |
| Повторне використання виробничих селекторів на тимчасових Подах | Скопіювати YAML швидше, ніж проєктувати тестові мітки | Ізолюйте експерименти окремими просторами імен та мітками, перш ніж створювати Сервіси чи Поди |
| Ігнорування посилань на власника під час прибирання | Ім’я Пода виглядає як єдиний задіяний об’єкт | Перевіряйте власників перед видаленням, щоб знати, чи контролер замінить Под |
Тест
Розділ «Тест»Ваша команда розгорнула API оформлення замовлень як прямий Под під час інциденту. Вузол виводиться на обслуговування, і оформлення замовлень зникає. Що пішло не так у дизайні, і що має володіти поведінкою заміни?
Дизайн зазнав невдачі, тому що прямий Под записує один бажаний об’єкт виконання, але не підтримує кількість реплік після видалення чи втрати вузла. Тривалий бездержавний API оформлення замовлень зазвичай має належати Деплойменту, який створює ReplicaSets та замінні Поди за шаблоном. Деплоймент дає команді плавні оновлення, масштабування та узгодження замість покладання на людину, яка відтворюватиме Под. Негайним відновленням може бути створення Деплойменту з того самого шаблону, але тривким виправленням є усунення шляху розгортання через прямий Под.
Под перебуває у `Running`, але Сервіс не має готових ендпоінтів, і користувачі отримують відповіді 503. Що ви перевіряєте першим, і чому фази Пода недостатньо?
Почніть із перевірки статусу готовності, селекторів Сервісу, об’єктів ендпоінтів та подій k describe pod. Фаза Running лише каже, що Под прив’язаний до вузла й щонайменше один контейнер запущений або запускається; вона не доводить, що застосунок пройшов пробу готовності. Хибний селектор також може тримати справні Поди поза Сервісом. Правильний діагноз порівнює мітки Пода, умову готовності та членство в ендпоінтах Сервісу замість сприйняття фази як доступності.
Застосунок пише логи до `/var/log/app.log`, а збирач логів має надсилати цей файл до центральної системи. Чи має збирач бути сайдкаром, чи окремим спільним сервісом?
Сайдкар добре підходить, коли збирач прив’язаний до однієї репліки застосунку й потребує прямого доступу до шляху спільного тому. Застосунок пише файл, сайдкар читає той самий змонтований том, і обидва контейнери дотримуються того самого життєвого циклу репліки. Окремому спільному сервісу знадобився б інший механізм для читання файлу, що зазвичай означає ширші дозволи чи складніший дизайн сховища. Сайдкар усе одно потребує обмежень ресурсів та поведінки здоров’я, бо зламаний помічник може вплинути на кожну репліку.
Два контейнери в одному Поді обидва намагаються прив'язатися до порту 8080. Перший запускається, а другий відмовляє. Яка концепція Kubernetes пояснює цю відмову?
Контейнери в одному Поді поділяють один мережевий простір імен, тож з погляду прив’язки портів вони поводяться як процеси на тій самій машині. Лише один процес може слухати ту саму комбінацію адреси й порту одночасно. Виправлення — налаштувати окремі порти, як-от 8080 для застосунку та 9090 для помічника, або розділити контейнери на різні Поди, якщо їм не потрібна спільна поведінка localhost. Надання кожному контейнеру іншого імені не дає йому окремий IP Пода.
Под Job завершується у `Succeeded`, але Под Деплойменту, що завершується у `Succeeded`, був би підозрілим. Чому ці випадки означають різні речі?
Job спроєктовано для скінченної роботи, тож Succeeded означає, що завдання завершилося з успішними виходами контейнерів. Деплоймент зазвичай представляє тривалий сервіс, тож Под, що успішно вийшов, може означати, що процес застосунку завершився, коли від нього очікували продовження обслуговування. Ту саму фазу Пода слід інтерпретувати через власника та тип навантаження. Саме тому діагностика життєвого циклу включає посилання на власника та задум контролера, а не лише рядок фази.
Ваша команда хоче помістити Redis у той самий Под, що й кожна репліка API, для швидшого доступу через localhost. Який компроміс має змусити вас заперечити?
Розміщення Redis у кожному Поді API прив’язує життєвий цикл та масштаб кешу до реплік API. Якщо API масштабується до багатьох реплік, команда отримує багато екземплярів Redis, кожен зі своєю пам’яттю, даними, часом оновлення та поведінкою при відмові. Спільний кеш зазвичай потребує власного контролера, Сервісу, плану ресурсів, історії резервного копіювання, якщо дані важливі, та незалежного розгортання. Розміщення в тому ж Поді доречне лише тоді, коли кеш одноразовий і строго на репліку.
Под залишається у стані `Pending` після створення. Які категорії доказів допомагають вам діагностувати проблему життєвого циклу перед зміною образу застосунку?
Перевірте докази планування та kubelet, перш ніж змінювати код застосунку. Події k describe pod можуть показати недостатньо CPU чи пам’яті, невідповідність селектора вузла, непокриті taint-и, проблеми з квотою, помилки завантаження образу чи збої монтування томів. k get pod -o wide може показати, чи призначено вузол. Под в очікуванні часто означає, що платформа не може розмістити чи підготувати Под, тож перезбірка образу може бути не пов’язана з фактичним блокувальником.
Практична вправа
Розділ «Практична вправа»Ця вправа використовує тимчасовий простір імен та прямі Поди, бо мета — оглянути сиру поведінку Подів перед тим, як наступний модуль додасть контролери навантажень. Ви можете виконати її на локальному навчальному кластері чи в одноразовому просторі імен у спільному кластері. Тримайте прямі Поди поза виробничими мітками й видаліть простір імен після завершення, щоб жоден тимчасовий об’єкт не міг випадково збігтися з реальним селектором Сервісу.
- Впровадьте простір імен Kubernetes 1.35+ під назвою
pod-labі створіть одноконтейнерний Под з образомnginx:1.25, міткоюapp=pod-lab-web, портом контейнера 80 та помірними обмеженнями CPU й пам’яті. - Порівняйте вигляд контейнера та вигляд Пода за допомогою
k get pod -n pod-lab -o wide,k describe pod -n pod-labтаk logs -n pod-lab. - Спроєктуйте багатоконтейнерний Под у
pod-labз одним контейнером застосунку та одним сайдкаром, що поділяють томemptyDirдля простої передачі файлу. - Продіагностуйте проблему життєвого циклу Пода, навмисно використавши хибний тег образу, а потім огляньте фазу, умови, події та статус контейнерів, доки не зможете пояснити відмову.
- Оцініть, чи кожен Под у лабораторній роботі має залишитися окремим, чи бути під власністю Деплойменту, Job чи DaemonSet у реальному середовищі.
- Приберіть кожен об’єкт лабораторної роботи й підтвердьте, що простір імен більше не містить Подів.
Запропоноване рішення
Спершу створіть простір імен, а потім застосуйте маніфест Пода замість того, щоб покладатися лише на згенеровані команди. Маніфест має використовувати унікальну мітку, що не може перетнутися з виробничими селекторами. Після запуску Пода огляньте широкий вивід для вузла та IP, опишіть його для умов та подій і прочитайте логи з контейнера. Для завдання із сайдкаром змонтуйте той самий том emptyDir в обидва контейнери й зробіть так, щоб один контейнер писав файл, а інший читав чи обслуговував його. Для завдання з хибним образом використайте явно недійсний тег, як-от nginx:no-such-training-tag, а потім за допомогою подій та стану контейнера поясніть збій завантаження образу. Нарешті видаліть простір імен командою k delete namespace pod-lab і переконайтеся, що Подів не залишилося.
Критерії успіху
Ви завершили, коли можете вказати на IP Пода, ім’я вузла, мітки, посилання на власника, стани контейнерів, кількість перезапусків та останні події для кожного Пода лабораторної роботи. Ви також маєте вміти пояснити, чому одноконтейнерний Под простий, чому Под із сайдкаром поділяє мережу та сховище, чому Под зі зламаним образом є відмовою життєвого циклу, а не відмовою готовності застосунку, і чому виробничі сервіси слід перенести до контролерів. Якщо ви не можете пояснити, який контролер володів би реальною версією кожного Пода, повторіть фреймворк ухвалення рішень, перш ніж рухатися далі.
Джерела
Розділ «Джерела»- Документація Kubernetes: Pods
- Документація Kubernetes: Pod lifecycle
- Документація Kubernetes: Init containers
- Документація Kubernetes: Sidecar containers
- Документація Kubernetes: Workload resources
- Документація Kubernetes: Deployments
- Документація Kubernetes: Jobs
- Документація Kubernetes: DaemonSet
- Документація Kubernetes: Services
- Документація Kubernetes: Configure probes
- Документація Kubernetes: Resource management for Pods and containers
- Документація Kubernetes: Volumes
- GitLab: GitLab.com Database Incident
Наступний модуль
Розділ «Наступний модуль»Модуль 1.6: Ресурси робочих навантажень — Деплойменти, ReplicaSets, Jobs, DaemonSets та інші контролери, що керують Подами замість того, щоб залишати репліки напризволяще.