Модуль 1.2: Інтерфейси розширення — CNI, CSI, CRI
Складність:
[СЕРЕДНЯ]— концептуальний матеріал із практичною діагностикою.Час на проходження: 35-45 хвилин.
Передумови: Модуль 1.1 (Площина управління).
Результати навчання
Розділ «Результати навчання»Після цього модуля ви зможете:
- Оцінити, чому Kubernetes делегує роботу із середовищем виконання контейнерів, мережею та сховищем інтерфейсам CRI, CNI та CSI замість того, щоб вбудовувати кожну реалізацію в основні компоненти.
- Визначити встановлене середовище виконання CRI, мережевий плагін CNI та драйвери сховища CSI на діючому кластері Kubernetes 1.35+ за допомогою полів вузла, ресурсів кластера, файлів плагінів та системних логів.
- Діагностувати збої пісочниці CNI, проблеми середовища виконання CRI та події монтування чи провізіонування CSI, пов’язуючи симптоми Под’ів та PVC з відповідними доказами.
- Порівняти поширені реалізації, такі як containerd, CRI-O, Calico, Cilium, Flannel, локальні томи та хмарні драйвери CSI, щоб ви могли обрати шлях усунення несправностей із правильними компромісами.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Гіпотетичний сценарій: ваша команда щойно створила невеликий кластер kubeadm для репетиції релізу. API-сервер відповідає, kubectl get nodes працює, а планувальник розміщує Под’и, але кожне застосункове робоче навантаження залишається у стані ContainerCreating, тоді як CoreDNS ніколи не стає готовим. Ніщо в маніфестах Деплойментів не виглядає незвичним, тож збій здається проблемою Kubernetes, хоча площина управління здебільшого виконує свою роботу. Відсутня ланка — це рівень розширення: kubelet може запросити пісочницю Под’а, але вузол не може зробити цю пісочницю корисною, доки середовище виконання та мережевий плагін не виконають свої контракти.
Kubernetes — це не єдина монолітна програма, яка вміє запускати кожен контейнерний рушій, з’єднувати кожну мережу та провізіонувати кожен диск. Його ядро навмисно вужче: надавати API, зберігати бажаний стан, планувати роботу та узгоджувати цей бажаний стан через контролери й kubelet’и. Щойно робота торкається виконання на рівні хоста, переадресації пакетів чи довговічного сховища, Kubernetes переходить від володіння реалізацією до забезпечення дотримання інтерфейсу. Саме завдяки цьому дизайну кластер може запускати containerd на одному дистрибутиві, CRI-O на іншому, Calico в дата-центрі, Cilium у середовищі з підвищеними вимогами до безпеки та різні драйвери CSI для AWS, Azure, vSphere, Ceph чи локальної розробки.
Цей модуль навчає інтерфейсів розширення як операційних контрактів, а не як термінів зі словника. Ви дізнаєтеся, чого kubelet очікує від інтерфейсу середовища виконання контейнерів (Container Runtime Interface), що має надати інтерфейс мережі контейнерів (Container Network Interface), перш ніж Под зможе спілкуватися, і як інтерфейс зберігання контейнерів (Container Storage Interface) відокремлює життєвий цикл тому від планування застосунків. Що важливіше, ви відпрацюєте читання слідів доказів: стовпці середовища виконання вузла, директорії конфігурації CNI, логи DaemonSet’ів, ресурси CSIDriver, події PVC, логи kubelet та шляхи до сокетів вузла. Мета — не запам’ятати назву кожного плагіна; вона полягає в тому, щоб знати, який рівень володіє симптомом, який ви спостерігаєте.
Найпростіша аналогія — це ноутбук, повний стандартних портів. Операційній системі не потрібен власний код для кожної будь-коли створеної клавіатури, накопичувача чи мережевого адаптера; їй потрібно, щоб ці пристрої дотримувалися контракту порту та протоколу. Інтерфейси розширення Kubernetes відіграють ту саму роль. CRI, CNI та CSI визначають, де зупиняється ядро і де починається спеціалізоване програмне забезпечення. Ця межа дозволяє вендорам та проєктам із відкритим кодом впроваджувати інновації, не змушуючи сам Kubernetes випускати нову версію щоразу, коли змінюється масив сховища, шлях даних eBPF чи прошарок середовища виконання.
Частина 1: Архітектура плагінів
Розділ «Частина 1: Архітектура плагінів»Kubernetes виріс навколо розподілу відповідальностей, який легко не помітити, коли ви тільки вивчаєте платформу. API-сервер, планувальник, менеджер контролерів та kubelet ухвалюють рішення щодо об’єктів і бажаного стану, але вони не є найкращим місцем для вбудовування кожної низькорівневої деталі реалізації. Виконання контейнерів залежить від просторів імен Linux, cgroups, снапшоттерів образів, середовищ виконання OCI та хостових служб. Мережа Под’ів залежить від виділення IP-адрес, маршрутів, мостів, оверлеїв, BGP, програм eBPF та забезпечення дотримання політик. Персистентне сховище залежить від хмарних API, блокових пристроїв, поширення монтувань, приєднання до вузла та поведінки файлової системи. Розміщення всього цього всередині ядра Kubernetes уповільнило б релізи, зробило б оновлення ризикованішими, а вибір платформи — набагато вужчим.
┌────────────────────────────────────────────────────────────────┐│ The Kubernetes Philosophy ││ ││ "Do one thing well, let others do the rest" ││ ││ Kubernetes Core: ││ ✓ API and resource management ││ ✓ Scheduling and orchestration ││ ✓ Controller patterns ││ ✓ Desired state reconciliation ││ ││ NOT Kubernetes Core (delegated to plugins): ││ ✗ Container runtime details ││ ✗ Network implementation ││ ✗ Storage provisioning ││ │└────────────────────────────────────────────────────────────────┘Це делегування — не відмова від відповідальності; це модель контрактів. Kubernetes досі володіє API, зверненим до користувача, та послідовністю операцій, але він просить спеціалізовані компоненти виконувати роботу через добре відомі інтерфейси. Перевага — це вибір, оскільки оператор кластера може обрати середовище виконання, модель мережі та драйвер сховища, які пасують до середовища. Перевага — це також інновації, бо Cilium може розвивати шлях даних eBPF, а вендор CSI може додати підтримку снапшотів, не вбудовуючи цей код у бінарний файл kubelet. Компроміс полягає в тому, що усунення несправностей вимагає від вас простежити запит через межі, замість того щоб залишатися всередині одного файлу логів.
| Інтерфейс | Призначення | З чим спілкується kubelet |
|---|---|---|
| CRI (Container Runtime Interface) | Запуск контейнерів | containerd, CRI-O |
| CNI (Container Network Interface) | Мережа Под’ів | Calico, Cilium, Flannel |
| CSI (Container Storage Interface) | Персистентне сховище | AWS EBS, GCP PD, Ceph |
Таблиця виглядає простою, але послідовність має значення. Kubelet використовує CRI, щоб створити пісочницю Под’а та запустити контейнери. Під час створення пісочниці середовище виконання викликає плагіни CNI, щоб розмістити пісочницю в мережі кластера. Окремо, коли Под’у потрібен персистентний том, контролери Kubernetes та kubelet координуються з компонентами CSI так, щоб том існував, був приєднаний до правильного вузла та змонтований у контейнер. Коли один рівень виходить з ладу, вищі рівні часто показують лише загальний стан очікування, тож навичка CKA полягає в тому, щоб пов’язати стан очікування з інтерфейсом, який мав просунутися наступним.
Зробіть паузу й передбачте: якщо API-сервер та планувальник справні, але на робочому вузлі не існує конфігурації CNI, які об’єкти Kubernetes досі виглядатимуть нормально, а яка фаза життєвого циклу Под’а викриє проблему? Зробіть прогноз, перш ніж прочитаєте приклади команд далі в цьому модулі, бо саме ця ментальна модель пояснює значну частку усунення несправностей на рівні вузла на іспиті.
Архітектура розширення також захищає портативність робочих навантажень. Деплоймент, який зазвичай запускає NGINX, не згадує containerd, Calico чи драйвер CSI EBS; він просить у Kubernetes Под, мережу та, можливо, заявку на том. Це означає, що маніфести застосунків переживають багато інфраструктурних відмінностей. Однак операційні маніфести не зникають. Доповнення кластера, конфігурація вузлів, StorageClass’и та DaemonSet’и плагінів стають частиною контракту платформи, і платформенні інженери мусять версіонувати їх, моніторити та налагоджувати з тією самою ретельністю, яку вони приділяють площині управління.
Ця відмінність особливо важлива, коли ви читаєте завдання іспиту. У формулюванні може йтися, що Под не запускається, але правильна відповідь може критися у службі вузла, відсутньому файлі CNI чи невідповідності StorageClass. Kubernetes дає вам спільну об’єктну модель, а не гарантію, що кожен збій розв’язується ще одним маніфестом робочого навантаження. Коли ви навчитеся запитувати «який контракт мав завершитися наступним», той самий невеликий набір команд стає набагато потужнішим. Ви перестаєте блукати ресурсами й починаєте доводити, де життєвий цикл перетнув межу від ядра Kubernetes до реалізації розширення.
Інший практичний наслідок полягає в тому, що справність інтерфейсу — це справність кластера. Площина управління може бути доступною, тоді як кластер непридатний для справжніх робочих навантажень, бо не існує мережі Под’ів. Вузол може бути зареєстрованим, тоді як kubelet не може створювати нові контейнери, бо зламана точка доступу до середовища виконання. Драйвер сховища може бути встановленим, тоді як заявки досі зазнають невдачі, бо облікові дані зовнішнього провайдера є хибними. Це не граничні випадки; це нормальні результати системи з плагінами. Ціна вибору в тому, що оператори мусять розуміти обрані плагіни достатньо добре, щоб перевіряти їх після встановлень, оновлень та заміни вузлів.
Частина 2: CRI — інтерфейс середовища виконання контейнерів
Розділ «Частина 2: CRI — інтерфейс середовища виконання контейнерів»Інтерфейс середовища виконання контейнерів визначає, як kubelet просить середовище виконання завантажувати образи, створювати пісочниці Под’ів, запускати контейнери, зупиняти контейнери, збирати статус та передавати логи. Історично багато тих, хто навчався, асоціювали Kubernetes із Docker, бо Docker був поширеним на ноутбуках розробників, але Kubernetes ніколи не потребував повного досвіду розробника Docker на кожному вузлі. Kubelet потребує служби середовища виконання, яка спілкується через CRI поверх gRPC, і сучасні кластери зазвичай задовольняють цей контракт за допомогою containerd чи CRI-O. Образи Docker досі запускаються, бо формат образу стандартизований; змінився шлях керування на боці вузла.
┌────────────────────────────────────────────────────────────────┐│ CRI Flow ││ ││ kubelet ││ │ ││ │ CRI (gRPC) ││ │ "Create container with image X" ││ │ "Start container Y" ││ │ "Stop container Z" ││ ▼ ││ ┌─────────────────┐ or ┌─────────────────┐ ││ │ containerd │ │ CRI-O │ ││ └────────┬────────┘ └────────┬────────┘ ││ │ │ ││ ▼ ▼ ││ ┌─────────┐ ┌─────────┐ ││ │ runc │ │ runc │ ││ └─────────┘ └─────────┘ ││ │ │ ││ ▼ ▼ ││ Linux containers Linux containers ││ │└────────────────────────────────────────────────────────────────┘Ця опосередкованість є цінною, бо kubelet може залишатися стабільним, тоді як середовища виконання вдосконалюються незалежно. Containerd зосереджується на керуванні образами, снапшоттерах, життєвому циклі контейнерів та інтеграції із середовищами виконання OCI, такими як runc. CRI-O навмисно звужує себе до сценаріїв використання Kubernetes і поширений у середовищах, орієнтованих на OpenShift. Обидва можуть задовольнити kubelet без того, щоб Kubernetes тримав специфічні для середовища виконання гілки для кожної операції. Якщо сокет середовища виконання зникає чи служба середовища виконання зависає, kubelet не може створювати нові контейнери, навіть якщо API-сервер може продовжувати приймати об’єкти Под.
| Середовище виконання | Опис | Де використовується |
|---|---|---|
| containerd | Галузевий стандарт, випускник CNCF | за замовчуванням у kubeadm, GKE, EKS, AKS |
| CRI-O | Орієнтоване на Kubernetes, легке | OpenShift, деякі корпоративні рішення |
| Docker | Підтримку як прямого середовища виконання kubelet припинено в Kubernetes 1.24 | Спадкові (legacy) кластери |
Важлива екзаменаційна відмінність полягає в тому, що інструменти збирання образів та середовища виконання вузла — це окремі речі. Docker досі може зібрати OCI-сумісний образ, відправити його до реєстру та створити артефакт, який containerd зможе запустити. Те, що Kubernetes прибрав у версії 1.24, — це dockershim, вбудований у дерево адаптер, який дозволяв kubelet спілкуватися з рушієм Docker так, ніби той був середовищем виконання CRI. Якщо ви підключаєтеся по SSH до сучасного вузла і docker ps недоступний, це не доказ того, що робочі навантаження зникли. Зазвичай це означає, що вам слід перевірити середовище виконання CRI за допомогою crictl, статусу kubelet та менеджера служб середовища виконання.
# What runtime is kubelet using?kubectl get nodes -o wide# Look at CONTAINER-RUNTIME column
# On a node, check containerdsystemctl status containerdcrictl info
# List running containerscrictl ps
# List imagescrictl images
# Inspect a containercrictl inspect <container-id>Перш ніж це запускати, який вивід ви очікуєте у стовпці CONTAINER-RUNTIME на кластері Kubernetes 1.35+ у стилі kubeadm? Якщо ваша відповідь містить containerd://, за яким іде версія, ви мислите на правильному рівні. Це поле надходить зі статусу вузла від kubelet і повідомляє вам, яку точку доступу середовища виконання вузол насправді використовує. Це часто швидше та безпечніше, ніж здогадуватися за встановленими пакетами, бо вузол може містити старі бінарні файли, яких уже немає на активному шляху.
# Container runtime not respondingsystemctl status containerdjournalctl -u containerd -f
# kubelet can't talk to runtimejournalctl -u kubelet | grep -i "runtime"
# Check CRI socketls -la /var/run/containerd/containerd.sock
# Verify kubelet configurationcat /var/lib/kubelet/config.yaml | grep -i containerУсунення несправностей CRI починається із симптому. Якщо вузол має стан NotReady і події kubelet згадують проблему середовища виконання контейнерів, спершу перевірте службу середовища виконання. Якщо Под’и застрягли в очікуванні образів, перевірте події завантаження образів, доступність реєстру та логи середовища виконання. Якщо kubelet не може під’єднатися до сокета, служба може бути зупинена, шлях до точки доступу може бути хибним, або могла змінитися специфічна для дистрибутива конфігурація. Вам не потрібно спершу налагоджувати простори імен ядра; вам потрібно довести, що kubelet може дістатися до справної служби CRI і що ця служба може виконувати запитувані операції життєвого циклу образів та контейнерів.
Корисна звичка — читати вузол як конвеєр. Об’єкт API може існувати, тоді як планувальник його ще не розмістив. Под можна запланувати, тоді як kubelet ще не створив пісочницю. Пісочниця може існувати, тоді як CNI ще не налаштував мережу. Контейнер можна створити, тоді як завантаження образу чи запуск зазнає невдачі. Докази CRI містяться на тих етапах, де kubelet та середовище виконання обмінюються інформацією про життєвий цикл контейнерів, тож команди на кшталт crictl ps, crictl pods, crictl inspect, journalctl -u kubelet та journalctl -u containerd є практичним містком між об’єктами Kubernetes та реальністю вузла.
Існує одна тонка пастка середовища виконання, яка з’являється у змішаних середовищах. Наявність пакета не завжди дорівнює активному середовищу виконання. Образ вузла може містити інструменти Docker для зручності збирання образів, containerd, бо це активне середовище виконання CRI, та специфічні для дистрибутива допоміжні скрипти зі старішого шляху ініціалізації. Якщо ви обираєте команди, базуючись лише на тому, що випадково встановлено, ви можете перевіряти мертву службу, тоді як kubelet використовує інший сокет. Стовпець середовища виконання у статусі вузла та конфігурація kubelet є кращими орієнтирами, бо вони показують шлях, яким kubelet насправді йде.
Вибір середовища виконання також впливає на радіус ураження від збою. Якщо containerd несправний на одному робочому вузлі, Под’и, що вже працюють на інших робочих вузлах, можуть продовжувати без проблем, і планувальник може розмістити Под’и-заміни деінде, якщо є потужності. Якщо кожен вузол у пулі має спільну зламану конфігурацію середовища виконання, кластер може приймати нові робочі навантаження, але не зможе їх запустити в усьому пулі. Саме тому розгортання пулів вузлів мають включати димові тести середовища виконання, а не лише успішне завантаження. Простий crictl info та невеликий тестовий Под можуть виявити погану точку доступу, перш ніж від неї залежатимуть справжні робочі навантаження.
Частина 3: CNI — інтерфейс мережі контейнерів
Розділ «Частина 3: CNI — інтерфейс мережі контейнерів»Інтерфейс мережі контейнерів опрацьовує налаштування мережі, яке робить Под чимось більшим, ніж процес на вузлі. Kubernetes вимагає, щоб кожен Под отримував власну IP-адресу і щоб Под’и могли спілкуватися один з одним без потреби застосунку виконувати ручний NAT. Kubelet не реалізує цю мережеву тканину безпосередньо. Під час створення пісочниці Под’а середовище виконання викликає плагіни CNI, використовуючи конфігурацію з вузла, і ці плагіни створюють інтерфейси, призначають IP-адреси, встановлюють маршрути та часто беруть участь у забезпеченні дотримання політик чи оверлейній маршрутизації.
┌────────────────────────────────────────────────────────────────┐│ CNI Flow ││ ││ 1. kubelet creates pod sandbox (pause container) ││ 2. kubelet calls CNI plugin: "Configure network for pod X" ││ 3. CNI plugin: ││ - Creates veth pair (virtual ethernet) ││ - Assigns IP from pool ││ - Sets up routes ││ - Connects pod to cluster network ││ 4. Pod can now communicate with other pods ││ │└────────────────────────────────────────────────────────────────┘Конкретна реалізація різко відрізняється між плагінами. Flannel наголошує на простій оверлейній мережі, що корисно, коли ви хочете менше регуляторів і вам не потрібна багата поведінка політик. Calico може використовувати функції маршрутизації та політик, які пасують до багатьох продакшн-кластерів, зокрема середовищ, де має значення BGP чи забезпечення дотримання політик. Cilium використовує eBPF для реалізації функцій мережі, безпеки та спостережуваності з іншою моделлю шляху даних. Хмарно-нативні плагіни, такі як AWS VPC CNI, інтегрують адреси Под’ів із мережею хмарного провайдера, що спрощує деякі шляхи трафіку, але прив’язує поведінку до обмежень керування адресами цього провайдера.
| Плагін | Основні особливості | Складність |
|---|---|---|
| Calico | NetworkPolicy, BGP-маршрутизація, висока продуктивність | Середня |
| Cilium | На основі eBPF, спостережуваність, безпека | Вища |
| Flannel | Проста оверлейна мережа | Низька |
| Weave | Шифрування, просте налаштування | Низька |
| AWS VPC CNI | Нативна мережа VPC | Специфічно для AWS |
Операційний контракт зазвичай видно у трьох місцях на кожному вузлі. Бінарні файли CNI містяться під /opt/cni/bin/, файли конфігурації — під /etc/cni/net.d/, а агенти плагінів часто працюють як Под’и DaemonSet у kube-system чи іншому платформенному просторі імен. Перший збіжний файл конфігурації може мати значення, ось чому застарілі файли від старих встановлень спричиняють несподівану поведінку після міграції. Кластер може мати справні Под’и Calico, але якщо вузол досі обирає стару конфігурацію Flannel, kubelet та середовище виконання можуть викликати хибний ланцюг плагінів.
# List CNI binariesls /opt/cni/bin/
# List CNI configurations (first file wins!)ls /etc/cni/net.d/
# Check the active CNI configcat /etc/cni/net.d/10-calico.conflist # Example for CalicoЗупиніться й поміркуйте: ви щойно запустили kubeadm init, площина управління запустилася, а Под’и CoreDNS перебувають у стані Pending чи застрягли під час запуску. Чого бракує і чому DNS викриває проблему рано? Відповідь у тому, що kubeadm не встановлює плагін CNI замість вас. CoreDNS — це одне з перших нормальних робочих навантажень, створених кластером, тож воно швидко викриває, чи можуть Под’и бути запланованими, поміщеними в пісочницю, отримати адреси та підключеними до мережі кластера.
# What CNI is running?kubectl get pods -n kube-system | grep -E "calico|cilium|flannel|weave"
# Check CNI pod logskubectl logs -n kube-system -l k8s-app=calico-node --tail=50
# Verify pod IP allocationkubectl get pods -o wide # Check IP column
# Test pod-to-pod connectivitykubectl exec pod-a -- ping <pod-b-ip>Діагностуючи CNI, відокремлюйте симптоми керування від симптомів шляху даних. Якщо Под’и не можуть вийти зі стану ContainerCreating, плагін може не викликатися успішно, бінарний файл може бути відсутнім, файл конфігурації може бути недійсним, або агент вузла може бути несправним. Якщо Под’и працюють (Running), але не можуть дістатися один одного, плагін може призначати адреси, але зазнавати невдачі на маршрутах, інкапсуляції, політиках чи інтеграції з хостовим фаєрволом. Якщо лише трафік між вузлами зазнає невдачі, підозрюйте оверлей, маршрутизацію, BGP, хмарні групи безпеки чи стан програм eBPF, перш ніж звинувачувати контейнери застосунку.
# Pods stuck in ContainerCreatingkubectl describe pod <pod-name># Look for: "failed to set up sandbox container network"
# Check CNI configuration existsls -la /etc/cni/net.d/
# Check CNI binary existsls -la /opt/cni/bin/
# Check CNI agent logskubectl logs -n kube-system -l k8s-app=calico-node -c calico-node
# Node network issuesip addr show # Check interfacesip route # Check routesСценарій вправи: той, хто навчається, будує кластер kubeadm, пропускає встановлення CNI й бачить, що кожне нормальне робоче навантаження залишається у стані ContainerCreating з подіями network not ready. Виправленням може бути єдина команда kubectl apply -f ... для обраного плагіна, але урок є ширшим за цю команду. Kubeadm готує компоненти площини управління Kubernetes; він не вирішує за вас, якою буде реалізація мережі Под’ів. У продакшні еквівалентний збій може виникнути через погане розгортання DaemonSet, застарілу конфігурацію CNI чи образ вузла, що не містив потрібних бінарних файлів, тож та сама діагностична послідовність досі застосовна.
NetworkPolicy додає ще один рівень відповідальності. Kubernetes визначає API NetworkPolicy, але забезпечення дотримання надається мережевим плагіном. Кластер, що використовує простий плагін без підтримки політик, може приймати об’єкти політик, не забезпечуючи їх дотримання, залежно від поведінки плагіна та середовища. Для цілей CKA пам’ятайте, що збій підключення після зміни політики може бути цілком справною поведінкою CNI, а не зламаною мережею. Прочитайте обраний плагін, мітки простору імен, мітки Под’а та правила політики, перш ніж припускати, що шлях даних пошкоджено.
CNI також має часові відносини з ініціалізацією кластера, які пояснюють багато несподіванок із першим кластером. Статичні Под’и площини управління можуть працювати в хостовій мережі, тож API-сервер може бути справним до того, як з’явиться загальна мережа Под’ів. CoreDNS та звичайні Под’и застосунків потребують мережі Под’ів, тож вони швидко викривають відсутнє доповнення. Саме тому кластер kubeadm може виглядати наполовину живим: kubectl працює, вузли можуть реєструватися, але робочі навантаження чекають, бо мережу пісочниці неможливо створити. Виправлення — це не переписати Деплойменти; це встановити та перевірити мережевий плагін, обраний для Pod CIDR та середовища.
У схожих на продакшн кластерах докази CNI слід збирати на рівні кожного вузла, а не лише на рівні кластера. DaemonSet може показувати більшість реплік готовими, тоді як один робочий вузол має застарілий файл конфігурації, відсутній бінарний файл чи дрейф хостового фаєрвола. Зміна політики може торкнутися лише Под’ів з певною міткою чи селектором простору імен. Хмарно-нативний CNI може вичерпати призначувані адреси Под’ів на підмножині вузлів навіть тоді, коли кластер досі має CPU та пам’ять. Саме через ці часткові збої kubectl get pods -o wide, імена вузлів та логи плагінів по вузлах мають значення під час діагностики мережі.
Нарешті, будьте обережні з тестами підключення. Успішний запит до Сервісу доводить інший шлях, ніж прямий запит до IP Под’а, бо може бути задіяний kube-proxy чи альтернативна реалізація сервісів. Пінг Под’а на тому самому вузлі доводить менше, ніж запит між вузлами, бо для трафіку між вузлами потрібні маршрутизація, інкапсуляція, хмарні правила чи програми eBPF, щоб працювати за межами локального хоста. Хороші тести називають шлях, який вони перевіряють. У практичній вправі ви створите два Под’и й явно прочитаєте їхні IP-адреси, щоб ви могли міркувати про рівень CNI, а не випадково тестувати лише DNS чи Сервіси.
Частина 4: CSI — інтерфейс зберігання контейнерів
Розділ «Частина 4: CSI — інтерфейс зберігання контейнерів»Інтерфейс зберігання контейнерів виносить реалізацію персистентних томів із ядра Kubernetes до драйверів сховища. PersistentVolumeClaim — це запит застосунку, а не диск сам по собі. StorageClass спрямовує цей запит до провізіонера, параметрів, політики повторного використання, поведінки прив’язування та правил розширення. Контролерні компоненти CSI створюють чи видаляють базовий том, тоді як вузлові компоненти CSI публікують том на вузлі, де працює Под. Цей поділ дозволяє системам сховища інтегруватися з Kubernetes без вимоги, щоб їхній код провізіонування містився всередині дерева Kubernetes.
┌────────────────────────────────────────────────────────────────┐│ CSI Flow ││ ││ PersistentVolumeClaim created ││ │ ││ ▼ ││ StorageClass defines CSI driver ││ │ ││ ▼ ││ CSI Controller (Deployment in kube-system) ││ "Provision 10Gi volume from AWS EBS" ││ │ ││ ▼ ││ Cloud Provider: Creates actual disk ││ │ ││ ▼ ││ PersistentVolume created and bound ││ │ ││ ▼ ││ Pod scheduled to node ││ │ ││ ▼ ││ CSI Node plugin: Attaches & mounts disk ││ │└────────────────────────────────────────────────────────────────┘CSI має дві операційні особистості. Контролерна сторона має охоплення на рівні кластера й опрацьовує таку роботу, як провізіонування, видалення, приєднання, від’єднання, створення снапшотів та зміна розміру, залежно від можливостей драйвера. Вузлова сторона працює на кожному робочому вузлі й опрацьовує публікацію, скасування публікації, монтування, розмонтування та реєстрацію драйвера для цього вузла. Наявні Под’и з уже змонтованими томами можуть деякий час продовжувати читати й записувати, якщо контролер не працює, але нове провізіонування PVC, операції приєднання та деякі зміни життєвого циклу зазнаватимуть невдачі. Ця відмінність не дає вам гнатися за хибними логами під час інциденту зі сховищем.
┌────────────────────────────────────────────────────────────────┐│ CSI Architecture ││ ││ ┌─────────────────────────────────────────────────────────┐ ││ │ CSI Controller (Deployment) │ ││ │ - Runs as pods in kube-system │ ││ │ - Handles provisioning, attach/detach │ ││ │ - Usually 1-3 replicas │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ ┌─────────────────────────────────────────────────────────┐ ││ │ CSI Node Plugin (DaemonSet) │ ││ │ - Runs on every node │ ││ │ - Handles mount/unmount │ ││ │ - Registers node with CSI driver │ ││ └─────────────────────────────────────────────────────────┘ ││ │└────────────────────────────────────────────────────────────────┘| Драйвер | Сховище | Середовище |
|---|---|---|
| ebs.csi.aws.com | AWS EBS | AWS EKS |
| pd.csi.storage.gke.io | GCP Persistent Disk | GKE |
| disk.csi.azure.com | Azure Disk | AKS |
| csi.vsphere.vmware.com | vSphere | VMware |
| rook-ceph.rbd.csi.ceph.com | Ceph RBD | Локальне (on-premises) |
| hostpath.csi.k8s.io | Local path | Розробка |
Локальне сховище та віддалене сховище мають різні режими збоїв. Локальний том може бути швидким, бо дані містяться на власному диску вузла, але він прив’язує робоче навантаження до цього вузла та ускладнює відновлення, коли вузол виходить з ладу. Віддалений блоковий том на основі CSI може додати затримку приєднання чи залежність від хмарного API, але він часто може переміщатися з перепланованим Под’ом у межах обмежень драйвера. Розподілені системи сховища, такі як Ceph, додають ще один набір компромісів: більше рухомих частин та операційної складності в обмін на незалежність сховища від єдиного хмарного провайдера чи вузла.
# List CSI drivers in clusterkubectl get csidrivers
# Check CSI podskubectl get pods -n kube-system | grep csi
# View StorageClasses (use CSI drivers)kubectl get storageclasseskubectl describe storageclass <name>
# Check PV provisionerkubectl get pv -o jsonpath='{.items[*].spec.csi.driver}'Що сталося б, якби Под контролера CSI впав, але вузлові плагіни CSI на кожному робочому вузлі досі працювали? Наявні змонтовані томи можуть продовжувати функціонувати, бо монтування вже існує на вузлі, але нові заявки та нові приєднання викриють відмову контролера. Це сховищевий еквівалент відокремлення кухні ресторану від кур’єрів доставки: вже доставлену страву можна з’їсти, тоді як нові замовлення затримуються, якщо кухня припиняє приймати роботу. Аналогія недосконала, але вона допомагає вам вирішити, чи перевіряти спершу логи контролера, чи логи вузлового плагіна.
# PVC stuck in Pendingkubectl describe pvc <pvc-name># Look for: Events showing provisioning errors
# Check CSI controller logskubectl logs -n kube-system -l app=ebs-csi-controller -c ebs-plugin
# Check CSI node logskubectl logs -n kube-system -l app=ebs-csi-node -c ebs-plugin
# Verify CSI driver registeredkubectl get csinodeskubectl describe csinode <node-name>Усунення несправностей PVC керується подіями. PVC у стані Pending із відсутнім StorageClass — це інша проблема, ніж StorageClass, що називає невстановлений провізіонер, і обидві відрізняються від драйвера, якому бракує хмарних дозволів. kubectl describe pvc повідомляє вам, який контролер намагався провізіонувати і яку помилку він отримав. kubectl get storageclasses повідомляє вам, які провізіонери доступні заявкам. kubectl get csidrivers та kubectl get csinodes повідомляють вам, чи бачить Kubernetes реєстрацію драйвера. Логи драйвера потім показують специфічні для провайдера деталі, які події Kubernetes можуть узагальнювати надто широко.
Міграція від вбудованих у дерево (in-tree) плагінів сховища до CSI — це також історія про обслуговування. Вбудовані плагіни змушували релізи Kubernetes нести специфічний для провайдера код сховища, через що еволюція сховища залежала від графіку основних релізів. CSI дозволяє проєктам сховища постачатися незалежно, виправляти баги у власному темпі та надавати специфічні для драйвера можливості через sidecar’и та CRD. Компроміс полягає в тому, що оператори кластера тепер мусять явно володіти цими доповненнями. Драйвер сховища — це не пасивна бібліотека; це набір робочих навантажень, RBAC, сокетів, реєстрацій вузлів та зовнішніх дозволів API, які слід моніторити та оновлювати.
Збої сховища часто розпізнаються повільніше за збої середовища виконання чи мережі, бо об’єктна модель має більше проміжних станів. PVC може деякий час бути в стані Pending, перш ніж хтось помітить, особливо якщо Деплоймент застосунку було застосовано одночасно і він чекає на заявку. PV може бути в стані Bound, тоді як Под досі не може його змонтувати на конкретному вузлі. Том може успішно приєднатися, але зазнати невдачі під час монтування файлової системи через залежності чи дозволи вузла. Читання подій PVC, подій Под’а та логів драйвера разом допомагає вам визначити, який перехід сховища зазнав невдачі, замість того щоб трактувати всі помилки сховища як однакові.
Топологія — це ще одна причина, чому діагностика CSI вимагає більшого, ніж перевірка наявності драйвера. Деякі томи обмежені зоною, регіоном, вузлом чи пулом сховища, і планувальник мусить дотримуватися цих обмежень під час розміщення Под’ів. StorageClass із відкладеним прив’язуванням може навмисно чекати на планування Под’а перед провізіонуванням, щоб том з’явився у правильній топології. Така поведінка є справною, але вона може виглядати заплутаною, якщо ви очікуєте, що кожен PVC прив’яжеться негайно. Коли ви бачите WaitForFirstConsumer чи топологічні терміни, читайте їх як координацію планування, а не як автоматичний доказ зламаного драйвера.
Частина 5: Читання доказів розширення від початку до кінця
Розділ «Частина 5: Читання доказів розширення від початку до кінця»Найшвидший спосіб налагодити інтерфейси розширення — це не трактувати CRI, CNI та CSI як роз’єднані абревіатури. Почніть зі спостережуваного об’єкта й запитайте, який контракт мав успішно завершитися безпосередньо перед тим, як об’єкт зміг просунутися. Под, який не заплановано, не дістався kubelet, тож налагодження розширень є передчасним. Под, призначений вузлу, але такий, що чекає на створення пісочниці, вказує на налаштування середовища виконання чи мережі. Под у стані Running із невдалим монтуванням вказує на публікацію сховища. PVC у стані Pending, який ніколи не прив’язувався, вказує на StorageClass, провізіонер, дозволи чи поведінку контролера, а не на код застосунку.
| Інтерфейс | З чим спілкується Kubernetes | Що надає плагін | Розташування конфігурації |
|---|---|---|---|
| CRI | Середовище виконання контейнерів | Життєвий цикл контейнера | /var/run/containerd/ |
| CNI | Мережевий плагін | IP-адреси Под’ів, маршрутизація, політики | /etc/cni/net.d/ |
| CSI | Драйвер сховища | Провізіонування томів, монтування | CRD драйверів CSI |
Підсумок інтерфейсів навмисно компактний, але кожна клітинка вказує на докази. Для CRI використовуйте статус вузла, стан служби середовища виконання, шляхи до сокетів CRI, crictl та помилки середовища виконання kubelet. Для CNI використовуйте директорії CNI вузла, логи DaemonSet’а плагіна, події Под’а, виділення IP-адрес та пакетні тести між Под’ами. Для CSI використовуйте StorageClass’и, події PVC, ресурси CSIDriver та CSINode, логи контролера, логи вузлового плагіна та докази монтування з цільового Под’а. Це не випадковий контрольний список; це карта від абстракції Kubernetes до компонента, який мусить її виконати.
Коли ви під тиском часу, запишіть поточний етап життєвого циклу простими словами. «Под було заплановано, але мережа пісочниці зазнала невдачі» — корисніше, ніж «Под зламаний». «Заявку не провізіоновано» — корисніше, ніж «сховище зламане». «Служба середовища виконання зупинена» — корисніше, ніж «вузол поганий». Ці короткі діагнози змушують вас назвати інтерфейс та відсутній перехід. Вони також дають чистіші виправлення, бо ви можете перевірити, що саме цей перехід тепер успішно завершується після вашої зміни.
# ===== CRI Issues =====# Symptom: Pods won't start, "container runtime not running"systemctl status containerdjournalctl -u containerdcrictl info
# ===== CNI Issues =====# Symptom: Pods stuck in ContainerCreating, "network not ready"ls /etc/cni/net.d/kubectl get pods -n kube-system | grep -E "calico|cilium|flannel"kubectl logs -n kube-system <cni-pod>
# ===== CSI Issues =====# Symptom: PVC stuck in Pending, "provisioning failed"kubectl get csidriverskubectl describe pvc <name>kubectl logs -n kube-system <csi-controller-pod>Який підхід ви обрали б тут і чому: починати зі служб вузла, починати з подій Под’а чи починати з Под’ів плагінів? На іспиті починайте з подій Kubernetes, коли у вас є симптом об’єкта, бо вони повідомляють вам, що площина управління та kubelet уже спробували. Переходьте до служб вузла, коли подія згадує збій середовища виконання, пісочниці чи монтування. Переходьте до Под’ів плагінів, коли подія називає плагін чи провізіонер. Цей порядок не дає вам витрачати дорогоцінний час на низькорівневі команди, перш ніж ви дізнаєтеся, який інтерфейс володіє збоєм.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Хороші платформенні команди трактують інтерфейси розширення як повноцінні компоненти кластера. Вони не просто застосовують CNI YAML один раз, встановлюють пакет середовища виконання один раз і забувають про існування системи. Вони версіонують образи вузлів, маніфести плагінів, RBAC, StorageClass’и та процедури оновлення разом, бо ці частини утворюють невидиму підлогу під кожним робочим навантаженням. Патерни нижче корисні, бо вони зменшують неоднозначність під час збоїв: кожен із них робить активну реалізацію виявною, придатною для тестування та замінною без опертя на пам’ять.
| Патерн | Коли його використовувати | Чому це працює | Міркування щодо масштабування |
|---|---|---|---|
| Оголошуйте одну активну конфігурацію CNI на вузол | Будь-який кластер kubeadm чи самокерований кластер | Kubelet та середовище виконання викликають передбачуваний ланцюг плагінів | Забезпечуйте перевірками збирання образів чи валідацією ініціалізації вузла |
Стандартизуйте перевірку середовища виконання через crictl | Вузли Kubernetes 1.35+, що використовують середовища виконання CRI | Інструмент спілкується тим самим інтерфейсом, яким користується kubelet | Послідовно налаштовуйте точки доступу між пулами вузлів |
| Трактуйте StorageClass’и як платформенні API | Багатокомандні кластери з динамічним провізіонуванням | Команди застосунків запитують можливості без вбудовування деталей провайдера | Документуйте значення за замовчуванням, політику повторного використання, розширення та поведінку топології |
| Моніторте Под’и контролера та вузлового плагіна окремо | Розгортання CSI та просунутого CNI | Збої контролера та збої вузла дають різні симптоми | Налаштуйте оповіщення про покриття DaemonSet, доступність контролера та ресурси реєстрації |
Антипатерни зазвичай походять із припущення, що ядро Kubernetes володіє більшим, ніж насправді. Команда бачить Под, застряглий у стані ContainerCreating, і перезапускає API-сервер, хоча подія каже, що налаштування CNI зазнало невдачі на робочому вузлі. Інша команда змінює YAML застосунку, щоб обійти PVC у стані Pending, хоча StorageClass вказує на відсутній драйвер. Ці реакції марнують час, бо борються з хибним рівнем. Краща альтернатива — простежити межу контракту й запитати, який зовнішній компонент не зміг виконати свою частину життєвого циклу.
| Антипатерн | Що йде не так | Краща альтернатива |
|---|---|---|
| Встановлення кількох CNI та залишення старих файлів конфігурації | Вузли можуть обрати застарілу конфігурацію раніше за призначений плагін | Видаляйте застарілі файли та валідуйте /etc/cni/net.d/ під час ініціалізації |
Використання команд docker як єдиної діагностики середовища виконання | Сучасні вузли можуть взагалі не запускати рушій Docker | Використовуйте kubectl get nodes -o wide та crictl проти точки доступу CRI |
| Створення PVC перед встановленням відповідного драйвера CSI | Заявки залишаються в стані Pending із помилками провізіонера | Встановіть та перевірте драйвер, потім визначте StorageClass’и та заявки |
| Трактування NetworkPolicy як завжди забезпеченої | Деякі плагіни не реалізують забезпечення дотримання політик | Підтвердьте можливості плагіна та протестуйте дозволені й заборонені шляхи |
| Ігнорування справності простору імен плагінів | Под’и доповнень можуть давати збій, тоді як основні компоненти виглядають справними | Включайте DaemonSet’и, Деплойменти та логи CNI й CSI у тріаж |
Патерн, який вам слід засвоїти, — це докази перед дією. Перезапуск kubelet, видалення Под’ів чи перевстановлення плагіна можуть здаватися тимчасовим виправленням симптому, але вони також можуть стерти докази, які допомогли б ідентифікувати справжнє порушення контракту. На практичному кластері ви можете вільно експериментувати, але в продакшн-мисленні ви спершу фіксуєте події, логи, обрану конфігурацію та стан ресурсів. Потім ви змінюєте найменший рівень, який пояснює симптом. Саме ця дисципліна винагороджується на іспиті CKA, коли завдання дає вам зламаний вузол чи заявку на сховище.
Для команд, що керують багатьма кластерами, ці патерни стають вимогами до автоматизації. Перевірки відповідності вузлів можуть верифікувати сокет середовища виконання, бінарні файли CNI, конфігурацію CNI та готовність DaemonSet’а плагіна, перш ніж вузол приєднається до планованого пулу. Димові тести сховища можуть створити невелику заявку, змонтувати її, записати файл і видалити її після оновлень. Мережеві димові тести можуть запускати перевірки підключення Под’ів на тому самому вузлі та між вузлами. Жоден із цих тестів не замінює моніторинг, але вони виявляють найбільш руйнівні регресії інтерфейсів у момент, коли їх вносять, поки відкат ще простий.
Фреймворк ухвалення рішень
Розділ «Фреймворк ухвалення рішень»Використовуйте фреймворк ухвалення рішень щодо інтерфейсів, коли робоче навантаження не досягає очікуваного вами стану. Перше відгалуження — це чи було об’єкт заплановано, бо незаплановані Под’и є проблемами планувальника чи розміщення ресурсів, а не проблемами CRI, CNI чи CSI. Друге відгалуження — це чи може kubelet створити пісочницю та контейнери. Третє відгалуження — це чи має Под мережеві чи сховищеві залежності, які зазнають невдачі після запуску контейнера. Це тримає ваш шлях усунення несправностей вирівняним із життєвим циклом, а не з тим ім’ям плагіна, яке ви згадуєте першим.
| Симптом | Перший інтерфейс для підозри | Докази для збору | Імовірний наступний крок |
|---|---|---|---|
Вузол NotReady із повідомленнями середовища виконання | CRI | journalctl -u kubelet, systemctl status containerd, crictl info | Відновити службу середовища виконання чи виправити точку доступу середовища виконання kubelet |
Под застряг у ContainerCreating із помилкою мережі пісочниці | CNI | Події Под’а, /etc/cni/net.d/, /opt/cni/bin/, логи DaemonSet’а CNI | Полагодити конфігурацію CNI, бінарні файли чи агент вузла |
| Под у стані Running, але трафік між вузлами зазнає невдачі | CNI | IP-адреси Под’ів, маршрути, логи плагіна, об’єкти політик, фаєрволи вузлів | Діагностувати маршрутизацію, оверлей, політику чи хмарні правила безпеки |
| PVC у стані Pending із подією провізіонування | CSI | Події PVC, провізіонер StorageClass, логи контролера CSI | Виправити StorageClass, встановлення драйвера чи зовнішні дозволи |
| Под не може змонтувати прив’язаний PVC | CSI | Події Под’а, CSINode, логи вузлового плагіна, шляхи монтування | Перевірити вузловий плагін та операції публікації тому |
| Образ контейнера завантажено, але процес не запускається | CRI та конфігурація навантаження | crictl inspect, логи контейнера, події Под’а | Відокремити збій середовища виконання від збою команди застосунку |
Обираючи між реалізаціями, починайте з обмежень середовища, а не з популярності. Containerd — сильний вибір за замовчуванням для багатьох кластерів, бо він поширений, зрілий і добре підтримуваний дистрибутивами Kubernetes. CRI-O може бути кращим там, де платформений стек стандартизується навколо нього. Calico часто є практичним мережевим вибором, коли мають значення гнучкість політик та маршрутизації. Cilium переконливий, коли функції спостережуваності та безпеки eBPF виправдовують додаткову криву навчання. Flannel досі може бути корисним у простих лабораторіях, де політики та просунута видимість не є метою. Вибір CSI зазвичай диктується тим, де містяться ваші дані та якої поведінки відновлення потребує робоче навантаження.
У цьому фреймворку також ховається рішення про міграцію. Заміна драйвера CNI чи CSI — це не те саме, що зміна мітки застосунку, бо можуть існувати наявний стан вузла, виділення IP-адрес, маршрути, приєднання томів та специфічні для плагіна CRD. Інтерфейс дає Kubernetes стандартний спосіб викликати реалізацію, але він не перетворює магічним чином операційний стан одного провайдера на стан іншого провайдера. Плануйте міграції з нотатками про сумісність, вікнами обслуговування, кроками відкату та тестами, які доводять, що нові Под’и, наявні Под’и, нові PVC та наявні томи поводяться очікувано.
Використовуйте значення за замовчуванням свідомо. StorageClass за замовчуванням зручний, бо розробники можуть створювати PVC, не називаючи клас, але це також платформена обіцянка щодо вартості, продуктивності, топології, поведінки повторного використання та розширення. Вибір CNI за замовчуванням зручний, бо кожне робоче навантаження отримує мережу без роздумів про реалізацію, але він також визначає вашу поведінку NetworkPolicy та опції спостережуваності. Середовище виконання за замовчуванням зменшує варіативність вузлів, але його все одно слід задокументувати у стандартах збирання вузлів. Значення за замовчуванням корисні, коли вони явні; вони небезпечні, коли ніхто не пам’ятає, хто їх обрав і як їх перевірити.
Той самий фреймворк допомагає вам спілкуватися під час інцидентів. Замість того щоб сказати «мережа Kubernetes лежить», скажіть «нові пісочниці Под’ів на пулі вузлів A зазнають невдачі під час налаштування CNI, тоді як наявні Под’и продовжують пропускати трафік». Замість того щоб сказати «сховище лежить», скажіть «нове провізіонування PVC через контролер EBS CSI зазнає невдачі з помилкою авторизації, тоді як уже змонтовані томи залишаються справними». Такий рівень точності змінює шлях ремонту та людей, яких ви залучаєте. Він також не дає командам застосунків змінювати код, коли справжнім збійним компонентом є контракт платформи.
Чи знали ви?
Розділ «Чи знали ви?»- Образи Docker продовжили працювати після того, як Kubernetes 1.24 прибрав dockershim, бо формат образу та адаптер середовища виконання kubelet — це різні речі; OCI-сумісні образи можуть завантажуватися та запускатися containerd чи CRI-O.
- Порядок файлів конфігурації CNI може мати значення, бо середовища виконання обирають конфігурацію з
/etc/cni/net.d/; числові префікси на кшталт10-calico.conflistзазвичай використовуються, щоб зробити вибір передбачуваним. - CSI було впроваджено, щоб вендори сховища могли постачати драйвери поза циклом основних релізів Kubernetes, замінивши старішу модель вбудованих у дерево плагінів стандартизованим зовнішнім інтерфейсом драйверів.
- Cilium покладається на можливості eBPF у ядрі Linux, ось чому версія ядра та підтримка дистрибутива є частиною операційного рішення, а не просто перевагою плагіна.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому це стається | Як це виправити |
|---|---|---|
| Забути встановити CNI після ініціалізації kubeadm | kubeadm створює площину управління, але навмисно залишає вибір мережі Под’ів оператору | Встановіть один підтримуваний плагін CNI, потім підтвердьте готовність вузла, готовність CoreDNS та виділення IP-адрес Под’ам |
| Залишення кількох файлів конфігурації CNI на вузлі | Старі файли плагінів залишаються після міграції чи лабораторних експериментів | Тримайте один призначений ланцюг конфігурації в /etc/cni/net.d/ та видаляйте застарілі файли під час ініціалізації вузла |
Використання docker ps як джерела істини про середовище виконання | Ті, хто навчається, пам’ятають старіші вузли на основі Docker і пропускають зміну CRI | Перевіряйте стовпець середовища виконання вузла та використовуйте crictl проти активної точки доступу CRI |
| Налагодження PVC у стані Pending спершу з Под’а застосунку | Заявку не провізіоновано, тож монтування на рівні Под’а ще не існує | Прочитайте події PVC, імена провізіонерів StorageClass та логи контролера CSI, перш ніж змінювати навантаження |
| Перевірка лише логів контролера CSI для збоїв монтування | Публікація тому відбувається на вузлі, де працює Под | Перевірте CSINode, логи вузлового плагіна та події Под’а на наявність доказів приєднання та монтування |
| Припущення, що кожен CNI забезпечує дотримання NetworkPolicy | Об’єкт API стандартний, але забезпечення дотримання залежить від можливостей плагіна | Перевірте підтримку плагіна та протестуйте обидва шляхи — дозволений і заборонений трафік |
| Перезапуск kubelet до збору доказів | Перезапуск може стерти підказки про час, сокет чи події, потрібні для діагностики | Зафіксуйте події Под’а, логи kubelet, логи плагіна та обрану конфігурацію, перш ніж застосовувати виправлення |
Тест
Розділ «Тест»1. Ваша команда мігрувала лабораторний кластер із Flannel на Cilium. Розробник питає, чи потрібно переписувати кожен маніфест Деплойменту, бо мережевий плагін змінився. Що ви відповісте?
Зазвичай переписувати маніфест застосунку лише тому, що змінилася реалізація CNI, не потрібно. Kubernetes просить обраний плагін надати мережу Под’ів через контракт CNI, тож Под’и досі отримують IP-адреси, Сервіси досі спрямовуються на Под’и, а DNS досі розв’язує імена через ті самі абстракції Kubernetes. Операційна поведінка може змінитися, особливо навколо NetworkPolicy, спостережуваності, маршрутизації та вимог до ядра, тож ви валідуєте підключення та поведінку політик після міграції. Правильна дія — протестувати рівень платформи, а не редагувати кожну специфікацію навантаження.
2. Після перезавантаження вузла Под'и на цьому вузлі залишаються у стані `ContainerCreating`. Вузол містить як `10-calico.conflist`, так і `05-flannel.conflist` під `/etc/cni/net.d/`. У чому ймовірна проблема та виправлення?
Імовірна проблема — вибір застарілої конфігурації CNI. Якщо середовище виконання читає ранішу конфігурацію Flannel, тоді як кластер призначений використовувати Calico, налаштування мережі пісочниці може зазнати невдачі, бо обраний ланцюг плагінів не відповідає встановленим агентам та бінарним файлам. Виправлення — видалити застарілу конфігурацію, підтвердити, що залишилася лише призначена конфігурація CNI, та перестворити чи перезапустити уражені Под’и після того, як kubelet зможе викликати правильний плагін. Вам також слід перевірити кроки ініціалізації вузла чи збирання образу, щоб той самий застарілий файл не повернувся на вузлах-замінах.
3. PersistentVolumeClaim перебуває у стані Pending кілька хвилин. `kubectl get csidrivers` перелічує очікуваний драйвер, а Под'и контролера працюють. Куди ви заглянете далі?
Почніть із kubectl describe pvc <name>, бо розділ Events повідомляє вам, який провізіонер опрацював заявку та яку помилку він повідомив. Потім порівняйте запитуваний PVC StorageClass із kubectl get storageclasses та перевірте логи контролера CSI на наявність специфічних для провайдера помилок. Поширені причини включають StorageClass, що називає інший провізіонер, відсутні зовнішні хмарні дозволи, непідтримувані параметри чи топологічні обмеження, що заважають провізіонуванню. Той факт, що CSIDriver існує, доводить реєстрацію, а не успішне створення тому.
4. Колега оновлюється з Kubernetes 1.23 на новіший реліз і панікує, бо `docker ps` більше не працює на вузлах, хоча Под'и досі працюють. Що ви йому скажете?
Скажіть йому, що втрата шляху Docker CLI не означає, що контейнери чи образи зникли. Kubernetes прибрав dockershim у версії 1.24, тож kubelet більше не потребує спілкуватися з рушієм Docker як зі своїм адаптером середовища виконання. Сучасні вузли зазвичай використовують containerd чи CRI-O через CRI, і crictl ps — правильний інструмент перевірки на боці вузла. Зібрані Docker образи досі працюють, коли вони OCI-сумісні, бо артефакт образу та інтерфейс середовища виконання kubelet — це різні речі.
5. Под перебуває у стані Running, але трафік до Под'а на іншому вузлі вичерпує час очікування, тоді як трафік до Под'а на тому самому вузлі успішний. Який інтерфейс володіє першим шляхом розслідування?
Це вказує спершу на поведінку шляху даних CNI, а не на CRI, бо контейнери вже працюють, а комунікація на тому самому вузлі звужує збій до мережевої маршрутизації чи політики між вузлами. Перевірте IP-адреси Под’ів, маршрути, логи DaemonSet’а CNI, об’єкти NetworkPolicy, фаєрволи вузлів, хмарні групи безпеки та специфічний для плагіна статус. Конкретна наступна команда залежить від плагіна, але міркування стабільне: комунікація між вузлами вимагає, щоб мережева реалізація правильно маршрутизувала, інкапсулювала чи програмувала шлях даних. CRI був би ймовірнішим, якби контейнери взагалі не запускалися.
6. Под, що використовує прив'язаний PVC, зазнає невдачі з помилкою монтування лише на одному робочому вузлі. PVC та PV виглядають справними. Який компонент CSI вам слід перевірити першим?
Перевірте вузловий плагін CSI на робочому вузлі, де було заплановано Под, разом із подіями Под’а та інформацією CSINode. Прив’язані PVC та PV показують, що провізіонування вдалося, тож контролерна сторона ймовірно зробила свою роботу. Монтування та публікація тому в Под — це вузлові відповідальності, і збій на одному вузлі зазвичай вказує на справність вузлового плагіна, хостові залежності монтування, приєднання пристрою, дозволи чи специфічну для вузла реєстрацію драйвера. Логи контролера досі можуть допомогти пізніше, але вони не є першим місцем для локального для вузла збою монтування.
Практична вправа
Розділ «Практична вправа»Ця вправа просить вас перевірити інтерфейси розширення на діючому практичному кластері. Використовуйте одноразовий кластер чи пов’язане лабораторне середовище, а не спільну продакшн-систему, бо кілька вправ навмисно досліджують режими збоїв. Основний шлях є доступним лише для читання, а необов’язкові вправи з поломкою та виправленням чітко позначені. Ваша мета — побудувати повторюваний діагностичний нотатник: визначити середовище виконання, визначити мережевий плагін, перевірити файли CNI вузла, довести підключення між Под’ами та знайти драйвери сховища, якщо кластер містить CSI.
Завдання: Дослідіть конфігурацію CRI, CNI та CSI вашого кластера від об’єктів Kubernetes аж до доказів на рівні вузла, потім поясніть, який інтерфейс доводить кожне спостереження.
Завдання 1: Визначте ваше середовище виконання контейнерів
Розділ «Завдання 1: Визначте ваше середовище виконання контейнерів»kubectl get nodes -o wide# Note the CONTAINER-RUNTIME columnНотатки до розв'язання
Шукайте значення на кшталт containerd://... чи cri-o://... у стовпці CONTAINER-RUNTIME. Це значення повідомляється через статус вузла і є кращою першою відповіддю, ніж здогадка за встановленими на хості пакетами. Якщо вузол має стан NotReady, поєднайте це з логами kubelet та статусом служби середовища виконання, перш ніж переходити до CNI чи CSI.
Завдання 2: Дослідіть CRI з вузла
Розділ «Завдання 2: Дослідіть CRI з вузла»# On a node (SSH or kubectl debug node)crictl infocrictl pscrictl images | head -10Нотатки до розв'язання
crictl info підтверджує, що точка доступу CRI відповідає. crictl ps показує контейнери, відомі середовищу виконання, а crictl images показує образи, кешовані на вузлі. Якщо ці команди не можуть під’єднатися, перевірте шлях до сокета середовища виконання та службу середовища виконання, перш ніж припускати, що об’єкти Kubernetes хибні.
Завдання 3: Визначте ваш плагін CNI
Розділ «Завдання 3: Визначте ваш плагін CNI»kubectl get pods -n kube-system | grep -E "calico|cilium|flannel|weave"Нотатки до розв'язання
Вивід зазвичай показує агента у стилі DaemonSet для активного мережевого плагіна. Деякі керовані кластери використовують специфічні для провайдера імена, тож відсутність цих точних рядків не є доказом того, що CNI не існує. Поєднайте цю перевірку з файлами CNI вузла та виділенням IP-адрес Под’ам.
Завдання 4: Перевірте конфігурацію CNI на вузлі
Розділ «Завдання 4: Перевірте конфігурацію CNI на вузлі»# On a nodels -la /etc/cni/net.d/cat /etc/cni/net.d/*.conflist | head -30Нотатки до розв'язання
Ви маєте побачити конфігурацію для призначеного плагіна, а не купу застарілих файлів від попередніх експериментів. Якщо існує кілька файлів, перевірте порядок та вміст. Невідповідність між запущеним DaemonSet’ом плагіна та обраною конфігурацією вузла — це класична причина помилок мережі пісочниці.
Завдання 5: Перевірте мережу Под’ів
Розділ «Завдання 5: Перевірте мережу Под’ів»# Create two podskubectl run test1 --image=nginx:alpinekubectl run test2 --image=nginx:alpine
# Wait for pods to be readykubectl wait --for=condition=Ready pod/test1 pod/test2 --timeout=60s
# Get their IPskubectl get pods -o wide
# Test connectivityTEST2_IP=$(kubectl get pod test2 -o jsonpath='{.status.podIP}')kubectl exec test1 -- wget -qO- $TEST2_IP:80Нотатки до розв'язання
Успішний вивід від NGINX доводить базовий трафік між Под’ами до цільового IP Под’а. Якщо Под’и ніколи не стають готовими, поверніться до подій та налаштування CNI. Якщо вони перебувають у стані Running, але з’єднання зазнає невдачі, перевірте політики, маршрути, логи плагіна та чи приземлилися Под’и на тому самому вузлі чи на різних вузлах.
Завдання 6: Перевірте драйвери CSI
Розділ «Завдання 6: Перевірте драйвери CSI»kubectl get csidriverskubectl get storageclassesНотатки до розв'язання
Деякі лабораторні кластери можуть не містити динамічного провізіонування CSI, тоді як керовані кластери зазвичай його містять. CSIDriver повідомляє вам, які драйвери зареєстровано, а StorageClass’и повідомляють вам, які провізіонери можуть запитувати команди застосунків. StorageClass без відповідного справного драйвера — це зламаний платформений API.
Критерії успіху: Ви завершили, коли можете підкріпити кожне твердження виводом команди, а не пам’яттю чи здогадкою про ім’я плагіна.
- Можете визначити використовуване середовище виконання контейнерів зі статусу вузла та інструментарію CRI.
- Можете використовувати
crictlдля перевірки контейнерів, образів та реагування середовища виконання. - Можете визначити плагін CNI та порівняти запущені Под’и доповнень із конфігурацією CNI вузла.
- Можете пояснити шлях мережі між Под’ами від створення пісочниці Под’а до підключення за IP.
- Можете визначити встановлені драйвери CSI та StorageClass’и або пояснити, чому їх немає в лабораторному кластері.
- Можете обрати перший діагностичний рівень для симптомів CRI, CNI та CSI без здогадок.
Очищення: Видаліть лише тимчасові Под’и, створені цією вправою, щоб кластер повернувся до попереднього стану робочих навантажень.
kubectl delete pod test1 test2Вправа 1: Ідентифікація інтерфейсів
Розділ «Вправа 1: Ідентифікація інтерфейсів»Зіставте кожен інструмент чи плагін з його інтерфейсом, перш ніж відкривати відповідь. Це виглядає просто, але будує рефлекс, потрібний вам під час іспитового тиску: спершу назвіть контракт, потім оберіть докази.
| Інструмент/Плагін | Інтерфейс (CRI/CNI/CSI) |
|---|---|
| containerd | ___ |
| Calico | ___ |
| AWS EBS driver | ___ |
| CRI-O | ___ |
| Cilium | ___ |
| Rook-Ceph | ___ |
Відповіді
- CRI — інтерфейс середовища виконання контейнерів
- CNI — інтерфейс мережі контейнерів
- CSI — інтерфейс зберігання контейнерів
- CRI — інтерфейс середовища виконання контейнерів
- CNI — інтерфейс мережі контейнерів
- CSI — інтерфейс зберігання контейнерів
Вправа 2: Усунення несправностей CRI — середовище виконання контейнерів не працює
Розділ «Вправа 2: Усунення несправностей CRI — середовище виконання контейнерів не працює»Запускайте це лише на одноразовому практичному вузлі, який ви можете відновити. Суть у тому, щоб спостерігати, що зупинене середовище виконання дає симптоми вузла та Под’а, навіть коли API-сервер продовжує відповідати.
# Setup: Stop containerd (WARNING: breaks cluster temporarily!)# Only do on practice nodes you can restart!sudo systemctl stop containerd
# Observe the damagekubectl get nodes # Node becomes NotReadyNODE_NAME=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')kubectl describe node $NODE_NAME | grep -A5 Conditions
# YOUR TASK: Restore containerd and verify recoveryРозв'язання
sudo systemctl start containerdsudo systemctl status containerd
# Wait for node to recoverkubectl wait --for=condition=Ready node --all --timeout=120s
# Verify containers runningsudo crictl psВправа 3: Усунення несправностей CNI — Под’и застрягли у ContainerCreating
Розділ «Вправа 3: Усунення несправностей CNI — Под’и застрягли у ContainerCreating»Запускайте це лише на одноразовому практичному вузлі. Видалення конфігурації CNI блокує нову мережу пісочниці на цьому вузлі, і саме тому цей режим збою настільки впізнаваний у лабораторіях kubeadm.
# Setup: Temporarily break CNI configsudo mkdir -p /tmp/cni-backupsudo mv /etc/cni/net.d/* /tmp/cni-backup/
# Create a test podkubectl run cni-broken --image=nginx
# Observekubectl get pods # ContainerCreating foreverkubectl describe pod cni-broken | grep -A10 Events
# YOUR TASK: Diagnose and fixРозв'язання
# Check CNI config directoryls /etc/cni/net.d/ # Empty!
# Restore CNI configsudo mv /tmp/cni-backup/* /etc/cni/net.d/
# Delete stuck pod and recreatekubectl delete pod cni-broken --force --grace-period=0kubectl run cni-fixed --image=nginxkubectl get pods # Running!
# Cleanupkubectl delete pod cni-fixedВправа 4: Майстерність crictl
Розділ «Вправа 4: Майстерність crictl»Практикуйте використання crictl, доки воно не почне відчуватися так само звично, як kubectl, для перевірки середовища виконання на рівні вузла. Команди нижче навмисно доступні лише для читання, окрім тих логів, які запущені контейнери вже виробляють.
# 1. List all running containerssudo crictl ps
# 2. List all pods (sandbox containers)sudo crictl pods
# 3. Get container logsCONT_ID=$(sudo crictl ps -q | head -n 1)sudo crictl logs $CONT_ID
# 4. Inspect a containersudo crictl inspect $CONT_ID | head -50
# 5. List imagessudo crictl images
# 6. Get runtime infosudo crictl infoВправа 5: Розслідування драйверів CSI
Розділ «Вправа 5: Розслідування драйверів CSI»Дослідіть ресурси CSI у вашому кластері та пов’яжіть кожен ресурс з етапом життєвого циклу, який він підтримує. Якщо у вашій лабораторії немає драйверів CSI, запишіть це явно; розпізнавання відсутності — це теж корисний доказ.
# List all CSI driverskubectl get csidrivers
# Get details on a driverDRIVER_NAME=$(kubectl get csidrivers -o jsonpath='{.items[0].metadata.name}')kubectl describe csidriver $DRIVER_NAME
# Check CSI nodeskubectl get csinodesNODE_NAME=$(kubectl get csinodes -o jsonpath='{.items[0].metadata.name}')kubectl describe csinode $NODE_NAME
# View StorageClasses using CSIkubectl get sc -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.provisioner}{"\n"}{end}'Вправа 6: Провізіонування CSI — створення PVC за допомогою StorageClass
Розділ «Вправа 6: Провізіонування CSI — створення PVC за допомогою StorageClass»Відпрацюйте повний робочий процес CSI від PVC до змонтованого тому. Ця вправа вимагає кластера з робочим StorageClass за замовчуванням, тож пропустіть її на лабораторіях, які навмисно не містять динамічного сховища.
# Check available StorageClasseskubectl get sc
# Create a PVC using the default StorageClasscat << 'EOF' | kubectl apply -f -apiVersion: v1kind: PersistentVolumeClaimmetadata: name: csi-test-pvcspec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi # storageClassName: standard # Uncomment to use specific classEOF
# Watch the PVC get bound (CSI provisioner creates PV)kubectl wait --for=jsonpath='{.status.phase}'=Bound pvc/csi-test-pvc --timeout=60s
# Check the dynamically provisioned PVkubectl get pv
# Create a pod that uses the PVCcat << 'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: csi-test-podspec: containers: - name: app image: nginx volumeMounts: - name: data mountPath: /data volumes: - name: data persistentVolumeClaim: claimName: csi-test-pvcEOF
# Wait for pod to be readykubectl wait --for=condition=Ready pod/csi-test-pod --timeout=60s
# Verify the volume is mountedkubectl exec csi-test-pod -- df -h /data
# Write test datakubectl exec csi-test-pod -- sh -c "echo 'CSI works!' > /data/test.txt"kubectl exec csi-test-pod -- cat /data/test.txt
# Cleanupkubectl delete pod csi-test-podkubectl delete pvc csi-test-pvcВправа 7: Тест мережевого підключення
Розділ «Вправа 7: Тест мережевого підключення»Перевірте поведінку CNI між вузлами, коли ваш кластер має більше ніж один робочий вузол. На одновузловій лабораторії це досі перевіряє виділення IP-адрес Под’ам та підключення на тому самому вузлі, але не доводить маршрутизацію між вузлами.
# Create pods on different nodesNODE1=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')NODE2=$(kubectl get nodes -o jsonpath='{.items[1].metadata.name}' 2>/dev/null)NODE2=${NODE2:-$NODE1} # single-node clusters fall back to NODE1kubectl run net-test-1 --image=nginx:alpine --overrides='{"spec":{"nodeName":"'"$NODE1"'"}}'kubectl run net-test-2 --image=nginx:alpine --overrides='{"spec":{"nodeName":"'"$NODE2"'"}}'
# Wait for runningkubectl wait --for=condition=Ready pod/net-test-1 pod/net-test-2 --timeout=60s
# Get IPsPOD1_IP=$(kubectl get pod net-test-1 -o jsonpath='{.status.podIP}')POD2_IP=$(kubectl get pod net-test-2 -o jsonpath='{.status.podIP}')
# Test cross-node connectivitykubectl exec net-test-1 -- wget -qO- --timeout=5 $POD2_IP:80kubectl exec net-test-2 -- wget -qO- --timeout=5 $POD1_IP:80
# Cleanupkubectl delete pod net-test-1 net-test-2Вправа 8: Виклик — визначте всі плагіни
Розділ «Вправа 8: Виклик — визначте всі плагіни»Без відкриття документації визначте всі три рівні розширення у вашому кластері та запишіть докази, що підтримують кожну відповідь. Це найближча до екзаменаційної поведінки вправа, бо вона змушує вас швидко класифікувати симптоми та докази.
# 1. Find container runtimekubectl get nodes -o wide | awk '{print $NF}'
# 2. Find CNI pluginls /etc/cni/net.d/kubectl get pods -n kube-system | grep -E "calico|cilium|flannel|weave"
# 3. Find CSI driverskubectl get csidriverskubectl get sc
# Write down what you found - this is exam knowledge!Джерела
Розділ «Джерела»- Kubernetes Container Runtimes
- Kubernetes CRI API
- Kubernetes Network Plugins
- Kubernetes Cluster Networking
- Kubernetes Network Policies
- Kubernetes Storage Classes
- Kubernetes CSI Drivers
- Kubernetes CSIDriver API
- Kubernetes Debug Running Pods
- containerd documentation
- CRI-O project
- CNI specification
- CSI specification
- KubeDojo lab: CKA 1.2 Extension Interfaces
Наступний модуль
Розділ «Наступний модуль»Модуль 1.3: Helm — Далі ви перейдете від інтерфейсів розширення вузла до пакування повторюваних застосунків Kubernetes за допомогою чартів, релізів, значень та робочих процесів оновлення.