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

Модуль 3.3: Налагодження у Kubernetes

Складність: [MEDIUM] — критично важлива екзаменаційна навичка, що потребує системного підходу

Час на проходження: 45-55 хвилин

Передумови: Модуль 3.1 (Проби), Модуль 3.2 (Логування)


Що ви зможете зробити

Розділ «Що ви зможете зробити»

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

  • Діагностувати збої Под’ів за допомогою статусу, подій, логів та виводу describe.
  • Налагоджувати стани Под’ів CrashLoopBackOff, ImagePullBackOff, Pending та NotReady в умовах браку часу.
  • Усувати неполадки мережі Сервісів і Под’ів за допомогою ендпоінтів, перевірок DNS, exec та ефемерних контейнерів налагодження.
  • Впровадити повторюваний робочий процес налагодження, який рухається від широких симптомів до конкретних доказів.

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

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

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

Налагодження Kubernetes відрізняється від налагодження окремого процесу на вашому ноутбуку, бо збій може водночас сидіти в кількох шарах. Контейнер може аварійно завершитися, бо застосунок написано неправильно; Под може залишатися у стані Pending, бо планувальник не може його розмістити; Сервіс може бути справним, але не вибирати жодного ендпоінта; а проба готовності може прибрати кожен бекенд із трафіку, навіть попри те, що контейнери досі у стані Running. Kubernetes 1.35+ дає вам потужні інструменти для інспекції, але ці інструменти винагороджують послідовність і карають за здогадки.

Цей модуль перетворює стару звичку “спробувати кілька команд і сподіватися” на драбину доказів, яку ви можете пройти під екзаменаційним тиском. Ви почнете зі статусу, перейдете до подій і стану контейнера, прочитаєте поточні та попередні логи, заходитимете в контейнери лише тоді, коли ці докази підкажуть, що це корисно, додаватимете ефемерні контейнери налагодження, коли образу застосунку бракує інструментів, і завершите трасуванням Сервісу від селектора до ендпоінта і до DNS. Мета — не завчити список команд; мета — вирішити, яке спостереження змінює ваш наступний крок.

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

Побудуйте мапу налагодження, перш ніж торкатися Под’а

Розділ «Побудуйте мапу налагодження, перш ніж торкатися Под’а»

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

Використовуйте робочий процес як мапу, а не як жорсткий ритуал. Якщо Под у стані Pending, логи не допоможуть, бо жоден контейнер не запустився, тож describe і події планувальника мають значення першими. Якщо Под у стані CrashLoopBackOff, поточні логи можуть показати лише найновіший перезапуск, тож попередні логи й останній стан завершення стають корисними доказами. Якщо Сервіс не має ендпоінтів, заходити в контейнер застосунку зазвичай передчасно, бо селектор, готовність або відображення портів можуть пояснити збій ще до того, як ви перевірите сокет.

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

+-----------------------------------------------------------+
| Systematic Debugging Workflow |
+-----------------------------------------------------------+
| |
| 1. GET STATUS |
| kubectl get pod POD -o wide |
| -> What state? Ready? Restarts? Node? |
| |
| 2. DESCRIBE |
| kubectl describe pod POD |
| -> Events? Conditions? Container status? |
| |
| 3. LOGS |
| kubectl logs POD [--previous] |
| -> What did the app say? Errors? |
| |
| 4. EXEC |
| kubectl exec -it POD -- sh |
| -> What's inside? Files? Processes? Network? |
| |
| 5. EVENTS |
| kubectl get events --sort-by='.lastTimestamp' |
| -> What happened cluster-wide? |
| |
+-----------------------------------------------------------+

Починайте з команди статусу, бо вона каже вам, на якій гілці дерева рішень ви перебуваєте. Стовпець READY відокремлює процес, що працює, від Под’а, який справді придатний для трафіку Сервісу, RESTARTS відокремлює стабільний збій від циклу аварійних завершень, а NODE каже, чи вже відбулося планування. Розширений вигляд має значення, бо ім’я вузла, IP Под’а або відсутній IP Под’а можуть підказати, чи слід думати про планування, середовище виконання або мережу.

Читайте контекст простору імен і селектора одночасно, особливо під час завдань CKAD, де кілька об’єктів можуть мати схожі імена. Рядок статусу з неправильного простору імен може спрямувати вас у хибне розслідування, а Под, вибраний за іншою міткою, може зробити Сервіс несправним на вигляд, навіть коли робоче навантаження, яке ви оглянули, справне. Звичка проста: підтвердіть ім’я об’єкта, простір імен, власника, готовність, кількість перезапусків, вузол та IP Под’а, перш ніж ставитися до решти виводу як до доказів.

Terminal window
# Pod status overview
kubectl get pod POD -o wide
# All pods in namespace
kubectl get pods
# Watch for changes
kubectl get pods -w

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

Блок статусу контейнера заслуговує на уважне читання, бо містить поточний стан і останній стан поруч. Waiting з причиною на кшталт ImagePullBackOff означає, що процес не запустився; Running із Ready: False вказує на проби або готовність застосунку; а Terminated чи Last State пояснює, як завершилася попередня спроба. Це Kubernetes-версія медичної карти: поточний симптом має значення, але попередній стан часто пояснює, як пацієнт до нього дійшов.

Terminal window
# Full pod details
kubectl describe pod POD
# Key sections to check:
# - Status/Conditions
# - Containers (State, Ready, Restart Count)
# - Events (bottom of output)

Логи найкорисніші після того, як ви знаєте, що контейнер справді запустився. У контейнера, що працює, є поточні логи, тоді як у перезапущеного контейнера є також попередній екземпляр, чий вивід часто є єдиним місцем, де з’являється фатальна помилка. Коли ви налагоджуєте Под’и з кількома контейнерами, завжди називайте контейнер; інакше ви можете випадково прочитати сайдкар і пропустити контейнер застосунку, який падає.

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

На kind та інших кластерах на базі containerd kubectl logs --previous може повернути unable to retrieve container logs під час дуже швидких циклів аварійних завершень, бо завершений екземпляр ще не збережено. Коли це трапляється, читайте Last State і terminationMessage з kubectl describe pod натомість і зачекайте ще на один цикл перезапуску, якщо докази досі порожні.

Terminal window
# Current logs
kubectl logs POD
# Previous instance (after crash)
kubectl logs POD --previous
# Fallback when --previous is empty (fast crash loops on kind/containerd):
kubectl describe pod POD | grep -A5 "Last State"
# Specific container
kubectl logs POD -c CONTAINER
# Stream logs
kubectl logs -f POD

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

Terminal window
# Interactive shell
kubectl exec -it POD -- sh
kubectl exec -it POD -- /bin/bash
# Run single command
kubectl exec POD -- ls /app
kubectl exec POD -- cat /etc/config
# Specific container
kubectl exec -it POD -c CONTAINER -- sh

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

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

Terminal window
# Namespace events (sorted by time)
kubectl get events --sort-by='.lastTimestamp'
# Filter by type
kubectl get events --field-selector type=Warning
# Events for specific pod
kubectl get events --field-selector involvedObject.name=POD

Робочий процес стає швидким, щойно ви перестаєте читати кожен рядок з однаковою увагою. Для завдання CKAD ваш перший прохід через статус і describe має відповісти на три запитання: чи відбулося планування, чи запустився образ і чи залишився процес живим достатньо довго, щоб стати Ready? Ці запитання розміщують проблему в певному шарі, і кожна наступна команда має або підтвердити цей шар, або просунути вас на один шар усередину.

Розшифруйте стани Под’а та докази завершення контейнера

Розділ «Розшифруйте стани Под’а та докази завершення контейнера»

Слова статусу Kubernetes — це стислі підсумки роботи різних контролерів і агентів вузла. Pending зазвичай вказує на планування, прив’язку тому або підготовку образу до того, як з’явиться основний процес. ImagePullBackOff вказує на те, що kubelet намагається й не може завантажити образ. CrashLoopBackOff означає, що процес запустився, а потім багаторазово завершувався, тоді як Running, але не Ready, означає, що контейнер живий, але придатність до трафіку не вдалася. Ставтеся до цих слів як до маршрутних міток для вашого розслідування.

Маршрутна мітка — лише перший натяк, а не повний діагноз. Pending може означати неможливість запланувати ресурси, але також може означати, що заявка на том очікує або пісочниця середовища виконання не готова. CrashLoopBackOff може означати неправильну команду, але також може означати, що проба життєздатності вбила процес, який повільно стартує. Ваше завдання — використати слово стану, щоб обрати наступне джерело доказів, а потім дозволити детальній події або стану контейнера назвати точне виправлення.

Под, що застряг у Pending, часто не є багом застосунку. Планувальник може бути неспроможним знайти вузол із достатньою кількістю ресурсів, правило nodeSelector чи affinity може виключати кожен вузол, taint може вимагати toleration, а PersistentVolumeClaim може бути ще не прив’язаною. Логи недоступні в цьому стані, бо немає процесу контейнера, що працює, тож корисні докази — це опис Под’а, події планувальника, мітки вузлів, ємність вузлів і стан прив’язки сховища.

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

Terminal window
# Check why
kubectl describe pod POD
# Common causes:
# 1. Insufficient resources
# -> Check node resources: kubectl describe node
# -> Reduce pod resource requests
# 2. No matching node (nodeSelector/affinity)
# -> Check node labels: kubectl get nodes --show-labels
# -> Fix selector or label nodes
# 3. PVC not bound
# -> Check PVC: kubectl get pvc
# -> Create matching PV

Зробіть паузу і спрогнозуйте: Под застряг у Pending, і kubectl describe pod показує 0/3 nodes are available: 3 Insufficient cpu. Це не виправляється перезапуском Под’а, бо планувальник ухвалить те саме рішення знову. Ваші варіанти — знизити запит, звільнити ємність, додати ємність або змінити правила розміщення, і правильним екзаменаційним виправленням зазвичай є найменша зміна маніфесту, що дозволяє планувальнику розмістити Под.

Збої завантаження образу трапляються до запуску застосунку, тож посилання на образ і шлях автентифікації реєстру мають більше значення, ніж команда контейнера. Текст події зазвичай називає образ, відповідь реєстру і те, чи проблема — у відсутньому тегу, неавторизованому доступі чи збої пошуку в реєстрі. ErrImagePull — це безпосередній збій, а ImagePullBackOff — стан відстрочки, у який Kubernetes входить після повторних спроб, тож обидва стани мають спершу спрямувати вас до розділу Events.

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

Terminal window
# Check events
kubectl describe pod POD | grep -A5 Events
# Common causes:
# 1. Wrong image name/tag
# -> Fix image in pod spec
# 2. Private registry without credentials
# -> Create imagePullSecret
# 3. Image doesn't exist
# -> Verify image exists in registry

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

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

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

Terminal window
# Check logs from crashed instance
kubectl logs POD --previous
# Fallback when --previous is empty (fast crash loops):
kubectl describe pod POD | grep -A5 "Last State"
# Check exit code and termination message
kubectl describe pod POD | grep -A5 "Last State"
# Common causes:
# 1. Application error (check logs)
# 2. Missing config/secrets
# 3. Wrong command/args
# 4. Liveness probe killing healthy app

Зупиніться і подумайте: Под показує CrashLoopBackOff із кодом виходу 137. Це значення зазвичай означає, що процес отримав SIGKILL, і в Kubernetes воно часто з’являється з причиною OOMKilled, коли контейнер перевищує свій ліміт пам’яті. Перш ніж змінювати команду, огляньте причину Last State, ліміти ресурсів і нещодавню поведінку пам’яті, бо цілком коректний застосунок може аварійно завершитися, коли ліміт замалий для його навантаження під час запуску.

Под може бути Running і все одно бути відсутнім серед ендпоінтів Сервісу. Готовність — це контракт трафіку, а не контракт життєздатності процесу, тож проба готовності, що падає, може тримати справний на вигляд процес поза балансуванням навантаження. Це одна з найпоширеніших екзаменаційних пасток, бо kubectl get pods може показувати фазу як Running, тоді як стовпець READY, події проб та ендпоінти розкривають, що застосунок не обслуговує трафік.

Готовність слід налагоджувати з обох боків контракту. З боку Под’а перевірте, чи шлях, порт, схема й початковий таймінг проби збігаються з тим, що застосунок справді обслуговує. З боку Сервісу перевірте, чи змінюється членство в ендпоінтах після того, як готовність стає істинною. Якщо Под стає Ready, але трафік усе одно падає, тоді ви пройшли далі за готовність і маєте оглянути селектор, targetPort, NetworkPolicy чи слухач застосунку.

Terminal window
# Check readiness probe
kubectl describe pod POD | grep -A5 Readiness
# Check endpoints
kubectl get endpoints SERVICE
# Common causes:
# 1. Wrong readiness probe path/port
# 2. App not fully started
# 3. Dependency not available

Перш ніж запускати мережевий тест, вирішіть, який результат довів би шар, який ви підозрюєте. Якщо ендпоінти порожні, поки Под’и у стані Running, але не Ready, проба готовності, що падає, є ймовірнішою, ніж DNS. Якщо ендпоінти містять IP Под’ів, але трафік усе одно падає, тоді DNS, NetworkPolicy, targetPort чи поведінка слухача застосунку стають правдоподібнішими. Ця звичка прогнозувати заощаджує час, бо кожна команда має своє завдання замість того, щоб стати ще одним випадковим зразком.

Налагоджуйте зсередини мережевого простору імен

Розділ «Налагоджуйте зсередини мережевого простору імен»

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

Інспекція контейнера найсильніша, коли у вас уже є гіпотеза. “Чи змонтований ConfigMap за шляхом /etc/config?” — гарне запитання для exec, бо одна ls чи cat може на нього відповісти. “Чому застосунок зламаний?” — надто широке, бо заохочує блукання файловою системою. Перш ніж відкрити оболонку, назвіть точну умову, яку ви очікуєте підтвердити чи спростувати, а потім закрийте оболонку, щойно отримаєте цю відповідь.

Використовуйте exec для спостереження, а не для дрейфу конфігурації. Оболонка дозволяє оглядати файли та мережеву поведінку, але зміни, внесені вручну всередині контейнера, не є тривким виправленням, бо контролери відтворюють Под’и з маніфестів. У роботі з CKAD ставтеся до exec як до способу довести, чи змонтувався конфігураційний файл, чи слухав порт або чи розв’язався DNS, перш ніж патчити декларативний об’єкт, який володіє цією поведінкою.

Terminal window
# Get shell
kubectl exec -it POD -- sh
# Check processes
kubectl exec POD -- ps aux
# Check network (busybox has netstat, not ss)
kubectl exec POD -- netstat -tlnp
# ss -tlnp requires a full image (netshoot/debian); busybox → use netstat
# Check DNS (prefer FQDN — see note below)
kubectl exec POD -- nslookup kubernetes.default.svc.cluster.local
kubectl exec POD -- cat /etc/resolv.conf
# Check connectivity
kubectl exec POD -- wget -qO- http://service:port
kubectl exec POD -- curl -s http://service:port
# Check files
kubectl exec POD -- ls -la /app
kubectl exec POD -- cat /etc/config/file

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

Примітка: Busybox nslookup не розгортає шлях search у /etc/resolv.conf так, як це роблять glibc чи netshoot, тож пошук за коротким іменем часто повертає NXDOMAIN на Kubernetes 1.35, навіть коли DNS кластера справний — і команда може завершитися з ненульовим кодом, навіть надрукувавши корисний рядок Address:. Віддавайте перевагу FQDN, як-от SERVICE.NAMESPACE.svc.cluster.local (наприклад, kubernetes.default.svc.cluster.local), або використовуйте netshoot dig, коли вам потрібна поведінка розв’язання за коротким іменем.

Коли оболонка недоступна

Розділ «Коли оболонка недоступна»

Образи на базі distroless та scratch часто опускають оболонки й мережеві інструменти, щоб зменшити поверхню атаки та розмір образу. Цей дизайн добрий для продакшену, але він змінює спосіб налагодження, бо kubectl exec POD -- sh може зазнати невдачі, навіть коли контейнер цілком справний. У кластерах Kubernetes 1.35+ ефемерні контейнери налагодження є кращим способом принести інструментарій у простори імен Под’а без перебудови чи перезапуску образу застосунку.

Ось чому “просто встановити curl в образ” не завжди є правильним уроком. Продакшен-образи мають формуватися потребами середовища виконання й безпеки, тоді як образи для налагодження можуть формуватися діагностичними потребами. Kubernetes дозволяє тримати ці питання окремо. Коли мінімальний образ блокує звичайний exec, збережіть мінімальний продакшен-образ і тимчасово приєднайте інструменти через kubectl debug чи спеціально створений діагностичний Под.

Terminal window
# Check if shell exists
kubectl exec POD -- /bin/sh -c 'echo works'
# If no shell, use debug container (Kubernetes 1.25+)
kubectl debug POD -it --image=busybox --target=container-name

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

Ефемерні контейнери налагодження

Розділ «Ефемерні контейнери налагодження»

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

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

Terminal window
# Add debug container to running pod
kubectl debug POD -it --image=busybox --target=container-name
# Debug with specific image
kubectl debug POD -it --image=nicolaka/netshoot
# Copy pod for debugging (doesn't affect original)
kubectl debug POD -it --copy-to=debug-pod --container=debug --image=busybox

Обирайте образ налагодження на основі доказів, які вам потрібні. BusyBox малий і корисний для базових перевірок оболонки, файлів і DNS, тоді як образ із фокусом на мережі, як-от nicolaka/netshoot, надає багатші інструменти для діагностики сервісів і DNS. Скопійований Под безпечніший, коли ви хочете змінити аргументи команди чи дослідити змінене середовище, бо оригінальний Под продовжує обслуговувати трафік, поки копія для налагодження поглинає експеримент.

Випадки використання контейнерів налагодження

Розділ «Випадки використання контейнерів налагодження»

Наведені нижче команди зберігають ситуації налагодження з оригінального модуля: мережеві перевірки, коли застосунку бракує curl, інспекція файлової системи, коли потрібно перевірити монтування, та інспекція процесів, коли це дозволяє розташування простору імен. Не припускайте, що кожен кластер надає однакові дозволи на налагодження, бо ефемерні контейнери все одно залежать від політики допуску, контексту безпеки та RBAC. Коли налагодження заблоковано, поверніться до тимчасового діагностичного Под’а в тому самому просторі імен і перевірте DNS Сервісу чи з’єднання звідти.

Terminal window
# Network debugging (no curl in original container)
kubectl debug POD -it --image=nicolaka/netshoot --target=app
# Then: curl, dig, nslookup, tcpdump
# File system inspection
kubectl debug POD -it --image=busybox --target=app
# Then: ls, cat, find
# Process debugging (--target shares the target container's process namespace)
kubectl debug POD -it --image=busybox --target=app
# Then: ps aux
# Copy-based alternative (--share-processes requires --copy-to)
kubectl debug POD --copy-to=debug-copy --share-processes --set-image='*=busybox' -- sleep 3600
# Then: kubectl exec debug-copy -- ps aux

Прапорець --target приєднує контейнер налагодження до наявного контейнера й розділяє простір імен процесів цієї цілі, тому ps aux може бачити процеси застосунку. Прапорець --share-processes застосовується лише з --copy-to; на звичайному приєднанні налагодження через --target він не має ефекту. Ефемерні контейнери налагодження потужні саме тому, що зменшують тиск мутувати зламане робоче навантаження. Замість додавання інструментів до продакшен-образу ви тимчасово розміщуєте інструменти поруч із ним. Замість перезапуску Под’а, який досі обслуговує частковий трафік, ви оглядаєте його з того самого мережевого контексту. Це розділення має значення на екзаменах і в реальних кластерах, бо спостереження не має створювати більше дрейфу, ніж сам початковий збій.

Трасуйте Сервіси від селектора до ендпоінта і до DNS

Розділ «Трасуйте Сервіси від селектора до ендпоінта і до DNS»

Налагодження Сервісу — це проблема зв’язків, перш ніж стати проблемою пакетів. Сервіс вибирає Под’и за міткою, Kubernetes публікує готові вибрані Под’и як ендпоінти чи EndpointSlice, DNS дає Сервісу стабільне ім’я, а kube-proxy або датаплейн кластера спрямовує трафік до цих бекендів. Якщо будь-який зв’язок зламано, просте “connection refused” чи таймаут може приховувати невідповідність селектора, пробу готовності, що падає, неправильний targetPort чи межу мережевої політики.

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

Перевірте з’єднання Сервіс-Под

Розділ «Перевірте з’єднання Сервіс-Под»

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

Terminal window
# Verify service exists
kubectl get svc SERVICE
# Check endpoints (should list pod IPs)
kubectl get endpoints SERVICE
# On Kubernetes 1.35+, kubectl may warn that EndpointSlice is preferred; the address list is still valid.
# If no endpoints:
# - Check pod labels match service selector
# - Check pod readiness
kubectl get pods --show-labels
kubectl describe svc SERVICE | grep Selector

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

Перевірте DNS Сервісу

Розділ «Перевірте DNS Сервісу»

Тести DNS корисні лише після того, як ви знаєте, яке ім’я має розв’язати клієнт. Коротке ім’я Сервісу розв’язується всередині того самого простору імен, тоді як клієнту з іншого простору імен потрібно або SERVICE.NAMESPACE, або повне DNS-ім’я кластера. Якщо пошук DNS вдається, але HTTP падає, DNS більше не є вашим головним підозрюваним; переходьте до targetPort, слухача застосунку, NetworkPolicy чи поведінки готовності.

Область імені — часте джерело хибнонегативних результатів. Под для налагодження в іншому просторі імен може не розв’язати коротке ім’я, навіть якщо справжній клієнт у просторі імен Сервісу досяг би успіху. І навпаки, повне DNS-ім’я кластера може розв’язатися з діагностичного Под’а, тоді як оригінальний клієнт усе одно падає, бо політика чи відображення портів відрізняються. Узгоджуйте місце тесту з клієнтом, що падає, щоразу, коли завдання дає вам цей контекст.

Terminal window
# From inside a pod (prefer FQDN — busybox nslookup ignores search domains)
kubectl exec POD -- nslookup SERVICE.NAMESPACE.svc.cluster.local
# Create test pod for debugging
kubectl run test --image=busybox --rm -it -- nslookup SERVICE.NAMESPACE.svc.cluster.local

Перевірте з’єднання Сервісу

Розділ «Перевірте з’єднання Сервісу»

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

Terminal window
# From inside a pod
kubectl exec POD -- wget -qO- http://SERVICE:PORT
kubectl exec POD -- curl -s http://SERVICE:PORT

Коли тест Сервісу падає, запишіть, який шар пройшов останнім. Селектор збігся, але ендпоінти порожні — означає готовність чи стан міток. Ендпоінти існували, але DNS упав — означає резолвер чи область імені. DNS розв’язався, але HTTP упав — означає targetPort, слухач, політику чи відповідь застосунку. Цей пошаровий підсумок утримує вас від циклічного перебору тих самих команд після кожного патча.

Пройдіть екзаменаційні сценарії налагодження

Розділ «Пройдіть екзаменаційні сценарії налагодження»

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

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

Сценарій 1: Под не запускається

Розділ «Сценарій 1: Под не запускається»

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

Terminal window
# Step 1: Check status
kubectl get pod broken-pod
# Step 2: Describe for events
kubectl describe pod broken-pod
# Step 3: Check if image exists
# If ErrImagePull: fix image name
# If Pending: check resources/node selector
# Step 4: Check logs if container started
kubectl logs broken-pod

Сценарій 2: Под постійно падає

Розділ «Сценарій 2: Под постійно падає»

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

Terminal window
# Step 1: Get restart count
kubectl get pod crashing-pod
# Step 2: Check previous logs
kubectl logs crashing-pod --previous
# Fallback when --previous is empty (fast crash loops):
kubectl describe pod crashing-pod | grep -A5 "Last State"
# Step 3: Check exit code and termination message
kubectl describe pod crashing-pod | grep -A5 "Last State"
# Step 4: Check liveness probe
kubectl describe pod crashing-pod | grep -A5 Liveness

Сценарій 3: Сервіс недоступний

Розділ «Сценарій 3: Сервіс недоступний»

Збої Сервісу найлегше розв’язувати, коли ви ставитеся до них як до ланцюга зв’язків. Об’єкт Сервісу має існувати, його селектор має збігатися з Под’ами, вибрані Под’и мають бути Ready, ендпоінти мають публікувати адреси бекендів, а клієнт має розв’язати ім’я й під’єднатися до правильного порту. Якщо список ендпоінтів порожній, спершу виправте селектор чи готовність; захоплення пакетів не відремонтує Сервіс, який не вибрав жодного бекенда.

Terminal window
# Step 1: Check service exists
kubectl get svc myservice
# Step 2: Check endpoints
kubectl get endpoints myservice
# Step 3: If no endpoints, check pod labels
kubectl get pods --show-labels
kubectl describe svc myservice | grep Selector
# Step 4: Test from inside cluster
kubectl run test --image=busybox --rm -i -- wget -qO- http://myservice

Ці сценарії також показують, чому шпаргалки команд недостатньо. Та сама команда kubectl describe означає різні речі залежно від того, чи читаєте ви події планувальника, помилки завантаження образу, збої проб чи останній стан завершення. Звичка, яку ви будуєте, — питати “який шар я зараз перевіряю?”, перш ніж набрати наступну команду, а потім перестати читати, щойно докази відповідають на це запитання.

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

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

Патерн: використовуйте драбину доказів, яка рухається від дешевих, широких спостережень до інвазивних, вузьких. Статус і describe дешеві, бо не заходять у контейнер і не змінюють об’єкт; логи вужчі, бо потребують спроби контейнера; а контейнери налагодження інвазивніші, бо додають тимчасовий стан середовища виконання. Цей патерн масштабується, бо працює однаково для одного Под’а, розгортання Deployment та збою Сервісу.

Патерн: порівнюйте задекларований намір зі спостережуваним станом на кожному шарі. Специфікація Под’а декларує образ, ресурси, проби, мітки, порти та монтування томів, тоді як статус і події звітують, що Kubernetes насправді зробив із цими деклараціями. Налагодження стає набагато чіткішим, коли ви формулюєте невідповідність явно: Сервіс декларує селектор app=web, а мітка Под’а — app=api; проба готовності декларує шлях /healthz, а контейнер обслуговує /; запит ресурсів декларує пам’ять, яку вузли не можуть задовольнити.

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

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

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

Антипатерн: використання exec як механізму ремонту створює дрейф, який контролер зітре. Редагування конфігураційного файлу всередині контейнера може на мить зробити один процес виправленим на вигляд, але перепланований Под повернеться до зламаного маніфесту. Використовуйте exec, щоб довести, що файл чи слухач неправильний, а потім патчте ConfigMap, посилання на Secret, команду, аргументи, пробу, селектор Сервісу чи шаблон Deployment, який насправді володіє станом.

Антипатерн: ставитися до збою DNS Сервісу, порожніх ендпоінтів і збою HTTP як до однієї проблеми — марнує час. Вони сидять на різних шарах, і кожен шар має різні докази. Розв’яжіть ім’я, щоб перевірити DNS; огляньте ендпоінти, щоб перевірити селектор і готовність; під’єднайтеся до порту Сервісу, щоб перевірити маршрутизацію й поведінку застосунку. Виправте перший зламаний зв’язок у ланцюгу, перш ніж рухатися глибше.

Антипатерн: копіювання команди з попереднього збою без перевірки поточного стану Под’а робить практику продуктивною на вигляд, водночас послаблюючи судження. Команда може бути дійсною, але дійсність — це не те саме, що доречність. kubectl logs --previous чудовий для циклу аварійних завершень і марний для Под’а, який ніколи не планувався. Краща альтернатива — промовити стан уголос, обрати джерело доказів для цього стану й лише потім запустити знайому команду.

Фреймворк ухвалення рішень

Розділ «Фреймворк ухвалення рішень»

Використовуйте фазу Под’а та стан готовності, щоб обрати першу гілку. Якщо Под у стані Pending, починайте з describe, подій планувальника, запитів ресурсів, міток вузлів, taint’ів, toleration’ів і заявок на томи. Якщо Под у стані очікування з пуллом образу, прочитайте подію завантаження образу й порівняйте посилання на образ, реєстр, тег та imagePullSecrets. Якщо Под у стані Running, але не Ready, прочитайте конфігурацію проб, події проб та ендпоінти, перш ніж тестувати довільні мережеві шляхи.

Використовуйте кількість перезапусків та останній стан завершення, щоб обрати гілку циклу аварійних завершень. Зростаюча кількість перезапусків спрямовує вас до kubectl logs --previous, Last State, коду виходу, причини завершення та подій проби життєздатності. Код виходу 1 зазвичай вказує на збій застосунку чи команди, код виходу 137 часто вказує на SIGKILL чи тиск пам’яті, а код виходу 0 усе одно може бути неправильним, коли контейнер мав бути довготривалим сервером.

Використовуйте членство в ендпоінтах, щоб обрати гілку Сервісу. Порожні ендпоінти означають селектор, готовність чи публікацію ендпоінтів; наявні ендпоінти означають область DNS, targetPort, NetworkPolicy, слухач застосунку чи поведінку відповіді. Який підхід ви обрали б тут і чому: пропатчити селектор Сервісу після виявлення порожніх ендпоінтів і незбіжних міток чи спершу запустити мережевий інструментарій? Патч селектора — кращий перший хід, бо він виправляє перший доведений зламаний зв’язок.

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

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

  • Kubernetes v1.25 позначив ефемерні контейнери як стабільні, тому сучасні кластери Kubernetes 1.35+ можуть використовувати kubectl debug як звичайний інструмент усунення неполадок, а не експериментальну функцію.

  • Код виходу 137 зазвичай тлумачать як 128 плюс сигнал 9, тож він часто вказує на SIGKILL; в описах Kubernetes поєднуйте його з причиною завершення, щоб підтвердити, чи залучено OOMKilled.

  • kubectl logs --previous читає завершений екземпляр контейнера, тому він часто корисніший за поточні логи під час розслідувань CrashLoopBackOff. Коли --previous порожній під час швидких циклів аварійних завершень, читайте Last State із kubectl describe pod натомість.

  • Сервіс із нульовою кількістю ендпоінтів усе одно може мати дійсний ClusterIP, бо членство в ендпоінтах контролюється збігами селектора й готовністю, а не тим, чи існує сам об’єкт Сервісу.

ПомилкаЧому це стаєтьсяЯк це виправити
Випадкове вгадуванняЗламаний Под відкриває багато симптомів, тож здається швидшим пробувати правки, ніж класифікувати шар.Дотримуйтеся робочого процесу: статус, describe, логи, exec чи debug, потім події для ширшого контексту.
Пропуск describeУчні припускають, що логи застосунку містять кожну причину, навіть коли контейнер ніколи не запускався.Читайте умови, стани контейнерів та Events, перш ніж шукати вивід процесу.
Неперевірка --previousCrashLoopBackOff створює свіжий контейнер, тож поточні логи можуть приховувати екземпляр, що зазнав збою.Використовуйте kubectl logs POD --previous; якщо порожньо, читайте Last State за допомогою kubectl describe pod POD | grep -A5 "Last State".
Ігнорування кодів виходуТой самий видимий цикл аварійних завершень може походити від виходу застосунку, OOMKilled чи завершення сигналом.Читайте причину завершення, код виходу, ліміти ресурсів та події проб разом.
Забування про готовністьКонтейнери, що працюють, виглядають справними, навіть коли готовність прибирає кожен бекенд із трафіку.Перевіряйте стовпець READY, події готовності та ендпоінти Сервісу.
Налагодження трафіку Сервісу до перевірки селекторівМережеві тести здаються конкретними, але Сервіс без ендпоінтів не має бекенда для маршрутизації.Порівняйте вивід селектора kubectl describe svc із kubectl get pods --show-labels.
Ставлення до контейнерів налагодження як до постійного виправленняОбраз-інструментарій розв’язує проблеми спостереження, а не конфігурації робочого навантаження.Використовуйте kubectl debug, щоб зібрати докази, а потім патчте відповідний маніфест чи контролер.
Запитання 1: Ваш Под у стані Pending, і `kubectl describe pod` звітує, що жоден із вузлів не має достатньо CPU. Що вам слід діагностувати першим і яка правка найімовірніше допоможе?

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

Запитання 2: Под на ім'я `api-server` у стані CrashLoopBackOff. Поточні логи показують лише новий рядок запуску, але кількість перезапусків зростає. Як ви знайдете справжній збій?

Використовуйте kubectl logs api-server --previous, бо попередній екземпляр контейнера — це той, що завершився. Якщо --previous не повертає логів під час швидкого циклу аварійних завершень, поверніться до kubectl describe pod api-server | grep -A5 "Last State" для причини завершення, коду виходу й terminationMessage. Потім огляньте події проби життєздатності в тому самому виводі describe. Поточні логи можуть бути неповними під час циклу аварійних завершень, бо вони належать найновішій спробі. Виправлення залежить від того, що кажуть докази: помилка застосунку, відсутня конфігурація, OOMKilled, неправильна команда чи агресивна проба.

Запитання 3: Нещодавно розгорнуте робоче навантаження показує ImagePullBackOff, а розробник каже, що образ було завантажено нещодавно. Який доказ відрізняє друкарську помилку від проблеми облікових даних приватного реєстру?

Прочитайте розділ Events із kubectl describe pod, бо kubelet записує відповідь реєстру саме там. Відсутній образ чи тег зазвичай породжує повідомлення в стилі not-found, яке називає посилання, яке Kubernetes намагався завантажити. Проблема приватного реєстру зазвичай показує збій автентифікації чи авторизації, що вказує на imagePullSecrets чи облікові дані реєстру. Не змінюйте селектори Сервісу, проби чи порти, доки образ справді не зможе завантажитися.

Запитання 4: Користувачі не можуть дістатися до застосунку через Сервіс. Под'и у стані Running, але `kubectl get endpoints myservice` повертає жодних адрес. Яка найімовірніша першопричина?

Найімовірніші причини — селектор Сервісу, який не збігається з жодним Под’ом, або готовність, яка виключає вибрані Под’и. Порівняйте селектор Сервісу з kubectl describe svc myservice із фактичними мітками Под’а з kubectl get pods --show-labels, потім перевірте стовпець READY та події готовності. Тести DNS і HTTP — пізніші перевірки, бо порожній список ендпоінтів означає, що Сервіс ще не має членства бекендів. Виправте селектор чи пробу готовності, перш ніж досліджувати маршрутизацію датаплейну.

Запитання 5: Вам потрібно усунути неполадки мережі Сервісу й Под'а з distroless-контейнера застосунку, який не має оболонки чи curl. Под обслуговує трафік і не має перезапускатися. Що вам слід зробити?

Використайте ефемерний контейнер налагодження з образом-інструментарієм або створіть копію для налагодження, якщо вам потрібно експериментувати вільніше. kubectl debug POD -it --image=nicolaka/netshoot --target=container-name дозволяє перевірити DNS і з’єднання з мережевого контексту Под’а без перебудови образу застосунку. Контейнер налагодження призначений для спостереження, а не для постійної частини робочого навантаження. Після того як ви визначите зламаний зв’язок, пропатчте маніфест, Сервіс, пробу чи політику, які володіють проблемою.

Запитання 6: У вас залишилося десять хвилин на екзаменаційне завдання. Deployment існує, Под багаторазово перезапускається, а Сервіс не має придатного бекенда. Як ви впровадите повторюваний робочий процес налагодження, не ганяючись за кожним симптомом?

Спершу класифікуйте стан Под’а за допомогою kubectl get pod -o wide, потім використайте kubectl describe pod, щоб прочитати стан контейнера, Last State, події та проби. Оскільки перезапуски присутні, отримайте kubectl logs --previous, перш ніж покладатися на поточні логи; якщо попередні логи недоступні, використайте kubectl describe pod | grep -A5 "Last State". Щойно Под стане стабільним і Ready, перевірте селектор Сервісу та ендпоінти, щоб підтвердити, що він може отримувати трафік. Ця послідовність відокремлює першопричину аварійного завершення від симптому Сервісу й не дає вам патчити мережу до того, як бекенд стане придатним.

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

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

Terminal window
# Create a broken pod (wrong image)
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: broken1
spec:
containers:
- name: app
image: nginx:nonexistent-tag
EOF
# Create a crashing pod
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: broken2
spec:
containers:
- name: app
image: busybox
command: ['sh', '-c', 'echo "Config not found"; exit 1']
EOF
# Create pod with resource issue
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: broken3
spec:
containers:
- name: app
image: nginx
resources:
requests:
memory: "999Gi"
EOF

Перш ніж щось виправляти, запишіть стан, який показує кожен об’єкт, і першу команду, що має його пояснити. broken1 має спрямувати вас до подій завантаження образу, broken2 має спрямувати вас до попередніх логів та Last State, а broken3 має спрямувати вас до доказів планування чи ресурсів. Цей короткий крок прогнозування — не церемонія; він утримує лабораторну роботу від перетворення на вправу з копіювання та вставлення.

Terminal window
# Debug broken1
kubectl get pod broken1
kubectl describe pod broken1 | tail -10
# Fix: Change image to nginx:latest
kubectl set image pod/broken1 app=nginx:latest
# Verify fix
kubectl wait --for=condition=Ready pod/broken1 --timeout=30s
# Debug broken2
kubectl get pod broken2
# Wait for crashloop to trigger a restart (minimum 10s backoff)
sleep 20
kubectl logs broken2 --previous
# Fallback when --previous is empty (fast crash loops):
kubectl describe pod broken2 | grep -A5 "Last State"
# Fix: Provide correct config by replacing the pod
kubectl delete pod broken2
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: broken2
spec:
containers:
- name: app
image: busybox
command: ['sh', '-c', 'sleep 3600']
EOF
# Verify fix
kubectl wait --for=condition=Ready pod/broken2 --timeout=30s
# Debug broken3
kubectl get pod broken3
kubectl describe pod broken3 | grep -A5 Events
# Fix: Reduce memory request by replacing the pod
kubectl delete pod broken3
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: broken3
spec:
containers:
- name: app
image: nginx
resources:
requests:
memory: "256Mi"
EOF
# Verify fix
kubectl wait --for=condition=Ready pod/broken3 --timeout=30s
Нотатки до розв'язання для зламаних Под'ів

broken1 має показати помилки завантаження образу в Events, тож зміна тегу образу — правильний ремонт. broken2 має показати екземпляр, що зазнав збою, а Под-заміна змінює команду з навмисного збою на довготривалий sleep. broken3 має показати тиск планування від надмірного запиту пам’яті, тож заміна його реалістичним запитом дозволяє планувальнику розмістити Под.

Terminal window
kubectl delete pod broken1 broken2 broken3

Тренувальні вправи

Розділ «Тренувальні вправи»

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

Вправа 1: Describe та події (Ціль: 2 хвилини)

Розділ «Вправа 1: Describe та події (Ціль: 2 хвилини)»
Terminal window
# Create pod
kubectl run drill1 --image=nginx
# Describe it
kubectl describe pod drill1
# Check events
kubectl get events --field-selector involvedObject.name=drill1
# Cleanup
kubectl delete pod drill1

Вправа 2: Exec у Под (Ціль: 2 хвилини)

Розділ «Вправа 2: Exec у Под (Ціль: 2 хвилини)»
Terminal window
# Create pod
kubectl run drill2 --image=nginx
kubectl wait --for=condition=Ready pod/drill2 --timeout=30s
# Exec into it (non-interactive command execution)
kubectl exec drill2 -- nginx -v
# Cleanup
kubectl delete pod drill2

Вправа 3: Налагодження Под’а, що падає (Ціль: 3 хвилини)

Розділ «Вправа 3: Налагодження Под’а, що падає (Ціль: 3 хвилини)»
Terminal window
# Create crashing pod
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: drill3
spec:
containers:
- name: app
image: busybox
command: ['sh', '-c', 'echo error; exit 1']
EOF
# Wait for crash and restart
sleep 20
kubectl get pod drill3
# Get logs from previous
kubectl logs drill3 --previous
# Fallback when --previous is empty:
kubectl describe pod drill3 | grep -A5 "Last State"
# Cleanup
kubectl delete pod drill3

Вправа 4: Налагодження ImagePullBackOff (Ціль: 3 хвилини)

Розділ «Вправа 4: Налагодження ImagePullBackOff (Ціль: 3 хвилини)»
Terminal window
# Create pod with bad image
kubectl run drill4 --image=invalid-registry.io/no-such-image:v1
# Wait for pull failure
sleep 5
# Check status
kubectl get pod drill4
# Describe for details
kubectl describe pod drill4 | grep -A5 Events
# Cleanup
kubectl delete pod drill4

Вправа 5: Налагодження Сервісу (Ціль: 4 хвилини)

Розділ «Вправа 5: Налагодження Сервісу (Ціль: 4 хвилини)»
Terminal window
# Create pod and service with mismatched labels
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: drill5
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
---
apiVersion: v1
kind: Service
metadata:
name: drill5-svc
spec:
selector:
app: wronglabel
ports:
- port: 80
EOF
# Check endpoints (should be empty)
kubectl get endpoints drill5-svc
# Find the problem
kubectl get pod drill5 --show-labels
kubectl describe svc drill5-svc | grep Selector
# Fix by patching service
kubectl patch svc drill5-svc -p '{"spec":{"selector":{"app":"myapp"}}}'
# Verify endpoints now exist
kubectl get endpoints drill5-svc
# Cleanup
kubectl delete pod drill5 svc drill5-svc

Вправа 6: Повний сценарій налагодження (Ціль: 5 хвилин)

Розділ «Вправа 6: Повний сценарій налагодження (Ціль: 5 хвилин)»

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

Terminal window
# Create "broken" deployment
cat << 'EOF' | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: drill6
spec:
replicas: 2
selector:
matchLabels:
app: drill6
template:
metadata:
labels:
app: drill6
spec:
containers:
- name: nginx
image: nginx
readinessProbe:
httpGet:
path: /nonexistent
port: 80
---
apiVersion: v1
kind: Service
metadata:
name: drill6-svc
spec:
selector:
app: drill6
ports:
- port: 80
EOF
# Check pods (running but not ready)
kubectl get pods -l app=drill6
# Check endpoints (empty)
kubectl get endpoints drill6-svc
# Describe pod for probe failure
kubectl describe pod -l app=drill6 | grep -A5 Readiness
# Fix readiness probe
kubectl patch deploy drill6 --type='json' -p='[{"op":"replace","path":"/spec/template/spec/containers/0/readinessProbe/httpGet/path","value":"/"}]'
# Wait for rollout
kubectl rollout status deploy drill6
# Verify endpoints
kubectl get endpoints drill6-svc
# Cleanup
kubectl delete deploy drill6 svc drill6-svc
Нотатки до розв'язання для вправ із Сервісом

Вправа 5 — це проблема селектора, тож порожні ендпоінти мають привести вас до порівняння селектора Сервісу з мітками Под’а. Вправа 6 — це проблема готовності, тож Deployment створює Под’и, але Сервіс не отримує готових бекендів, доки шлях проби не виправлено. В обох вправах перевірка ендпоінтів — це доказ того, що зв’язок Сервісу змінився.

  • Діагностувати збої Под’ів, фіксуючи статус, події, логи та вивід describe перед редагуванням.
  • Налагодити CrashLoopBackOff за допомогою kubectl logs --previous, повертаючись до Last State у describe, коли попередні логи недоступні.
  • Налагодити ImagePullBackOff, читаючи події завантаження образу й виправляючи лише посилання на образ.
  • Діагностувати Pending, читаючи події планування чи ресурсів перед пошуком логів.
  • Усунути неполадки мережі Сервісу й Под’а, порівнюючи селектори, мітки, готовність, ендпоінти та DNS.
  • Впровадити повторюваний робочий процес налагодження без використання аліасів оболонки чи ручних ремонтів усередині контейнера.

Перевірка засвоєного

Розділ «Перевірка засвоєного»

Перш ніж рухатися далі, переконайтеся, що можете пояснити ці пункти ремедіації власними словами:

Busybox nslookup не розгортає шлях search у /etc/resolv.conf так, як це роблять glibc чи netshoot, тож пошук за коротким іменем часто повертає NXDOMAIN на Kubernetes 1.35, навіть коли DNS кластера справний — і команда може завершитися з ненульовим кодом, навіть надрукувавши корисний рядок Address:.

Прапорець --target приєднує контейнер налагодження до наявного контейнера й розділяє простір імен процесів цієї цілі, тому ps aux може бачити процеси застосунку. Прапорець --share-processes застосовується лише з --copy-to; на звичайному приєднанні налагодження через --target він не має ефекту.

На kind та інших кластерах на базі containerd kubectl logs --previous може повернути unable to retrieve container logs під час дуже швидких циклів аварійних завершень, бо завершений екземпляр ще не збережено.

Модуль 3.4: Моніторинг застосунків — моніторте справність застосунку та використання ресурсів після того, як уже вмієте діагностувати збої Под’ів, Сервісів, готовності та середовища виконання за прямими доказами Kubernetes.