Модуль 3.3: Налагодження в Kubernetes
Складність:
[MEDIUM]— Критична навичка для іспиту, що вимагає системного підходуЧас на виконання: 45–55 хвилин
Передумови: Модуль 3.1 (Проби), Модуль 3.2 (Логування)
Що ви зможете робити
Розділ «Що ви зможете робити»Після завершення цього модуля ви зможете:
- Діагностувати збої Підів систематично, використовуючи події, логи, describe та exec
- Діагностувати стани CrashLoopBackOff, ImagePullBackOff та Pending під тиском часу
- Діагностувати проблеми мережі між Підами за допомогою тимчасових контейнерів для зневадження
- Реалізувати повторюваний процес зневадження: статус, події, логи, exec, мережа
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Налагодження — це те, де виграється або програється іспит. Коли щось не працює, вам потрібен системний підхід, щоб швидко знайти проблему. Іспит CKAD навмисно включає зламані конфігурації — ви повинні діагностувати та виправити їх під тиском часу.
Цей модуль охоплює:
- Налагодження подів, що не запускаються
- Налагодження працюючих подів з проблемами
- Використання ефемерних контейнерів для налагодження
- Системний процес налагодження
Аналогія з детективом
Налагодження — це робота детектива. Ви прибуваєте на місце злочину (зламаний під) і мусите знайти улики. Ви перевіряєте історію жертви (
describe), досліджуєте докази (logs), допитуєте свідків (events) і іноді потрібно діяти під прикриттям (exec), щоб зловити злочинця. Системне розслідування перемагає випадкові здогадки.
Процес налагодження
Розділ «Процес налагодження»┌─────────────────────────────────────────────────────────────┐│ Системний процес налагодження │├─────────────────────────────────────────────────────────────┤│ ││ 1. ПЕРЕВІРИТИ СТАТУС ││ k get pod POD -o wide ││ └── Який стан? Ready? Перезапуски? Вузол? ││ ││ 2. ОПИСАТИ ││ k describe pod POD ││ └── Події? Умови? Стан контейнера? ││ ││ 3. ЛОГИ ││ k logs POD [--previous] ││ └── Що сказав застосунок? Помилки? ││ ││ 4. ВИКОНАТИ КОМАНДУ ││ k exec -it POD -- sh ││ └── Що всередині? Файли? Процеси? Мережа? ││ ││ 5. ПОДІЇ ││ k get events --sort-by='.lastTimestamp' ││ └── Що відбулося на рівні кластера? ││ │└─────────────────────────────────────────────────────────────┘Команди для налагодження
Розділ «Команди для налагодження»Швидка перевірка статусу
Розділ «Швидка перевірка статусу»# Огляд стану подаk get pod POD -o wide
# Усі поди в просторі іменk get pods
# Спостерігати за змінамиk get pods -wDescribe для деталей
Розділ «Describe для деталей»# Повні деталі подаk describe pod POD
# Ключові розділи для перевірки:# - Status/Conditions# - Containers (State, Ready, Restart Count)# - Events (внизу виводу)Перегляд логів
Розділ «Перегляд логів»# Поточні логиk logs POD
# Попередній екземпляр (після падіння)k logs POD --previous
# Конкретний контейнерk logs POD -c CONTAINER
# Потокові логиk logs -f PODВиконання команд
Розділ «Виконання команд»# Інтерактивна оболонкаk exec -it POD -- shk exec -it POD -- /bin/bash
# Виконати одну командуk exec POD -- ls /appk exec POD -- cat /etc/config
# Конкретний контейнерk exec -it POD -c CONTAINER -- shПерегляд подій
Розділ «Перегляд подій»# Події простору імен (відсортовані за часом)k get events --sort-by='.lastTimestamp'
# Фільтр за типомk get events --field-selector type=Warning
# Події для конкретного подаk get events --field-selector involvedObject.name=PODТипові стани подів та їх виправлення
Розділ «Типові стани подів та їх виправлення»Pending
Розділ «Pending»Під застряг у стані Pending.
# Перевірити причинуk describe pod POD
# Типові причини:# 1. Недостатньо ресурсів# → Перевірити ресурси вузла: k describe node# → Зменшити запити ресурсів пода
# 2. Немає відповідного вузла (nodeSelector/affinity)# → Перевірити мітки вузлів: k get nodes --show-labels# → Виправити селектор або додати мітки вузлам
# 3. PVC не прив'язаний# → Перевірити PVC: k get pvc# → Створити відповідний PVImagePullBackOff / ErrImagePull
Розділ «ImagePullBackOff / ErrImagePull»Не вдається завантажити образ контейнера.
# Перевірити подіїk describe pod POD | grep -A5 Events
# Типові причини:# 1. Неправильна назва/тег образу# → Виправити образ у специфікації пода
# 2. Приватний реєстр без облікових даних# → Створити imagePullSecret
# 3. Образ не існує# → Перевірити наявність образу в реєстріCrashLoopBackOff
Розділ «CrashLoopBackOff»Контейнер постійно падає.
# Перевірити логи екземпляра, що впавk logs POD --previous
# Перевірити код виходуk describe pod POD | grep "Last State"
# Типові причини:# 1. Помилка застосунку (перевірте логи)# 2. Відсутня конфігурація/секрети# 3. Неправильна команда/аргументи# 4. Проба liveness вбиває справний застосунокRunning, але Not Ready
Розділ «Running, але Not Ready»Контейнер працює, але readiness не проходить.
# Перевірити пробу readinessk describe pod POD | grep -A5 Readiness
# Перевірити ендпоінтиk get endpoints SERVICE
# Типові причини:# 1. Неправильний шлях/порт проби readiness# 2. Застосунок не повністю запустився# 3. Залежність недоступнаНалагодження всередині контейнерів
Розділ «Налагодження всередині контейнерів»Базові команди
Розділ «Базові команди»# Отримати оболонкуk exec -it POD -- sh
# Перевірити процесиk exec POD -- ps aux
# Перевірити мережуk exec POD -- netstat -tlnpk exec POD -- ss -tlnp
# Перевірити DNSk exec POD -- nslookup kubernetesk exec POD -- cat /etc/resolv.conf
# Перевірити з'єднанняk exec POD -- wget -qO- http://service:portk exec POD -- curl -s http://service:port
# Перевірити файлиk exec POD -- ls -la /appk exec POD -- cat /etc/config/fileКоли оболонка недоступна
Розділ «Коли оболонка недоступна»Деякі контейнери (distroless, scratch) не мають оболонки:
# Перевірити наявність оболонкиk exec POD -- /bin/sh -c 'echo works'
# Якщо оболонки немає, використайте debug-контейнер (Kubernetes 1.25+)k debug POD -it --image=busybox --target=container-nameЕфемерні контейнери для налагодження
Розділ «Ефемерні контейнери для налагодження»Kubernetes 1.25+ підтримує ефемерні контейнери для налагодження:
# Додати debug-контейнер до працюючого подаk debug POD -it --image=busybox --target=container-name
# Налагодження з конкретним образомk debug POD -it --image=nicolaka/netshoot
# Скопіювати під для налагодження (не впливає на оригінал)k debug POD -it --copy-to=debug-pod --container=debug --image=busyboxВипадки використання debug-контейнерів
Розділ «Випадки використання debug-контейнерів»# Налагодження мережі (немає curl в оригінальному контейнері)k debug POD -it --image=nicolaka/netshoot --target=app# Потім: curl, dig, nslookup, tcpdump
# Інспекція файлової системиk debug POD -it --image=busybox --target=app# Потім: ls, cat, find
# Налагодження процесівk debug POD -it --image=busybox --target=app --share-processes# Потім: ps auxНалагодження Service
Розділ «Налагодження Service»Перевірка з’єднання Service-Під
Розділ «Перевірка з’єднання Service-Під»# Перевірити існування сервісуk get svc SERVICE
# Перевірити ендпоінти (повинні містити IP подів)k get endpoints SERVICE
# Якщо ендпоінтів немає:# - Перевірте, чи мітки подів відповідають селектору сервісу# - Перевірте readiness подаk get pods --show-labelsk describe svc SERVICE | grep SelectorПеревірка DNS сервісу
Розділ «Перевірка DNS сервісу»# Зсередини подаk exec POD -- nslookup SERVICEk exec POD -- nslookup SERVICE.NAMESPACE.svc.cluster.local
# Створити тестовий під для налагодженняk run test --image=busybox --rm -it -- nslookup SERVICEПеревірка з’єднання з сервісом
Розділ «Перевірка з’єднання з сервісом»# Зсередини подаk exec POD -- wget -qO- http://SERVICE:PORTk exec POD -- curl -s http://SERVICE:PORTСценарії налагодження
Розділ «Сценарії налагодження»Сценарій 1: Під не запускається
Розділ «Сценарій 1: Під не запускається»# Крок 1: Перевірити статусk get pod broken-pod
# Крок 2: Describe для подійk describe pod broken-pod
# Крок 3: Перевірити, чи існує образ# Якщо ErrImagePull: виправити назву образу# Якщо Pending: перевірити ресурси/nodeSelector
# Крок 4: Перевірити логи, якщо контейнер запустивсяk logs broken-podСценарій 2: Під постійно падає
Розділ «Сценарій 2: Під постійно падає»# Крок 1: Отримати кількість перезапусківk get pod crashing-pod
# Крок 2: Перевірити попередні логиk logs crashing-pod --previous
# Крок 3: Перевірити код виходуk describe pod crashing-pod | grep -A3 "Last State"
# Крок 4: Перевірити пробу livenessk describe pod crashing-pod | grep -A5 LivenessСценарій 3: Service недоступний
Розділ «Сценарій 3: Service недоступний»# Крок 1: Перевірити існування сервісуk get svc myservice
# Крок 2: Перевірити ендпоінтиk get endpoints myservice
# Крок 3: Якщо ендпоінтів немає, перевірити мітки подівk get pods --show-labelsk describe svc myservice | grep Selector
# Крок 4: Перевірити зсередини кластераk run test --image=busybox --rm -it -- wget -qO- http://myserviceЧи знали ви?
Розділ «Чи знали ви?»-
kubectl debugстворює ефемерні контейнери, що поділяють мережевий простір і простір процесів пода. Це означає, що ви можете бачити мережеві з’єднання та процеси з debug-контейнера. -
Код виходу 137 означає OOMKilled (Out of Memory). Контейнер було вбито, бо він перевищив ліміт пам’яті.
-
Код виходу 1 — це загальна помилка, зазвичай від самого застосунку. Перевірте логи для деталей.
-
Код виходу 0 означає успіх — але якщо контейнер завершився з кодом 0 і не повинен був, це все одно проблема (неправильна команда).
Типові помилки
Розділ «Типові помилки»| Помилка | Чому це шкодить | Рішення |
|---|---|---|
| Випадкові здогадки | Витрачає час на іспиті | Дотримуйтеся системного процесу |
Пропуск describe | Пропуск очевидних подій | Завжди перевіряйте події першими |
Не перевіряєте --previous | Пропуск логів падіння | Перевіряйте попередній екземпляр при CrashLoop |
| Ігнорування кодів виходу | Пропуск OOM/сигнальних проблем | Перевіряйте Last State в describe |
| Забули про readiness | Під працює, але без трафіку | Перевірте ендпоінти та проби |
Тест
Розділ «Тест»-
Яка команда показує логи попереднього екземпляра контейнера, що впав?
Відповідь
`kubectl logs POD --previous` або `kubectl logs POD -p` -
Як отримати події, відсортовані за часовою міткою?
Відповідь
`kubectl get events --sort-by='.lastTimestamp'` -
Що зазвичай означає код виходу 137?
Відповідь
OOMKilled — контейнер перевищив свій ліміт пам'яті і був вбитий ядром. -
Як додати ефемерний debug-контейнер до працюючого пода?
Відповідь
`kubectl debug POD -it --image=busybox --target=container-name`
Практична вправа
Розділ «Практична вправа»Завдання: Відлагодити та виправити зламані поди.
Підготовка:
# Створити зламаний під (неправильний образ)cat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: broken1spec: containers: - name: app image: nginx:nonexistent-tagEOF
# Створити під, що падаєcat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: broken2spec: containers: - name: app image: busybox command: ['sh', '-c', 'echo "Config not found"; exit 1']EOF
# Створити під з проблемою ресурсівcat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: broken3spec: containers: - name: app image: nginx resources: requests: memory: "999Gi"EOFНалагодження кожного:
# Налагодити broken1k get pod broken1k describe pod broken1 | tail -10# Виправлення: Змінити образ на nginx:latest
# Налагодити broken2k get pod broken2k logs broken2 --previous# Виправлення: Надати правильну конфігурацію
# Налагодити broken3k get pod broken3k describe pod broken3 | grep -A5 Events# Виправлення: Зменшити запит пам'ятіОчищення:
k delete pod broken1 broken2 broken3Практичні вправи
Розділ «Практичні вправи»Вправа 1: Describe та події (Ціль: 2 хвилини)
Розділ «Вправа 1: Describe та події (Ціль: 2 хвилини)»# Створити підk run drill1 --image=nginx
# Описати йогоk describe pod drill1
# Перевірити подіїk get events --field-selector involvedObject.name=drill1
# Очищенняk delete pod drill1Вправа 2: Exec в під (Ціль: 2 хвилини)
Розділ «Вправа 2: Exec в під (Ціль: 2 хвилини)»# Створити підk run drill2 --image=nginx
# Зайти в ньогоk exec -it drill2 -- bash
# Всередині: перевірити, що nginx працюєps aux | grep nginxexit
# Очищенняk delete pod drill2Вправа 3: Налагодження пода, що падає (Ціль: 3 хвилини)
Розділ «Вправа 3: Налагодження пода, що падає (Ціль: 3 хвилини)»# Створити під, що падаєcat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: drill3spec: containers: - name: app image: busybox command: ['sh', '-c', 'echo error; exit 1']EOF
# Зачекати на падінняk get pod drill3 -w
# Отримати логи попереднього екземпляраk logs drill3 --previous
# Очищенняk delete pod drill3Вправа 4: Налагодження ImagePullBackOff (Ціль: 3 хвилини)
Розділ «Вправа 4: Налагодження ImagePullBackOff (Ціль: 3 хвилини)»# Створити під з неправильним образомk run drill4 --image=invalid-registry.io/no-such-image:v1
# Перевірити статусk get pod drill4
# Describe для деталейk describe pod drill4 | grep -A5 Events
# Очищенняk delete pod drill4Вправа 5: Налагодження Service (Ціль: 4 хвилини)
Розділ «Вправа 5: Налагодження Service (Ціль: 4 хвилини)»# Створити під і сервіс з невідповідними міткамиcat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: drill5 labels: app: myappspec: containers: - name: nginx image: nginx---apiVersion: v1kind: Servicemetadata: name: drill5-svcspec: selector: app: wronglabel ports: - port: 80EOF
# Перевірити ендпоінти (мають бути порожні)k get endpoints drill5-svc
# Знайти проблемуk get pod drill5 --show-labelsk describe svc drill5-svc | grep Selector
# Виправити через patch сервісуk patch svc drill5-svc -p '{"spec":{"selector":{"app":"myapp"}}}'
# Перевірити, що ендпоінти з'явилисяk get endpoints drill5-svc
# Очищенняk delete pod drill5 svc drill5-svcВправа 6: Повний сценарій налагодження (Ціль: 5 хвилин)
Розділ «Вправа 6: Повний сценарій налагодження (Ціль: 5 хвилин)»Сценарій: Застосунок розгорнуто, але він недоступний.
# Створити «зламаний» deploymentcat << 'EOF' | k apply -f -apiVersion: apps/v1kind: Deploymentmetadata: name: drill6spec: replicas: 2 selector: matchLabels: app: drill6 template: metadata: labels: app: drill6 spec: containers: - name: nginx image: nginx readinessProbe: httpGet: path: /nonexistent port: 80---apiVersion: v1kind: Servicemetadata: name: drill6-svcspec: selector: app: drill6 ports: - port: 80EOF
# Перевірити поди (працюють, але не готові)k get pods -l app=drill6
# Перевірити ендпоінти (порожні)k get endpoints drill6-svc
# Describe пода для невдачі пробиk describe pod -l app=drill6 | grep -A5 Readiness
# Виправити пробу readinessk patch deploy drill6 --type='json' -p='[{"op":"replace","path":"/spec/template/spec/containers/0/readinessProbe/httpGet/path","value":"/"}]'
# Зачекати на розгортанняk rollout status deploy drill6
# Перевірити ендпоінтиk get endpoints drill6-svc
# Очищенняk delete deploy drill6 svc drill6-svcНаступний модуль
Розділ «Наступний модуль»Модуль 3.4: Моніторинг застосунків — Моніторинг стану застосунків та використання ресурсів.