Модуль 1.6: Ресурси робочих навантажень
Складність:
[СЕРЕДНЯ]— базові концепції ресурсів.Час на проходження: 30–35 хвилин.
Передумови: Модуль 1.5 (Поди).
Контекст: Цей модуль припускає, що ви вмієте читати маніфест Пода й тепер маєте обрати контролер, який володітиме цими Подами у справжньому кластері.
Результати навчання
Розділ «Результати навчання»Після завершення цього модуля ви зможете робити вибір робочого навантаження, виходячи зі спостережуваних вимог, а не з заучених назв ресурсів:
- Порівнювати контролери робочих навантажень Kubernetes за ідентичністю Пода, життєвим циклом, областю планування та поведінкою під час оновлення.
- Проєктувати доречний вибір ресурсу робочого навантаження для застосунків без стану, систем зі станом, агентів на кожному вузлі, одноразових Job’ів та CronJob’ів.
- Діагностувати поведінку розгортання Деплойменту, простежуючи, як Деплойменти, ReplicaSet’и та Поди розподіляють володіння під час масштабування, оновлень та відкату.
- Впроваджувати базові ресурси робочих навантажень Kubernetes 1.35+ за допомогою команд
k, міток, селекторів та перевірок статусу.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Гіпотетичний сценарій: операційна команда переводить платіжний API з одного образу контейнера на інший і очікує, що Kubernetes утримає сервіс стабільним. Вони протестували новий образ, але розгорнули його як «голий» Под, бо так здавалося простіше під час попереднього спринту. Голий Под цілком підходить для швидкого тесту, проте він не переживає обслуговування вузла, якщо щось не створить його заново. Коли вузол, на якому розміщувався цей Под, було виведено з обслуговування для термінового патчу ядра, застосунок зник, доки людина не помітила невдалих покупок, не створила Под вручну й не відновила endpoint Сервісу. Корінною причиною був не зламаний контейнер і не загадковий збій платформи. Команда обрала неправильний ресурс робочого навантаження для цього завдання.
У протилежному сценарії інша команда розміщує кластеризовану базу даних у Деплойменті, бо Деплойменти були знайомими, ставлячись до замінних веб-рівнів та іменованих учасників бази даних як до однієї операційної проблеми, а потім спостерігає, як один Под-замінник повертається з новим іменем та іншою заявкою на том, ніж очікував учасник бази даних. Затримка реплікації зростала, доки застосунок повторно намагався записати дані, і інженери провели пів дня, відокремлюючи ідентичність сховища від мислення про розгортання без стану. Їхньою проблемою було не те, що Деплойменти погані; їхня проблема полягала в тому, що Деплойменти розв’язують інший клас задач, ніж StatefulSet’и, Job’и, CronJob’и та DaemonSet’и.
Цей модуль навчає навичці прийняття рішень, що стоїть за цими інцидентами. Kubernetes дає вам контролери, які стежать за бажаним станом і узгоджують Поди до цього стану, але кожен контролер несе інше обіцяння щодо ідентичності, тривалості життя, планування, поведінки оновлення та відновлення. KCNA очікує, що ви розпізнаєте ці обіцяння, а робота на продакшені очікує, що ви застосуєте їх ще до того, як напишете YAML. До кінця ви маєте вміти подивитися на вимогу застосунку й вирішити, чи потрібен їй Деплоймент, ReplicaSet, StatefulSet, DaemonSet, Job чи CronJob, а потім перевірити, що контролер виконує ту роботу, яку ви задумали.
Контролери перетворюють Поди на кероване навантаження
Розділ «Контролери перетворюють Поди на кероване навантаження»Под — це найменша одиниця запуску в Kubernetes, але Под сам по собі ближчий до окремого процесу, ніж до стратегії керування застосунком. Якщо цей Под завершується, переміщується або потребує нового образу, контролер вищого рівня має вирішити, що станеться далі. Ресурси робочих навантажень — це і є ці контролери вищого рівня. Вони утримують бажаний стан, порівнюють його з поточним станом кластера й діють, доки ці два стани не збігатимуться достатньо близько для правил контролера.
Ключова ментальна модель — це узгодження. Ви оголошуєте, що хочете три веб-Поди, по одному збирачу логів на кожному вузлі, учасника бази даних на ім’я mysql-0 або міграцію, яка завершується один раз. Контролери Kubernetes постійно запитують: «Що існує зараз, що має існувати і яка зміна наближає реальність до запиту?» Саме цей цикл пояснює, чому видалення Пода, створеного Деплойментом, зазвичай призводить до заміни, тоді як видалення завершеного Пода Job’а не означає, що Job має працювати вічно.
Початкова діаграма ієрархії варта збереження, бо вона показує найпоширеніший ланцюг контролерів, який ви зустрінете першим. Деплоймент — це не більш декоративний файл Пода. Він керує ReplicaSet’ами, а ці ReplicaSet’и керують Подами. Цей додатковий рівень дає Kubernetes місце для представлення старої та нової версій під час розгортання, через що Деплоймент може скасувати поганий реліз, не змушуючи вас пам’ятати кожен попередній шаблон Пода вручну.
┌─────────────────────────────────────────────────────────────┐│ WORKLOAD RESOURCE HIERARCHY │├─────────────────────────────────────────────────────────────┤│ ││ You create: Deployment ││ │ ││ │ creates & manages ││ ▼ ││ Auto-created: ReplicaSet ││ │ ││ │ creates & manages ││ ▼ ││ Auto-created: Pod Pod Pod ││ ││ Why this hierarchy? ││ ───────────────────────────────────────────────────────── ││ • Deployment: Handles updates and rollbacks ││ • ReplicaSet: Maintains desired number of Pods ││ • Pod: Runs the actual containers ││ │└─────────────────────────────────────────────────────────────┘Контролери також використовують мітки та селектори як свою мову володіння. ReplicaSet володіє не кожним Подом, який випадково запускає той самий образ; він володіє Подами, що відповідають його селектору, і створює Поди зі свого шаблону, коли відповідних Подів бракує. Ця деталь має значення, бо помилки в селекторах можуть створити осиротілі Поди, несподіване усиновлення або двох контролерів, що б’ються за одну й ту саму форму застосунку. Мітки виглядають дрібними, але саме вони є клеєм між наміром контролера й реальністю Пода.
Уявіть собі контролер робочого навантаження радше як експедитора на кухні, ніж як кухаря. Под готує страву, запускаючи контейнери, тоді як контролер стежить за дошкою замовлень і утримує кухню укомплектованою під поточний попит. Експедитор-Деплоймент дбає про стабільне обслуговування та контрольовані заміни. Експедитор-Job дбає про те, щоб скінченне завдання завершилося. Експедитор-DaemonSet дбає про те, щоб на кожній станції був саме той агент, який їй потрібен.
Зупиніться й передбачте: якщо Деплоймент хоче три репліки, а ви вручну видаляєте один із його Подів, який об’єкт першим помічає відсутній Под і чому Деплоймент не потребує, щоб ви запускали другу команду? Ваша відповідь має згадати селектор та бажану кількість реплік, бо саме ці факти контролер може спостерігати.
Питання KCNA часто формулюють це як вибір ресурсу, але реальні операції формулюють це як наслідок. Чи збереже Под-замінник те саме ім’я? Чи створить контролер Под на новому вузлі автоматично? Чи зупиняє успішне завершення робоче навантаження, чи платформа трактує вихід як збій і перезапускає його? Ці питання надійніші за заучування списку, бо вони безпосередньо відображають обіцяння, які дає кожен ресурс робочого навантаження.
Наведена нижче таблиця є попереднім оглядом поверхні рішень. Не сприймайте її як заміну решти модуля; сприймайте її як стислу карту, до якої ви повернетеся після того, як побачите, як кожен контролер поводиться під впливом змін. Найкорисніший стовпець — це ідентичність Пода, бо ідентичність часто розкриває, чи керуєте ви замінними працівниками застосунку, чи іменованими учасниками скоординованої системи.
| Ресурс | Призначення | Ідентичність Пода | Масштабування / оновлення |
|---|---|---|---|
| Deployment | Застосунки без стану | Випадкові імена | Декларативна кількість + історія розгортань |
| ReplicaSet | Підтримання кількості | Випадкові імена | Декларативна кількість, без API розгортання |
| StatefulSet | Застосунки зі станом | Стабільні імена | Упорядкована, стабільна ідентичність |
| DaemonSet | Агент на кожен вузол | На кожен вузол | По одному на вузол |
| Job | Виконання до завершення | Тимчасові | До завершення |
| CronJob | Заплановані Job’и | Тимчасові | За розкладом |
Деплойменти та ReplicaSet’и керують змінами без стану
Розділ «Деплойменти та ReplicaSet’и керують змінами без стану»Деплоймент — це повсякденний ресурс робочого навантаження для застосунків без стану, таких як вебсервери, API-сервіси, фонові обробники, які можна вільно замінювати, та невеликі внутрішні інструменти, що зберігають довговічні дані десь в іншому місці. «Без стану» не означає, що застосунок узагалі не має даних. Це означає, що будь-який окремий Под може зникнути й бути заміненим без втрати унікального локального стану, необхідного для коректності, бо довговічний стан утримується в базі даних, черзі, об’єктному сховищі чи іншому сервісі, спроєктованому для зберігання.
Деплойменти існують, бо застосунки на продакшені змінюються. Ви масштабуєте їх, розгортаєте нові образи, скасовуєте погані версії та перевіряєте статус, доки трафік ще тече. Голий Под не може надати таку історію релізів, а прямий ReplicaSet може підтримувати кількість реплік, але не дає вам того самого інтерфейсу розгортання. Деплоймент володіє стратегією розгортання, створює ReplicaSet’и для версій шаблону Пода й використовує ці ReplicaSet’и, щоб переносити потужність зі старого на нове, не скидаючи бажану форму сервісу одразу всю.
Збережена діаграма Деплойменту дає практичну картину. Ви кажете: «Я хочу три репліки цього шаблону», і Kubernetes створює об’єкти нижчого рівня, щоб це стало правдою. Згенеровані імена Подів не є контрактними ідентичностями; це деталі реалізації. Якщо один Под помирає, замінник з іншим суфіксом є прийнятним, бо кожна репліка має бути рівноцінною з погляду застосунку.
┌─────────────────────────────────────────────────────────────┐│ DEPLOYMENT │├─────────────────────────────────────────────────────────────┤│ ││ What it does: ││ ───────────────────────────────────────────────────────── ││ • Declaratively manages ReplicaSets and Pods ││ • Provides rolling updates ││ • Supports rollbacks ││ • Scales applications up/down ││ ││ Example: ││ ───────────────────────────────────────────────────────── ││ "I want 3 replicas of nginx:1.25" ││ ││ ┌─────────────────────────────────────────────────────┐ ││ │ Deployment: nginx │ ││ │ replicas: 3 │ ││ │ image: nginx:1.25 │ ││ │ │ ││ │ └─→ ReplicaSet: nginx-7b8d6c │ ││ │ │ │ ││ │ ├─→ Pod: nginx-7b8d6c-abc12 │ ││ │ ├─→ Pod: nginx-7b8d6c-def34 │ ││ │ └─→ Pod: nginx-7b8d6c-ghi56 │ ││ └─────────────────────────────────────────────────────┘ ││ ││ When to use: Stateless applications ││ │└─────────────────────────────────────────────────────────────┘Діаграма розгортання показує, чому проміжний рівень важливий. Під час оновлення образу Деплоймент не змінює старий ReplicaSet на місці. Він створює новий ReplicaSet для нового шаблону Пода, а потім масштабує старий і новий ReplicaSet’и відповідно до стратегії розгортання. Це дає Kubernetes дві видимі версії, які можна порівнювати, призупиняти, масштабувати та відкочувати, замість одного розмитого об’єкта, чию історію вже перезаписано.
┌─────────────────────────────────────────────────────────────┐│ ROLLING UPDATE │├─────────────────────────────────────────────────────────────┤│ ││ Update from nginx:1.25 to nginx:1.26: ││ ││ Step 1: Create new ReplicaSet ││ ┌─────────────────────────────────────────────────────┐ ││ │ Old RS (nginx:1.25): ●●● (3 pods) │ ││ │ New RS (nginx:1.26): ○ (1 pod starting) │ ││ └─────────────────────────────────────────────────────┘ ││ ││ Step 2: Scale new up, old down ││ ┌─────────────────────────────────────────────────────┐ ││ │ Old RS (nginx:1.25): ●● (2 pods) │ ││ │ New RS (nginx:1.26): ○○ (2 pods) │ ││ └─────────────────────────────────────────────────────┘ ││ ││ Step 3: Complete ││ ┌─────────────────────────────────────────────────────┐ ││ │ Old RS (nginx:1.25): (0 pods, kept for rollback)│ ││ │ New RS (nginx:1.26): ○○○ (3 pods) │ ││ └─────────────────────────────────────────────────────┘ ││ ││ Benefits: ││ • Zero downtime ││ • Gradual rollout ││ • Rollback available via revision history (`k rollout undo`) ││ │└─────────────────────────────────────────────────────────────┘Слово «автоматично» в обговореннях розгортання потребує обережності. Kubernetes автоматично узгоджується з тим розгортанням, яке ви оголосили, і він може перестати вважати розгортання справним, коли перевищено дедлайни поступу, але він не знає магічно вашу бізнес-метрику чи правило сумісності бази даних. Деплоймент може сказати вам, що нові Поди не стають доступними, а k rollout undo може повернутися до попереднього ReplicaSet’а, але вам усе одно потрібні проби готовності, моніторинг та дисципліна релізів, щоб вирішити, коли відкат є правильною операційною дією.
ReplicaSet’и — це механізм підрахунку, що лежить під Деплойментами. Основна відповідальність ReplicaSet’а проста: гарантувати, що існує задана кількість відповідних Подів. Якщо селектору відповідає замало Подів, він створює більше зі шаблону. Якщо відповідає забагато Подів, він видаляє зайві. Така поведінка потужна, але вона навмисно вужча за поведінку керування релізами Деплойменту, через що більшість команд застосунків не повинні створювати ReplicaSet’и напряму.
┌─────────────────────────────────────────────────────────────┐│ REPLICASET │├─────────────────────────────────────────────────────────────┤│ ││ What it does: ││ ───────────────────────────────────────────────────────── ││ • Ensures specified number of Pods are running ││ • Creates new Pods if too few ││ • Deletes Pods if too many ││ • Uses labels to identify Pods it owns ││ ││ Example: ││ ───────────────────────────────────────────────────────── ││ ReplicaSet wants: 3 pods ││ Currently: 2 pods ││ Action: Create 1 more pod ││ ││ ReplicaSet wants: 3 pods ││ Currently: 4 pods ││ Action: Delete 1 pod ││ ││ Important: ││ ───────────────────────────────────────────────────────── ││ You rarely create ReplicaSets directly! ││ Use Deployments—they manage ReplicaSets for you. ││ │└─────────────────────────────────────────────────────────────┘Корисний практичний приклад починається з крихітного Деплойменту. Наведений нижче маніфест націлений на Kubernetes 1.35+ і використовує мітки, що пов’язують селектор Деплойменту з шаблоном Пода. Мітка app: quote-api — це не прикраса; це контракт, який повідомляє контролеру, які Поди зараховуються до бажаної кількості реплік. Якщо мітки селектора й шаблону не збігаються, API-сервер відхиляє Деплоймент, бо контролер ніколи не зміг би безпечно керувати власними Подами.
apiVersion: apps/v1kind: Deploymentmetadata: name: quote-api labels: app: quote-apispec: replicas: 3 selector: matchLabels: app: quote-api template: metadata: labels: app: quote-api spec: containers: - name: quote-api image: nginx:1.26 ports: - containerPort: 80 readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 3 periodSeconds: 5Упродовж усіх практичних команд у цьому модулі k означає інструмент командного рядка kubectl. Якщо ваша оболонка ще не визначає цей скорочений запис, виконайте псевдонім один раз у поточному сеансі термінала, перш ніж використовувати команди на кшталт k get deploy, k describe rs та k rollout status.
alias k=kubectlПерш ніж це запускати, який вивід ви очікуєте від k get deploy,rs,pod -l app=quote-api після застосування Деплойменту? Важливе передбачення — це не точний згенерований суфікс. Важливе передбачення в тому, що ви маєте побачити один Деплоймент, один активний ReplicaSet для поточного шаблону та три Поди, чиї імена містять хеш ReplicaSet’а, бо саме ReplicaSet їх створив.
Ланцюг володіння стає видимим зі звичайними командами перевірки. k get deployment quote-api -o wide повідомляє вам кількість бажаних, оновлених, готових та доступних реплік. k get rs -l app=quote-api показує ReplicaSet, який задовольняє поточний шаблон. k describe deployment quote-api показує події та умови розгортання, які часто є найшвидшим способом помітити проблему завантаження образу, збій проби готовності або розгортання, що не просувається.
k apply -f quote-api-deployment.yamlk get deploy,rs,pod -l app=quote-apik describe deployment quote-apik rollout status deployment/quote-apiКоли образ змінюється, Деплоймент створює новий ReplicaSet, бо змінився шаблон Пода. Масштабування реплік із трьох до п’яти, навпаки, змінює бажану потужність, не обов’язково створюючи новий ReplicaSet, бо шаблон може залишитися тим самим. Ця відмінність допомагає в усуненні несправностей: новий ReplicaSet натякає на ревізію шаблону, тоді як змінена кількість реплік натякає на тиск масштабування чи ручне коригування потужності.
k set image deployment/quote-api quote-api=nginx:1.27k rollout status deployment/quote-apik get rs -l app=quote-apik rollout history deployment/quote-apiГіпотетичний сценарій: одна команда колись подумала, що розгортання провалилося, бо старі ReplicaSet’и все ще були видимі після успішного релізу. Вони видалили старі ReplicaSet’и, щоб «прибрати», а потім виявили, що прибрали найлегший шлях відкату за лічені хвилини до появи регресії на боці клієнта. Старий ReplicaSet із нульовою кількістю реплік був не сміттям; це була історія ревізій, представлена як об’єкт Kubernetes.
Деплойменти — правильний типовий вибір для замінних реплік застосунку, але вони не є універсальною відповіддю. Якщо ім’я Пода стає частиною членства в кластері, якщо кожна репліка потребує унікального персистентного тому, якщо завдання має зупинитися після успіху або якщо один Под має працювати на кожному вузлі, сильні сторони Деплойменту стають невідповідностями. Хороше проєктування в Kubernetes починається з питання, яке обіцяння потрібне робочому навантаженню, перш ніж обирати знайомий ресурс.
StatefulSet’и зберігають ідентичність та сховище
Розділ «StatefulSet’и зберігають ідентичність та сховище»StatefulSet’и обслуговують застосунки, де кожна репліка має довговічну ідентичність. Учаснику бази даних, вузлу брокера повідомлень або кластеризованому процесу координації може знадобитися стабільне ім’я хоста, порядковий номер та сховище, яке залишається асоційованим із цим учасником під час перепланування. Деплоймент може відтворити потужність, але він трактує репліки як взаємозамінні. StatefulSet каже, що mysql-0 — це не просто «якийсь Под бази даних»; це іменований учасник з ідентичністю, яку інші учасники можуть розпізнати.
Збережена діаграма StatefulSet’а охоплює ці гарантії. Імена передбачувані, заявки на томи прив’язані до порядкової ідентичності, а запуск чи завершення можна впорядкувати. Цей порядок не церемоніальний. Багатьом системам зі станом потрібно, щоб первинний учасник ініціалізувався перш ніж приєднаються підлеглі, або потрібне коректне завершення, щоб учасник міг залишити кворум, не пошкодивши припущень про реплікацію.
┌─────────────────────────────────────────────────────────────┐│ STATEFULSET │├─────────────────────────────────────────────────────────────┤│ ││ What it provides: ││ ───────────────────────────────────────────────────────── ││ • Stable, unique network identifiers ││ • Stable, persistent storage ││ • Ordered, graceful deployment and scaling ││ • Ordered, graceful deletion and termination ││ ││ Example: Database cluster ││ ───────────────────────────────────────────────────────── ││ ┌─────────────────────────────────────────────────────┐ ││ │ StatefulSet: mysql │ ││ │ │ ││ │ mysql-0 ──→ PVC: mysql-data-0 (10GB) │ ││ │ mysql-1 ──→ PVC: mysql-data-1 (10GB) │ ││ │ mysql-2 ──→ PVC: mysql-data-2 (10GB) │ ││ │ │ ││ │ DNS: mysql-0.mysql.default.svc.cluster.local │ ││ └─────────────────────────────────────────────────────┘ ││ ││ Key differences from Deployment: ││ • Pods get persistent names (mysql-0, mysql-1) ││ • Each Pod gets its own PVC ││ • Created in order (0, then 1, then 2) ││ ││ When to use: Databases, clustered apps, ordered startup ││ │└─────────────────────────────────────────────────────────────┘Ідентичність StatefulSet’а має дві основні частини: порядкове іменування та стабільну мережеву ідентичність. Поди іменуються з нуля й вище, наприклад mysql-0, mysql-1 та mysql-2. За допомогою headless-Сервісу кожен Под також може отримати стабільне DNS-ім’я. Це дає кластеризованому ПЗ надійний спосіб формувати списки однорангових учасників та зберігати ролі, навіть якщо базовий вузол чи середовище виконання контейнерів можуть змінюватися з часом.
Сховище — це друга половина. StatefulSet може використовувати volumeClaimTemplates, щоб кожен Под отримував власну заявку на персистентний том (PersistentVolumeClaim), похідну від того самого шаблону. Коли mysql-1 переплановується, він має повернутися із заявкою на сховище для mysql-1, а не позичити випадковий том в іншого учасника. У цьому полягає різниця між масштабуванням взаємозамінних працівників та керуванням іменованими учасниками довговічної системи.
apiVersion: apps/v1kind: StatefulSetmetadata: name: mysqlspec: serviceName: mysql replicas: 3 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:8.4 ports: - containerPort: 3306 name: mysql volumeMounts: - name: mysql-data mountPath: /var/lib/mysql volumeClaimTemplates: - metadata: name: mysql-data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10GiЦей маніфест навмисно неповний для продакшен-бази даних, бо облікові дані, проби, конфігурація, резервне копіювання та операційна безпека потребують більшого проєктування. Він достатньо повний, щоб навчити обіцянню контролера: StatefulSet володіє іменованими Подами, а шаблон заявки на том створює сховище для кожного Пода. Питання рівня KCNA зазвичай зосередиться на цьому виборі контролера, а не на повному тягарі адміністрування бази даних.
Зупиніться й подумайте: кластеру бази даних потрібні Поди зі стабільними мережевими ідентичностями на кшталт mysql-0, mysql-1 та mysql-2, які зберігаються між перезапусками. Чому звичайний Деплоймент не може цього забезпечити, і що сталося б із налаштуванням реплікації бази даних, якби імена Подів були випадковими? Сильна відповідь відокремлює ідентичність на рівні застосунку від простої кількості реплік.
StatefulSet’и також змінюють те, як ви міркуєте про зменшення масштабу. Видалення репліки з Деплойменту зазвичай видаляє взаємозамінного працівника. Видалення репліки StatefulSet’а спершу видаляє Под із найбільшим порядковим номером, а його заявка на персистентний том може залишитися заради безпеки залежно від політики збереження та налаштування сховища. Така консервативна поведінка запобігає випадковій втраті даних, але вона також означає, що очищення є навмисною операцією зі сховищем, а не автоматичним побічним ефектом.
Компроміс — це операційна складність. StatefulSet’и дають сильніші гарантії ідентичності, але вони не роблять ПЗ зі станом простим. Вам усе одно потрібно розуміти резервне копіювання, відновлення, оновлення, кворум, продуктивність сховища та режими відмов самого застосунку. Kubernetes надає стабільну оболонку; він не перетворює кожну базу даних на саморегенерувальну розподілену систему.
Використовуйте StatefulSet, коли протокол застосунку дбає про іменованих учасників, упорядковані зміни чи довговічне сховище для кожної репліки. Використовуйте Деплоймент, коли репліки навмисно замінні й будь-який Под може обробити будь-який запит після того, як стане готовим. Ця відмінність важливіша за те, чи «має застосунок дані» в розпливчастому сенсі, бо багато сервісів без стану читають і записують дані через зовнішні системи, не потребуючи локальної ідентичності.
DaemonSet’и розміщують агентів на вузлах
Розділ «DaemonSet’и розміщують агентів на вузлах»DaemonSet’и розв’язують іншу проблему планування: запустити копію Пода на обраних вузлах. Звичні приклади — це збирачі логів, агенти метрик, мережеві компоненти, локальні для вузла, та драйвери сховища. Ці робочі навантаження не масштабуються за обсягом запитів так само, як репліки застосунку. Їхнє завдання — супроводжувати вузли, спостерігати за вузлами чи надавати функціональність на рівні вузла, тож одиницею планування є вузол, а не довільна кількість реплік.
Збережена діаграма DaemonSet’а показує, чому Деплоймент є неправильною абстракцією для цього випадку. Деплоймент із чотирма репліками може розмістити два Поди на одному вузлі, один на іншому й жодного на третьому залежно від обмежень планування та доступної потужності. DaemonSet прив’язує бажаний стан до членства вузлів. Коли приєднується новий придатний вузол, DaemonSet має створити Под там; коли вузол вибуває, асоційований Под зникає разом із ним.
┌─────────────────────────────────────────────────────────────┐│ DAEMONSET │├─────────────────────────────────────────────────────────────┤│ ││ What it does: ││ ───────────────────────────────────────────────────────── ││ • Runs one Pod per node ││ • Automatically adds Pod when new node joins ││ • Removes Pod when node leaves ││ ││ Example: Log collector ││ ───────────────────────────────────────────────────────── ││ ││ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ │ Node 1 │ │ Node 2 │ │ Node 3 │ │ Node 4 │ ││ │┌───────┐│ │┌───────┐│ │┌───────┐│ │┌───────┐│ ││ ││fluent-││ ││fluent-││ ││fluent-││ ││fluent-││ ││ ││ bit ││ ││ bit ││ ││ bit ││ ││ bit ││ ││ │└───────┘│ │└───────┘│ │└───────┘│ │└───────┘│ ││ └─────────┘ └─────────┘ └─────────┘ └─────────┘ ││ ││ Common use cases: ││ • Log collectors (Fluentd, Fluent Bit) ││ • Monitoring agents (Prometheus Node Exporter) ││ • Network plugins (CNI) ││ • Storage drivers ││ │└─────────────────────────────────────────────────────────────┘DaemonSet’и все одно використовують шаблони Подів, мітки, стратегії оновлення та правила планування, але їхня кількість реплік виводиться з придатних вузлів. Ви можете обмежити придатність за допомогою селекторів вузлів, спорідненості вузлів (node affinity) або taint’ів і toleration’ів, що поширене, коли агент має працювати лише на Linux-вузлах, GPU-вузлах, вузлах сховища чи в певному пулі вузлів. Обіцяння контролера — «по одному на кожен відповідний вузол», а не «N реплік десь».
apiVersion: apps/v1kind: DaemonSetmetadata: name: node-observer namespace: kube-systemspec: selector: matchLabels: app: node-observer template: metadata: labels: app: node-observer spec: containers: - name: node-observer image: busybox:1.36 command: ["sh", "-c", "while true; do date; sleep 30; done"]Операційний режим відмови легко пропустити. Якщо ви розгорнете збирач логів як Деплоймент, а потім масштабуєте кластер, деякі вузли можуть так і не запустити збирач, а це означає, що інциденти на цих вузлах залишають менше слідів. Якщо ви розгорнете бізнес-API як DaemonSet просто щоб «розкидати його», ви прив’яжете потужність застосунку до кількості вузлів і ускладните звичайне автомасштабування. Контролер має відповідати одиниці потреби.
DaemonSet’и також задіяні в інфраструктурі кластера, через що вони можуть здаватися складнішими за Деплойменти в повсякденній роботі із застосунками. Мережеві плагіни, компоненти інтерфейсу сховища та експортери вузлів часто живуть як DaemonSet’и, бо кожному вузлу потрібна локальна допомога, перш ніж робочі навантаження вищого рівня поводитимуться нормально. Під час усунення прогалини у спостережуваності в масштабі кластера k get daemonset -A може сказати вам, чи присутні агенти рівня вузла справді скрізь, де вони мають бути.
Який підхід ви б тут обрали й чому: API виявлення шахрайства, якому потрібно десять реплік під час пікового трафіку, чи експортер метрик, який має читати локальні файли вузла на кожному робочому вузлі? Перший хоче Деплоймент, бо репліки — це взаємозамінна сервісна потужність. Другий хоче DaemonSet, бо вимогою є охоплення вузлів.
Job’и та CronJob’и моделюють скінченну роботу
Розділ «Job’и та CronJob’и моделюють скінченну роботу»Не кожне робоче навантаження має працювати вічно. Міграція, резервне копіювання, генератор звітів, очищення образів чи імпорт даних можуть мати чітку фінішну межу. Якщо ви помістите це завдання в Деплоймент, Kubernetes інтерпретує вихід контейнера як проблему, бо Деплойменти спроєктовані тримати Поди застосунку запущеними. Job перевертає це припущення: успішне завершення є бажаним кінцевим станом, а поведінка повторних спроб існує, щоб допомогти завданню надійно досягти цього кінцевого стану.
Збережена діаграма Job’а показує скінченний контракт. Job створює Поди, стежить за їхнім статусом виходу, повторює спроби після збоїв у межах налаштованих лімітів і фіксує завершення. Параметри на кшталт completions, parallelism та backoffLimit дають змогу виразити, чи має робота виконатися один раз, багато разів, чи з контрольованою паралельністю. Це інша поверхня проєктування, ніж у Деплойменту, чия основна турбота — доступна сервісна потужність.
┌─────────────────────────────────────────────────────────────┐│ JOB │├─────────────────────────────────────────────────────────────┤│ ││ What it does: ││ • Creates Pods that run to completion ││ • Retries if Pod fails ││ • Tracks successful completions ││ ││ Example: Database backup ││ Job "backup" → Creates Pod → Pod runs backup → Completes ││ ││ Options: ││ • completions: 5 (run 5 times total) ││ • parallelism: 2 (run 2 at a time) ││ • backoffLimit: 3 (retry 3 times on failure) ││ │└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐│ CRONJOB │├─────────────────────────────────────────────────────────────┤│ ││ What it does: ││ • Creates Jobs on a schedule ││ • Uses cron syntax ││ ││ Example: Nightly backup ││ schedule: "0 2 * * *" # Every day at 2 AM ││ ││ ┌──────┐ ┌──────┐ ┌──────┐ ││ │ Day 1│ │ Day 2│ │ Day 3│ ││ │ 2 AM │ │ 2 AM │ │ 2 AM │ ││ │ ↓ │ │ ↓ │ │ ↓ │ ││ │ Job │ │ Job │ │ Job │ ││ └──────┘ └──────┘ └──────┘ ││ │└─────────────────────────────────────────────────────────────┘Маніфест Job’а часто невеликий, але семантика важлива. Політика перезапуску для Подів Job’а зазвичай Never або OnFailure, а не Always, бо контролер Job’а відповідає за відстеження спроб та завершень. backoffLimit запобігає нескінченним циклам повторних спроб, коли погана команда, відсутня конфігурація чи недоступна залежність інакше продовжували б спалювати ресурси кластера без поступу.
apiVersion: batch/v1kind: Jobmetadata: name: schema-checkspec: backoffLimit: 3 template: spec: restartPolicy: Never containers: - name: schema-check image: busybox:1.36 command: ["sh", "-c", "echo checking schema; sleep 5; echo complete"]CronJob’и додають планування поверх Job’ів. CronJob не запускає вашу команду напряму; він створює Job’и відповідно до cron-виразу, а ці Job’и створюють Поди. Цей додатковий рівень дає вам ліміти історії, політику паралельності, призупинення, обробку пропущених розкладів та поведінку часових поясів. Якщо розклад є продуктовою вимогою, використовуйте CronJob. Якщо людина чи конвеєр запускає скінченне завдання за потреби, використовуйте Job.
apiVersion: batch/v1kind: CronJobmetadata: name: nightly-schema-checkspec: schedule: "0 2 * * *" concurrencyPolicy: Forbid successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 3 jobTemplate: spec: template: spec: restartPolicy: Never containers: - name: schema-check image: busybox:1.36 command: ["sh", "-c", "date; echo complete"]Найпоширеніша несподіванка CronJob’а — це накладання. Якщо нічне завдання інколи триває довше за добу, чи має наступний запуск усе одно стартувати, пропуститися чи замінити старий запуск? Kubernetes відкриває цей вибір через concurrencyPolicy. Allow дозволяє накладання, Forbid пропускає новий запуск, доки попередній ще активний, а Replace зупиняє поточний запуск і стартує новий. Жодна не є універсально правильною; правильна відповідь залежить від того, чи безпечне дублювання роботи.
Job’и та CronJob’и також мають звички спостережуваності, що відрізняються від Деплойментів. Завершений Job може не мати запущених Подів, тож сам по собі k get pods може ввести вас в оману, ніби нічого не сталося. Перевіряйте k get jobs, k describe job та логи Подів, доки історія зберігається. Для CronJob’ів перевіряйте і сам CronJob, і Job’и, які він створив, бо збої планування та виконання живуть на різних рівнях.
Перш ніж запускати резервне копіювання як CronJob, передбачте, що має статися, якщо вчорашнє резервне копіювання ще активне, коли спрацьовує сьогоднішній розклад. Потім оберіть Allow, Forbid чи Replace на основі ризику дубльованих записів, пропущених точок відновлення та часткового виводу. Це той вид операційного міркування, який вибір ресурсу має втиснути в проєктування.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Найнадійніший патерн — починати з семантики життєвого циклу. Якщо процес має продовжувати обслуговування, використовуйте контролер, побудований для тривалої доступності. Якщо процес має завершитися, використовуйте контролер, побудований для завершення. Це звучить очевидно, але багато помилок на продакшені виникають через копіювання знайомого маніфесту Деплойменту й зміну лише команди. Kubernetes робить саме те, що обіцяє обраний контролер, тож помилка проєктування може виглядати як впертість платформи, коли контролер сумлінно перезапускає завдання, яке мало виконатися один раз.
Другий патерн — ставитися до ідентичності Пода як до контракту застосунку. Для API без стану ідентичність належить поза Подом, зазвичай у Сервісі, базі даних, черзі чи шляху запиту клієнта. Для кластеризованої бази даних ідентичність може жити всередині протоколу застосунку, де імена учасників та розташування сховища несуть значення. Тому вибір між Деплойментом та StatefulSet’ом не про те, чи цінний застосунок; він про те, чи може Под-замінник безпечно стати «будь-якою реплікою», чи має повернутися як конкретний учасник.
Третій патерн — перевіряти володіння зверху вниз. Почніть із k get deployment, k get statefulset, k get daemonset, k get job чи k get cronjob, а потім простежте підпорядковані об’єкти донизу. Такий порядок утримує бажаний стан у полі зору, доки ви усуваєте симптоми. Якщо ви почнете з розглядання одного Пода, ви можете пропустити, що Деплоймент призупинено, Job уже досяг свого ліміту повторних спроб, або DaemonSet навмисно виключає вузол через спорідненість.
Патерни масштабування також відрізняються за контролером. Масштабування Деплойменту змінює сервісну потужність, тож воно природно поєднується з пробами готовності, горизонтальним автомасштабуванням та бюджетами розгортання. Масштабування StatefulSet’а змінює іменоване членство, тож воно вимагає специфічного для застосунку міркування про кворум, реплікацію та очищення сховища. Масштабування DaemonSet’а здебільшого є масштабуванням вузлів, бо придатні вузли визначають кількість Подів. Масштабування Job’а означає завершення та паралельність, тоді як масштабування CronJob’а зазвичай означає частоту розкладу та політику накладання.
Небезпечний антипатерн — карго-культ контролерів. Команда спочатку вивчає Деплойменти, тож кожне робоче навантаження стає Деплойментом, доки міграція не повториться, база даних не втратить ідентичність або агент вузла не пропустить половину флоту. Інша команда вивчає StatefulSet’и під час проєкту з базою даних, тож вони надмірно використовують стабільну ідентичність там, де взаємозамінні репліки були б простішими. Kubernetes дає цим ресурсам схожі форми YAML, але схожий синтаксис не означає схожих операційних обіцянь.
Ще один антипатерн — ставитися до згенерованих імен як до стабільних контрактів інтерфейсу. Ім’я Пода Деплойменту може змінитися щоразу, коли контролер замінює Под, а хеш ReplicaSet’а може змінитися щоразу, коли змінюється шаблон Пода. Якщо скрипти, дашборди чи конфігурація однорангових учасників залежать від цих згенерованих імен, наступне розгортання може зламати припущення поза Kubernetes. Використовуйте Сервіси, мітки, селектори, порядкові номери StatefulSet’а чи виявлення на рівні застосунку залежно від того, яка ідентичність має бути стабільною.
Уникайте використання очищення як заміни розуміння. Старі ReplicaSet’и, завершені Job’и та історія CronJob’ів можуть виглядати як сміття, але вони часто пояснюють, що сталося під час розгортання чи запланованого виконання. Видалення їх надто рано прибирає докази й інколи прибирає варіанти відкату. Кращий патерн — навмисно встановлювати ліміти історії, зберігати достатньо операційного контексту для діагностики й очищати ресурси після того, як ви знаєте, який контролер їх створив і чому.
Нарешті, уникайте ототожнення «контролер створив Под» зі «застосунок справний». Деплоймент може підтримувати три Поди, які всі не проходять перевірку готовності. StatefulSet може зберегти ідентичність сховища для неправильно налаштованої бази даних. DaemonSet може працювати скрізь, доки агенту бракує дозволів. Job’и та CronJob’и можуть завершитися з командою, яка дала поганий бізнес-результат. Ресурси робочих навантажень керують життєвим циклом Kubernetes; вони не замінюють перевірки застосунку.
Каркас прийняття рішень
Розділ «Каркас прийняття рішень»Початкова діаграма рішень дає швидкий маршрут крізь поширені варіанти вибору. Її порядок корисний, бо скінченна робота та розміщення на кожному вузлі є чіткішими обмеженнями, ніж загальне питання, чи є застосунок «без стану». Якщо робоче навантаження — це одноразове завдання, оберіть Job, перш ніж сперечатися про Деплоймент. Якщо воно має працювати на кожному вузлі, оберіть DaemonSet, перш ніж думати про кількість реплік. Якщо йому потрібна стабільна ідентичність та сховище, оберіть StatefulSet, перш ніж тягнутися до знайомого YAML Деплойменту.
┌─────────────────────────────────────────────────────────────┐│ CHOOSING A WORKLOAD RESOURCE │├─────────────────────────────────────────────────────────────┤│ ││ Is it a one-time task? ││ └─→ YES: Job ││ ││ Does it need to run on a schedule? ││ └─→ YES: CronJob ││ ││ Does it need to run on every node? ││ └─→ YES: DaemonSet ││ ││ Does it need stable identity and storage? ││ └─→ YES: StatefulSet ││ ││ Is it a stateless application? ││ └─→ YES: Deployment (most common!) ││ │└─────────────────────────────────────────────────────────────┘Сильніший каркас рішень ставить п’ять питань послідовно. По-перше, чи означає успіх, що процес завершується? Якщо так, використовуйте Job чи CronJob. По-друге, чи є розклад частиною вимоги? Якщо так, CronJob обгортає створення Job’ів. По-третє, чи прив’язане бажане розміщення до кожного вузла? Якщо так, використовуйте DaemonSet. По-четверте, чи потрібне кожній репліці стабільне ім’я або власний довговічний том? Якщо так, використовуйте StatefulSet. По-п’яте, чи є репліки взаємозамінною сервісною потужністю? Якщо так, використовуйте Деплоймент.
| Сигнал вимоги | Найкращий стартовий ресурс | Перевірка міркування | Стежте уважно |
|---|---|---|---|
| Замінні веб- або API-Поди | Deployment | Ідентичність репліки не важлива, але розгортання та масштабування важливі. | Проби готовності, історія розгортань та мітки селекторів. |
| Пряме керування ReplicaSet’ом | ReplicaSet | Рідко доречне поза особливими експериментами з контролерами чи навчанням. | Втрачена поведінка розгортання та заплутане володіння. |
| Іменовані кластеризовані учасники | StatefulSet | Порядковий номер Пода та ідентичність сховища важливі для протоколу застосунку. | Життєвий цикл заявки на персистентний том та впорядковані операції. |
| Один агент на вузол | DaemonSet | Охоплення вузлів є одиницею бажаного стану. | Селектори вузлів, toleration’и та кількість придатних вузлів. |
| Скінченне завдання, запущене один раз | Job | Завершення є успіхом, а не збоєм. | Ліміти повторних спроб, логи та історія завершених Подів. |
| Скінченне завдання за розкладом | CronJob | Розклад створює Job’и, а кожен Job створює Поди. | Політика паралельності, пропущені розклади та ліміти історії. |
Патерни випливають із цього каркасу. Використовуйте Деплойменти як типовий вибір для сервісних навантажень без стану, бо вони поєднують керування репліками, статус розгортання, історію відкату та масштабування в одному знайомому API. Використовуйте StatefulSet’и, коли сам застосунок іменує учасників, бо Kubernetes не може здогадатися, що випадковий суфікс Пода має зберегти роль у базі даних. Використовуйте DaemonSet’и для інфраструктури вузлів, бо пропуск одного вузла може означати пропуск саме того вузла, який відмовляє під час інциденту.
Антипатерни — це дзеркальне відображення. Не використовуйте голий Под для будь-чого, що має пережити перепланування, бо жоден контролер не створить його заново за вас. Не використовуйте Деплоймент для скінченної міграції, бо вихід виглядатиме як щось для перезапуску, а не як щось для фіксації як завершене. Не використовуйте CronJob для високочастотної обробки подій, коли Деплоймент-споживач черги забезпечив би чіткіший зворотний тиск та масштабування.
Підсумок «найкращих практик» із початкового модуля все ще тримається, але він переконливіший після глибшого огляду. Майже ніколи не створюйте Поди чи ReplicaSet’и напряму для звичайних застосунків. Створюйте контролер, що відповідає обіцянню робочого навантаження, а потім дайте Kubernetes створювати й лагодити Поди як деталі реалізації. Саме так ви переходите від «я можу запустити контейнер» до «платформа може тримати живим правильний вид робочого навантаження».
| Ресурс | Випадок використання |
|---|---|
| Deployment | Застосунки без стану (вебсервери, API) |
| StatefulSet | Застосунки зі станом (бази даних, кеші) |
| DaemonSet | Агенти на кожен вузол (логування, моніторинг) |
| Job | Одноразові завдання (резервні копії, міграції) |
| CronJob | Заплановані завдання (нічні Job’и) |
Під час усунення несправностей завжди перевіряйте контролер, перш ніж надто глибоко перевіряти окремі Поди. Несправний Под може показати вам симптоми, але контролер пояснює намір: бажані репліки, відповідність селектора, статус розгортання, кількість завершень чи охоплення вузлів. Цей контекст не дає вам полагодити неправильний рівень, наприклад видалити Под, який ReplicaSet негайно створює заново з тим самим поганим шаблоном.
Ієрархія контролерів також пояснює, чому списки об’єктів Kubernetes можуть здаватися гучними. Один Деплоймент може породити рядок Деплойменту, один чи більше рядків ReplicaSet’ів та кілька рядків Подів. CronJob може породжувати рядки Job’ів та Подів із часом. Цей шум осмислений, якщо ви читаєте його як історію володіння, а не як непов’язане сміття.
Ви можете перетворити цей каркас на швидку звичку перегляду проєкту. Попросіть власника застосунку описати, що має статися, коли контейнер завершується, коли вузол зникає, коли образ змінюється і коли дві копії роботи виконуються одночасно. Ці чотири питання розкривають більшість невідповідностей робочого навантаження ще до того, як хтось напише маніфест. Вони також тримають обговорення прив’язаним до поведінки, яку легше перевірити, ніж розпливчасте твердження, що застосунок «хмарно-нативний».
Для сервісів без стану питання про вихід зазвичай має просту відповідь: Под слід замінити, бо сервісна потужність має залишатися доступною. Ця відповідь вказує на Деплоймент, але вона також має викликати питання про готовність, темп розгортання та впевненість у відкаті. Деплоймент може замінювати Поди поступово, проте він залежить від точних сигналів готовності, щоб знати, коли новий Под має отримувати трафік. Вибір ресурсу — це початок проєктування, а не кінець продакшен-чеклиста.
Для систем зі станом питання про зникнення вузла розкриває більше. Якщо застосунок каже: «поверни того самого учасника з тим самим сховищем», ви на території StatefulSet’а. Якщо він каже: «запусти будь-якого справного працівника й знову підключися до спільного сховища чи зовнішньої бази даних», Деплоймент усе ще може бути правильним. Саме тому та сама широка категорія, наприклад «кеш», може привести до різних варіантів вибору залежно від того, чи кеш — це одноразовий рівень продуктивності, чи кластеризована система з правилами членства.
Для агентів вузлів питання про зміну образу має включати радіус ураження. Оновлення DaemonSet’а може торкнутися кожного агента рівня вузла, тож поганий образ може зменшити спостережуваність, мережу чи підтримку сховища в усьому кластері. Kubernetes підтримує стратегії оновлення DaemonSet’а, але операційний перегляд усе одно має враховувати, чи є агент критичною інфраструктурою і чи мають вузли оновлюватися поступово. Контролер дає вам розміщення; ваша політика розгортання контролює, скільки ризику рівня вузла рухається за раз.
Для скінченної роботи питання про накладання часто є найважливішим. Резервне копіювання, експорт рахунків, звіт чи міграція можуть бути нешкідливими, коли повторюються в іграшковій лабораторії, і небезпечними, коли повторюються щодо стану продакшену. Job’и та CronJob’и дають змогу виразити семантику завершення та розкладу, але вони не можуть вирішити, чи безпечне дублювання роботи. Це рішення належить проєктуванню робочого навантаження, а маніфест має робити обрану політику видимою через поля на кшталт backoffLimit та concurrencyPolicy.
Перевірка має віддзеркалювати ті самі питання проєктування. Для Деплойменту перевіряйте статус розгортання, активні ReplicaSet’и та доступні репліки. Для StatefulSet’а перевіряйте впорядковані імена Подів та заявки на томи. Для DaemonSet’а порівнюйте бажані Поди з придатними вузлами, а не з вручну обраною кількістю реплік. Для Job’а перевіряйте умови завершення та логи. Для CronJob’а перевіряйте розклад, політику паралельності та Job’и, створені з шаблону. Кожна перевірка доводить обіцяння контролера, яке ви обрали.
Ця звичка також допомагає під час реагування на інциденти. Коли сповіщення каже «Поди відмовляють», першим корисним питанням є те, який контролер володіє цими Подами. Якщо ними володіє Деплоймент, ви можете дивитися на погане розгортання, збій готовності чи проблему потужності. Якщо ними володіє Job, ви можете дивитися на повторні спроби та затримку. Якщо ними володіє DaemonSet, ви можете дивитися на придатність вузлів чи дрейф інфраструктури. Контролер звужує діагноз ще до того, як логи додадуть деталей.
Чи знали ви?
Розділ «Чи знали ви?»- Деплойменти зберігають старі ReplicaSet’и — за замовчуванням Kubernetes зберігає 10 старих ReplicaSet’ів через
revisionHistoryLimit, що дає командіk rollout undoконкретний попередній шаблон, який можна знову масштабувати. - Поди StatefulSet’а за замовчуванням створюються послідовно — упорядкована поведінка означає, що
pod-0зазвичай стає готовим перш ніж стартуєpod-1, що захищає застосунки, яким потрібне передбачуване формування кластера. - DaemonSet’и тепер за замовчуванням працюють із планувальником — сучасний Kubernetes планує Поди DaemonSet’а через звичайні шляхи планувальника, що дає змогу спорідненості вузлів, taint’ам, toleration’ам та тиску на ресурси брати участь у розміщенні.
- Часові пояси CronJob’ів є явними в сучасному Kubernetes — CronJob’и підтримують поле
.spec.timeZone, тож команди можуть уникнути випадкової залежності від локального часового поясу контролер-менеджера.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому вона трапляється | Як її виправити |
|---|---|---|
| Створення голого Пода для сервісу | Маніфест одного Пода здається простішим під час навчання, але жоден контролер робочого навантаження не створює його заново після видалення, виведення вузла з обслуговування чи зміни шаблону. | Використовуйте Деплоймент для замінних сервісних реплік без стану, а потім перевіряйте статус Деплойменту та ReplicaSet’а замість того, щоб ставитися до Подів як до джерела істини. |
| Пряме створення ReplicaSet’ів | ReplicaSet’и відкривають механізм підрахунку реплік, тож вони виглядають як менший Деплоймент, але вони не надають той самий процес розгортання та відкату. | Створюйте Деплойменти для звичайних застосунків і дайте Деплойменту керувати ReplicaSet’ами як об’єктами ревізій. |
| Використання Деплойменту для учасника бази даних | Деплойменти дають випадкові імена Подів та взаємозамінні репліки, що конфліктує з членством у базі даних, стабільним DNS та сховищем для кожного учасника. | Використовуйте StatefulSet із headless-Сервісом та шаблонами заявок на томи, коли застосунок вимагає стабільної ідентичності. |
| Запуск агента вузла як Деплойменту | Кількість реплік Деплойменту не гарантує по одному Поду на вузол, тож деяким вузлам може бракувати підтримки логування, моніторингу, мережі чи сховища. | Використовуйте DaemonSet і за потреби обмежуйте придатні вузли спорідненістю, селекторами чи toleration’ами. |
| Запуск скінченної міграції як Деплойменту | Контролер Деплойменту трактує вихід контейнера як причину для перезапуску, тож успішна міграція може стати повторюваною міграцією. | Використовуйте Job для одноразової скінченної роботи й встановіть чіткий backoffLimit, а потім перевірте завершення Job’а та логи. |
| Ігнорування політики паралельності CronJob’а | Заплановані завдання можуть накладатися, коли попередній запуск триває довше за очікуване, спричиняючи дубльовані записи чи заплутаний вивід звітів. | Оберіть Allow, Forbid чи Replace залежно від того, чи безпечні запуски, що накладаються, для робочого навантаження. |
| Налагодження лише найновішого Пода | Поди показують симптоми, але умови контролера пояснюють бажаний стан, поступ розгортання, відповідність селектора та відстеження завершень. | Почніть із k describe deployment, k describe job, k get daemonset чи k get statefulset, а потім заглиблюйтеся в Поди. |
Тест
Розділ «Тест»Ваша команда розгорнула API оформлення замовлення (checkout) як голий Под, і Под зник під час обслуговування вузла. Який ресурс робочого навантаження має його замінити, і яка поведінка контролера запобігає повторенню інциденту?
Використовуйте Деплоймент, бо репліки API оформлення замовлення мають бути замінною сервісною потужністю. Деплоймент підтримує бажаний стан через ReplicaSet, тож якщо відповідний Под зникає, контролер створює замінник зі шаблону Пода. Це не означає, що застосунок автоматично коректний за будь-якого релізу, але це означає, що обслуговування вузла не має стерти все робоче навантаження. Відповідь має згадати і Деплоймент, і ReplicaSet, бо ReplicaSet виконує узгодження кількості реплік під керуванням розгортанням Деплойменту.
Кластеру бази даних потрібні учасники на ім'я `db-0`, `db-1` та `db-2`, і кожен учасник має зберігати власний том після перепланування. Чому StatefulSet підходить краще, ніж Деплоймент?
StatefulSet кращий, бо він зберігає стабільну ідентичність Пода через порядкові імена й може створювати заявки на персистентні томи (PersistentVolumeClaim) для кожної репліки з шаблону. Деплоймент трактує репліки як взаємозамінні й дає Подам згенеровані імена, які можуть змінюватися під час заміни. Для кластеризованих баз даних імена та томи часто беруть участь у реплікації, кворумі та логіці відновлення, тож випадкова заміна може зламати припущення, які робить база даних. Вибір контролера стосується гарантій ідентичності та сховища, а не того, чи бази даних важливі.
Команда безпеки хоче агента на кожному робочому Linux-вузлі для збору локальних логів аудиту. Вони пропонують Деплоймент із такою самою кількістю реплік, як поточна кількість вузлів. Що ви порадите?
Порадьте DaemonSet, бо вимога — це охоплення вузлів, а не довільна кількість реплік. Деплоймент із сьогоднішньою кількістю вузлів усе одно може розмістити кілька Подів на одному вузлі й жодного на іншому, і він не скоригується правильно автоматично, коли придатні вузли приєднуються чи вибувають. DaemonSet створює по одному Поду на кожному відповідному вузлі й може бути обмежений робочими Linux-вузлами через селектори чи спорідненість. Це робить так, що ресурс робочого навантаження відповідає операційному обіцянню.
Міграція схеми має виконатися один раз, повторити спробу кілька разів у разі збою й зупинитися після успіху. Чому Job безпечніший за Деплоймент для цього робочого навантаження?
Job трактує успішне завершення як бажаний стан, тоді як Деплоймент трактує зупинений контейнер як щось для заміни. Контролер Job’а може відстежувати завершення, створювати Поди-замінники для невдалих спроб у межах backoffLimit, а потім перестати створювати Поди після успіху. Деплоймент продовжував би намагатися підтримувати запущені репліки, що може повторити міграцію, яка мала бути скінченною. Безпечніше проєктування — зробити так, щоб умова успіху контролера відповідала умові успіху завдання.
Під час розгортання Деплойменту ви бачите два ReplicaSet'и для тієї самої мітки застосунку: один із нульовою кількістю реплік і один із трьома. Чи це автоматично проблема?
Ні, це може бути нормальною історією розгортання. Деплоймент створює новий ReplicaSet, коли змінюється шаблон Пода, і зменшує масштаб старого ReplicaSet’а після того, як новий стає доступним. Старий ReplicaSet може залишитися з нульовою кількістю реплік, щоб Kubernetes міг відкотитися до того шаблону за потреби. Вам слід перевірити статус та умови розгортання, перш ніж видаляти старі ReplicaSet’и, бо вони можуть представляти корисну історію ревізій, а не осиротілі об’єкти.
Нічний CronJob звіту інколи триває довше за інтервал між розкладами, і дубльовані звіти бентежать користувачів нижче за течією. Яке налаштування CronJob'а вам слід оцінити першим?
Оцініть concurrencyPolicy, особливо Forbid, якщо новий запуск слід пропустити, доки попередній ще активний. Це налаштування існує, бо CronJob’и створюють Job’и з часом, і контролеру потрібне правило для розкладів, що накладаються. Allow може підійти для незалежної роботи, але генерація звітів часто записує спільні виходи чи надсилає сповіщення, тож накладання може бути шкідливим. Відповідь має пов’язати рівень планування зі створенням Job’а, а не ставитися до CronJob’а лише як до таймера команд.
Ви застосовуєте маніфест Деплойменту, потім `k get pods` показує Поди, але `k rollout status deployment/web` ніколи не завершується. Що ви перевіряєте далі й чому?
Перевірте умови Деплойменту та ReplicaSet’а за допомогою k describe deployment web, k get rs -l app=web та деталей Подів на предмет збоїв готовності, завантаження образу чи планування. Список Подів показує, що об’єкти існують, але статус розгортання залежить від того, чи стають готовими оновлені та доступні репліки відповідно до правил Деплойменту. Збій проби готовності може залишити Поди запущеними, але недоступними, тоді як проблема завантаження образу може взагалі не дати новим Подам стартувати. Діагностика контролера першою тримає вас зосередженими на бажаному стані та поступі розгортання.
Практична вправа
Розділ «Практична вправа»У цій вправі ви створите й перевірите кілька ресурсів робочих навантажень у кластері Kubernetes 1.35+. Локального кластера kind, minikube чи керованого кластера для розробки достатньо, за умови, що у вас є дозвіл створювати ресурси в одноразовому просторі імен. Команди використовують псевдонім k, представлений раніше, а маніфести навмисно використовують невеликі образи та прості команди, щоб поведінка контролера залишалася видимою.
Спершу створіть простір імен, щоб очищення було передбачуваним. Простір імен — це не урок, але він дає вам чітку межу для перелічення ресурсів та видалення всього в кінці. Якщо у вас уже є особистий простір імен для практики, ви можете підставити його, але тримайте команди узгодженими, доки порівнюєте поведінку контролерів.
k create namespace workload-labk config set-context --current --namespace=workload-lab- Створіть Деплоймент на ім’я
quote-apiіз трьома репліками й перевірте ланцюг володіння Деплоймент → ReplicaSet → Под.
Розв'язання
cat > quote-api-deployment.yaml <<'YAML'apiVersion: apps/v1kind: Deploymentmetadata: name: quote-api labels: app: quote-apispec: replicas: 3 selector: matchLabels: app: quote-api template: metadata: labels: app: quote-api spec: containers: - name: quote-api image: nginx:1.26 ports: - containerPort: 80YAMLk apply -f quote-api-deployment.yamlk rollout status deployment/quote-apik get deploy,rs,pod -l app=quote-apiУспіх означає, що ви можете вказати на один Деплоймент, один активний ReplicaSet та три Поди, чиї згенеровані імена показують володіння ReplicaSet’а. Якщо розгортання не завершується, перевірте k describe deployment quote-api, перш ніж змінювати маніфест.
- Оновіть образ Деплойменту й перевірте, що з’являється новий ReplicaSet, тоді як історія розгортання залишається доступною.
Розв'язання
k set image deployment/quote-api quote-api=nginx:1.27k rollout status deployment/quote-apik get rs -l app=quote-apik rollout history deployment/quote-apiУспіх означає, що новий ReplicaSet володіє активними репліками й принаймні один старіший ReplicaSet залишається видимим із нульовою кількістю реплік. Цей старий об’єкт корисний, бо відкату потрібен попередній шаблон Пода для відновлення.
- Створіть Job на ім’я
schema-check, поспостерігайте, як він завершується, і порівняйте його статус із Деплойментом, що все ще працює.
Розв'язання
cat > schema-check-job.yaml <<'YAML'apiVersion: batch/v1kind: Jobmetadata: name: schema-checkspec: backoffLimit: 3 template: spec: restartPolicy: Never containers: - name: schema-check image: busybox:1.36 command: ["sh", "-c", "echo checking schema; sleep 5; echo complete"]YAMLk apply -f schema-check-job.yamlk wait --for=condition=complete job/schema-check --timeout=90sk get job,pod -l job-name=schema-checkk logs job/schema-checkУспіх означає, що Job досягає умови завершення й не тримає Под, що працює постійно. Порівняйте це з Деплойментом, який продовжує підтримувати три запущені API-Поди.
- Створіть CronJob у призупиненому режимі, перевірте розклад, а потім вручну запустіть один Job із його шаблону.
Розв'язання
cat > report-cronjob.yaml <<'YAML'apiVersion: batch/v1kind: CronJobmetadata: name: report-checkspec: schedule: "0 2 * * *" suspend: true concurrencyPolicy: Forbid jobTemplate: spec: template: spec: restartPolicy: Never containers: - name: report-check image: busybox:1.36 command: ["sh", "-c", "date; echo report complete"]YAMLk apply -f report-cronjob.yamlk get cronjob report-checkk create job report-check-manual --from=cronjob/report-checkk wait --for=condition=complete job/report-check-manual --timeout=90sk logs job/report-check-manualУспіх означає, що CronJob існує, не спрацьовуючи автоматично в лабораторії, а вручну створений Job завершується з шаблону CronJob’а. Політика паралельності Forbid видима в маніфесті для обговорення, навіть якщо лабораторія не чекає на розклади, що накладаються.
- Поясніть, використовуючи створені вами ресурси, чому Деплоймент — це не Job і чому CronJob — це не просто Под із таймером.
Розв'язання
Використайте k get deploy,rs,pod,job,cronjob і порівняйте ієрархію об’єктів. Деплоймент володіє ReplicaSet’ами, які тримають Поди запущеними, тоді як Job фіксує завершення й зупиняється після успіху. CronJob володіє розкладом та шаблоном Job’а, а потім створює Job’и замість того, щоб запускати команду напряму. Повна відповідь має описати обіцяння контролера для кожного ресурсу, а не просто перелічити імена об’єктів.
Коли закінчите, очистіть лабораторний простір імен. Видалення простору імен прибирає ресурси, які ви створили для цієї вправи, але очищення на продакшені має бути більш навмисним, коли задіяні заявки на персистентні томи (PersistentVolumeClaim), зовнішні балансувальники навантаження чи спільні простори імен.
k delete namespace workload-labСкористайтеся цим чеклистом критеріїв успіху, щоб підтвердити, що ви відпрацювали обіцяння контролерів, а не лише застосували файли YAML:
- Ви можете пояснити ієрархію Деплоймент → ReplicaSet → Под із живого виводу
k get. - Ви можете визначити, який ReplicaSet представляє поточний шаблон Деплойменту після оновлення образу.
- Ви можете показати, що Job фіксує завершення замість того, щоб підтримувати Под запущеним назавжди.
- Ви можете пояснити, як CronJob створює Job’и за розкладом і чому
concurrencyPolicyмає значення. - Ви можете обрати між Деплойментом, StatefulSet’ом, DaemonSet’ом, Job’ом та CronJob’ом для нового сценарію, не покладаючись лише на заучені імена.
Джерела
Розділ «Джерела»- Документація Kubernetes: Workloads
- Документація Kubernetes: Workload management
- Документація Kubernetes: Deployments
- Документація Kubernetes: ReplicaSet
- Документація Kubernetes: StatefulSets
- Документація Kubernetes: DaemonSet
- Документація Kubernetes: Jobs
- Документація Kubernetes: CronJob
- Документація Kubernetes: Labels and selectors
- Документація Kubernetes: Managing resources with kubectl
Наступний модуль
Розділ «Наступний модуль»Модуль 1.7: Сервіси — далі ви з’єднаєте ці керовані Поди зі стабільним виявленням та шляхами трафіку всередині кластера й за його межами.