Модуль 4.5: Усунення проблем зі сховищем
Складність:
[СЕРЕДНЯ]— діагностика та виправлення проблем зі сховищем.Час на проходження: 35-45 хвилин.
Передумови: Модуль 4.1, Модуль 4.2, Модуль 4.3 та Модуль 4.4.
Що ви зможете зробити
Розділ «Що ви зможете зробити»Після цього модуля ви зможете:
- Діагностувати збої сховища системно — від PVC у стані Pending до помилок монтування, проблем з місткістю та симптомів «у доступі відмовлено» (permission denied).
- Простежити ланцюжок надання сховища від Pod’а до PVC, StorageClass, провізіонера, PV, приєднання до ноди й остаточного монтування.
- Виправити типові проблеми зі сховищем, обираючи найменш руйнівне виправлення для прив’язки, режиму доступу, квоти та проблем з власністю.
- Спроєктувати контрольний список з усунення проблем сховища, який працює як у сценаріях іспиту CKA, так і у реагуванні на виробничі інциденти.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Гіпотетичний сценарій: розгортання Deployment виглядає буденним, аж поки половина подів не залишається у стані ContainerCreating, а застосунок не починає віддавати застарілі дані з реплік, що вціліли. Образ контейнера справний, проби звичайні, а планувальник розмістив поди на нодах — проте робоче навантаження не може відкрити свій каталог даних. У цей момент перезапуск подів — це переважно шум, бо збій лежить не всередині процесу застосунку; він десь у контракті між заявкою, томом, драйвером сховища, нодою та поданням файлової системи всередині контейнера.
Усунення проблем сховища важливе тому, що Kubernetes навмисно розподіляє відповідальність між кількома контролерами. Планувальник міркує про ноди, контролер персистентних томів міркує про заявки, зовнішній CSI-провізіонер спілкується з бекендом сховища, контролер приєднання-від’єднання координує приєднання до ноди, а kubelet виконує монтування, яке контейнер зрештою бачить. Цей розподіл потужний, але він означає, що видимий симптом на кшталт Pending, FailedMount чи Permission denied сам по собі рідко називає всю першопричину.
Іспит CKA винагороджує інженерів, які вміють швидко звузити шлях збою, не пошкоджуючи при цьому стан системи. На виробництві та сама звичка запобігає ризикованим виправленням — як-от видаленню PVC до прочитання його політики повернення (reclaim policy) чи примусовому видаленню старого пода до того, як ви довели, що збійна нода більше не пише в том із режимом ReadWriteOnce. Цей модуль навчає повторюваного шляху, який можна застосувати знову і знову: почати з події пода, простежити граф об’єктів сховища, перевіряти контролер чи драйвер лише тоді, коли докази вказують саме туди, і обрати виправлення, яке передусім зберігає дані.
Аналогія з детективом із початкової версії модуля все ще пасує, але зробімо її радше операційною, ніж театральною. Подія пода — це перший свідок, PVC та PV — це паперовий слід доказів, StorageClass пояснює діючу політику, а журнали CSI — це розмова зі спеціалістом, до якої ви вдаєтеся лише після того, як ранні докази скажуть вам, що задіяний саме драйвер. Хороший фахівець з налагодження сховища не запам’ятовує напам’ять кожен можливий рядок помилки; натомість він знає, який рівень володіє кожним рішенням і яка саме команда доведе, чи виконав цей рівень свою частину контракту.
Почніть з моделі збою сховища
Розділ «Почніть з моделі збою сховища»Сховище Kubernetes найлегше налагоджувати, коли ви ставитеся до нього як до конвеєра, а не як до єдиного об’єкта. Pod посилається на PVC за іменем у власному просторі імен, PVC просить місткість і семантику доступу, StorageClass обирає провізіонера й політику прив’язки, PV фіксує фактичний том, а kubelet монтує цей том у контейнер. Збій на будь-якому етапі може проявитися як под, який не запускається, тож перше завдання — визначити етап, на якому передача зупинилася.
Використовуйте цей шлях як мапу в голові, перш ніж виконувати команди. Він зберігає діаграму усунення проблем із початкової версії модуля, замінюючи скорочення на повні імена команд, які можна скопіювати в оболонку чи скрипт. Зверніть увагу, що потік не починається з драйвера CSI; більшість інцидентів зі сховищем видно у статусі об’єктів та подіях ще до того, як знадобляться журнали контролерів.
┌─────────────────────────────────────────────────────────────────────┐│ Storage Troubleshooting Path ││ ││ Pod Issue ││ │ ││ ▼ ││ 1. kubectl describe pod <name> ││ └─► Check Events section ││ └─► Check volume mount errors ││ │ ││ ▼ ││ 2. kubectl get pvc <name> ││ └─► Is STATUS "Bound"? ││ └─► If "Pending", check Events ││ │ ││ ▼ ││ 3. kubectl get pv ││ └─► Does matching PV exist? ││ └─► Is STATUS "Available" or "Bound"? ││ │ ││ ▼ ││ 4. kubectl get sc <storageclass> ││ └─► Does StorageClass exist? ││ └─► Is provisioner correct? ││ │ ││ ▼ ││ 5. Check CSI driver ││ └─► Is driver installed? ││ └─► Check driver pod logs ││ │└─────────────────────────────────────────────────────────────────────┘Важлива звичка тут — читати від споживача до постачальника, а не навпаки. Якщо под посилається на неправильне ім’я заявки, то PV та StorageClass можуть бути цілком ідеальними й водночас узагалі не мати значення для цього збою. Якщо PVC не прив’язано, бо StorageClass не існує, то журнали монтування на ноді лише відволікатимуть вас від справжньої причини. Якщо ж PVC прив’язано, а подія пода каже FailedMount, то контракт об’єктів, імовірно, уже завершився, і вам слід перенести увагу на приєднання, монтування, права доступу чи поведінку локального шляху на ноді.
Тримайте під рукою один набір команд, поки працюєте. Окремі команди нижче звичайні, але саме їхній порядок відрізняє чисту діагностику від довгого пошуку серед сторонніх журналів. В умовах іспиту цей порядок також береже ваш час, бо ви можете зупинитися щойно один рівень доведе місце розриву.
# Pod-level debuggingkubectl describe pod <pod-name>kubectl get pod <pod-name> -o yamlkubectl logs <pod-name>Под — правильна точка входу, бо він поєднує подання планування, тому й контейнера. kubectl describe pod особливо корисна, бо розділ Events часто містить точне повідомлення, видане операцією приєднання чи монтування. kubectl logs допомагає лише після того, як контейнер запустився; коли под усе ще в стані ContainerCreating, події зазвичай важливіші за журнали застосунку.
# PVC debuggingkubectl get pvckubectl describe pvc <pvc-name>kubectl get pvc <pvc-name> -o yamlPVC каже вам, чи задовольнив Kubernetes заявку. Заявка у стані Bound означає, що площина управління знайшла або створила PV, тоді як Pending означає, що прив’язка все ще очікує або зазнала невдачі. Подання YAML корисне, коли вам потрібні точні поля — як-от storageClassName, запитувана місткість, режими доступу, анотації обраної ноди чи повідомлення про умови (conditions).
# PV debuggingkubectl get pvkubectl describe pv <pv-name>kubectl get pv <pv-name> -o yamlPV має область видимості кластера, тож він може пережити простір імен чи робоче навантаження, які першими його використали. Читайте PV, коли йдеться про статичне прив’язування, коли заявка, схоже, націлена на наявний том, або коли політика повернення впливає на безпечність видалення. PV у стані Released чи Failed — це не те саме, що Available PV, навіть якщо місткість та режими доступу на перший погляд виглядають привабливими.
# StorageClass debuggingkubectl get sckubectl describe sc <sc-name>kubectl get sc <sc-name> -o yamlStorageClass фіксує політику, а не конкретний диск. Він відповідає на запитання на кшталт: який провізіонер відповідальний, чи дозволено розширення, який режим прив’язки використовується та які параметри бекенду передаються драйверу. Багато PVC у стані Pending пояснюються неправильно написаним ім’ям класу, несподіваним класом за замовчуванням або поведінкою WaitForFirstConsumer, яка є нормальною, а не зламаною.
# Events, often the highest-signal viewkubectl get events --sort-by='.lastTimestamp'kubectl get events --field-selector involvedObject.name=<pvc-name>kubectl get events --field-selector involvedObject.name=<pod-name>Події — це не повний журнал аудиту, але вони чудові орієнтири під час активного усунення проблем. Сортуйте за часовою позначкою, коли вам потрібні найновіші збої, і використовуйте селектори полів, коли простір імен зашумлений. Якщо ви бачите, що та сама подія повторюється, читайте і причину (reason), і повідомлення (message), бо причина часто загальна, а повідомлення містить деталь, специфічну для бекенду чи об’єкта.
# CSI debuggingkubectl get pods -n kube-system | grep csikubectl logs -n kube-system <csi-pod> -c <container>kubectl get csidriverskubectl get csinodeЖурнали CSI потужні, але вони не перша зупинка для кожної проблеми. Звертайтеся туди, коли події згадують зовнішнє провізіонування, імена драйверів, збої приєднання чи помилки API бекенду. У керованих кластерах контролер CSI та плагін ноди можуть бути встановлені поза простором імен вашого застосунку, тож простір імен та ім’я контейнера мають значення, коли ви отримуєте журнали.
Зупиніться та передбачте: якщо под застряг у стані ContainerCreating, але PVC, на який він посилається, уже у стані Bound, які два етапи конвеєра, ймовірно, завершилися, і який етап вам слід перевірити наступним?
Сценарій вправи: учень повідомляє, що kubectl get pvc показує Pending, і одразу запитує, чи не вийшов з ладу драйвер CSI. Перш ніж перевіряти журнали драйвера, спершу запитайте, чи вже якийсь под споживає цю заявку і чи використовує StorageClass відкладену прив’язку. Це одне запитання може відокремити справжній збій провізіонування від навмисного дизайну WaitForFirstConsumer.
Діагностуйте проблеми прив’язки PVC
Розділ «Діагностуйте проблеми прив’язки PVC»PVC, що застряг у стані Pending, означає, що заявку ще не зіставлено з жодним PV. Це може бути жорсткий збій — наприклад, відсутній StorageClass — або ж навмисне очікування, як-от клас, що використовує WaitForFirstConsumer. Ваше завдання на цьому етапі — вирішити, чи контролер заблоковано, чи він просто чекає на контекст планування, чи він не може знайти сумісний том серед наявних.
kubectl get pvcNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASSmy-pvc Pending fast-ssdНе сприймайте Pending як першопричину. Це статус, який каже, що прив’язки ще не сталося, а причина живе в подіях, політиці StorageClass чи в інвентарі статичних PV. Прочитайте деталі PVC, перш ніж щось змінювати, бо багато полів на заявках фактично є частиною контракту прив’язки і можуть вимагати перестворення, а не латання вже наявної заявки.
kubectl describe pvc my-pvcКоли використовується статичне провізіонування, найпоширеніший збій полягає в тому, що жоден доступний PV не задовольняє заявку. Зіставлення суворіше за «десь є том із достатнім обсягом місця». PV має задовольняти режими доступу, місткість, клас сховища, вимоги селектора та інші обмеження прив’язки, перш ніж контролер зможе його заявити.
Events: Type Reason Message ---- ------ ------- Normal FailedBinding no persistent volumes available for this claimЯкщо ви бачите це повідомлення, порівняйте запит PVC із доступними PV, а не створюйте випадковий новий об’єкт. Місткість має бути принаймні такою ж великою, як заявка, режими доступу мають покривати те, що запитує заявка, а імена класів сховища мають збігатися. PV із політикою повернення Retain також може нести старі посилання на заявки чи дані, тож не використовуйте його повторно наосліп, не перевіривши, чи це справді безпечно.
kubectl get pvc my-pvc -o yaml | grep -A8 spec:kubectl get pvkubectl describe pv <pv-name>Відсутній StorageClass діагностувати швидше, бо подія зазвичай називає клас. Це часто стається після копіювання YAML між кластерами, де імена класів відрізняються, або після покладання на клас за замовчуванням в одному кластері та використання явного класу в іншому. У навчальних кластерах CKA імена класів навмисно прості, але реальні кластери часто використовують імена, що кодують тип диска, політику зон, реплікацію, шифрування чи рівень продуктивності.
Events: Type Reason Message ---- ------ ------- Warning ProvisioningFailed storageclass.storage.k8s.io "fast-ssd" not foundШвидке виправлення — вивести список доступних класів, видалити заявку у стані Pending та перестворити її з дійсним storageClassName. Після створення зміни полів PVC навмисно вузькі: запити на зміну розміру можна змінювати, коли дозволено розширення, але зміна класу сховища вимагає нової заявки. Не змінюйте та не редагуйте побіжно вже прив’язану заявку; для непов’язаної навчальної заявки видалення та перестворення з правильним класом зазвичай є найчистішим ходом на іспиті.
kubectl get sckubectl delete pvc my-pvccat <<'EOF' | kubectl apply -f -apiVersion: v1kind: PersistentVolumeClaimmetadata: name: my-pvcspec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: standardEOFЗбої динамічного провізіонування інакші, бо StorageClass існує, але зовнішній провізіонер не може створити том. Подія PVC може казати, що вона очікує на зовнішнього провізіонера, або може містити специфічну для бекенду помилку, повернену драйвером. Це момент, коли журнали контролера CSI стають доречними, бо саме сайдкар-провізіонер володіє запитом на створення.
Events: Type Reason Message ---- ------ ------- Warning ProvisioningFailed failed to provision volume: no csi driverkubectl get csidriverskubectl get pods -n kube-system | grep csiВідкладена прив’язка — це виняток, який збиває з пантелику багатьох учнів. PVC може залишатися Pending за задумом, коли StorageClass використовує volumeBindingMode: WaitForFirstConsumer, бо провізіонеру потрібен вибір ноди планувальником, перш ніж створювати том, прив’язаний до зони. Якби кластер створив том негайно, под пізніше міг би бути запланований на ноду в іншій зоні й не зміг би приєднатися.
kubectl get sc fast-ssd -o jsonpath='{.volumeBindingMode}'WaitForFirstConsumerPVC із відкладеною прив’язкою без події помилки не зламано лише тому, що він у стані Pending. Створіть чи перевірте под, який його споживає, а потім спостерігайте за плануванням та прив’язкою разом. Якщо под теж не може запланувати, першопричиною можуть бути селектори нод, обмеження топології чи тиск ресурсів, а не сам бекенд сховища.
kubectl get pvc my-pvcSTATUS: PendingНевідповідність режимів доступу — ще один класичний збій статичного провізіонування. PV, що пропонує ReadWriteOnce, не може задовольнити PVC, який просить ReadWriteMany, бо заявка просить семантику спільного доступу, якої том не надає. Kubernetes не знижує ваш запит за вас — і не повинен, бо це непомітно змінило б модель безпеки застосунку.
kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUSpv-1 100Gi RWO Retain Availablekubectl get pvcNAME STATUS ACCESS MODES STORAGECLASSmy-pvc Pending RWX manualВиправлення — скоригувати архітектуру, а не лише YAML. Якщо робоче навантаження потребує диска з єдиним записувачем, змініть PVC на ReadWriteOnce і запускайте робоче навантаження відповідно. Якщо кільком нодам справді потрібен спільний запис, оберіть бекенд, який підтримує ReadWriteMany, як-от належно налаштовану мережеву файлову систему чи хмарний файловий сервіс, і прийміть інші характеристики продуктивності та узгодженості.
Невідповідності StorageClass виглядають схоже, бо обидва об’єкти можуть здаватися дійсними окремо. PV із storageClassName: manual не задовольнить заявку, що просить fast, навіть коли місткість та режим доступу збігаються. Клас є частиною ідентичності прив’язки, тож порівнюйте його явно, коли відповідний PV здається очевидним, але контролер відмовляється прив’язувати.
kubectl get pv pv-1 -o jsonpath='{.spec.storageClassName}'manualkubectl get pvc my-pvc -o jsonpath='{.spec.storageClassName}'fastПерш ніж це запускати: який вивід ви очікуєте, якщо заявка не має явного storageClassName, а кластер має StorageClass за замовчуванням? Продумайте, чи буде PVC просити клас за замовчуванням, просити жодного класу, чи чекати на ручний PV, а потім перевірте фактичне поле в YAML, не покладаючись на коротке табличне подання.
kubectl get pvc my-pvc -o yaml | grep -E 'storageClassName:|volumeName:|accessModes:|storage:'Діагностуйте помилки монтування та приєднання тому
Розділ «Діагностуйте помилки монтування та приєднання тому»Щойно PVC прив’язано, місце збою зміщується з провізіонування на приєднання до ноди й монтування файлової системи. Под, що застряг у стані ContainerCreating, часто означає, що планувальник уже обрав ноду, але kubelet не може зробити том доступним усередині контейнера. Подія пода зазвичай скаже вам, чи заявка відсутня, чи том не може приєднатися, чи минув час очікування монтування, чи провалилася перевірка шляху, чи, зрештою, права файлової системи не збігаються з користувачем контейнера.
kubectl get podsNAME READY STATUS RESTARTS AGEmy-pod 0/1 Pending 0 5mПерша команда налагодження — це все ще опис пода, а не журнал ноди. Потік подій з’єднує под з операцією над томом, яку спробував Kubernetes, і він зазвичай містить ім’я заявки, ім’я тому, ноду чи помилку драйвера. Якщо подія називає відсутній PVC, специфікація пода вказує на об’єкт, якого не існує в цьому просторі імен; сучасні кластери часто повідомляють про це як про подію FailedScheduling з боку планувальника, перш ніж под взагалі дійде до монтування на ноді.
kubectl describe pod my-podEvents: Warning FailedScheduling 0/3 nodes are available: persistentvolumeclaim "my-pvc" not foundПосилання на PVC є локальними для простору імен. Заявка з іменем my-pvc у default не задовольняє под у payments, а помилки в імені заявки достатньо, щоб затримати под перед плануванням. Саме тому ви завжди маєте включати простір імен у свої перевірки, коли под не у просторі імен default.
kubectl get pvc my-pvc -n <namespace>kubectl get pod my-pod -n <namespace> -o yaml | grep -A6 persistentVolumeClaimПомилки множинного приєднання (multi-attach) небезпечніші, бо вони часто стосуються реального тому та реальних даних. Том із режимом ReadWriteOnce може бути змонтований для читання-запису лише однією нодою за раз, тож под-заміна на іншій ноді може чекати, поки стара нода все ще володіє приєднанням. Це часто з’являється під час збоїв нод, повільного завершення чи ручного переміщення подів.
Events: Warning FailedAttachVolume Multi-Attach error for volume "pvc-abc": Volume is already attached to node "node-1"Швидке виправлення з початкової версії модуля полягало в примусовому видаленні старого пода, але ця дія потребує контексту. Спершу доведіть, що старий под справді застряг, що стара нода несправна, а застосунок може витримати раптове завершення. Примусове видалення прибирає об’єкт API негайно; воно не гарантує, що процес зупинився чисто чи що файлову систему було чисто розмонтовано на недосяжній ноді.
kubectl get pod <old-pod> -o widekubectl get node node-1kubectl describe node node-1 | grep -A8 ConditionsЯкщо стара нода недосяжна, а інцидент потребує відновлення, ви можете примусово видалити старий под та перевірити об’єкти VolumeAttachment. Безпечніша послідовність — зібрати докази, вжити найменш руйнівної дії, а потім запустити перевірки цілісності на рівні застосунку після того, як робоче навантаження повернеться. Для баз даних, брокерів повідомлень та систем з інтенсивним записом успіх приєднання сховища — це не те саме, що узгодженість даних.
kubectl delete pod <old-pod> --force --grace-period=0kubectl get volumeattachmentПомилки прав доступу — це інша категорія, бо том може приєднатися та змонтуватися правильно, а процес усе одно не зможе писати. Це зазвичай з’являється після переходу від контейнера з root на контейнер без root, зміни UID образу чи відновлення даних, створених з іншою власністю. Под може бути Running, але журнали застосунку показують збої запису.
Events: Warning FailedMount MountVolume.SetUp failed: mount failed: exit status 32, permission deniedВиправлення засобами Kubernetes — зробити так, щоб контекст безпеки пода збігався з моделлю власності файлової системи. fsGroup просить kubelet зробити змонтований том доступним для групи, тоді як runAsUser змушує процес контейнера працювати від імені потрібного користувача. Це не безкоштовно на дуже великих томах, бо рекурсивне опрацювання власності може сповільнити перше монтування, але це зазвичай краще за повернення застосунку до root.
# Add securityContext to podspec: securityContext: fsGroup: 1000 containers: - name: app securityContext: runAsUser: 1000 runAsNonRoot: trueВам слід перевірити і конфігурацію Kubernetes, і подання файлової системи зсередини контейнера. Якщо под працює, але застосунок не може писати, kubectl exec може показати числовий ідентифікатор користувача, групу та права монтування напряму. Ці факти кажуть вам, чи було застосовано контекст безпеки і чи належить шлях у спосіб, який процес може використати.
kubectl exec my-pod -- idkubectl exec my-pod -- ls -ld /dataПомилки hostPath простіші, але їх легко не помітити, бо вони залежать від локального стану ноди. Том hostPath із типом Directory вимагає, щоб шлях існував на обраній ноді до запуску пода. Якщо шлях відсутній, kubelet правильно відхиляє монтування, бо специфікація обіцяла наявний каталог.
Events: Warning FailedMount hostPath type check failed: path /data/myapp does not existДля лабораторій та контрольованих локальних сценаріїв на ноді DirectoryOrCreate дозволяє kubelet створити шлях, коли його немає. Це корисно для навчальних сценаріїв, але це не загальна заміна довговічному сховищу, бо hostPath прив’язує дані до однієї ноди й обходить багато гарантій ізоляції. На виробництві використовуйте hostPath ощадливо й зазвичай лише для агентів нод чи системних інтеграцій.
volumes:- name: data hostPath: path: /data/myapp type: DirectoryOrCreateТайм-аути монтування зазвичай вказують на проблему драйвера, бекенду чи ноди, а не на помилку в YAML. Заявка може бути прив’язана, але нода не може приєднати чи змонтувати базове сховище до завершення тайм-ауту. У цей момент вам потрібно зіставити події пода з журналами контролера CSI, журналами плагіна ноди CSI, станом ноди та будь-якими обмеженнями з боку провайдера.
Events: Warning FailedMount Unable to attach or mount volumes: timeout expired waiting for volumes to attachkubectl get pods -n kube-system | grep csikubectl logs -n kube-system <csi-controller-pod> -c csi-provisionerkubectl describe node <node-name> | grep -A8 ConditionsЗупиніться й подумайте: под застряг у стані ContainerCreating, а подія каже Multi-Attach error. Ви знаєте, що том має режим ReadWriteOnce. Перш ніж примусово видаляти старий под, які докази переконали б вас, що старий записувач зник, і яку перевірку на рівні застосунку слід запустити після відновлення?
Діагностуйте проблеми з місткістю, розширенням та квотою
Розділ «Діагностуйте проблеми з місткістю, розширенням та квотою»Збої місткості проявляються у двох зовсім різних місцях. Збої місткості під час провізіонування стаються ще до того, як PV узагалі існує, коли бекенд чи квота не можуть задовольнити запитуваний розмір. Збої переповнення файлової системи, навпаки, стаються вже після того, як робоче навантаження певний час працює, коли на змонтованому томі більше немає достатньо вільного місця для застосунку. Ці дві проблеми потребують різних команд для діагностики, бо одна з них — це проблема прив’язки на рівні площини управління, а інша — проблема файлової системи всередині самого пода.
kubectl get pvc my-pvcNAME STATUS VOLUME CAPACITY ACCESS MODESmy-pvc Bound pvc-1a2b3c4d-1111-2222-3333-444455556666 10Gi RWOМісткість PVC — це запитаний чи наданий розмір, а не поточне використання файлової системи. Щоб побачити, чи заповнив застосунок том, перевірте монтування зсередини пода. Це розрізнення важливе, бо Kubernetes може повідомляти про справну, прив’язану заявку, поки процес контейнера зазнає невдачі під час запису зі звичайними помилками No space left on device.
kubectl exec my-pod -- df -h /dataFilesystem Size Used Avail Use% Mounted on/dev/xvdf 9.8G 9.6G 120M 99% /dataЯкщо StorageClass підтримує розширення, збільшення запиту PVC часто є найчистішим виправленням. Розширення — це вибір політики на StorageClass, а точна поведінка зміни розміру файлової системи залежить від драйвера та режиму тому. Завжди підтверджуйте allowVolumeExpansion перед латанням, а потім спостерігайте за умовами PVC та поведінкою пода, поки файлова система не відобразить новий розмір.
kubectl get sc <storageclass> -o jsonpath='{.allowVolumeExpansion}'truekubectl patch pvc my-pvc -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'kubectl describe pvc my-pvc | grep -A8 ConditionsОчищення даних також є дійсним виправленням, коли дані одноразові, але ставтеся до rm -rf як до рішення на рівні застосунку, а не до загальних ліків для сховища. Тимчасові файли, кеші та артефакти збірки часто можна безпечно видалити; файли баз даних, сегменти черг та завантаження користувачів — ні. У реальному регламенті (runbook) команда очищення має точно називати каталог та правило зберігання.
kubectl exec my-pod -- rm -rf /data/tmp/*Збої місткості під час провізіонування з’являються до створення тому. Подія може казати insufficient capacity, або журнали CSI можуть нести специфічне для провайдера повідомлення про квоту, топологію, тип тому чи доступність бекенду. У просторах імен із ResourceQuota API Kubernetes може відхиляти чи затримувати запити навіть тоді, коли в бекенді сховища є місце.
Events: Warning ProvisioningFailed insufficient capacitykubectl get resourcequota -n <namespace>kubectl get limitrange -n <namespace>Квоти особливо важливі в іспитових та навчальних кластерах, бо вони можуть змусити правильний YAML-файл зазнати невдачі з причин середовища. Заявка, що просить більше сховища, ніж дозволяє квота простору імен, не прив’яжеться, а пізніше збільшення запиту може наразитися на ту саму політику. Коли об’єкт виглядає дійсним, але подія згадує квоту, розв’язуйте невідповідність політики, а не ганяйтеся за драйвером CSI.
kubectl describe resourcequota -n <namespace>Правильною виробничою відповіддю може бути зміна рівня сховища, зменшення запиту, розширення місткості бекенду чи переміщення робочого навантаження в топологію, де є місткість. Хмарне блокове сховище може мати регіональні, зональні, акаунтні та поодноптомні обмеження, а подія Kubernetes може показати лише частину цього ланцюжка. Використовуйте докази Kubernetes, щоб визначити, який виклик API бекенду провалився, а потім використовуйте інструменти провайдера чи документацію, щоб перевірити базове обмеження.
Який підхід ви б тут обрали і чому: розширити PVC, очистити старі дані, зменшити запитувану місткість чи перейти на інший StorageClass? Найкраща відповідь залежить від того, чи збій спричинений поточним використанням, політикою простору імен, квотою бекенду чи місткістю топології, тож назвіть рівень, перш ніж називати виправлення.
Діагностуйте проблеми драйвера CSI та хмарних прав
Розділ «Діагностуйте проблеми драйвера CSI та хмарних прав»Container Storage Interface дозволяє Kubernetes використовувати багато різних бекендів сховища через спільну модель інтеграції, але він також додає чимало рухомих частин. Типове розгортання CSI має компоненти контролера, які провізіонують та приєднують томи, компоненти ноди, які публікують томи на кожній окремій ноді, та сайдкари на кшталт зовнішнього провізіонера, приєднувача (attacher), розширювача (resizer) та снапшотера (snapshotter). Коли події об’єктів вказують саме на драйвер, вам потрібно знати, який конкретний компонент володіє провальною дією.
kubectl describe pvc my-pvcEvents: Warning ProvisioningFailed error getting CSI driver nameПочніть з підтвердження, що драйвер зареєстровано. Об’єкти CSIDriver описують встановлені драйвери на рівні кластера, тоді як об’єкти CSINode показують інформацію про драйвер, пов’язану з окремими нодами. Якщо драйвер відсутній в обох поданнях, StorageClass може посилатися на провізіонера, якого не встановлено в кластері.
kubectl get csidriverskubectl get csinodeПотім перевірте поди, які запускають драйвер. Керовані дистрибутиви відрізняються, але компоненти CSI зазвичай живуть у kube-system чи в іншому платформному просторі імен. Подивіться і на Deployment контролера, і на DaemonSet ноди, бо збої провізіонування й монтування можуть жити в різних компонентах.
kubectl get pods -n kube-system | grep csiNAME READY STATUS RESTARTSebs-csi-controller-abc 0/6 CrashLoopBackOff 5Для контролера в стані crashloop важать журнали з кожного відповідного сайдкара. Зовнішній провізіонер опрацьовує створення тому з PVC, приєднувач опрацьовує операції приєднання для приєднуваних томів, а контейнер драйвера спілкується з API бекенду. Один под може містити кілька контейнерів, тож включайте -c, а не припускайте, що контейнер за замовчуванням — це той, що має корисні журнали.
kubectl logs -n kube-system ebs-csi-controller-abc -c csi-provisionerkubectl logs -n kube-system ebs-csi-controller-abc -c csi-attacherХмарні права — поширене джерело збоїв CSI, бо драйверу зазвичай потрібна ідентичність поза API Kubernetes. В AWS контролер EBS CSI зазвичай використовує права IAM через анотацію сервісного акаунта в кластерах стилю EKS. У GCP права можуть надавати Workload Identity чи сервісні акаунти нод. В Azure операції з дисками може авторизувати керована ідентичність чи сервісний принципал.
kubectl get sa -n kube-system ebs-csi-controller-sa -o yamlmetadata: annotations: eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/example-ebs-csi-roleСтавтеся до ідентичності провайдера як до конфігурації, яка може дрейфувати. Драйвер CSI, який працював учора, може зазнати невдачі сьогодні, якщо було видалено анотацію сервісного акаунта, змінено політику ролі, змінено ідентичність пулу нод чи оновлення драйвера змінило потрібні права. Події Kubernetes можуть лише казати, що провізіонування провалилося, тоді як журнал драйвера назве провальну дію API.
kubectl describe sc <storageclass>kubectl get sc <storageclass> -o yamlПараметри StorageClass також заслуговують на перевірку, коли один клас зазнає невдачі, а інший працює. Помилка в типі тому, ключі шифрування, типі файлової системи, параметрі топології чи опції продуктивності може змусити зазнати невдачі лише конкретний клас. Журнал драйвера зазвичай точніший за подію PVC, бо він містить відмову бекенду.
kubectl describe pvc my-pvckubectl logs -n kube-system <csi-controller-pod> -c <driver-container>Зупиніться та передбачте: под контролера CSI у стані CrashLoopBackOff, а журнали кажуть, що він не зміг прийняти роль IAM. YAML StorageClass та PVC не змінювалися. Який об’єкт Kubernetes ви б перевірили першим, і яку зовнішню конфігурацію ви б звірили після цього?
Побудуйте швидкий довідник, не пропускаючи діагностику
Розділ «Побудуйте швидкий довідник, не пропускаючи діагностику»Швидкі довідники корисні лише тоді, коли вони зберігають шлях міркувань. Таблиця нижче зберігає шпаргалку повідомлень про помилки з початкової версії модуля, але кожен рядок слід читати як стартову гіпотезу, а не як остаточну відповідь. Відсутня заявка часто проявляється як FailedScheduling, тоді як FailedMount може вказувати на тайм-аут драйвера, проблему шляху на ноді чи проблему прав, тож завжди поєднуйте повідомлення з об’єктом та рівнем, який його породив.
| Повідомлення про помилку | Імовірна причина | Швидке виправлення |
|---|---|---|
persistentvolumeclaim "..." not found | Под посилається на відсутню заявку, часто повідомляється як FailedScheduling до монтування | Виправте claimName пода або створіть названу заявку в просторі імен пода |
no persistent volumes available | Немає відповідного PV для статичного провізіонування | Створіть або полагодьте відповідний PV |
storageclass not found | Неправильне ім’я StorageClass | Перевірте доступні класи та видаліть + перестворіть PVC із дійсним класом |
waiting for first consumer | Режим прив’язки WaitForFirstConsumer | Створіть або перевірте под, що використовує PVC |
Multi-Attach error | Том RWO запитано на кількох нодах | Перевірте старий записувач, потім видаліть старий под чи скоригуйте планування |
permission denied | Невідповідність власності файлової системи чи контексту безпеки | Встановіть fsGroup, runAsUser та перевірте власність |
path does not exist | Суворий тип hostPath із відсутнім шляхом на ноді | Створіть шлях або використайте DirectoryOrCreate у лабораторних сценаріях |
timeout waiting for volumes | Проблема драйвера CSI, бекенду чи приєднання на ноді | Перевірте поди CSI, журнали, стан ноди та обмеження бекенду |
insufficient capacity | Квоту простору імен чи місткість бекенду вичерпано | Перевірте квоту, розмір запиту, топологію та місткість провайдера |
volume is already attached | Застаріле чи активне приєднання до іншої ноди | Перевірте старий под, стан ноди та об’єкти VolumeAttachment |
Однорядкова команда нижче зберігає початковий намір швидкого налагодження, але вона краща як знімок стану, а не як діагностика. Використовуйте її, щоб зорієнтуватися, а потім повертайтеся до виводу describe, специфічного для об’єкта, заради фактичного повідомлення про збій. Стіна ресурсів менш корисна за короткий ланцюжок фактів, що доводить, де розірвався контракт сховища.
echo "=== PVCs ===" && kubectl get pvc && \echo "=== PVs ===" && kubectl get pv && \echo "=== StorageClasses ===" && kubectl get sc && \echo "=== Recent Events ===" && kubectl get events --sort-by='.lastTimestamp' | tail -20kubectl describe pod <pod-name>kubectl describe pvc <pvc-name>kubectl describe sc <storageclass>kubectl get volumeattachmentПатерни та антипатерни
Розділ «Патерни та антипатерни»Патерни усунення несправностей багаторазові саме тому, що вони зменшують кількість здогадок, які ви робите під тиском часу. Мета тут — не виконати кожну можливу команду в кожному інциденті; вона радше в тому, щоб перейти від симптому до рівня-власника з мінімальним ризиком для даних. Хороше налагодження сховища завжди тримає в голові стан даних, навіть тоді, коли безпосереднє завдання іспиту виглядає як проста проблема запуску пода.
| Патерн | Коли його використовувати | Чому він працює | Що враховувати при масштабуванні |
|---|---|---|---|
| Трасування від споживача до постачальника | Будь-який збій сховища пода чи PVC | Починається з видимого симптому й слідує фактичному ланцюжку посилань об’єктів | Добре працює у великих просторах імен, бо кожен крок звужує набір об’єктів |
| Діагностика з подій насамперед | Збої Pending, ContainerCreating, приєднання чи монтування | Події зазвичай містять найновішу причину й повідомлення контролера | Зберігання подій обмежене, тож фіксуйте корисні повідомлення під час активних інцидентів |
| Політика перед зміною | Перед видаленням PVC, PV чи старих подів | Політика повернення, режим доступу й режим прив’язки визначають ризик для даних | Потребує регламентів, що називають безпечні умови видалення для кожного класу навантажень |
| Ескалація до драйвера за доказами | Коли події називають зовнішнє провізіонування, приєднання чи помилки API бекенду | Журнали CSI мають високий сигнал після того, як факти на рівні об’єктів вказали на драйвер | Платформним командам слід задокументувати простори імен, імена контейнерів та ідентичності драйверів |
Антипатерни зазвичай походять від ставлення до сховища як до проблеми перезапуску без стану. Под можна відтворити дешево, але том, на який він посилається, може містити єдину копію важливого стану. Краща альтернатива — довести, чи збій є проблемою посилання, політики, драйвера, ноди чи файлової системи, перш ніж обирати зміну.
| Антипатерн | Що йде не так | Краща альтернатива |
|---|---|---|
| Видалення PVC до прочитання PV та політики повернення | Базовий том може бути несподівано видалено чи звільнено | Перевірте PVC, PV, політику повернення та снапшоти перед видаленням заявок |
| Гонитва за журналами CSI до прочитання подій пода й PVC | Ви витрачаєте час у зашумлених журналах контролера, поки помилка в YAML очевидна | Почніть з describe pod та describe pvc, ескалюйте лише коли події вказують туди |
| Ставлення до кожного PVC у стані Pending як до зламаного | Відкладена прив’язка може бути нормальною з топологічно-обізнаним сховищем | Перевірте volumeBindingMode та чи існує под-споживач |
| Примусове видалення старих подів під час Multi-Attach без доказів про ноду | Записувач, що все ще працює, може пошкодити дані застосунку | Підтвердьте стан ноди, завершення пода та безпеку навантаження перед примусовим видаленням |
| Розв’язання permission denied запуском від root | Застосунок стартує, але стан безпеки регресує | Використовуйте fsGroup, runAsUser та перевірку власності |
| Масштабування Deployment, що ділить одну заявку RWO | Зайві репліки зазнають невдачі чи борються за один том, приєднаний до ноди | Використайте одну репліку, окремі PVC через StatefulSet або сховище RWX |
Структура ухвалення рішень
Розділ «Структура ухвалення рішень»Найшвидша структура ухвалення рішень — це класифікувати збій за першим же об’єктом, що доводить щось неправильне. Якщо под посилається на відсутній PVC, то виправте ім’я пода чи заявки. Якщо PVC перебуває у стані Pending, то перевірте вхідні дані прив’язки. Якщо PVC прив’язано, але под усе одно не може змонтувати том, то перевірте приєднання, ноду, шлях, права й поведінку драйвера. Якщо ж под працює, але застосунок не може писати, то перевірте використання файлової системи й власність зсередини самого контейнера.
Storage symptom | +-- Pod says PVC not found? | | | +-- Verify namespace and claimName, then correct the pod spec or create the claim. | +-- PVC is Pending? | | | +-- Check StorageClass, binding mode, access modes, capacity, selectors, and quota. | +-- PVC is Bound but pod is ContainerCreating? | | | +-- Check FailedMount, FailedAttach, Multi-Attach, hostPath, node, and CSI events. | +-- Pod runs but app cannot write? | +-- Check df, ownership, runAsUser, fsGroup, and application retention policy.Використовуйте цю матрицю рішень, коли вам потрібно обрати виправлення під тиском часу. Вона навмисно відокремлює безпечні перевірки лише для читання від змін, бо відновлення сховища часто має незворотні кроки. У практиці CKA від вас можуть очікувати видалення й перестворення зламаного тестового об’єкта; на виробництві те саме видалення може прибрати єдину прив’язку до реальних даних.
| Доказ | Основний рівень | Перевірки лише для читання | Кандидат на виправлення |
|---|---|---|---|
| Подія PVC каже, що клас не знайдено | Вибір StorageClass | kubectl get sc, kubectl describe pvc | Видалити + перестворити непов’язаний PVC з наявним класом |
| Подія PVC каже про очікування на першого споживача | Планувальник і топологія | kubectl get sc -o yaml, перевірити под-споживач | Створити под або виправити обмеження планування |
| Наявний PV не прив’язується | Контракт PV/PVC | Порівняти місткість, режими доступу, клас, селектори та claimRef | Узгодити заявку або створити сумісний PV |
| Подія пода каже, що заявку не знайдено | Посилання тому пода | Перевірити простір імен пода та claimName | Виправити специфікацію пода або створити названу заявку в просторі імен |
| Помилка Multi-Attach | Приєднання до ноди | Перевірити старий под, стан ноди та VolumeAttachment | Зачекати, перемістити навантаження чи примусово видалити лише після оцінки ризику |
| Permission denied після монтування | Власність файлової системи | kubectl exec з id, ls -ld та журнали застосунку | Встановити fsGroup, runAsUser чи виправити власність через схвалену Job |
| Файлова система переповнена | Місткість під час роботи | df -h, розмір PVC, розкладка даних застосунку | Розширити заявку, якщо дозволено, або очистити безпечні одноразові дані |
Проєктуйте свій контрольний список усунення несправностей як послідовність фактів, а не як мішок команд. Кожен рядок має відповідати на одне запитання: чи посилається под на правильну заявку, чи прив’язано заявку, чи обрав клас потрібного провізіонера, чи приєднала нода том, чи вдалося монтування, і чи може процес писати? Коли контрольний список написано таким чином, він стає корисним для статичних PV, динамічного провізіонування CSI, локального лабораторного сховища та хмарних блокових томів.
Розбір прикладу: читання доказів за порядком
Розділ «Розбір прикладу: читання доказів за порядком»Припустімо, вправа дає вам под з іменем api-0, який не запускається, PVC з іменем api-data та StorageClass з іменем fast-block. Спокусливий хід — одразу перевірити всі три об’єкти, але чистіший хід — запитати, що под уже знає. Якщо подія пода каже, що заявка відсутня, клас і драйвер ще не релевантні; якщо подія каже, що монтування перевищило тайм-аут, ім’я заявки вже розв’язано, і ви можете рухатися глибше.
Тепер уявіть, що подія пода каже persistentvolumeclaim "api-data" not found, але kubectl get pvc у вашій поточній оболонці показує справну заявку з цим іменем. Наступне запитання не в тому, чи Kubernetes неузгоджений; воно в тому, чи використала ваша команда простір імен пода. Заявка з простору імен default не задовольняє под у backend, тож докази штовхають вас до виправлення простору імен, а не до ремонту провізіонування.
Якщо подія пода називає заявку, а заявка у стані Pending, перейдіть до потоку подій PVC. Повідомлення про storageclass not found вказує на невідповідність конфігурації, яку можна виправити, обравши наявний клас чи створивши потрібний клас. Повідомлення про очікування на першого споживача вказує на контекст топології планувальника, тож створення чи виправлення под-споживача — правильний наступний хід. Те саме слово-статус, отже, веде до різних дій залежно від повідомлення події.
Якщо PVC у стані Bound, утримайтеся від спокуси редагувати його лише тому, що под усе ще нездоровий. Прив’язка означає, що площина управління вже асоціювала заявку з PV, а випадкові правки можуть ускладнити осмислення ситуації. На цьому етапі події пода про FailedAttachVolume, FailedMount, hostPath type check failed чи проблеми з правами корисніші за зміни заявки. Рівень-власник перемістився з прив’язки на приєднання до ноди, налаштування монтування чи доступ процесу.
Для Multi-Attach порядок доказів захищає дані. Спершу знайдіть старий под і ноду, потім вирішіть, чи старий записувач зник, чи лише недосяжний з боку API-сервера. Якщо стара нода все ще Ready, примусове видалення — погана звичка, бо вихідний процес може все ще тримати файлову систему відкритою. Якщо нода NotReady і потрібне відновлення, задокументуйте ризик, приберіть застарілий об’єкт API та сплануйте перевірку цілісності застосунку після того, як под-заміна стартує.
Для permission denied порядок доказів запобігає регресу безпеки. Под, що працює, із журналами застосунку, які скаржаться на /data, відрізняється від пода, який взагалі не може змонтувати том. Перевірте id, членство в групах та власність каталогу зсередини контейнера, потім полагодьте контекст безпеки пода чи власність даних. Повернення до root зазвичай є ознакою того, що діагностика зупинилася на симптомі замість пояснення, чому процесу бракувало прав на запис.
Для місткості відокремте запитувану місткість від використаної. Прив’язаний PVC на 20Gi усе одно може бути переповнений з точки зору застосунку, а PVC на 20Gi у стані Pending може зазнати невдачі до того, як будь-яка файлова система існуватиме, бо квота чи місткість бекенду блокують провізіонування. Виправленням для першого випадку може бути розширення чи очищення; для другого — коригування квоти, менші запити, зміни топології чи місткість з боку провайдера. Вивід команди має сказати вам, у якому світі ви перебуваєте, перш ніж ви оберете.
Цей розбір прикладу — це звичка, яку ви хочете мати в день іспиту: прочитайте найближчу подію, визначте власника наступного рішення й уникайте руйнівних змін, поки докази їх не підтримають. Усунення несправностей зі сховищем здається масштабним, бо система має багато рівнів, але більшість інцидентів стають малими, щойно ви можете сказати: «посилання пода провалилося», «заявка не прив’язалася», «драйвер не зміг провізіонувати», «нода не змогла приєднати» чи «процес не може писати». Це речення — міст між діагностикою та безпечним виправленням.
Перевірка для учня
Розділ «Перевірка для учня»Після створення зміни полів PVC навмисно вузькі: запити на зміну розміру можна змінювати, коли дозволено розширення, але зміна класу сховища вимагає нової заявки.
Ваш PVC усе ще Pending, його подія каже storageclass.storage.k8s.io "fast-ssd" not found, а kubectl get sc показує лише standard. Яка дія безпечно змінює клас, не намагаючись пропатчити незмінне поле?
Чи знали ви?
Розділ «Чи знали ви?»- Kubernetes увів підтримку CSI як стабільну в циклі релізу 1.13, що допомогло винести інтеграції сховища з основного дерева коду до незалежно підтримуваних драйверів.
volumeBindingMode: WaitForFirstConsumerіснує тому, що топологічно-обізнане сховище має знати обрану ноду чи зону, перш ніж безпечно провізіонувати том.- Розширення PVC контролюється полем
allowVolumeExpansionу StorageClass, тож дві заявки в одному кластері можуть мати різну поведінку розширення. ReadWriteOnceстосується семантики приєднання на рівні ноди для багатьох блокових томів; це не означає, що кожна репліка в Deployment автоматично отримує приватний диск.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому вона стається | Як її виправити |
|---|---|---|
| Не перевіряти Events насамперед | Коротка таблиця get приховує фактичне повідомлення контролера | Запустіть kubectl describe pod чи kubectl describe pvc та прочитайте розділ Events |
| Ігнорувати простір імен | Імена PVC локальні для простору імен, але PV та StorageClass мають область видимості кластера | Перевірте простір імен пода й PVC, перш ніж налагоджувати бекенд |
Забути про WaitForFirstConsumer | PVC у стані Pending виглядає зламаним, коли він насправді чекає на под-споживач | Перевірте режим прив’язки StorageClass та перевірте под, що використовує заявку |
| Видаляти PVC до перевірки політики повернення | Видалення може звільнити чи прибрати базове сховище | Перевірте PV, політику повернення, снапшоти та власність даних перед видаленням |
| Пропускати журнали CSI, коли події називають провізіонера | Загальні події PVC можуть приховувати деталі API бекенду | Перевірте конкретний контейнер контролера чи плагіна ноди CSI, названий у збої |
| Виправляти права запуском від root | Це маскує симптом, послаблюючи ізоляцію | Використовуйте fsGroup, runAsUser та явні перевірки власності |
| Масштабувати репліки, що ділять одну заявку RWO | Другий под приземляється на іншу ноду й не може приєднати том | Використайте одну репліку, StatefulSet з окремими заявками чи сховище з підтримкою RWX |
Тест
Розділ «Тест»Питання 1: Розробник каже, що под застряг у стані `ContainerCreating` десять хвилин, і перестворення не допомогло. Яку послідовність усунення несправностей сховища ви запускаєте і чому?
Почніть з kubectl describe pod <name>, бо подія пода каже вам, чи збій є відсутньою заявкою, проблемою приєднання чи проблемою монтування. Якщо подія називає PVC, перевірте kubectl get pvc <name> та kubectl describe pvc <name>, щоб довести, чи заявку прив’язано, чи вона у стані Pending. Якщо заявка у стані Pending, перевірте StorageClass, сумісність PV, квоту та відкладену прив’язку; якщо заявку прив’язано, перевірте докази приєднання, ноди, CSI, hostPath та прав. Ця послідовність працює, бо вона слідує фактичному ланцюжку посилань, а не стрибає до сторонніх журналів драйвера.
Питання 2: PVC у стані Pending дві години, але `kubectl describe pvc` каже лише, що він чекає на першого споживача. Інший член команди хоче перевстановити драйвер CSI. Що ви робите?
Не перевстановлюйте драйвер на основі лише цього повідомлення. Перевірте StorageClass та підтвердьте, чи volumeBindingMode дорівнює WaitForFirstConsumer, бо заявка у стані Pending може бути очікуваною, поки под, що її використовує, не заплановано. Наступна корисна дія — створити чи перевірити под-споживач та перевірити, чи обмеження планування перешкоджають вибору ноди. Перевстановлення драйвера додало б ризику, ігноруючи докази того, що Kubernetes чекає на контекст топології.
Питання 3: Под StatefulSet на збійній ноді використовував том RWO, а под-заміна повідомляє про помилку Multi-Attach на іншій ноді. Який шлях відновлення врівноважує швидкість та безпеку даних?
Спершу підтвердьте стан старої ноди й старого пода за допомогою kubectl get pod -o wide, kubectl get node та умов ноди, бо записувач, що все ще працює, — це небезпечний випадок. Якщо нода справді недосяжна, а навантаження потребує відновлення, примусово видаліть старий под лише після прийняття ризику для застосунку, потім перевірте об’єкти VolumeAttachment, якщо приєднання залишається застарілим. Щойно новий под змонтує том, запустіть перевірки цілісності на рівні застосунку, бо успіх приєднання в Kubernetes не доводить, що попередній записувач завершився чисто. Безпечне міркування — довести володіння, перш ніж розривати старе приєднання.
Питання 4: Новий образ працює як UID 1000, PVC монтується успішно, але журнали застосунку кажуть, що він не може писати в `/data/app.log`. Яка першопричина та виправлення засобами Kubernetes?
Імовірна першопричина — власність файлової системи, створена старим контейнером, що працював від root, чи процесом відновлення з іншою числовою власністю. PVC та монтування справні, тож події пода можуть не показувати збій сховища. Додайте контекст безпеки пода з fsGroup: 1000 та контекст безпеки контейнера на кшталт runAsUser: 1000 та runAsNonRoot: true, потім перевірте за допомогою kubectl exec -- id та ls -ld /data. Запуск застосунку від root змусив би симптом зникнути, але послабив би модель безпеки.
Питання 5: PVC, що використовує `premium-ssd`, залишається у стані Pending, StorageClass існує, а подія каже, що зовнішній провізіонер не створив том. Куди ви дивитеся далі?
Подивіться на поди й журнали контролера CSI, бо заявка досягла рівня динамічного провізіонування. Використайте kubectl get pods -n kube-system | grep csi, потім отримайте журнали з контейнерів на кшталт csi-provisioner, csi-attacher чи контейнера драйвера. Імовірними причинами є контролер у стані crashloop, відсутні хмарні права, недійсні параметри StorageClass, квота бекенду чи місткість топології. Перевірка іншого StorageClass за замовчуванням також може сказати вам, чи збій специфічний для класу, чи поширений на весь кластер.
Питання 6: Deployment має дві репліки, які обидві монтують той самий прив'язаний PVC. Один под Running на node-a, інший застряг на node-b, а режим доступу PV — RWO. Яке виправлення на іспиті та яке на виробництві?
Безпосередня проблема в тому, що одну заявку на основі RWO використовують поди на різних нодах. На іспиті найшвидше безпечне виправлення зазвичай — масштабувати Deployment до однієї репліки чи обмежити планування так, щоб приєднання потребувала лише одна нода, залежно від формулювання завдання. Виробниче виправлення — переробити форму сховища: використати StatefulSet з volumeClaimTemplates, щоб кожна репліка отримала власну заявку, або перейти на сховище з підтримкою RWX, якщо застосунок справді потребує спільного запису. Відповідь має згадати режим доступу, бо зміна реплік без зміни семантики сховища лише приховує проблему дизайну.
Питання 7: Квота простору імен дозволяє 10Gi сховища, а учень створює PVC на 20Gi, який ніколи не прив'язується. StorageClass та драйвер CSI справні. Як ви довести та виправите проблему?
Перевірте kubectl describe pvc на події, пов’язані з квотою, потім запустіть kubectl get resourcequota -n <namespace> та kubectl describe resourcequota -n <namespace>, щоб порівняти запитуване сховище з політикою. Виправлення — зменшити запит, попросити зміну квоти чи використати простір імен, призначений для більших заявок. Перезапуски драйвера не релевантні, бо політика API відхиляє чи блокує запит ще до того, як постане питання місткості бекенду. Ця відповідь узгоджує докази з рівнем, що володіє відмовою.
Практична вправа: сценарії усунення несправностей зі сховищем
Розділ «Практична вправа: сценарії усунення несправностей зі сховищем»Ця вправа зберігає три зламані конфігурації з початкової версії модуля й перетворює їх на прогресивну лабораторну роботу з усунення несправностей. Використовуйте одноразовий кластер чи лабораторне середовище, бо ви створюватимете заявки й поди, які навмисно неправильні, перш ніж їх виправляти. Мета — не запам’ятати фінальний YAML; вона в тому, щоб попрактикувати читання події, називання зламаного рівня й застосування найменшого виправлення, яке робить навантаження справним.
Налаштування
Розділ «Налаштування»kubectl create ns storage-debugСценарій 1: PVC не прив’язується, бо StorageClass неправильний
Розділ «Сценарій 1: PVC не прив’язується, бо StorageClass неправильний»Створіть зламану заявку точно так, як написано. Ім’я StorageClass навмисно недійсне для більшості кластерів, тож заявка має залишитися у стані Pending, а події PVC мають назвати відсутній клас. Якщо у вашому кластері випадково є клас із саме цим іменем, змініть його на інше явно відсутнє ім’я перед застосуванням об’єкта.
cat <<'EOF' | kubectl apply -f -apiVersion: v1kind: PersistentVolumeClaimmetadata: name: broken-pvc-1 namespace: storage-debugspec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: nonexistent-classEOFkubectl get pvc -n storage-debug broken-pvc-1kubectl describe pvc -n storage-debug broken-pvc-1kubectl get scВиправлення — перестворити заявку з реальним StorageClass для вашого кластера. Якщо ваш лабораторний кластер не має динамічного провізіонера, цей сценарій усе одно навчає правильної діагностики: заявка просить клас, який кластер не може задовольнити. У цьому випадку зафіксуйте докази й пропустіть заявку-заміну, або створіть статичний PV, якщо ваш інструктор очікує ручного провізіонування.
kubectl delete pvc -n storage-debug broken-pvc-1cat <<'EOF' | kubectl apply -f -apiVersion: v1kind: PersistentVolumeClaimmetadata: name: broken-pvc-1 namespace: storage-debugspec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: standardEOFЯкщо клас використовує WaitForFirstConsumer, перебування PVC у стані Pending без подій помилок очікуване, поки под не посилається на заявку.
Нотатки до розв'язання сценарію 1
Очікуваним доказом є подія на кшталт storageclass.storage.k8s.io "nonexistent-class" not found. Правильне виправлення — не перезапускати поди й не перевіряти журнали CSI першими; це зробити так, щоб заявка просила клас, який існує, чи надати відповідний статичний PV. Якщо standard немає у вашому кластері, підставте фактичне ім’я класу, показане kubectl get sc.
Сценарій 2: Под не може змонтувати, бо ім’я заявки неправильне
Розділ «Сценарій 2: Под не може змонтувати, бо ім’я заявки неправильне»Цей сценарій починається з дійсної заявки, а потім створює под, що посилається на інше ім’я. Очікуваний збій — на рівні посилання тому пода, а не на рівні провізіонування. Це означає, що PVC може бути справним, поки под усе одно не може нічого змонтувати.
cat <<'EOF' | kubectl apply -f -apiVersion: v1kind: PersistentVolumeClaimmetadata: name: correct-pvc namespace: storage-debugspec: accessModes: - ReadWriteOnce resources: requests: storage: 1GiEOFcat <<'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: broken-pod-1 namespace: storage-debugspec: containers: - name: app image: busybox:1.36 command: ['sleep', '3600'] volumeMounts: - name: data mountPath: /data volumes: - name: data persistentVolumeClaim: claimName: wrong-pvc-nameEOFkubectl get pod -n storage-debug broken-pod-1kubectl describe pod -n storage-debug broken-pod-1Виправлення — перестворити под із правильним claimName. Для реального Deployment ви б пропатчили чи оновили шаблон контролера, а не редагували «голий» под, бо контролери відтворюють поди зі своїх шаблонів. У цій лабораторній роботі видалення й перестворення пода тримає фокус на посиланні сховища.
kubectl delete pod -n storage-debug broken-pod-1cat <<'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: broken-pod-1 namespace: storage-debugspec: containers: - name: app image: busybox:1.36 command: ['sleep', '3600'] volumeMounts: - name: data mountPath: /data volumes: - name: data persistentVolumeClaim: claimName: correct-pvcEOFНотатки до розв'язання сценарію 2
Подія пода має згадувати, що persistentvolumeclaim "wrong-pvc-name" not found. Важлива деталь — локальне для простору імен іменування: Kubernetes не шукає в інших просторах імен заявку з цим іменем, а справна заявка з іншим іменем не задовольняє специфікацію пода. Найменше виправлення — зробити так, щоб под посилався на correct-pvc.
Третій сценарій використовує hostPath, бо він породжує чітку помилку локального монтування на ноді без потреби в хмарному провайдері. Шлях навмисно відсутній, а тип — Directory, що вимагає, щоб каталог існував до запуску пода. Це корисно для навчання, але пам’ятайте, що hostPath рідко є правильною абстракцією для даних застосунку на виробництві.
cat <<'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: broken-pod-2 namespace: storage-debugspec: containers: - name: app image: busybox:1.36 command: ['sleep', '3600'] volumeMounts: - name: data mountPath: /data volumes: - name: data hostPath: path: /tmp/nonexistent-path-xyz type: DirectoryEOFkubectl describe pod -n storage-debug broken-pod-2Полагодьте под, використавши DirectoryOrCreate, який просить kubelet створити каталог на обраній ноді, якщо його не існує. Це доречно для лабораторної роботи, бо шлях одноразовий. У виробничому дизайні ви б зазвичай замінили hostPath на PV, том на основі CSI чи патерн, специфічний для агента ноди.
kubectl delete pod -n storage-debug broken-pod-2cat <<'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: broken-pod-2 namespace: storage-debugspec: containers: - name: app image: busybox:1.36 command: ['sleep', '3600'] volumeMounts: - name: data mountPath: /data volumes: - name: data hostPath: path: /tmp/nonexistent-path-xyz type: DirectoryOrCreateEOFНотатки до розв'язання сценарію 3
Очікувана подія — збій перевірки типу hostPath. Виправлення змінює тип hostPath, а не PVC, StorageClass чи драйвери CSI, бо цей том локальний для ноди й не використовує контролер персистентних томів. Це розрізнення — головний урок: правильне виправлення слідує типу тому, який фактично з’являється у специфікації пода.
Практичні вправи
Розділ «Практичні вправи»Наступні вправи зберігають початкові швидкі перевірки як короткі повторення. Запустіть їх після сценаріїв, потім поясніть одним реченням, що доводить кожна команда. Якщо ви не можете назвати рівень, який перевіряє кожна команда, повторюйте попередні розділи, поки команда не матиме призначення замість того, щоб здаватися завченим закляттям.
kubectl get pvc -n <namespace>kubectl describe pvc <pvc-name> | grep -A20 Eventskubectl exec <pod> -- df -hkubectl exec <pod> -- ls -la /datakubectl describe pod <pod-name>kubectl get pods -n kube-system | grep csikubectl get csidriverskubectl get pvc <pvc-name> -o yaml | grep -E 'storage:|accessModes:|storageClassName:'kubectl get pv <pv-name> -o yaml | grep -E 'storage:|accessModes:|storageClassName:'kubectl get volumeattachmentkubectl get events --field-selector reason=FailedBindingkubectl get events --field-selector reason=ProvisioningFailedkubectl get events --sort-by='.lastTimestamp' | tail -20kubectl get pod <pod-name> -o widekubectl get sc <storageclass> -o yamlkubectl describe node <node-name> | grep -A8 Conditionskubectl logs -n kube-system <csi-controller-pod> -c csi-provisionerkubectl logs -n kube-system <csi-controller-pod> -c csi-attacherkubectl get resourcequota -n <namespace>kubectl describe resourcequota -n <namespace>Контрольний список усунення несправностей зі сховищем
Розділ «Контрольний список усунення несправностей зі сховищем»Використовуйте цей контрольний список як фінальний артефакт лабораторної роботи. Він навмисно написаний як докази для збору, а не як команди для бездумного виконання. У реальному інциденті прикріплюйте повідомлення подій та виводи команд до тікета, щоб наступний інженер міг побачити, чому ви обрали виправлення.
□ Pod stuck? → kubectl describe pod → check Events□ PVC Pending? → kubectl describe pvc → check Events□ StorageClass exists? → kubectl get sc□ PV available? → kubectl get pv□ Access modes match? → Compare PVC and PV□ StorageClassName match? → Compare PVC and PV□ CSI driver running? → kubectl get pods -n kube-system | grep csi□ Permissions issue? → Check securityContext fsGroup□ Capacity issue? → Check quotas and storage backendКритерії успіху
Розділ «Критерії успіху»- Виявили помилку StorageClass з подій PVC та виправили заявку, щоб вона використовувала дійсний клас для вашого кластера.
- Виявили неправильне ім’я PVC з подій пода та виправили посилання тому пода.
- Виявили вимогу типу hostPath з подій пода та безпечно виправили тип для лабораторної роботи.
- Пояснили, чи належав кожен збій до рівня посилання пода, прив’язки PVC, монтування на ноді чи драйвера сховища.
- Написали короткий контрольний список усунення несправностей сховища, що починається з подій та уникає руйнівного видалення як першого ходу.
Очищення
Розділ «Очищення»kubectl delete ns storage-debugДжерела
Розділ «Джерела»- Документація Kubernetes: Persistent Volumes
- Документація Kubernetes: Storage Classes
- Документація Kubernetes: Volumes
- Документація Kubernetes: Dynamic Volume Provisioning
- Документація Kubernetes: Volume Snapshots
- Документація Kubernetes: CSI Drivers
- Документація Kubernetes: Configure a Security Context
- Документація Kubernetes: Resource Quotas
- Документація Kubernetes: Debug Pods
- Документація Kubernetes: Finalizers
- Kubernetes CSI external-provisioner
- Kubernetes CSI external-attacher
Наступний модуль
Розділ «Наступний модуль»Перейдіть до Підсумкового тесту частини 4, щоб перевірити свої знання про сховище перед переходом до ширшого усунення несправностей Kubernetes.