Перейти до вмісту

Модуль 1.3: Архітектура Kubernetes — площина управління

Складність: [СЕРЕДНЯ] — основні концепції архітектури

Час на проходження: 60–75 хвилин

Передумови: Модулі 1.1 та 1.2

Версія Kubernetes: 1.35+

Команди в цьому модулі використовують k як короткий псевдонім для kubectl. Якщо ваша оболонка ще не визначає його, виконайте наведене нижче один раз перед практичною роботою, щоб кожна команда збігалася з прикладами.

Terminal window
alias k=kubectl

Результати навчання

Розділ «Результати навчання»

Після завершення цього модуля ви зможете виконувати такі діагностичні та проєктувальні завдання щодо кластера Kubernetes 1.35+:

  1. Діагностувати збої компонентів площини управління, зіставляючи симптоми API-сервера, etcd, планувальника, менеджера контролерів та cloud-controller-manager з імовірними причинами.
  2. Простежити запит на створення Pod’а через валідацію API-сервером, збереження в etcd, узгодження контролерами, призначення планувальником та виконання kubelet’ом.
  3. Порівняти одновузлову та високодоступну конструкції площини управління, зокрема масштабування API-сервера, вибори лідера та поведінку кворуму etcd.
  4. Оцінити експлуатаційні докази з команд k, події та поля об’єктів, щоб вирішити, що саме площина управління вже виконала.

Чому цей модуль важливий

Розділ «Чому цей модуль важливий»

Гіпотетичний сценарій: торгова платформа зазнає публічного збою після оновлення площини управління, яке оголює слабке місце в її рівні керування. Застосунки, орієнтовані на клієнтів, не впали всі одразу; багато контейнерів продовжували працювати там, де вони вже були. Проте вплив на бізнес усе одно став болючим, бо інженери не могли надійно створювати нові робочі навантаження, переміщувати збійні Pod’и або застосовувати термінові зміни конфігурації, поки площина управління була нездоровою. Урок прямий: доступність застосунків у Kubernetes залежить не лише від контейнерів, а й від системи керування, яка фіксує бажаний стан і перетворює його на дії.

Той самий патерн з’являється і в менш драматичних внутрішніх інцидентах. Команда бачить, що вебтрафік погіршується після збою вузла, проте першим її інстинктом є перевірити саме Деплоймент, образ контейнера або об’єкт Сервіс. Ці перевірки справді важливі, але вони можуть проґавити справжню несправність, якщо планувальник не може прив’язати замінні Pod’и, якщо менеджер контролерів не створює нові Pod’и або якщо etcd взагалі не може приймати записи. Саме тому архітектура площини управління — це аж ніяк не дрібниця лише для питань сертифікації; це карта, яка дозволяє вам відокремити помилки робочих навантажень від збоїв керування кластером під тиском реального інциденту.

Цей модуль навчає площини управління як набору взаємодійних циклів керування, а не як завченого списку демонів. Ви пов’яжете кожен компонент з експлуатаційною відповідальністю, простежите запит від k create deployment до запущеного контейнера та порівняєте невеликий навчальний кластер із високодоступною продакшн-конструкцією. Коли KCNA запитає, який компонент зберігає стан кластера, призначає Pod’и або узгоджує бажаний стан, ви матимете ментальну модель, засновану на реальному потоці запитів, а не на ізольованих визначеннях.

Практична віддача від цього — це впевненість під час діагностики. Якщо API-запит відхилено, ви вже знаєте, що треба міркувати про допуск, авторизацію, валідацію та зберігання. Якщо Pod створено, але він залишається в стані Pending, ви знаєте, що треба перевірити саме докази планування. Якщо ж Деплоймент існує, але жоден ReplicaSet чи Pod так і не з’являється, ви дивитеся в бік узгодження контролерами. Саме це покомпонентне розмежування перетворює Kubernetes із непрозорої чорної скриньки на систему, яку ви можете впевнено налагоджувати.

Архітектура кластера Kubernetes

Розділ «Архітектура кластера Kubernetes»

Kubernetes розділяє відповідальність між площиною управління та робочими вузлами. Площина управління — це рівень керування, який приймає бажаний стан, зберігає його та координує контролери, що намагаються привести реальність у відповідність до цього бажаного стану. Робочі вузли запускають контейнери, звітують про статус і виконують отримані призначення. Цей поділ подібний до операційного центру аеропорту та окремих наземних бригад: операційний центр не завантажує фізично кожну валізу, але йому належать розклад, план і рішення, які координують роботу.

Важлива межа тут полягає в тому, що користувачі й автоматизація зазвичай спілкуються саме з API-сервером, а не безпосередньо з kubelet’ами чи з etcd. Запит k apply спершу потрапляє до площини управління, перевіряється там на відповідність політиці та зберігається як частина запису кластера. Інші компоненти вже потім спостерігають за цим записом і вживають відповідних заходів. Така архітектура дозволяє Kubernetes залишатися розширюваним, бо нові контролери можуть спостерігати за тим самим API, і вона зберігає чітку відповідальність, бо кожен учасник бачить одне й те саме джерело істини.

┌─────────────────────────────────────────────────────────────┐
│ KUBERNETES CLUSTER ARCHITECTURE │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ CONTROL PLANE (Master) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ API │ │ Scheduler│ │Controller│ │ │
│ │ │ Server │ │ │ │ Manager │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ ┌──────────┐ ┌──────────┐ │ │
│ │ │ etcd │ │ Cloud │ │ │
│ │ │ │ │Controller│ │ │
│ │ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ │ API calls │
│ │ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ WORKER NODES │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Node 1 │ │ Node 2 │ │ Node 3 │ │ │
│ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │
│ │ │ │ kubelet │ │ │ │ kubelet │ │ │ │ kubelet │ │ │ │
│ │ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │ │
│ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │
│ │ │ │kube-proxy│ │ │ │kube-proxy│ │ │ │kube-proxy│ │ │ │
│ │ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │ │
│ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │
│ │ │ │Container│ │ │ │Container│ │ │ │Container│ │ │ │
│ │ │ │ Runtime │ │ │ │ Runtime │ │ │ │ Runtime │ │ │ │
│ │ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

Не дозволяйте історичному слову «master» відвертати вашу увагу від фактичної конструкції. Сучасна документація Kubernetes уживає термін «control plane» (площина управління), бо ця роль ширша за одну машину і бо продакшн-кластери зазвичай запускають кілька вузлів площини управління. Компоненти можуть працювати як статичні Pod’и на вузлах, створених kubeadm, як керовані процеси в хмарному сервісі або як прихована інфраструктура, керована провайдером. Концепція KCNA залишається тією самою: ці компоненти реалізують відповідальність за Kubernetes API, зберігання, планування, узгодження та хмарну інтеграцію.

Діаграма також показує, чому проблеми площини управління часто здаються дивними під час збою. Запущені контейнери на робочих вузлах можуть продовжувати обслуговувати наявний трафік навіть тоді, коли деякі дії керування не вдаються, бо kubelet і середовище виконання контейнерів уже мають локальні інструкції. Водночас кластер може бути нездатний прийняти новий бажаний стан або відновити збійну потужність. Цей поділ між «наявні Pod’и продовжують працювати» та «нові рішення перестають ухвалюватися» — це повторюваний діагностичний натяк.

Ви можете запам’ятати площину управління за типом питання, на яке відповідає кожен компонент. API-сервер відповідає: «Чи дозволено цей запит і чи він валідний?» etcd відповідає: «Який зафіксований стан кластера?» Планувальник відповідає: «Де має працювати цей незапланований Pod?» Менеджер контролерів відповідає: «Яка робота потрібна, щоб привести поточний стан у відповідність до бажаного?» cloud-controller-manager відповідає: «Що треба створити чи оновити у зовнішнього хмарного провайдера?»

КомпонентОсновна відповідальністьЕксплуатаційний симптом при нездоровому стані
kube-apiserverТочка входу до API, автентифікація, авторизація, допуск, валідаціяКоманди k не виконуються, контролери та kubelet’и не можуть надійно читати чи записувати стан
etcdСтійке розподілене сховище для об’єктів та метаданих KubernetesЗаписи не вдаються, стан кластера може бути застарілим, відновлення залежить від кворуму або резервних копій
kube-schedulerРішення про розміщення Pod’ів без .spec.nodeNameНові Pod’и залишаються в стані Pending без призначеного вузла
kube-controller-managerВбудовані цикли узгодження для Деплойментів, ReplicaSet’ів, Нод, Job’ів тощоБажані об’єкти існують, але залежні об’єкти чи відновлення не з’являються
cloud-controller-managerСпецифічна для хмари інтеграція для вузлів, маршрутів та балансувальників навантаженняХмарні балансувальники навантаження, життєвий цикл вузлів або маршрути не відповідають об’єктам Kubernetes

Зупиніться та спрогнозуйте: якщо об’єкт Деплоймент існує, але жоден об’єкт Pod не створюється, який компонент ви досліджували б перш ніж звинувачувати планувальник? Планувальник бачить лише ті Pod’и, що вже існують і не мають призначення вузла, тож відсутній Pod указує раніше в ланцюзі — у бік узгодження контролерами.

API-сервер та etcd: вхідні двері й джерело істини

Розділ «API-сервер та etcd: вхідні двері й джерело істини»

kube-apiserver — це єдиний компонент, якого більшість користувачів торкається безпосередньо, проте він є чимось більшим за простий HTTP-проксі. Він завершує запити Kubernetes API, автентифікує абонента, перевіряє авторизацію, виконує логіку допуску, валідує схеми об’єктів і координує зберігання. Кожен контролер, kubelet, планувальник та зовнішній інструмент залежать від API-сервера, бо він є послідовним входом до стану кластера. Цей центральний вхід — навмисний: одну точку контролю легше захистити, проаудитувати, масштабувати та розширити, ніж десятки компонентів, які записують стан незалежно.

Шлях запиту через API-сервер також пояснює, чому Kubernetes може додавати нову політику без переписування кожного окремого контролера. Автентифікація встановлює, хто саме викликає, авторизація вирішує, чи може ця ідентичність виконати запитану дію над запитаним ресурсом, допуск може змінити або зовсім відхилити об’єкт, а валідація підтверджує, що остаточний об’єкт відповідає схемі API. Лише після всіх цих кроків запит нарешті стає стійким станом кластера. Коли команда не виконується, точна стадія збою часто підказує вам, з чим саме ви маєте справу: облікові дані, RBAC, політика допуску, некоректний YAML чи проблема зі сховищем.

Це особливо має значення під час оновлень, бо API Kubernetes постійно еволюціонують, тоді як клієнти, контролери та вебхуки допуску можуть рухатися зовсім не одночасно. API-сервер — це саме те місце, де застарілі поля, видалені версії, поведінка за функціональними прапорцями та побічні ефекти допуску стають по-справжньому видимими. Уважний оператор читає помилки API як структуровані докази, а не як загальний текст про збій. Якщо, наприклад, користувацький вебхук допуску недосяжний, API-сервер може відхиляти записи, навіть якщо etcd і планувальник цілком здорові.

┌─────────────────────────────────────────────────────────────┐
│ KUBE-APISERVER │
├─────────────────────────────────────────────────────────────┤
│ │
│ What it does: │
│ ───────────────────────────────────────────────────────── │
│ • Exposes the Kubernetes API (REST interface) │
│ • All communication goes through it │
│ • Authenticates and authorizes requests │
│ • Validates API objects │
│ • Only component that talks to etcd │
│ │
│ Who talks to it: │
│ ───────────────────────────────────────────────────────── │
│ kubectl ────────→ ┌──────────────┐ │
│ Dashboard ──────→ │ API Server │ ←──── kubelet │
│ Other tools ────→ └──────────────┘ ←──── Controllers │
│ │
│ Key point: │
│ The API server is the ONLY component that reads/writes │
│ to etcd. Everything else talks to the API server. │
│ │
└─────────────────────────────────────────────────────────────┘

Те, що API-сервер не зберігає стану (stateless), є великою перевагою для масштабування. Якщо один процес API-сервера падає у високодоступному кластері, інший може відповісти на такий самий запит, бо стійкий стан не зберігається на локальному диску цього процесу. Саме тому продакшн-кластери розміщують кілька екземплярів API-сервера за балансувальником навантаження. Балансувальник навантаження дає клієнтам стабільну кінцеву точку, тоді як API-сервери спільно використовують той самий кластер etcd як бекенд.

etcd — це стійке сховище за тими вхідними дверима. Це розподілена база даних типу «ключ — значення», яка зберігає об’єкти Kubernetes, версії ресурсів, оренди (leases), записи вузлів, Secret’и, ConfigMap’и, об’єкти RBAC та метадані, які контролери використовують для координації роботи. Kubernetes використовує etcd, бо стан площини управління потребує сильної узгодженості. Якщо два API-сервери приймуть суперечливі записи, кожен контролер працював би з іншою версією реальності, а це найшвидший шлях до непередбачуваної автоматизації.

Резервні копії — це невіддільна частина архітектури, а не якийсь необов’язковий експлуатаційний клопіт. У самокерованому кластері знімок etcd — це різниця між відновленням зафіксованого бажаного стану та болісною відбудовою просторів імен, RBAC, Деплойментів, Сервісів, Secret’ів та конфігурації з розкиданих маніфестів чи з пам’яті. Практика створення знімків має включати тренувальні відновлення, бо резервна копія, яку ніхто не може відновити під тиском, — це лише втішний файл. Керовані сервіси часто приховують операції з etcd, але концепція все одно з’являється в гарантіях аварійного відновлення та документації провайдера.

Продуктивність etcd також впливає на всю площину управління, бо багато дрібних дій Kubernetes перетворюються на читання, записи чи спостереження зі сховища. Повільні диски, перевантажені мережі або перевантажені API-сервери можуть робити узгодження млявим навіть тоді, коли контролери логічно правильні. Коли ви бачите широкі симптоми в незв’язаних робочих навантаженнях, врахуйте у своїх міркуваннях спільний шлях площини управління. Один зламаний Деплоймент може бути проблемою застосунку, але багато незв’язаних записів, що одночасно вичерпують час очікування, часто вказують на здоров’я API чи сховища.

┌─────────────────────────────────────────────────────────────┐
│ ETCD │
├─────────────────────────────────────────────────────────────┤
│ │
│ What it is: │
│ ───────────────────────────────────────────────────────── │
│ • Distributed key-value store │
│ • Stores ALL cluster state │
│ • Highly available (usually 3 or 5 nodes) │
│ • Uses Raft consensus algorithm │
│ │
│ What it stores: │
│ ───────────────────────────────────────────────────────── │
│ • Pod definitions │
│ • Service configurations │
│ • Secrets and ConfigMaps │
│ • Node information │
│ • RBAC policies │
│ • Everything in the cluster! │
│ │
│ Key point: │
│ If etcd is lost, the entire cluster state is lost. │
│ Backup etcd regularly! │
│ │
└─────────────────────────────────────────────────────────────┘

Уявляйте etcd як юридичний реєстр кластера, а не як двигун виконання. Він не запускає Pod’и, не завантажує образи, не маршрутизує пакети й не вирішує розміщення. Він записує бажані та спостережені факти, які інші компоненти читають через API-сервер. Якщо etcd втрачає кворум, кластер захищає узгодженість, відмовляючись від записів, а не вгадуючи. Така поведінка може здаватися жорсткою під час інциденту, але прийняття суперечливих записів було б гіршим, бо цикли узгодження діяли б на основі стану, який пізніше може бути відкинутий.

API-сервер та etcd також пояснюють, чому клієнти Kubernetes використовують оптимістичну конкурентність. Об’єкти містять версії ресурсів, а спостереження транслюють зміни після відомої версії. Контролер може, по суті, сказати: «Я спостерігав цю версію і хочу її оновити». Якщо інший учасник змінив об’єкт першим, оновлення можна відхилити та повторити. Саме так багато незалежних контролерів співпрацюють, не беручи гігантське глобальне блокування навколо всього кластера.

Перш ніж це запускати, який вивід ви очікуєте, якщо ваш кластер досяжний, але ваш обліковий запис не має дозволу переглядати Secret’и? API-сервер усе одно має відповісти, але авторизація має відхилити саме цей запит. Ця різниця має значення, бо відмова в авторизації доводить, що API-сервер живий і застосовує політику, тоді як тайм-аут мережі чи відмова в з’єднанні вказують на зв’язність, кінцеву точку або доступність API-сервера.

Terminal window
k cluster-info
k auth can-i list secrets --all-namespaces
k get --raw=/readyz

Діагностуючи шлях API, читайте помилку уважно. Forbidden означає, що автентифікована ідентичність досягла API-сервера, але не має дозволу. Unauthorized часто означає, що облікові дані були відсутні або недійсні. The connection to the server was refused указує на момент до авторизації, часто на мертву кінцеву точку, неправильний kubeconfig, збійний локальний тунель або недоступний API-сервер. etcdserver: request timed out указує за API-сервер — у бік тиску на сховище або проблеми з кворумом.

Гіпотетичний сценарій: платформна команда якось звинуватила нову політику допуску, бо розробники не могли створювати Деплойменти після технічного вікна. Фактичним збоєм була заміна члена etcd, яка залишила кластер etcd без кворуму. Процес API-сервера все ще слухав на своєму порту, через що прості перевірки здоров’я виглядали оманливо живими, але записи не могли бути зафіксовані. Корисним натяком було те, що запити лише на читання іноді працювали, тоді як створення об’єктів стабільно застрягало або не вдавалося.

Сертифікаційний бік прямий, але експлуатаційний бік багатший. Якщо питання запитує, де зберігається стан Kubernetes, відповідайте — etcd. Якщо воно запитує, який компонент валідує об’єкти API або надає REST API, відповідайте — kube-apiserver. Якщо воно запитує, чи кожен компонент записує безпосередньо до etcd, відкиньте цю модель. API-сервер — це опосередкований, придатний для аудиту шлях, а etcd — це узгоджене сховище-бекенд, яке робить решту площини управління безпечною для автоматизації.

Планування та узгодження: рішення стають роботою

Розділ «Планування та узгодження: рішення стають роботою»

Планувальник і менеджер контролерів дуже часто плутають між собою, бо обидва реагують уже після того, як користувач створює об’єкт. Різниця ж полягає в тому, що контролери створюють або оновлюють об’єкти, потрібні для відповідності бажаному стану, тоді як планувальник лише призначає вже створені Pod’и конкретним вузлам. Контролер Деплойменту не обирає вузол, а планувальник, своєю чергою, не вирішує, що Деплоймент потребує власного ReplicaSet’а. Кожен компонент спостерігає за API у пошуках певного виду розриву, а потім записує невелику корекцію назад через API-сервер.

kube-scheduler стежить за Pod’ами, які існують, але ще не мають установленого .spec.nodeName. Для кожного незапланованого Pod’а він відфільтровує вузли, які не можуть запустити цей Pod, оцінює вузли, що залишилися, і прив’язує Pod до обраного вузла, оновлюючи API-сервер. Фаза фільтрації відкидає неможливі варіанти, як-от вузли без достатньої кількості CPU, вузли, заблоковані taint’ами, або вузли, що не відповідають селекторам. Фаза оцінювання ранжує можливі варіанти на основі політик, таких як розподіл навантаження чи задоволення переваг спорідненості (affinity).

┌─────────────────────────────────────────────────────────────┐
│ KUBE-SCHEDULER │
├─────────────────────────────────────────────────────────────┤
│ │
│ What it does: │
│ ───────────────────────────────────────────────────────── │
│ • Watches for newly created Pods with no node assigned │
│ • Selects a node for each Pod to run on │
│ • Does NOT run the Pod (kubelet does) │
│ │
│ How it decides: │
│ ───────────────────────────────────────────────────────── │
│ Filtering: │
│ • Does node have enough resources? │
│ • Does node match Pod's node selector? │
│ • Does node satisfy affinity rules? │
│ │
│ Scoring: │
│ • Spread Pods across nodes (balance) │
│ • Prefer nodes with image already cached │
│ • Consider custom priorities │
│ │
│ New Pod → Scheduler → "Run on Node 2" → kubelet runs it │
│ │
└─────────────────────────────────────────────────────────────┘

Вивід планувальника невеликий за обсягом, але насправді вирішальний. Він записує обраний вузол прямо на Pod, а вже потім kubelet на цьому вузлі бачить це призначення. kubelet завантажує потрібні образи через локальне середовище виконання контейнерів, монтує томи, запускає контейнери та звітує про їхній статус назад до API-сервера. Саме цей поділ робить хибним твердження «планувальник запускає Pod’и». Планувальник ухвалює рішення про розміщення; kubelet робочого вузла виконує локальне виконання.

Планування — це не просто пошук будь-якого вільного вузла. Kubernetes має поважати жорсткі вимоги, такі як запити на ресурси, селектори вузлів, обов’язкову спорідненість, taint’и без толерацій, обмеження топології та розміщення томів. Він також може враховувати м’якіші переваги під час оцінювання. Це розрізнення пояснює, чому Pod може бути непланованим навіть у кластері з, на перший погляд, незавантаженими машинами. Вузол із вільною пам’яттю все одно недійсний, якщо Pod вимагає мітки, якої вузол не має, або не має толерації для taint’а.

Для міркувань рівня KCNA зосередьтеся на контракті планувальника, а не на кожній деталі плагінів. Планувальник спостерігає за Pod’ами без призначень вузлів, оцінює придатні вузли, обирає один і записує прив’язку. Він не змінює образ контейнера, не створює Pod, не обходить запити на ресурси та не відновлює збійний вузол. Якщо планувальник каже, що жоден вузол не підходить, корисною реакцією є перевірити обмеження та потужність, які дали цю відповідь, а не припускати, що планувальник зламаний, бо він відмовився від неможливого розміщення.

kube-controller-manager запускає багато вбудованих контролерів в одному процесі. Контролер — це цикл узгодження: спостерігати бажаний стан, спостерігати поточний стан, порівняти їх і зробити найменшу корисну зміну. Контролер Деплойменту створює ReplicaSet’и. Контролер ReplicaSet створює або видаляє Pod’и, щоб відповідати кількості реплік. Контролер Нод реагує на зміни здоров’я вузлів. Інші контролери керують Job’ами, ендпоінтами, сервісними акаунтами, просторами імен тощо. Усі вони дотримуються того самого патерну: спостерігати за API та записувати корекції через API.

┌─────────────────────────────────────────────────────────────┐
│ KUBE-CONTROLLER-MANAGER │
├─────────────────────────────────────────────────────────────┤
│ │
│ What it does: │
│ ───────────────────────────────────────────────────────── │
│ • Runs controller processes │
│ • Each controller watches for specific resources │
│ • Controllers make current state match desired state │
│ │
│ Important controllers: │
│ ───────────────────────────────────────────────────────── │
│ Node Controller: │
│ • Monitors node health │
│ • Responds when nodes go down │
│ │
│ ReplicaSet Controller: │
│ • Maintains correct number of Pods │
│ • Creates/deletes Pods as needed │
│ │
│ Endpoints Controller: │
│ • Populates Endpoints objects │
│ • Links Services to Pods │
│ │
│ ServiceAccount Controller: │
│ • Creates default ServiceAccounts │
│ │
└─────────────────────────────────────────────────────────────┘

Узгодження — це ідея, яка змушує Kubernetes відчуватися самовідновлюваним. Людина не перезапускає постійно кожен збійний контейнер і не створює вручну кожен замінний Pod. Натомість користувачі декларують бажаний стан, як-от «цей Деплоймент має мати три репліки», а контролери продовжують працювати в напрямку цього стану. Якщо Pod зникає, контролер ReplicaSet помічає, що кількість занадто мала, і створює інший Pod. Якщо вузол стає нездоровим, контролер Нод оновлює інформацію про стан вузла та taint’и, яку можуть використовувати інші контролери.

Контролери навмисно повторювані, бо світ постійно змінюється. Контролер може спробувати оновити об’єкт і програти гонку іншому учаснику, тож він повторює спробу, побачивши нову версію ресурсу. Він може створити залежний об’єкт, а потім чекати, поки статус наздожене. Він може спостерегти, що нічого не треба змінювати, і просто продовжити спостереження. Цей сталий цикл надійніший за одноразовий скрипт, бо тимчасові збої, відкладений статус і конкурентні зміни є нормою в розподілених системах.

Посилання на власника (owner references) допомагають зробити узгодження видимим. Pod, створений для ReplicaSet’а, записує метадані власника, а цей ReplicaSet записує своє відношення до Деплойменту. Збирання сміття та історія розгортань залежать від цих відношень. Коли ви простежуєте проблему, посилання на власника підказують вам, який контролер має дбати про залежний об’єкт. Якщо Pod не має очікуваного власника, ви, можливо, дивитеся на створений вручну Pod, на інший контролер або на зламаний шлях породження.

Саме тому усунення несправностей у Kubernetes виграє від питання: «Який розрив ще не закрито?» Якщо Деплоймент існує, але ReplicaSet не існує, розрив контролера Деплойменту залишається відкритим. Якщо ReplicaSet існує, але Pod’ів немає, перевірте події та квоти ReplicaSet’а. Якщо Pod’и існують, але не мають вузла, перевірте події планувальника, потужність вузлів, селектори, спорідненості та taint’и. Якщо Pod’и мають вузол, але контейнери не запущені, перевірте kubelet, завантаження образів, томи та середовище виконання контейнерів на цьому вузлі.

Зупиніться та спрогнозуйте: Pod залишається в стані Pending, а k get pod -o wide не показує імені вузла. Чи почали б ви з налагодження логів контейнера? Логів контейнера, ймовірно, ще не існує, бо жодному kubelet’у ще не доручили запустити контейнер. Кращий перший крок — перевірити події Pod’а та обмеження планування, бо збій усе ще на стадії розміщення.

Terminal window
k get pods -o wide
k describe pod <pending-pod-name>
k get events --sort-by=.lastTimestamp
k explain pod.spec.nodeName

Простий Деплоймент дає вам наочний приклад межі між контролером і планувальником. Об’єкт Деплоймент — це бажаний стан користувача. Контролер Деплойменту створює ReplicaSet, щоб представити версіоновану ціль реплік. Контролер ReplicaSet створює об’єкти Pod. Планувальник призначає кожен Pod вузлу. Нарешті, kubelet на обраному вузлі запускає контейнери. Жоден окремий компонент не виконує всю операцію, і саме тому діагностика працює найкраще, коли ви простежуєте ланцюг об’єктів.

apiVersion: apps/v1
kind: Deployment
metadata:
name: control-plane-demo
spec:
replicas: 2
selector:
matchLabels:
app: control-plane-demo
template:
metadata:
labels:
app: control-plane-demo
spec:
containers:
- name: web
image: nginx:1.29
ports:
- containerPort: 80

Цей YAML навмисно звичайний, бо урок архітектури — у побічних ефектах. Його застосування створює один верхньорівневий бажаний об’єкт, а потім контролери та планувальник створюють і оновлюють кілька залежних об’єктів. Корисна вправа — запустити k get deployment,replicaset,pods -w в одному терміналі, застосовуючи файл в іншому. Ви побачите, як Kubernetes поступово закриває розриви між бажаним та спостереженим станом.

Гіпотетичний сценарій: прикладна команда якось збільшила Деплоймент із двох реплік до восьми під час сплеску трафіку й побачила, що шість Pod’ів сидять у стані Pending. Вони припустили, що реєстр образів повільний, але k describe pod показав події планування Insufficient cpu. Планувальник працював правильно; він відмовлявся прив’язувати Pod’и до вузлів, які не могли задовольнити запити. Виправленням було налаштування потужності та запитів, а не перезапуск планувальника чи зміна образу.

Комунікація площини управління та потік запитів

Розділ «Комунікація площини управління та потік запитів»

Усі компоненти Kubernetes спілкуються між собою через API-сервер, а це означає, що потік запитів — це здебільшого історія про спостережувані об’єкти та оновлення, а не про прямі віддалені виклики процедур між кожною окремою парою компонентів. Контролери не телефонують планувальнику, щоб попросити в нього розміщення. Планувальник, своєю чергою, не телефонує kubelet’у, щоб той запустив контейнер. Натомість кожен учасник спостерігає за API-сервером у пошуках ресурсів, релевантних його роботі, записує оновлення через API-сервер і покладається на те, що наступний учасник спостереже новий стан.

┌─────────────────────────────────────────────────────────────┐
│ HOW COMPONENTS COMMUNICATE │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ │
│ │ kubectl │ │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ Controller ─────→ │ API Server │ ←───── Scheduler │
│ Manager └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ etcd │ │
│ └──────────────┘ │
│ │
│ Flow example - Creating a Deployment: │
│ │
│ 1. kubectl creates Deployment via API Server │
│ 2. API Server stores it in etcd │
│ 3. Deployment Controller sees new Deployment │
│ 4. Controller creates ReplicaSet │
│ 5. ReplicaSet Controller creates Pods │
│ 6. Scheduler sees unscheduled Pods │
│ 7. Scheduler assigns Pods to nodes │
│ 8. kubelet on node sees assignment, runs Pods │
│ │
└─────────────────────────────────────────────────────────────┘

Патерн спостереження (watch) ефективний, бо компонентам не потрібно постійно перелічувати кожен об’єкт і порівнювати все з нуля. Контролер може встановити спостереження й отримувати зміни для типу ресурсу, яким він володіє. API-сервер використовує версії ресурсів, щоб дозволити клієнтам продовжувати з відомої точки в потоці подій. Коли спостереження переривається, клієнт може перелічити заново та відновитися. Саме така конструкція дозволяє контролерам швидко реагувати, не перетворюючи API-сервер на вузьке місце опитувань.

Ця архітектура на основі спостереження також пояснює, чому статус може відставати від бажаного стану, не означаючи, що кластер зламаний. Створення об’єкта часто є миттєвим, але поля статусу відображають роботу, виконану іншими компонентами після того, як вони спостережуть цей об’єкт. Деплоймент може існувати до того, як існуватиме його ReplicaSet, Pod може існувати до того, як його заплановано, а запланований Pod може існувати до того, як його контейнери стануть готовими. Час між цими стадіями — це місце, де події, умови та версії ресурсів дають корисний контекст.

Умови (conditions) особливо корисні, бо вони підсумовують поточне судження компонента у спосіб, який можуть прочитати і машини, і люди. Умова Деплойменту може повідомити, що поступ відбувається або застопорився. Умова Pod’а може показати, чи завершено планування, ініціалізацію, готовність або запуск контейнерів. Хороші оператори не сприймають статус як декоративний вивід; вони читають його як пояснення площини управління того, що сталося досі і що залишається заблокованим.

Простеження запиту Деплойменту дає вам надійний ментальний налагоджувач. По-перше, клієнт надсилає Деплоймент до API-сервера. По-друге, API-сервер автентифікує, авторизує, допускає, валідує та зберігає об’єкт до etcd. По-третє, контролер Деплойменту помічає бажаний Деплоймент без потрібного ReplicaSet’а й створює його. По-четверте, контролер ReplicaSet помічає, що кількість реплік нижча за бажану, і створює Pod’и. По-п’яте, планувальник прив’язує ці Pod’и до вузлів. По-шосте, kubelet на кожному обраному вузлі запускає контейнери та звітує про статус.

СтадіяКомпонент, що дієДокази для перевірки
Запит прийнятоkube-apiserverВідповідь API, журнали аудиту, об’єкт існує в k get
Бажаний стан збереженоetcd через API-серверЗміни версії ресурсу, об’єкт можна прочитати знову
ReplicaSet створеноkube-controller-managerk get rs, умови Деплойменту, події
Pod’и створеноконтролер ReplicaSetk get pods, посилання на власника, події ReplicaSet’а
Pod’и призначеноkube-scheduler.spec.nodeName, події планувальника
Контейнери запущеноkubelet та середовище виконанняУмови Pod’а, статус контейнерів, події вузла

Який підхід ви обрали б тут і чому: якщо користувач повідомляє, що k create deployment повернув успіх, але жоден контейнер не запущено, ви перевіряли б спочатку API-сервер чи простежували б стадії об’єктів? У більшості випадків успішна відповідь уже доводить, що перша стадія спрацювала, тож простеження Деплойменту, ReplicaSet’а, Pod’а, подій планувальника та статусу kubelet дає кращі докази, ніж розглядання самого лише API-сервера.

Модель стадій також запобігає шумним перезапускам. Перезапуск планувальника не допоможе, якщо об’єкта Pod не існує. Перезапуск kubelet не допоможе, якщо Pod не має призначеного вузла. Перезапуск API-сервера може погіршити інцидент, якщо справжнім вузьким місцем є etcd, а клієнти вже повторюють спроби. Хороша експлуатація Kubernetes залежить від звуження збійної стадії перед тим, як торкатися компонентів, особливо в продакшн-кластерах, де перезапуски площини управління можуть зачепити багато команд одночасно.

k describe залишається корисним, бо він збирає події та статус, створені кількома компонентами. Для Деплойменту він може розкрити умови розгортання та створення ReplicaSet’а. Для Pod’а він може розкрити рішення планувальника, помилки завантаження образів, помилки монтування томів та збої готовності. Сприймайте події як хлібні крихти від площини управління. Вони не є ідеальним журналом аудиту, але вони часто визначають компонент, який нещодавно намагався просунути об’єкт і зазнав невдачі.

Події тимчасові й можуть бути ущільнені або видалені під час ротації, тож вони мають спрямовувати діагностику, а не слугувати єдиним записом. Якщо інцидент важливий, зафіксуйте відповідний YAML об’єкта, події, логи контролерів і час перед тим, як очищення видалить докази. Що коротший збій, то легше втратити контекст після того, як повторні спроби вдадуться. Це ще одна причина діагностувати за стадіями: навіть коли події зникають, ланцюг об’єктів і поля статусу часто зберігають достатньо структури, щоб реконструювати, де запит зупинився.

Terminal window
k create deployment control-plane-demo --image=nginx:1.29 --replicas=2
k get deployment,replicaset,pods -o wide
k describe deployment control-plane-demo
k describe pod <new-pod-name>

Гіпотетичний сценарій: під час платформної міграції команда відкрила інцидент, бо Деплоймент показував правильну кількість реплік, тоді як трафік усе одно падав. Ланцюг об’єктів виявив, що Pod’и були створені та заплановані, але проби готовності зазнавали невдачі після того, як kubelet запускав контейнери. Площина управління виконала свою роботу; застосунок відмовлявся ставати готовим. Без простеження стадій команда змарнувала б час, звинувачуючи планувальник і контролери у проблемі перевірки здоров’я рівня робочого навантаження.

Хмарна інтеграція та висока доступність

Розділ «Хмарна інтеграція та висока доступність»

cloud-controller-manager існує саме тому, що Kubernetes потребував чіткішої межі між базовою оркестрацією та поведінкою, специфічною для конкретного хмарного провайдера. Кластер, що працює локально на ноутбуці, не має ані API хмарного балансувальника навантаження, ані таблиці маршрутів провайдера, ані сервісу метаданих екземплярів. Кластер, що працює на AWS, Google Cloud, Azure або в іншого інфраструктурного провайдера, часто потребує, щоб Сервіси, Ноди та маршрути Kubernetes відображали зовнішні ресурси провайдера. Відокремлення хмарної логіки в cloud-controller-manager дозволяє базовому Kubernetes еволюціонувати, не вбудовуючи кожну інтеграцію провайдера безпосередньо в центральний менеджер контролерів.

┌─────────────────────────────────────────────────────────────┐
│ CLOUD-CONTROLLER-MANAGER │
├─────────────────────────────────────────────────────────────┤
│ │
│ What it does: │
│ ───────────────────────────────────────────────────────── │
│ • Cloud-specific control logic │
│ • Only present in cloud environments │
│ • Separates cloud code from core K8s │
│ │
│ Controllers it runs: │
│ ───────────────────────────────────────────────────────── │
│ Node Controller: │
│ • Checks if node still exists in cloud │
│ │
│ Route Controller: │
│ • Sets up routes in cloud infrastructure │
│ │
│ Service Controller: │
│ • Creates cloud load balancers for Services │
│ │
│ Example: │
│ Service type: LoadBalancer → cloud-controller creates │
│ an AWS ELB, GCP Load Balancer, or Azure LB │
│ │
└─────────────────────────────────────────────────────────────┘

Найвидимішою поведінкою cloud-controller-manager для початківців є Сервіс типу LoadBalancer. Об’єкт Сервіс зберігається в Kubernetes, але фактичний балансувальник навантаження створюється в API хмарного провайдера. Ця робота асинхронна. Сервіс може існувати миттєво, тоді як зовнішня адреса залишається в очікуванні, поки провайдер не створить і не повідомить ресурс. Якщо хмарна інтеграція нездорова або неправильно налаштована, Kubernetes може назавжди записати бажаний Сервіс, так і не отримавши придатної зовнішньої кінцевої точки.

Хмарна інтеграція — це хороший приклад того, як Kubernetes розширює модель узгодження за межі кластера. Контролер Сервісу не стає хмарним балансувальником навантаження; він просить API провайдера привести зовнішню інфраструктуру у відповідність до Сервісу Kubernetes. Це означає, що збої можуть жити поза кластером, усе одно з’являючись як статус Kubernetes. IAM провайдера, виявлення підмереж, квоти, правила брандмауера та регіональні ліміти сервісів — усе це може заблокувати остаточний результат, навіть коли YAML Сервісу валідний.

Керовані сервіси Kubernetes можуть приховувати ці деталі, але архітектура все одно має значення. Коли керований кластер не може забезпечити балансувальник навантаження, збій може бути в конфігурації Сервісу Kubernetes, дозволах хмарного IAM, квотах провайдера, тегах підмереж або інтеграції cloud-controller. Модель площини управління допомагає вам уникнути поверхневого висновку на кшталт «мережа Kubernetes зламана». Ви можете запитати, який цикл узгодження володіє зовнішнім ресурсом і які докази він записав на Сервісі.

Висока доступність застосовує ту саму модель відповідальності до кількох машин. API-сервери можна реплікувати горизонтально, бо вони не зберігають стану. Планувальники та менеджери контролерів можуть запускати кілька екземплярів, але вибори лідера гарантують, що лише один активний лідер виконує заданий цикл керування в певний момент. etcd працює як кластер на основі кворуму, бо він зберігає стійкий стан. Продакшн-конструкція має тримати ці відмінності чітко; дублювання процесів — це не те саме, що захист сховища даних.

┌─────────────────────────────────────────────────────────────┐
│ HIGH AVAILABILITY SETUP │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Load Balancer │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────┼────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ Master 1 │ │ Master 2 │ │ Master 3 │ │
│ │ │ │ │ │ │ │
│ │ API Server │ │ API Server │ │ API Server │ │
│ │ Scheduler │ │ Scheduler │ │ Scheduler │ │
│ │ Controller │ │ Controller │ │ Controller │ │
│ │ etcd │ │ etcd │ │ etcd │ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
│ • Multiple API servers (all active) │
│ • Scheduler/Controller use leader election │
│ • etcd requires quorum (odd number: 3, 5, 7) │
│ │
└─────────────────────────────────────────────────────────────┘

Кворум — це причина, чому кластери etcd зазвичай використовують непарну кількість членів. У триелементному кластері etcd два члени утворюють кворум, тож кластер може пережити збій одного члена. У п’ятиелементному кластері три члени утворюють кворум, тож він може пережити збій двох членів. Додавання четвертого члена до триелементного кластера не покращує кількість допустимих збоїв, бо кворум стає три; кластер усе одно може пережити лише один збій. Непарна кількість зазвичай дає кращу відмовостійкість на машину.

Вибори лідера відрізняються від кворуму etcd. Планувальник і менеджер контролерів можуть запускати кілька реплік, але лише обраний лідер активно записує рішення для заданого циклу керування. Резервні репліки продовжують спостерігати й можуть перебрати роль, якщо лідер зникне. Це уникає суперечливих дій, як-от двох планувальників, що намагаються по-різному прив’язати той самий Pod, або двох контролерів, що змагаються за дублювання відновлень. Об’єкт оренди (lease), що використовується для виборів лідера, сам зберігається через API-сервер.

Кластери з однією площиною управління доречні для навчання, локальної розробки та деяких некритичних середовищ, бо вони простіші й дешевші. Їх також спочатку легше осягнути: один API-сервер, один планувальник, один менеджер контролерів і зазвичай один локальний etcd. Компроміс очевидний під час обслуговування чи збою. Якщо цей єдиний вузол площини управління недоступний, операції керування призупиняються, навіть якщо контейнери на робочих вузлах продовжують працювати.

Високодоступні площини управління коштують більше й вводять більше рухомих частин, але вони зменшують єдині точки відмови для керування кластером. Вам потрібна надійна кінцева точка для API-серверів, ретельне керування сертифікатами та конфігурацією, практика резервного копіювання й відновлення etcd та моніторинг, який відрізняє здоров’я API-сервера від здоров’я etcd. Кластер може мати кілька здорових процесів API-сервера і все одно бути нездатним записувати, якщо etcd не має кворуму, тож моніторингу лише живучості процесів недостатньо.

Зріла HA-конструкція також враховує поведінку під час обслуговування. Оновлення, ротація сертифікатів, заміна вузлів і відновлення з резервної копії — усе це навантажує ті самі частини площини управління, що й збої. Якщо єдиний задокументований план відновлення — це «провайдер впорається» або «перезапустіть вузол», команда фактично не порівняла режими відмов. Навіть керовані кластери заслуговують на інструкції (runbook), які визначають, які симптоми належать провайдеру, які належать пулам вузлів, керованих користувачем, а які можна перевірити через об’єкти Kubernetes.

Для самокерованих кластерів відновлення etcd — це сценарій, який треба відпрацювати, перш ніж він комусь знадобиться. Відновлення знімка зазвичай означає ретельні рішення щодо ідентичності кластера, конфігурації членів, сертифікатів і точки в часі, яку ви відновлюєте. Недбале відновлення може воскресити старий бажаний стан або конфліктувати з робочими навантаженнями, які продовжували працювати після знімка. Безпечна експлуатаційна звичка — репетирувати процедуру на ізольованому кластері й точно задокументувати, чого прикладні команди мають очікувати після відновлення.

Гіпотетичний сценарій: команда запускала три API-сервери, але розмістила всіх членів etcd на одному й тому самому хості віртуалізації. Їхня архітектурна діаграма виглядала високодоступною, проте збій одного хоста видаляв усе сховище даних. Кінцева точка API все ще мала кілька налаштованих бекендів, але жоден не міг зафіксувати стан. Висока доступність — це не галочка, що рахується за кількістю реплік процесів; це конструкція домену відмов, яка запитує, які фізичні, мережеві та сховищні збої кластер фактично може пережити.

Патерни та антипатерни

Розділ «Патерни та антипатерни»

Хороша експлуатація площини управління завжди починається з діагностики, що ґрунтується саме на доказах. Замість того щоб перезапускати компоненти лише через нездорове робоче навантаження, досвідчені оператори натомість простежують ланцюг об’єктів і запитують, який цикл керування ще не завершив свою відповідальність. Цей патерн добре масштабується, бо він працює однаково як для простих прикладів для початківців, так і для серйозних продакшн-збоїв. Деплоймент, Job, Сервіс і Нода — кожен має бажаний стан, спостережений стан, події та володіння контролером, які можна перевірити перед зміною системи.

ПатернКоли використовуватиЧому він працює
Простежити ланцюг об’єктівЗапит робочого навантаження вдався, але результат неповнийВін розділяє прийняття API, узгодження контролерами, планування та виконання kubelet
Читати події перед перезапуском компонентівPod’и залишаються в стані Pending, Сервіси застрягли, або розгортання стопоритьсяПодії зазвичай визначають компонент, який намагався просунути об’єкт, і чому він зазнав невдачі
Робити резервні копії та тестувати відновлення etcdБудь-яка самокерована продакшн-площина управлінняetcd — це стійкий запис кластера, а нетестовані резервні копії — це лише сповнені надії файли
Використовувати HA з реальними доменами відмовПродакшн-кластери зі спільними командами чи впливом на дохідКілька реплік допомагають лише тоді, коли вони переживають різні збої машин, зон і сховищ

Найсильніший патерн — сприймати API як контракт координації. Контролери, планувальники, kubelet’и та хмарні інтеграції мають спілкуватися через об’єкти та статус Kubernetes, а не через приховані бічні канали. Це зберігає систему придатною для перевірки. Якщо інструмент створює зовнішні ресурси, не записуючи корисний статус чи події назад до Kubernetes, оператори втрачають слід, який робить налагодження площини управління практичним.

Антипатерни зазвичай походять від злиття відповідальностей у вашій голові. Якщо ви вважаєте, що планувальник створює Pod’и, ви налагоджуватимете не той компонент, коли ReplicaSet не зможе їх створити. Якщо ви вважаєте, що API-сервер зберігає стійкі дані локально, ви недоінвестуєте в резервне копіювання etcd. Якщо ви вважаєте, що всі репліки площини управління є активними записувачами, ви неправильно зрозумієте вибори лідера. Ці помилки поширені, бо кінцевий досвід користувача відчувається як одна команда, хоча роботу виконали багато компонентів.

АнтипатернЩо йде не такКраща альтернатива
Перезапуск планувальника для кожного Pod’а в стані PendingСправжньою причиною можуть бути потужність, taint’и, спорідненість або квотиСпочатку перевірте події Pod’а та обмеження вузлів
Сприйняття резервного копіювання etcd як необов’язковогоВтрачене сховище даних може означати відбудову бажаного стану кластераАвтоматизуйте знімки та практикуйте відновлення на непродакшн-кластері
Моніторинг лише живучості процесу API-сервераAPI може бути живим, тоді як записи до сховища не вдаютьсяМоніторте готовність, помилки запитів, затримку та здоров’я etcd разом
Запуск «HA»-компонентів в одному домені відмовЗбій одного хоста, стійки чи зони може видалити всі реплікиРозподіліть площину управління та членів etcd по незалежних доменах відмов

Є практична причина тримати ці патерни дисциплінованими. Під час інциденту кожен широкий перезапуск чи спекулятивна зміна конфігурації додає шуму до доказів. Kubernetes уже записує для вас багато стану, але лише якщо ви прочитаєте його, перш ніж перезаписати. Краща звичка — рухатися від запиту користувача до об’єкта API, від посилання на власника до залежного об’єкта, від подій до відповідальності компонента і від відповідальності компонента до найвужчого виправлення.

Каркас ухвалення рішень

Розділ «Каркас ухвалення рішень»

Коли ви стикаєтеся із симптомом площини управління, почніть із рішення, чи збій на краю API, у стійкому сховищі, в узгодженні, у плануванні чи на вузлі. Перше питання — чи API-сервер взагалі відповідає. Якщо k get namespaces не може з’єднатися, виправте kubeconfig, мережевий шлях, балансувальник навантаження, сертифікати або доступність API-сервера, перш ніж досліджувати контролери. Якщо API відповідає, але операції запису не вдаються або вичерпують час, додайте до наступних перевірок здоров’я та кворум etcd.

Якщо API приймає верхньорівневий об’єкт, простежте далі залежні об’єкти. Деплоймент без ReplicaSet’а вказує на поведінку менеджера контролерів, побічні ефекти допуску або недійсне володіння контролером. ReplicaSet без достатньої кількості Pod’ів указує на узгодження ReplicaSet’а, квоти або пов’язані події. Pod’и без призначень вузлів указують на рішення планувальника. Pod’и з призначеннями вузлів, але нездоровими контейнерами вказують на kubelet, образ, том, пробу, середовище виконання або проблеми застосунку.

СимптомПерший імовірний рівеньКорисні перші перевірки
k не може з’єднатися з кластеромКінцева точка API або kubeconfigk cluster-info, контекст kubeconfig, кінцева точка API-сервера, здоров’я балансувальника навантаження
Читання працює, але записи вичерпують часШлях від API-сервера до etcdГотовність API-сервера, кворум etcd, затримка сховища, логи площини управління
Деплоймент існує, але ReplicaSet не з’являєтьсяМенеджер контролерівУмови Деплойменту, здоров’я менеджера контролерів, події, квоти
Pod існує, але не має вузлаПланувальникk describe pod, ресурси вузлів, taint’и, селектори, спорідненості
Pod має вузол, але контейнери очікуютьKubelet або середовище виконанняПодії Pod’а, статус завантаження образу, монтування томів, умови вузла
Сервіс LoadBalancer залишається в очікуванніcloud-controller-manager або хмарний провайдерПодії Сервісу, дозволи провайдера, підмережі, квоти, логи хмарної інтеграції

Для архітектурних рішень порівнюйте радіус ураження зі складністю. Навчальний кластер може запускати одну площину управління, бо простій прийнятний, а простіші операції допомагають студентам зосередитися. Спільний staging-кластер може потребувати резервного копіювання та моніторингу, навіть якщо йому не потрібна повна багатозональна HA. Продакшн-кластер, що підтримує клієнтський трафік, зазвичай потребує реплікованих API-серверів, надійного кворуму etcd, протестованого відновлення та явного планування доменів відмов. Магічного порогу немає, але експлуатаційне питання полягає в тому, чи може бізнес витримати втрату керування кластером протягом очікуваного вікна ремонту.

Використовуйте цей потік рішень, коли вам потрібно обрати, куди дивитися далі, і сприймайте кожну відповідь як доказ, що звужує наступну команду, а не як привід стрибати випадково по кластеру:

Request or workload symptom
Can the API server answer basic reads?
├── No → Check kubeconfig, network, load balancer, API server health
└── Yes
Do writes succeed and persist?
├── No → Check admission failures, authorization, API readiness, etcd quorum
└── Yes
Do dependent objects appear?
├── No → Check controller manager, owner references, quotas, events
└── Yes
Do Pods receive node assignments?
├── No → Check scheduler events, node fit, taints, affinity, resources
└── Yes → Check kubelet, runtime, image pulls, volumes, probes

Каркас навмисно поетапний, бо й сам Kubernetes поетапний. Ви уникаєте вгадування, дотримуючись того самого шляху, яким іде площина управління. Спочатку запит стає збереженим бажаним станом. Потім контролери створюють залежний бажаний стан. Потім планувальник обирає вузли. Потім kubelet’и запускають контейнери та звітують про статус. Проблема все одно може бути тонкою, але простір пошуку стає меншим на кожному кроці.

Каркас також допомагає під час екзаменаційних питань, бо він перетворює формулювання на володіння компонентом. Слова на кшталт «валідувати», «автентифікувати», «авторизувати», «допустити» та «надати API» вказують у бік kube-apiserver. Слова на кшталт «зберігати», «знімок», «кворум» або «стійкий стан кластера» вказують у бік etcd. Слова на кшталт «призначити», «прив’язати», «вибір вузла», «taint’и» та «спорідненості» вказують у бік планувальника. Слова на кшталт «узгодити», «бажаний стан», «ReplicaSet», «здоров’я вузла» та «ендпоінти» вказують у бік менеджера контролерів. Слова на кшталт «хмарний балансувальник навантаження», «маршрут» і «життєвий цикл вузла провайдера» вказують у бік cloud-controller-manager.

Коли ви не впевнені, запитайте, який об’єкт має існувати наступним. Якщо наступний відсутній об’єкт — це ReplicaSet, контролер мав би його створити. Якщо наступне відсутнє поле — це .spec.nodeName, планувальник мав би його записати. Якщо наступний відсутній статус — це готовність контейнера, то тепер задіяні kubelet і робоче навантаження. Це формулювання «спершу об’єкт» просте, але воно запобігає багатьом дорогим відхиленням, бо воно дотримується власного контракту Kubernetes.

  • etcd означає «/etc distributed» — назва поєднує конфігураційний каталог Unix /etc з ідеєю розподіленого зберігання, що відповідає його ролі стійкого конфігураційного запису кластера.
  • Вибори лідера запобігають суперечливим записувачам — кілька реплік планувальника чи менеджера контролерів можуть працювати, але лише обраний лідер активно виконує задану відповідальність, тоді як резервні репліки чекають, щоб перебрати роль.
  • API-сервер не зберігає стану — екземпляри API-сервера зберігають стійкий стан кластера в etcd, а не в локальній пам’яті процесу, і саме тому їх можна масштабувати за балансувальником навантаження.
  • Контролери використовують спостереження замість сліпого опитування — потоки спостереження дозволяють контролерам ефективно реагувати на зміни об’єктів, використовуючи версії ресурсів, щоб відновлюватися з відомих точок після переривань.
ПомилкаЧому вона трапляєтьсяЯк її виправити
Казати, що планувальник запускає Pod’иКористувач бачить одну команду k create deployment і припускає, що один компонент виконує всю роботуПам’ятайте, що планувальник призначає .spec.nodeName, тоді як kubelet на цьому вузлі запускає контейнери
Сприйняття etcd як необов’язковогоМалі кластери приховують etcd за статичними Pod’ами чи керованими сервісамиВизначте, де живе etcd, моніторте кворум і тримайте протестовані резервні копії для самокерованих кластерів
Переконання, що API-сервер зберігає стійкі дані локальноAPI-сервер — це видима точка входу для кожного запитуРозділіть обробку запитів і зберігання: API-сервер валідує та координує, etcd зберігає стан
Перезапуск компонентів площини управління перед читанням подійІнциденти створюють тиск швидко «щось зробити»Спочатку простежте об’єкти та події, щоб виправлення націлювалося на збійну стадію
Очікування, що кожна репліка менеджера контролерів діє одночасноВисока доступність звучить так, ніби всі репліки активно записуютьВивчіть вибори лідера: резервні репліки готові, але один лідер виконує активне узгодження
Ігнорування cloud-controller-manager під час збоїв LoadBalancerОб’єкт Сервіс існує всередині Kubernetes, тож про хмарну частину легко забутиПеревірте події Сервісу та інтеграцію провайдера, коли зовнішні адреси залишаються в очікуванні
Називання кластера високодоступним лише тому, що в нього кілька процесівДіаграми можуть приховувати спільні хости, сховище чи домени мережевих відмовРозподіліть API-сервери та членів etcd по реальних доменах відмов і протестуйте поведінку при відмові
Ваша команда створює Деплоймент, команда API повертає успіх, і об'єкт Деплоймент існує, але жоден ReplicaSet не з'являється через кілька хвилин. Яку область площини управління ви досліджуєте першою і чому?

Почніть з узгодження контролерами, особливо kube-controller-manager та доказів контролера Деплойменту. API-сервер уже прийняв і зберіг Деплоймент, тож край запиту, ймовірно, не є першим збоєм. Планувальник також надто пізно в ланцюзі, бо він діє лише на Pod’ах, які вже існують. Перевірте умови Деплойменту, події, здоров’я менеджера контролерів, квоти та помилки, пов’язані з посиланнями на власника, перш ніж змінювати налаштування планувальника.

Pod застряг у стані `Pending`, а `k get pod -o wide` показує порожній стовпець вузла. Що це говорить вам про потік запитів і що слід перевірити далі?

Pod створено, але планувальник не зміг успішно прив’язати його до вузла. Це означає, що узгодження контролерами зайшло достатньо далеко, щоб створити Pod, тоді як виконання kubelet не почалося, бо жоден вузол ще не володіє Pod’ом. Перевірте k describe pod, недавні події, потужність вузлів, taint’и, селектори, правила спорідненості та запити на ресурси. Логи контейнера навряд чи допоможуть, бо контейнер, ймовірно, ще не запустився.

Процес API-сервера достатньо здоровий, щоб відповідати на деякі запити читання, але кожна спроба створити чи оновити об'єкти вичерпує час. Який компонент стає серйозним підозрюваним, і який принцип конструкції пояснює симптом?

etcd стає серйозним підозрюваним, бо записи мають бути зафіксовані в стійкому сховищі-бекенді, перш ніж стан кластера зможе просунутися. API-сервер не зберігає стану й координує зберігання, а не тримає постійний запис локально. Якщо etcd має втрату кворуму, сильну затримку чи тиск на сховище, кінцева точка API може все ще здаватися частково живою, тоді як записи не вдаються. Перевірте готовність API, здоров’я etcd, кворум і затримку сховища разом.

Ваш колега каже, що тривузлова площина управління автоматично є високодоступною, бо є три API-сервери. Яке важливе питання ви поставили б, перш ніж прийняти це твердження?

Запитайте, де фактично працюють члени etcd і вузли площини управління з погляду домену відмов. Три процеси API-сервера допомагають лише тоді, коли сховище-бекенд стану та шлях кінцевої точки можуть пережити реалістичні збої. Якщо всі члени etcd сидять на одному хості, стійці, дисковій системі чи зоні, один інфраструктурний збій усе одно може видалити стійкий стан кластера. Висока доступність вимагає незалежних доменів відмов, планування кворуму та протестованого відновлення, а не лише кількості процесів.

Сервіс LoadBalancer залишається в очікуванні в керованому хмарному кластері. Об'єкт Сервіс існує, а звичайні Сервіси ClusterIP працюють. Який компонент площини управління чи інтеграцію слід включити до розслідування?

Включіть cloud-controller-manager або еквівалентну хмарну інтеграцію керованого провайдера. Сервіс LoadBalancer вимагає, щоб бажаний стан Kubernetes був узгоджений із зовнішнім хмарним балансувальником навантаження, що залежить від API провайдера, дозволів, квот, конфігурації підмереж і здоров’я контролера. Базовий API-сервер може працювати ідеально, тоді як зовнішній ресурс залишається нествореним. Події Сервісу та діагностика на стороні провайдера зазвичай дають наступний корисний доказ.

Запущений застосунок продовжує обслуговувати трафік після того, як API-сервер стає недоступним, але масштабування Деплойменту не вдається. Як обидва спостереження можуть бути правдивими?

Наявні контейнери можуть продовжувати працювати, бо kubelet і локальне середовище виконання контейнерів уже мають інструкції, потрібні, щоб тримати їх живими. Масштабування вимагає нового запису до Kubernetes API, узгодження контролерами, створення Pod’а, планування та виконання kubelet для нових Pod’ів. Якщо API-сервер недоступний, цей шлях керування не може просунутися, навіть якщо наявний стан виконання триває. Цей поділ — класична ознака того, що виконання робочого навантаження та керування площиною управління пов’язані, але окремі.

Вас просять оцінити, чи є збій розгортання проблемою планувальника. Деплоймент, ReplicaSet і Pod'и існують, кожен Pod має ім'я вузла, але контейнери очікують на завантаження образів. Який ваш висновок?

Це насамперед не проблема планувальника, бо планувальник уже завершив свою ключову відповідальність, призначивши вузли. Збій тепер на стороні виконання вузла, задіюючи kubelet, середовище виконання контейнерів, доступ до реєстру, ім’я образу, облікові дані чи мережеву політику. Вам слід перевірити події Pod’а, повідомлення про помилки завантаження образу та доступ на рівні вузла до реєстру. Перезапуск планувальника не вирішив би збою завантаження образу контейнера.

Мета: спостерігати площину управління Kubernetes у дії, визначити, що робить кожен основний компонент, і простежити запит Pod’а від подання API до розміщення на вузлі.

  • Підтвердьте доступ до кластера й визначте вузол чи вузли площини управління.

    Terminal window
    k cluster-info
    k get nodes -o wide

    Команди перевірки:

    Terminal window
    k get nodes
    k get namespaces
  • Перевірте компоненти площини управління, що працюють у kube-system.

    Terminal window
    k get pods -n kube-system -o wide
    k get pods -n kube-system | grep -E 'apiserver|etcd|scheduler|controller-manager'

    Команди перевірки:

    Terminal window
    k get pods -n kube-system --show-labels
    k describe pod -n kube-system <control-plane-pod-name>
  • Дослідіть API-сервер і підтвердьте, що він є головною точкою входу для операцій кластера.

    Terminal window
    k describe pod -n kube-system <kube-apiserver-pod-name>
    k get --raw=/readyz

    Команди перевірки:

    Terminal window
    k api-resources | head
    k version
  • Дослідіть etcd і пов’яжіть його зі збереженим станом кластера.

    Terminal window
    k describe pod -n kube-system <etcd-pod-name>
    k get configmaps,secrets,serviceaccounts -A | head -20

    Команди перевірки:

    Terminal window
    k get pods -A
    k get svc -A
  • Дослідіть планувальник і менеджер контролерів, а потім визначте їхні окремі відповідальності.

    Terminal window
    k describe pod -n kube-system <kube-scheduler-pod-name>
    k describe pod -n kube-system <kube-controller-manager-pod-name>

    Команди перевірки:

    Terminal window
    k get events -A --sort-by=.lastTimestamp | tail -20
    k explain pod.spec.nodeName
  • Створіть Деплоймент і спостерігайте, як площина управління його обробляє.

    Terminal window
    k create deployment control-plane-demo --image=nginx:1.29 --replicas=2
    k get deployment,pods -w

    Команди перевірки:

    Terminal window
    k describe deployment control-plane-demo
    k describe pod <new-pod-name>
  • Простежте планування, перевіривши, якому вузлу було призначено кожен Pod і які події було записано.

    Terminal window
    k get pods -o wide
    k get events --sort-by=.lastTimestamp

    Команди перевірки:

    Terminal window
    k get pod <new-pod-name> -o jsonpath='{.spec.nodeName}{"\n"}'
    k describe pod <new-pod-name> | grep -A5 Events
  • Порівняйте свій кластер із високодоступною конструкцією, підрахувавши екземпляри площини управління та кінцеву точку сервісу Kubernetes.

    Terminal window
    k get nodes -l node-role.kubernetes.io/control-plane
    k get endpoints kubernetes -n default

    Команди перевірки:

    Terminal window
    k cluster-info
    k get componentstatuses 2>/dev/null || true

    componentstatuses застаріло від Kubernetes v1.19 і може бути порожнім або відсутнім на кластері 1.35, тож не сприймайте його вивід як авторитетний.

  • Очистіть ресурси вправи.

    Terminal window
    k delete deployment control-plane-demo

    Команди перевірки:

    Terminal window
    k get deployment control-plane-demo
    k get pods | grep control-plane-demo
Підказка з розв'язання для простеження Деплойменту

Після створення Деплойменту дослідіть спочатку Деплоймент, потім ReplicaSet, потім Pod’и. Очікуваний ланцюг об’єктів — це Деплоймент → ReplicaSet → Pod’и. Деплоймент і ReplicaSet — це докази менеджера контролерів, тоді як призначення вузла Pod’у — це доказ планувальника. Якщо Pod’и мають імена вузлів і статуси контейнерів, kubelet уже почав стадію виконання на стороні вузла.

Підказка з розв'язання для визначення володіння компонентом

Використовуйте карту «симптом — компонент» з уроку. Проблеми з’єднання та валідації API вказують насамперед на kube-apiserver. Проблеми стійкого запису та відновлення стану вказують у бік etcd. Відсутні залежні об’єкти вказують у бік узгодження менеджером контролерів. Pod’и без імен вузлів указують у бік планувальника. Pod’и з іменами вузлів, але збоями виконання вказують у бік kubelet або середовища виконання контейнерів на вузлі.

Критерії успіху для цієї лабораторної роботи наведено нижче; використовуйте їх як фінальну самоперевірку, що пов’язує спостережений вивід команд назад з архітектурною моделлю:

  • API-сервер, etcd, планувальник і менеджер контролерів було знайдено в kube-system або визначено як компоненти, керовані провайдером.
  • Роль кожного компонента площини управління було зіставлено з реальними об’єктами чи подіями кластера.
  • Деплоймент було створено, а його Pod’и спостерігалися під час переходу із запитаного стану в запланований.
  • Призначення вузла для принаймні одного Pod’а було визначено за допомогою k.
  • Різницю між однією площиною управління та високодоступною компонуванням було описано за допомогою спостереженого виводу кластера.
  • Деплоймент вправи було видалено після перевірки.

Модуль 1.4: Архітектура Kubernetes — компоненти вузла — розуміння робочих машин, які запускають ваші застосунки та завершують рішення площини управління, описані тут.