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

Модуль 1.2: Інтерфейси розширення — CNI, CSI, CRI

Hands-On Lab Available
K8s Cluster intermediate 35 min
Launch Lab ↗

Opens in Killercoda in a new tab

Складність: [СЕРЕДНЯ] — концептуальний матеріал із практичною діагностикою.

Час на проходження: 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 та менеджера служб середовища виконання.

Terminal window
# What runtime is kubelet using?
kubectl get nodes -o wide
# Look at CONTAINER-RUNTIME column
# On a node, check containerd
systemctl status containerd
crictl info
# List running containers
crictl ps
# List images
crictl images
# Inspect a container
crictl inspect <container-id>

Перш ніж це запускати, який вивід ви очікуєте у стовпці CONTAINER-RUNTIME на кластері Kubernetes 1.35+ у стилі kubeadm? Якщо ваша відповідь містить containerd://, за яким іде версія, ви мислите на правильному рівні. Це поле надходить зі статусу вузла від kubelet і повідомляє вам, яку точку доступу середовища виконання вузол насправді використовує. Це часто швидше та безпечніше, ніж здогадуватися за встановленими пакетами, бо вузол може містити старі бінарні файли, яких уже немає на активному шляху.

Terminal window
# Container runtime not responding
systemctl status containerd
journalctl -u containerd -f
# kubelet can't talk to runtime
journalctl -u kubelet | grep -i "runtime"
# Check CRI socket
ls -la /var/run/containerd/containerd.sock
# Verify kubelet configuration
cat /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, інтегрують адреси Под’ів із мережею хмарного провайдера, що спрощує деякі шляхи трафіку, але прив’язує поведінку до обмежень керування адресами цього провайдера.

ПлагінОсновні особливостіСкладність
CalicoNetworkPolicy, BGP-маршрутизація, висока продуктивністьСередня
CiliumНа основі eBPF, спостережуваність, безпекаВища
FlannelПроста оверлейна мережаНизька
WeaveШифрування, просте налаштуванняНизька
AWS VPC CNIНативна мережа VPCСпецифічно для AWS

Операційний контракт зазвичай видно у трьох місцях на кожному вузлі. Бінарні файли CNI містяться під /opt/cni/bin/, файли конфігурації — під /etc/cni/net.d/, а агенти плагінів часто працюють як Под’и DaemonSet у kube-system чи іншому платформенному просторі імен. Перший збіжний файл конфігурації може мати значення, ось чому застарілі файли від старих встановлень спричиняють несподівану поведінку після міграції. Кластер може мати справні Под’и Calico, але якщо вузол досі обирає стару конфігурацію Flannel, kubelet та середовище виконання можуть викликати хибний ланцюг плагінів.

Terminal window
# List CNI binaries
ls /opt/cni/bin/
# List CNI configurations (first file wins!)
ls /etc/cni/net.d/
# Check the active CNI config
cat /etc/cni/net.d/10-calico.conflist # Example for Calico

Зупиніться й поміркуйте: ви щойно запустили kubeadm init, площина управління запустилася, а Под’и CoreDNS перебувають у стані Pending чи застрягли під час запуску. Чого бракує і чому DNS викриває проблему рано? Відповідь у тому, що kubeadm не встановлює плагін CNI замість вас. CoreDNS — це одне з перших нормальних робочих навантажень, створених кластером, тож воно швидко викриває, чи можуть Под’и бути запланованими, поміщеними в пісочницю, отримати адреси та підключеними до мережі кластера.

Terminal window
# What CNI is running?
kubectl get pods -n kube-system | grep -E "calico|cilium|flannel|weave"
# Check CNI pod logs
kubectl logs -n kube-system -l k8s-app=calico-node --tail=50
# Verify pod IP allocation
kubectl get pods -o wide # Check IP column
# Test pod-to-pod connectivity
kubectl exec pod-a -- ping <pod-b-ip>

Діагностуючи CNI, відокремлюйте симптоми керування від симптомів шляху даних. Якщо Под’и не можуть вийти зі стану ContainerCreating, плагін може не викликатися успішно, бінарний файл може бути відсутнім, файл конфігурації може бути недійсним, або агент вузла може бути несправним. Якщо Под’и працюють (Running), але не можуть дістатися один одного, плагін може призначати адреси, але зазнавати невдачі на маршрутах, інкапсуляції, політиках чи інтеграції з хостовим фаєрволом. Якщо лише трафік між вузлами зазнає невдачі, підозрюйте оверлей, маршрутизацію, BGP, хмарні групи безпеки чи стан програм eBPF, перш ніж звинувачувати контейнери застосунку.

Terminal window
# Pods stuck in ContainerCreating
kubectl describe pod <pod-name>
# Look for: "failed to set up sandbox container network"
# Check CNI configuration exists
ls -la /etc/cni/net.d/
# Check CNI binary exists
ls -la /opt/cni/bin/
# Check CNI agent logs
kubectl logs -n kube-system -l k8s-app=calico-node -c calico-node
# Node network issues
ip addr show # Check interfaces
ip 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.comAWS EBSAWS EKS
pd.csi.storage.gke.ioGCP Persistent DiskGKE
disk.csi.azure.comAzure DiskAKS
csi.vsphere.vmware.comvSphereVMware
rook-ceph.rbd.csi.ceph.comCeph RBDЛокальне (on-premises)
hostpath.csi.k8s.ioLocal pathРозробка

Локальне сховище та віддалене сховище мають різні режими збоїв. Локальний том може бути швидким, бо дані містяться на власному диску вузла, але він прив’язує робоче навантаження до цього вузла та ускладнює відновлення, коли вузол виходить з ладу. Віддалений блоковий том на основі CSI може додати затримку приєднання чи залежність від хмарного API, але він часто може переміщатися з перепланованим Под’ом у межах обмежень драйвера. Розподілені системи сховища, такі як Ceph, додають ще один набір компромісів: більше рухомих частин та операційної складності в обмін на незалежність сховища від єдиного хмарного провайдера чи вузла.

Terminal window
# List CSI drivers in cluster
kubectl get csidrivers
# Check CSI pods
kubectl get pods -n kube-system | grep csi
# View StorageClasses (use CSI drivers)
kubectl get storageclasses
kubectl describe storageclass <name>
# Check PV provisioner
kubectl get pv -o jsonpath='{.items[*].spec.csi.driver}'

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

Terminal window
# PVC stuck in Pending
kubectl describe pvc <pvc-name>
# Look for: Events showing provisioning errors
# Check CSI controller logs
kubectl logs -n kube-system -l app=ebs-csi-controller -c ebs-plugin
# Check CSI node logs
kubectl logs -n kube-system -l app=ebs-csi-node -c ebs-plugin
# Verify CSI driver registered
kubectl get csinodes
kubectl 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 до компонента, який мусить її виконати.

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

Terminal window
# ===== CRI Issues =====
# Symptom: Pods won't start, "container runtime not running"
systemctl status containerd
journalctl -u containerd
crictl 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 csidrivers
kubectl 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 із повідомленнями середовища виконанняCRIjournalctl -u kubelet, systemctl status containerd, crictl infoВідновити службу середовища виконання чи виправити точку доступу середовища виконання kubelet
Под застряг у ContainerCreating із помилкою мережі пісочниціCNIПодії Под’а, /etc/cni/net.d/, /opt/cni/bin/, логи DaemonSet’а CNIПолагодити конфігурацію CNI, бінарні файли чи агент вузла
Под у стані Running, але трафік між вузлами зазнає невдачіCNIIP-адреси Под’ів, маршрути, логи плагіна, об’єкти політик, фаєрволи вузлівДіагностувати маршрутизацію, оверлей, політику чи хмарні правила безпеки
PVC у стані Pending із подією провізіонуванняCSIПодії PVC, провізіонер StorageClass, логи контролера CSIВиправити StorageClass, встановлення драйвера чи зовнішні дозволи
Под не може змонтувати прив’язаний PVCCSIПодії Под’а, 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 після ініціалізації kubeadmkubeadm створює площину управління, але навмисно залишає вибір мережі Под’ів операторуВстановіть один підтримуваний плагін 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: Визначте ваше середовище виконання контейнерів»
Terminal window
kubectl get nodes -o wide
# Note the CONTAINER-RUNTIME column
Нотатки до розв'язання

Шукайте значення на кшталт containerd://... чи cri-o://... у стовпці CONTAINER-RUNTIME. Це значення повідомляється через статус вузла і є кращою першою відповіддю, ніж здогадка за встановленими на хості пакетами. Якщо вузол має стан NotReady, поєднайте це з логами kubelet та статусом служби середовища виконання, перш ніж переходити до CNI чи CSI.

Завдання 2: Дослідіть CRI з вузла

Розділ «Завдання 2: Дослідіть CRI з вузла»
Terminal window
# On a node (SSH or kubectl debug node)
crictl info
crictl ps
crictl images | head -10
Нотатки до розв'язання

crictl info підтверджує, що точка доступу CRI відповідає. crictl ps показує контейнери, відомі середовищу виконання, а crictl images показує образи, кешовані на вузлі. Якщо ці команди не можуть під’єднатися, перевірте шлях до сокета середовища виконання та службу середовища виконання, перш ніж припускати, що об’єкти Kubernetes хибні.

Завдання 3: Визначте ваш плагін CNI

Розділ «Завдання 3: Визначте ваш плагін CNI»
Terminal window
kubectl get pods -n kube-system | grep -E "calico|cilium|flannel|weave"
Нотатки до розв'язання

Вивід зазвичай показує агента у стилі DaemonSet для активного мережевого плагіна. Деякі керовані кластери використовують специфічні для провайдера імена, тож відсутність цих точних рядків не є доказом того, що CNI не існує. Поєднайте цю перевірку з файлами CNI вузла та виділенням IP-адрес Под’ам.

Завдання 4: Перевірте конфігурацію CNI на вузлі

Розділ «Завдання 4: Перевірте конфігурацію CNI на вузлі»
Terminal window
# On a node
ls -la /etc/cni/net.d/
cat /etc/cni/net.d/*.conflist | head -30
Нотатки до розв'язання

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

Завдання 5: Перевірте мережу Под’ів

Розділ «Завдання 5: Перевірте мережу Под’ів»
Terminal window
# Create two pods
kubectl run test1 --image=nginx:alpine
kubectl run test2 --image=nginx:alpine
# Wait for pods to be ready
kubectl wait --for=condition=Ready pod/test1 pod/test2 --timeout=60s
# Get their IPs
kubectl get pods -o wide
# Test connectivity
TEST2_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»
Terminal window
kubectl get csidrivers
kubectl get storageclasses
Нотатки до розв'язання

Деякі лабораторні кластери можуть не містити динамічного провізіонування CSI, тоді як керовані кластери зазвичай його містять. CSIDriver повідомляє вам, які драйвери зареєстровано, а StorageClass’и повідомляють вам, які провізіонери можуть запитувати команди застосунків. StorageClass без відповідного справного драйвера — це зламаний платформений API.

Критерії успіху: Ви завершили, коли можете підкріпити кожне твердження виводом команди, а не пам’яттю чи здогадкою про ім’я плагіна.

  • Можете визначити використовуване середовище виконання контейнерів зі статусу вузла та інструментарію CRI.
  • Можете використовувати crictl для перевірки контейнерів, образів та реагування середовища виконання.
  • Можете визначити плагін CNI та порівняти запущені Под’и доповнень із конфігурацією CNI вузла.
  • Можете пояснити шлях мережі між Под’ами від створення пісочниці Под’а до підключення за IP.
  • Можете визначити встановлені драйвери CSI та StorageClass’и або пояснити, чому їх немає в лабораторному кластері.
  • Можете обрати перший діагностичний рівень для симптомів CRI, CNI та CSI без здогадок.

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

Terminal window
kubectl delete pod test1 test2

Вправа 1: Ідентифікація інтерфейсів

Розділ «Вправа 1: Ідентифікація інтерфейсів»

Зіставте кожен інструмент чи плагін з його інтерфейсом, перш ніж відкривати відповідь. Це виглядає просто, але будує рефлекс, потрібний вам під час іспитового тиску: спершу назвіть контракт, потім оберіть докази.

Інструмент/ПлагінІнтерфейс (CRI/CNI/CSI)
containerd___
Calico___
AWS EBS driver___
CRI-O___
Cilium___
Rook-Ceph___
Відповіді
  1. CRI — інтерфейс середовища виконання контейнерів
  2. CNI — інтерфейс мережі контейнерів
  3. CSI — інтерфейс зберігання контейнерів
  4. CRI — інтерфейс середовища виконання контейнерів
  5. CNI — інтерфейс мережі контейнерів
  6. CSI — інтерфейс зберігання контейнерів

Вправа 2: Усунення несправностей CRI — середовище виконання контейнерів не працює

Розділ «Вправа 2: Усунення несправностей CRI — середовище виконання контейнерів не працює»

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

Terminal window
# Setup: Stop containerd (WARNING: breaks cluster temporarily!)
# Only do on practice nodes you can restart!
sudo systemctl stop containerd
# Observe the damage
kubectl get nodes # Node becomes NotReady
NODE_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
Розв'язання
Terminal window
sudo systemctl start containerd
sudo systemctl status containerd
# Wait for node to recover
kubectl wait --for=condition=Ready node --all --timeout=120s
# Verify containers running
sudo crictl ps

Вправа 3: Усунення несправностей CNI — Под’и застрягли у ContainerCreating

Розділ «Вправа 3: Усунення несправностей CNI — Под’и застрягли у ContainerCreating»

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

Terminal window
# Setup: Temporarily break CNI config
sudo mkdir -p /tmp/cni-backup
sudo mv /etc/cni/net.d/* /tmp/cni-backup/
# Create a test pod
kubectl run cni-broken --image=nginx
# Observe
kubectl get pods # ContainerCreating forever
kubectl describe pod cni-broken | grep -A10 Events
# YOUR TASK: Diagnose and fix
Розв'язання
Terminal window
# Check CNI config directory
ls /etc/cni/net.d/ # Empty!
# Restore CNI config
sudo mv /tmp/cni-backup/* /etc/cni/net.d/
# Delete stuck pod and recreate
kubectl delete pod cni-broken --force --grace-period=0
kubectl run cni-fixed --image=nginx
kubectl get pods # Running!
# Cleanup
kubectl delete pod cni-fixed

Вправа 4: Майстерність crictl

Розділ «Вправа 4: Майстерність crictl»

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

Terminal window
# 1. List all running containers
sudo crictl ps
# 2. List all pods (sandbox containers)
sudo crictl pods
# 3. Get container logs
CONT_ID=$(sudo crictl ps -q | head -n 1)
sudo crictl logs $CONT_ID
# 4. Inspect a container
sudo crictl inspect $CONT_ID | head -50
# 5. List images
sudo crictl images
# 6. Get runtime info
sudo crictl info

Вправа 5: Розслідування драйверів CSI

Розділ «Вправа 5: Розслідування драйверів CSI»

Дослідіть ресурси CSI у вашому кластері та пов’яжіть кожен ресурс з етапом життєвого циклу, який він підтримує. Якщо у вашій лабораторії немає драйверів CSI, запишіть це явно; розпізнавання відсутності — це теж корисний доказ.

Terminal window
# List all CSI drivers
kubectl get csidrivers
# Get details on a driver
DRIVER_NAME=$(kubectl get csidrivers -o jsonpath='{.items[0].metadata.name}')
kubectl describe csidriver $DRIVER_NAME
# Check CSI nodes
kubectl get csinodes
NODE_NAME=$(kubectl get csinodes -o jsonpath='{.items[0].metadata.name}')
kubectl describe csinode $NODE_NAME
# View StorageClasses using CSI
kubectl get sc -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.provisioner}{"\n"}{end}'

Вправа 6: Провізіонування CSI — створення PVC за допомогою StorageClass

Розділ «Вправа 6: Провізіонування CSI — створення PVC за допомогою StorageClass»

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

Terminal window
# Check available StorageClasses
kubectl get sc
# Create a PVC using the default StorageClass
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-test-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
# storageClassName: standard # Uncomment to use specific class
EOF
# 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 PV
kubectl get pv
# Create a pod that uses the PVC
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: csi-test-pod
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: csi-test-pvc
EOF
# Wait for pod to be ready
kubectl wait --for=condition=Ready pod/csi-test-pod --timeout=60s
# Verify the volume is mounted
kubectl exec csi-test-pod -- df -h /data
# Write test data
kubectl exec csi-test-pod -- sh -c "echo 'CSI works!' > /data/test.txt"
kubectl exec csi-test-pod -- cat /data/test.txt
# Cleanup
kubectl delete pod csi-test-pod
kubectl delete pvc csi-test-pvc

Вправа 7: Тест мережевого підключення

Розділ «Вправа 7: Тест мережевого підключення»

Перевірте поведінку CNI між вузлами, коли ваш кластер має більше ніж один робочий вузол. На одновузловій лабораторії це досі перевіряє виділення IP-адрес Под’ам та підключення на тому самому вузлі, але не доводить маршрутизацію між вузлами.

Terminal window
# Create pods on different nodes
NODE1=$(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 NODE1
kubectl 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 running
kubectl wait --for=condition=Ready pod/net-test-1 pod/net-test-2 --timeout=60s
# Get IPs
POD1_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 connectivity
kubectl exec net-test-1 -- wget -qO- --timeout=5 $POD2_IP:80
kubectl exec net-test-2 -- wget -qO- --timeout=5 $POD1_IP:80
# Cleanup
kubectl delete pod net-test-1 net-test-2

Вправа 8: Виклик — визначте всі плагіни

Розділ «Вправа 8: Виклик — визначте всі плагіни»

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

Terminal window
# 1. Find container runtime
kubectl get nodes -o wide | awk '{print $NF}'
# 2. Find CNI plugin
ls /etc/cni/net.d/
kubectl get pods -n kube-system | grep -E "calico|cilium|flannel|weave"
# 3. Find CSI drivers
kubectl get csidrivers
kubectl get sc
# Write down what you found - this is exam knowledge!

Модуль 1.3: Helm — Далі ви перейдете від інтерфейсів розширення вузла до пакування повторюваних застосунків Kubernetes за допомогою чартів, релізів, значень та робочих процесів оновлення.