Модуль 5.7: Логування та моніторинг
Складність:
[СЕРЕДНЯ]— базові навички спостережуваності.Час на проходження: 40–50 хвилин.
Передумови: Модуль 5.1 (Методологія), Модулі 5.2–5.6 (конкретні випадки усунення несправностей).
Що ви зможете зробити
Розділ «Що ви зможете зробити»Після цього модуля ви зможете:
- Діагностувати журнали контейнерів за допомогою
kubectl logs, використовуючи вибір контейнера, попередні журнали, режим стеження, мітки часу та селектори за лейблами. - Оцінювати події Kubernetes, щоб діагностувати збої планування, монтування, проб, перезапусків та витіснення, перш ніж сплине час зберігання подій.
- Впроваджувати логування на основі sidecar для застосунків, які пишуть у файли замість
stdoutтаstderr. - Спостерігати за використанням ресурсів через
kubectl top, пояснюючи, як Metrics Server переносить метрики kubelet до APImetrics.k8s.io. - Співвідносити журнали на рівні ноди, журнали контейнерів, події та метрики, щоб обрати наступну діагностичну дію під час сесії усунення несправностей у Kubernetes 1.35.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Hypothetical scenario: Деплоймент розгортається під час релізного вікна, нові Pod’и чергують між станами Running та CrashLoopBackOff, команда застосунку каже, що їхній endpoint справності пройшов перевірку в staging, а команда платформи не бачить очевидного збою ноди. У цей момент корисне питання — не «де журнали?», а «яке джерело доказів усе ще може відповісти на поточне питання?». Журнали контейнера можуть показати виняток, попередні журнали контейнера можуть показати рядок безпосередньо перед перезапуском, події можуть показати збій завантаження образу або проби, а метрики ресурсів можуть показати, що Pod дроселюється (throttling) або вбивається під тиском.
Логування та моніторинг у Kubernetes навмисно розділені на шари, тому що жоден окремий API не може розповісти всю історію. Kubelet захоплює stdout та stderr контейнера, API server зберігає короткочасні події, Metrics Server відкриває нещодавні вимірювання CPU та пам’яті, а служби ноди, такі як kubelet та containerd, ведуть власні журнали. Сильний фахівець з усунення несправностей рухається крізь ці шари послідовністю гіпотез, а не вдивляється в один шумний потік журналів, сподіваючись, що важливий рядок з’явиться.
Цей модуль перетворює швидкі команди з попередніх уроків з усунення несправностей на операційний робочий процес. Ви попрактикуєтеся читати поточні та попередні журнали контейнерів, інтерпретувати події, перевіряти метрики ресурсів, використовувати sidecar для файлових журналів та повертатися до журналів ноди, коли API Kubernetes недоступний або неповний. Суть не в тому, щоб запам’ятати кожен прапорець; суть у тому, щоб знати, який спостережуваний об’єкт усе ще може містити докази, чого кожен інструмент показати не може, і як звузити збій, не вигадуючи історію.
Журнали контейнерів: поточні, попередні та докази з кількох контейнерів
Розділ «Журнали контейнерів: поточні, попередні та докази з кількох контейнерів»Логування в Kubernetes починається з простого контракту: застосунки мають писати корисний діагностичний вивід у stdout та stderr, а нода зробить цей вивід доступним через kubelet. Середовище виконання контейнерів записує потік у файли журналів на ноді, kubelet відкриває ці файли через свій API, а kubectl logs отримує вміст через шлях API Kubernetes. Такий дизайн тримає контейнери застосунків простими, але це також означає, що рядок журналу прив’язаний до екземпляра контейнера, а не до Деплойменту, Сервісу чи довготривалого бізнес-процесу.
┌──────────────────────────────────────────────────────────────┐│ CONTAINER LOGGING FLOW ││ ││ Container ││ ┌────────────────────────────────────────────────────┐ ││ │ Application │ ││ │ │ │ ││ │ ├── stdout ──────┐ │ ││ │ │ │ │ ││ │ └── stderr ──────┼────▶ Container runtime │ ││ │ │ captures output │ ││ └────────────────────────────────────────────────────┘ ││ │ ││ ▼ ││ Node filesystem ││ /var/log/containers/<pod>_<ns>_<container>-<id>.log ││ │ ││ ▼ ││ kubectl logs (reads these files via kubelet API) ││ │└──────────────────────────────────────────────────────────────┘Практичний наслідок полягає в тому, що перша команда журналів, яку ви запускаєте, має відповідати режиму збою, який ви перевіряєте. Стабільний Pod з одним контейнером зазвичай можна оглянути напряму, тоді як перезапущений контейнер часто потребує --previous, а Pod з кількома контейнерами потребує явного вибору контейнера. Якщо ви пропустите цей вибір, ви можете оглянути не той потік і побудувати хибну діагностику, особливо коли sidecar, init-контейнер чи пересилач журналів є компонентом, який насправді відмовляє.
# View logs from a pod (single container)kubectl logs <pod>
# View logs from specific container (multi-container pod)kubectl logs <pod> -c <container>
# Follow logs in real-timekubectl logs <pod> -f
# Show last N lineskubectl logs <pod> --tail=50
# Show logs since timekubectl logs <pod> --since=1hkubectl logs <pod> --since=30m
# Show logs with timestampskubectl logs <pod> --timestamps
# Combine optionskubectl logs <pod> --tail=100 --timestamps -fЗробіть паузу й передбачте: якщо Pod має два контейнери, а ви запускаєте kubectl logs <pod> без -c, який вивід ви очікуєте від Kubernetes отримати, і який ризик це створює для вашого розслідування? Важлива звичка — питати, з якої межі об’єкта читає команда. Pod є одиницею планування, але журнали належать контейнерам усередині цього Pod’а, тож команда, яка не називає контейнер, може бути неоднозначною, коли існує більше одного потоку.
Pod’и з кількома контейнерами поширені у production навіть тоді, коли сам застосунок здається простим. Проксі service mesh, процес, що відстежує файли, помічник автентифікації чи експортер метрик — усі можуть жити поряд з основним застосунком і відмовляти незалежно. Коли симптом стосується трафіку, логування, порядку запуску чи спільних томів, огляньте перелік контейнерів, перш ніж припускати, що контейнер застосунку є єдиним корисним джерелом доказів.
# List containers in a podkubectl get pod <pod> -o jsonpath='{.spec.containers[*].name}'
# Get logs from specific containerkubectl logs <pod> -c <container>
# Get logs from all containerskubectl logs <pod> --all-containers=true
# Get logs from init containerskubectl logs <pod> -c <init-container>Попередні журнали контейнера є необхідними для CrashLoopBackOff, тому що поточний екземпляр контейнера може ще не дійти до проблемного шляху коду. kubectl logs <pod> за замовчуванням читає активний екземпляр, тож він може показати лише банер запуску, тоді як корисне трасування стека прив’язане до екземпляра, який помер мить тому. Прапорець --previous змінює ціль з поточного контейнера на останній завершений екземпляр, що часто є різницею між тим, щоб побачити «starting application», і тим, щоб побачити виняток, який спричинив перезапуск.
# Get logs from previous container instance (after crash)kubectl logs <pod> --previouskubectl logs <pod> -c <container> --previous
# This shows what was logged before the container died# Essential for understanding why it crashedФайлове логування — незручний випадок, тому що Kubernetes автоматично не збирає довільні файли всередині файлової системи контейнера. Застарілий процес, який пише лише в /var/log/app.log, може бути цілком балакучим з погляду застосунку й цілковито мовчазним з погляду kubectl logs. Звичним містком є sidecar-контейнер, який ділить том із застосунком, відстежує файл командою tail і пише той самий вміст у власний stdout, де kubelet може захопити його у звичайний спосіб.
apiVersion: v1kind: Podmetadata: name: legacy-appspec: containers: - name: main-app image: legacy-app:1.0 volumeMounts: - name: shared-logs mountPath: /var/log - name: log-tailer image: busybox:1.36 command: ["/bin/sh", "-c", "touch /var/log/app.log 2>/dev/null; tail -n+1 -F /var/log/app.log"] volumeMounts: - name: shared-logs mountPath: /var/log volumes: - name: shared-logs emptyDir: {}Потім ви можете переглянути журнали, запитавши sidecar командою kubectl logs legacy-app -c log-tailer. Цей патерн корисний, коли ви не можете швидко змінити застосунок, але він має компроміси: sidecar споживає ресурси, спільний emptyDir є локальним для ноди й ефемерним, а наївний tail -f може пропустити поведінку ротації, якщо застосунок і sidecar не узгодять обробку файлів. Ставтеся до нього як до патерну сумісності, а не як до приводу ігнорувати сучасні практики stdout та структурованого логування.
Вибір журналів за лейблами та контролером допомагає, коли проблемна поведінка існує в усіх репліках. Звичайна kubectl logs deployment/<name> слідує за зв’язком з контролером, але стрімить журнали лише з одного представницького Pod’а в цьому Деплойменті; додайте --all-pods=true, коли вам потрібна кожна репліка. kubectl logs -l app=nginx обирає Pod’и за лейблами, що корисно, коли Деплоймент, StatefulSet чи Job створили кілька Pod’ів зі спільним симптомом. Ці команди зручні, але вони також можуть давати переплетений вивід, тож поєднуйте їх із мітками часу, іменами контейнерів і невеликим --tail, коли намагаєтеся відтворити хронологію.
# Logs from all pods with a labelkubectl logs -l app=nginx
# Logs from all pods in a deployment (--all-pods=true required)kubectl logs deployment/my-deployment --all-pods=true
# Follow logs from all matching podskubectl logs -l app=nginx -f
# With container name for multi-container podskubectl logs -l app=nginx -c <container>Перш ніж запускати це, який вивід ви очікуєте, якщо один обраний Pod усе ще pending, а інший уже running? Команда може повернути журнали лише для контейнерів, які виробили журнали, тож відсутність виводу не завжди є доказом того, що застосунок мовчить. Це може означати, що контейнер так і не запустився, було обрано не той Простір імен, лейбл відповідав меншій кількості Pod’ів, ніж очікувалося, або корисні докази живуть у подіях, а не в журналах.
Події Kubernetes: короткочасні підказки з площини управління
Розділ «Події Kubernetes: короткочасні підказки з площини управління»Події — це об’єкти Kubernetes, які фіксують помітні зміни стану та операційні попередження. Вони не є журналами застосунку й не є постійним аудиторським слідом; це короткочасні підказки, які виробляють такі компоненти, як планувальник, kubelet, контролери та API server. Під час усунення несправностей події зазвичай є першим місцем для перегляду, коли Pod перебуває у стані pending, не може змонтувати том, провалює пробу, повільно завантажує образ, витісняється чи перезапускається до того, як застосунок встигне записати корисні журнали.
┌──────────────────────────────────────────────────────────────┐│ KUBERNETES EVENTS ││ ││ Events are generated by: ││ • Scheduler (scheduling decisions) ││ • kubelet (container lifecycle) ││ • Controllers (resource management) ││ • API server (API operations) ││ ││ Event Types: ││ • Normal: Informational, things working as expected ││ • Warning: Something unexpected, might need attention ││ ││ Important: Events expire after ~1 hour by default! ││ │└──────────────────────────────────────────────────────────────┘Найважливіше обмеження — це час зберігання. Стандартний TTL подій API server становить одну годину (--event-ttl на kube-apiserver), що означає, що події призначені для діагностики майже в реальному часі, а не для розслідувань вихідного дня. Якщо пакетне завдання провалилося два дні тому й конвеєра експорту подій не існує, kubectl get events може правдиво нічого не повернути, навіть якщо Kubernetes свого часу видавав корисні попередження. Саме тому production-стеки спостережуваності часто відправляють події до журнальної платформи чи спеціалізованого збирача подій, перш ніж API server збере їх як сміття.
# All events in current namespacekubectl get events
# All events cluster-widekubectl get events -A
# Sort by time (most recent last)kubectl get events --sort-by='.lastTimestamp'
# Sort by time (most recent first)kubectl get events --sort-by='.lastTimestamp' | tac
# Filter by typekubectl get events --field-selector type=Warning
# Events for specific objectkubectl get events --field-selector involvedObject.name=<pod-name>
# Watch events in real-timekubectl get events -wЗробіть паузу й передбачте: якщо Pod було створено три дні тому й він перезапускається відтоді, які події ще можуть бути присутніми, а які ранні події, ймовірно, зникли? Вам слід очікувати, що нещодавні події перезапуску, backoff, проб чи образу будуть доступні, якщо вони все ще видаються, але початкові події планування та створення можуть застаріти. Стовпець віку — теж доказ; він каже вам, чи дивитеся ви на початок інциденту, чи лише на найновіше повторення.
| Reason | Type | Що це означає |
|---|---|---|
| Scheduled | Normal | Pod призначено ноді |
| Pulled | Normal | Образ успішно завантажено |
| Created | Normal | Контейнер створено |
| Started | Normal | Контейнер запущено |
| Killing | Normal | Контейнер завершується |
| FailedScheduling | Warning | Не вдалося знайти придатну ноду |
| FailedMount | Warning | Монтування тому провалилося |
| Unhealthy | Warning | Проба провалилася |
| BackOff | Warning | Контейнер падає, відкладається |
| FailedCreate | Warning | Контролер не зміг створити Pod |
| Evicted | Warning | Pod витіснено з ноди |
| OOMKilling | Warning | Контейнер убито через OOM |
kubectl describe залишається цінним, тому що він розміщує стан об’єкта, конфігурацію та пов’язані події в одному вигляді. Для Pod’а у стані pending розділ Events часто каже вам, чи бракувало планувальнику CPU, пам’яті, відповідних лейблів ноди, толерантностей чи прив’язаного тому. Для running, але нездорового Pod’а вивід describe може пов’язати налаштування проб з подіями Unhealthy, показуючи, чи спричинений цикл перезапусків падіннями застосунку, чи тим, що kubelet убиває контейнер, який провалює перевірки liveness.
# Events appear in describe outputkubectl describe pod <pod># Look for the Events section at the bottom
kubectl describe node <node># Shows node-level events
kubectl describe pvc <pvc># Shows volume binding eventsПодії та журнали відповідають на різні питання. Журнали кажуть вам, що процес записав зсередини контейнера, тоді як події кажуть вам, що компоненти Kubernetes спостерегли ззовні цього процесу. Pod у стані pending не має корисних журналів застосунку, тому що контейнер не запустився, але він може мати багаті події планування. Pod, що падає, може мати обидва: події можуть показати поведінку перезапуску та backoff, тоді як попередні журнали пояснюють, що процес робив до завершення.
Метрики ресурсів: kubectl top, Metrics Server та сигнали тиску
Розділ «Метрики ресурсів: kubectl top, Metrics Server та сигнали тиску»Метрики ресурсів — це нещодавні вимірювання використання CPU та пам’яті, а не історичні графіки й не планування ємності саме по собі. У кластері Kubernetes 1.35 kubectl top спілкується з API metrics.k8s.io, який зазвичай обслуговує Metrics Server. Metrics Server опитує endpoint ресурсів kubelet на кожній ноді, агрегує поточне використання та відкриває легкий API, який підтримує швидкі операційні перевірки та вхідні дані для автомасштабування, але це не повноцінна база даних моніторингу.
┌──────────────────────────────────────────────────────────────┐│ METRICS SERVER ││ ││ Nodes Metrics Server ││ ┌───────────────────┐ ┌──────────────┐ ││ │ kubelet │───│ Collects │ ││ │ /metrics/resource │ │ aggregates │ ││ └───────────────────┘ │ exposes │ ││ └──────┬───────┘ ││ │ ││ metrics.k8s.io API ││ │ ││ ▼ ││ kubectl top ││ ││ Without Metrics Server → kubectl top fails ││ │└──────────────────────────────────────────────────────────────┘Оскільки kubectl top залежить від агрегованого API, його збій не означає автоматично, що нода перестала вимірювати ресурси. Це може означати, що Metrics Server не встановлено, реєстрація APIService недоступна, автентифікація TLS чи kubelet відмовляє, або RBAC блокує запит. Найшвидша перевірка — оглянути Pod Metrics Server та реєстрацію APIService, перш ніж ганятися за лімітами ресурсів застосунку.
# Check if Metrics Server is installedkubectl -n kube-system get pods | grep metrics-server
# Check metrics APIkubectl get apiservices | grep metrics
# If not installed, top commands will failkubectl top nodes # Error: Metrics API not availablekubectl top навмисно малий та миттєвий. Він допомагає вам визначити гарячі Pod’и, порівняти ноди та вирішити, чи може збій бути спричинений тиском пам’яті, дроселюванням CPU чи екстремальним дисбалансом. Він не каже вам, що сталося минулої ночі, і не замінює Prometheus, OpenTelemetry чи вендорну платформу моніторингу для довгострокового аналізу трендів. Використовуйте його як швидкий інструмент поточного стану під час діагностики, особливо на іспиті CKA, де вбудовані інструменти мають значення.
# Node resource usagekubectl top nodes
# Pod resource usage (current namespace)kubectl top pods
# Pod resource usage (all namespaces)kubectl top pods -A
# Sort by CPUkubectl top pods --sort-by=cpu
# Sort by memorykubectl top pods --sort-by=memory
# Per-container usagekubectl top pods --containers
# Specific podkubectl top pod <pod-name>Одиниці в kubectl top компактні, але точні. CPU зазвичай показано в тисячних частках ядра (мілікорах), де 100m — це одна десята ядра, а 1000m — одне повне ядро. Пам’ять часто показано в двійкових одиницях, таких як Mi та Gi. Вимірювання стає осмисленим лише тоді, коли ви порівнюєте його із запитами, лімітами, доступною ємністю ноди та симптомом, який ви розслідуєте.
┌────────────────────────────────────────────────────────────────────────────────────────────┐│ METRIC INTERPRETATION ││ ││ NAME CPU(cores) MEMORY(bytes) ││ my-pod 100m 256Mi ││ ││ CPU: 100m = 100 millicores = 0.1 CPU core ││ 1000m = 1 core ││ ││ Memory: Mi = mebibytes (1024 * 1024 bytes) ││ Gi = gibibytes ││ ││ Compare against requests/limits: ││ usage above requests: under-requested; scheduling/QoS + eviction risk under node pressure││ memory near/above limit: OOMKilled ││ CPU at limit: throttled (not killed) ││ │└────────────────────────────────────────────────────────────────────────────────────────────┘Перш ніж запускати це, який вивід ви очікуєте, коли Pod використовує більше CPU, ніж його запит, але менше за його ліміт? Запити CPU впливають на планування, тоді як ліміти CPU впливають на дроселювання (throttling), тож Pod може законно використовувати більше за свій запит після запуску, якщо доступний вільний CPU. Пам’ять поводиться інакше, тому що перевищення ліміту пам’яті може завершити контейнер, ось чому стрибки пам’яті часто потребують співвіднесення з лічильниками перезапусків, статусом OOMKilled та попередніми журналами.
# Compare actual usage vs requests# Step 1: Get requestskubectl get pod <pod> -o jsonpath='{.spec.containers[0].resources.requests}'
# Step 2: Get actual usagekubectl top pod <pod>
# If actual >> requests, pod is under-requested# If actual << requests, pod is over-requestedМетрики стають особливо корисними, коли ви поєднуєте їх з подіями. Pod у стані pending з FailedScheduling може взагалі не потребувати журналів; йому може знадобитися налаштування запитів чи додаткова ємність ноди. Running Pod з високою пам’яттю та причиною перезапуску OOMKilled потребує попередніх журналів та перегляду лімітів. Pod з високим CPU та повільними відповідями може дроселюватися, навіть якщо процес не падає, що змінює наступну дію з «прочитати трасування стека» на «порівняти ліміти CPU, затримку та метрики дроселювання».
Журнали на рівні ноди та площини управління
Розділ «Журнали на рівні ноди та площини управління»Більшість повсякденного усунення несправностей слід починати з API Kubernetes, тому що вони зберігають контекст об’єкта й уникають непотрібного доступу до ноди. Журнали на рівні ноди мають значення, коли API server недоступний, поведінка kubelet є підозрюваним збоєм, операції середовища виконання контейнерів порушені, або потрібні вам докази розташовані нижче абстракції Pod’а. На Linux-нодах журнали контейнерів зазвичай доступні через /var/log/containers, тоді як журнали kubelet та середовища виконання контейнерів зазвичай доступні через journalctl, коли systemd керує цими службами.
┌──────────────────────────────────────────────────────────────┐│ NODE LOG LOCATIONS ││ ││ Container logs (symlinks): ││ /var/log/containers/<pod>_<ns>_<container>-<id>.log ││ ││ Pod logs (actual files): ││ /var/log/pods/<ns>_<pod>_<uid>/ ││ ││ kubelet logs: ││ journalctl -u kubelet ││ ││ Container runtime logs: ││ journalctl -u containerd ││ journalctl -u docker (if using docker) ││ ││ System logs: ││ /var/log/syslog or /var/log/messages ││ journalctl ││ │└──────────────────────────────────────────────────────────────┘Пряме обстеження ноди має вищий операційний ризик, ніж kubectl, тому що ви залишаєте звичайний робочий процес API. Вам потрібен доступ до ноди, вам потрібно знати структуру операційної системи, і ви маєте уникати зміни файлів під час розслідування. Усе ж це законний запасний варіант, коли kubectl logs не може дістатися kubelet, коли API server лежить, або коли специфічна для ноди проблема — як-от тиск диску, збій сертифіката kubelet чи помилки середовища виконання контейнерів — заважає звичайній діагностиці на рівні об’єкта.
# SSH to node firstssh <node>
# Container logs directlyls /var/log/containers/tail -f /var/log/containers/<pod>*.log
# kubelet logsjournalctl -u kubelet -fjournalctl -u kubelet --since "10 minutes ago"journalctl -u kubelet | grep -i error
# Container runtime logsjournalctl -u containerd -f
# System messagesdmesg | tail -50journalctl -xeЖурнали компонентів площини управління залежать від того, як було встановлено кластер. У кластерах у стилі kubeadm основні компоненти площини управління часто працюють як статичні Pod’и в kube-system, що робить їхні журнали видимими через kubectl logs, коли API server достатньо здоровий, щоб відповідати. В інших дистрибутивах компоненти можуть бути службами systemd, керованими контейнерами чи хостованими процесами площини управління, які потребують специфічного для провайдера доступу. Діагностичний принцип залишається тим самим: спочатку знайдіть межу компонента, потім використовуйте механізм логування для цієї межі.
# If using static pods (kubeadm)# Logs available via kubectlkubectl -n kube-system logs kube-apiserver-<node>kubectl -n kube-system logs kube-scheduler-<node>kubectl -n kube-system logs kube-controller-manager-<node>kubectl -n kube-system logs etcd-<node>
# Or directly on node via journalctl (if systemd services)journalctl -u kube-apiserverjournalctl -u kube-schedulerjournalctl -u kube-controller-managerjournalctl -u etcdЖурнали ноди також пояснюють, чому має значення ротація журналів. Kubelet керує файлами журналів контейнерів відповідно до своєї конфігурації, що захищає ноди від необмеженого зростання диску, але також означає, що старий вміст журналу може зникнути локально. Якщо шумний застосунок швидко заповнює журнали, ваше вікно kubectl logs --previous може бути коротшим, ніж ви очікуєте. Для production-систем локальне для ноди зберігання журналів слід трактувати як буфер, доки журнали не відправлено в надійне сховище, а не як систему обліку.
Співвіднесення журналів, подій та метрик у робочий процес
Розділ «Співвіднесення журналів, подій та метрик у робочий процес»Усунення несправностей стає швидшим, коли ви ставите по одному питанню про докази за раз. Почніть зі стану об’єкта та нещодавніх подій, тому що вони кажуть вам, чи зміг Kubernetes запланувати, завантажити, змонтувати, запустити й тримати контейнер живим. Потім огляньте поточні чи попередні журнали контейнера залежно від поведінки перезапуску. Використовуйте метрики, коли симптом може бути тиском, дроселюванням чи дисбалансом. Нарешті, переходьте до журналів на рівні ноди лише тоді, коли вигляд API відсутній, суперечливий чи нижчий за шар, де живе проблема.
┌──────────────────────────────────────────────────────────────┐│ LOG ANALYSIS WORKFLOW ││ ││ 1. Start with events ││ kubectl describe <resource> | grep -A 20 Events ││ ││ 2. Check recent events cluster-wide ││ kubectl get events --sort-by='.lastTimestamp' | tail ││ ││ 3. Get container logs ││ kubectl logs <pod> ││ kubectl logs <pod> --previous (if crashed) ││ ││ 4. Filter for errors ││ kubectl logs <pod> | grep -i error ││ kubectl logs <pod> | grep -i exception ││ ││ 5. Check timing ││ kubectl logs <pod> --timestamps --since=10m ││ ││ 6. Check related components ││ If pod issues: check node ││ If network issues: check CNI, kube-proxy ││ If DNS issues: check CoreDNS ││ │└──────────────────────────────────────────────────────────────┘Фільтрація корисна лише після того, як ви розумієте потік, який фільтруєте. Команда grep -i error може виявити важливі рядки, але вона також може приховати рядок контексту перед помилкою чи пропустити застосунки, які логують збої як fatal, exception, panic чи структуровані поля JSON. Використовуйте фільтрацію, щоб зменшити шум, а не щоб делегувати судження. Коли час має значення, додайте --timestamps та звужуйте за допомогою --since чи --since-time перед пошуком.
# Search for errorskubectl logs <pod> | grep -i errorkubectl logs <pod> | grep -i exceptionkubectl logs <pod> | grep -i fatal
# Exclude noisekubectl logs <pod> | grep -v "INFO"kubectl logs <pod> | grep -v "health check"
# Complex filterskubectl logs <pod> | grep -E "error|warning|failed"
# With timestamps and filteringkubectl logs <pod> --timestamps | grep "2024-01-15T10:3"
# Count error occurrenceskubectl logs <pod> | grep -c errorАналіз кількох Pod’ів — це проблема співвіднесення, а не просто більший текстовий потік. Коли кілька реплік відмовляють, ви хочете знати, чи всі Pod’и відмовляють однаково, чи зачеплено лише одну ноду, чи задіяна одна версія чи набір лейблів, і чи sidecar’и повідомляють про іншу послідовність, ніж контейнери застосунку. Використовуйте вибір за контролером і лейблами для широти, потім звужуйте до представницького Pod’а для точних міток часу та попередніх журналів.
# Logs from all pods in deployment (--all-pods=true required)kubectl logs deployment/<name> --all-pods=true --all-containers=true
# Aggregate logs from multiple pods with labelskubectl logs -l app=frontend --all-containers
# Using stern (not built-in, but useful)# stern <pod-name-pattern>
# Workaround: loop through podsfor pod in $(kubectl get pods -l app=nginx -o name); do echo "=== $pod ===" kubectl logs $pod --tail=5doneСпіввіднесення подій та журналів — це місце, де багато розслідувань стають вирішальними. Якщо подія каже, що проба liveness провалилася в певний час, журнали навколо цієї мітки часу можуть показати, чи застосунок усе ще завантажувався, чекав на базу даних, відхиляв трафік чи був у взаємному блокуванні. Якщо подія каже, що контейнер було вбито, попередні журнали можуть показати, що сталося до завершення, тоді як метрики можуть показати, чи зробив тиск пам’яті це вбивство передбачуваним.
# Get event timekubectl get events --field-selector involvedObject.name=my-pod
# Note the timestamp, then check logs around that timekubectl logs my-pod --since-time="2024-01-15T10:30:00Z"
# Or use relative timekubectl logs my-pod --since=5mЯкий підхід ви оберете тут і чому: почати зі стеження за живими журналами чи спочатку відсортувати нещодавні події Warning у Просторі імен? Якщо симптом — «новий Pod так і не стає Ready», події зазвичай мають вищий сигнал, тому що вони виявляють збої завантаження, монтування, планування та проб, які трапляються поза процесом застосунку. Якщо симптом — «Ready Pod повертає помилки під трафіком», живі журнали плюс мітки часу можуть бути кращим першим кроком.
Патерни моніторингу для іспиту та операцій
Розділ «Патерни моніторингу для іспиту та операцій»Швидкий прохід здоров’я кластера має бути достатньо малим, щоб виконати його під тиском, і достатньо широким, щоб вловити очевидні збої. Почніть з нод, не-running Pod’ів, поточних метрик та подій Warning. Це не замінює глибшу спостережуваність, але дає вам послідовну базову лінію, перш ніж ви станете ганятися за окремим компонентом. На іспиті CKA ця звичка також запобігає марнуванню часу всередині журналів застосунку, коли справжній збій — це стан ноди чи обмеження планування.
# Quick cluster health checkkubectl get nodeskubectl get pods -A | grep -v Runningkubectl top nodeskubectl get events -A --field-selector type=Warning
# Create a simple monitoring scriptwatch -n 5 'kubectl get pods -A | grep -v Running | grep -v Completed'Виявлення тиску на ресурси потребує і статусу об’єкта, і поточних вимірювань. Умови ноди, такі як MemoryPressure, DiskPressure та PIDPressure, пояснюють, чому kubelet може витісняти Pod’и чи відхиляти роботу. Команди top показують поточних споживачів, тоді як pending Pod’и можуть виявити запити, які жодна нода не може задовольнити. Мета — відокремити несправність застосунку від несправності ємності кластера чи здоров’я ноди, перш ніж ви зміните не той маніфест.
# Check for node pressurekubectl describe nodes | grep -E "MemoryPressure|DiskPressure|PIDPressure"
# Check for pods using excessive resourceskubectl top pods -A --sort-by=memory | head -10kubectl top pods -A --sort-by=cpu | head -10
# Check for pending pods (might indicate resource shortage)kubectl get pods -A --field-selector=status.phase=PendingТимчасові діагностичні Pod’и корисні, коли вам потрібні інструменти всередині мережі кластера, але їх слід створювати усвідомлено. Використовуйте --rm, щоб Pod видалявся, коли оболонка завершується, і використовуйте --restart=Never, щоб ви створювали голий Pod, а не кероване контролером робоче навантаження. Ретельно обирайте Простір імен та сервісний акаунт, тому що діагностичний Pod, що працює з не тією ідентичністю, може довести лише те, що не та ідентичність має доступ.
# Create debug pod with networking toolskubectl run debug --image=nicolaka/netshoot --rm -it --restart=Never -- bash
# Simple debug podkubectl run debug --image=busybox:1.36 --rm -it --restart=Never -- sh
# Debug with specific service accountkubectl run debug --image=busybox:1.36 --rm -it --restart=Never --overrides='{"spec":{"serviceAccountName":"<sa>"}}' -- sh
# Debug in specific namespacekubectl run debug -n <namespace> --image=busybox:1.36 --rm -it --restart=Never -- shНайкращий патерн моніторингу — це цикл прийняття рішень: спостерігайте, формуйте гіпотезу, запускайте найменшу команду, яка може її спростувати, потім оновлюйте свій шлях. Якщо гіпотеза — «застосунок упав», попередні журнали мають високу цінність. Якщо це — «Pod так і не запланувався», події та вивід describe важать більше. Якщо це — «нода нездорова», умови ноди та журнали kubelet релевантніші за вивід застосунку.
Розбір прикладу: побудова хронології доказів
Розділ «Розбір прикладу: побудова хронології доказів»Сценарій вправи: Простір імен на ім’я payments містить Деплоймент, чиї нові Pod’и не стають здоровими після зміни конфігурації. Сервіс усе ще частково доступний, тому що старіші репліки залишаються ready, але розгортання застрягло, і черговому інженеру треба вирішити, чи робити відкат, виправляти конфігурацію чи змінювати налаштування ресурсів. Вам не сказано наперед першопричину, тому що навичка, яку відпрацьовують, — це послідовність доказів, а не запам’ятовування команд.
Перше спостереження — це стан контролера, а не журнал застосунку. Застрягле розгортання каже вам, що частина бажаних реплік недоступна, але воно не пояснює, чи Pod’и провалили планування, завантаження образу, запуск, готовність чи виконання в усталеному режимі. Початок з kubectl describe deployment та kubectl get pods -n payments -o wide дає вам імена об’єктів, розміщення на нодах, лічильники перезапусків та фази статусу. Це запобігає поширеній помилці: прочитати журнал одного Pod’а й припустити, що він представляє все розгортання.
Припустимо, таблиця Pod’ів показує два нові Pod’и у стані Running з лічильниками перезапусків, що зростають, і один старіший Pod, усе ще Running з нульовими перезапусками. Це одразу звужує проблему до нового ReplicaSet чи конфігурації, а не до універсального простою ноди. Наступний корисний крок — оглянути один проблемний Pod за допомогою kubectl describe pod, тому що розділ Events може виявити, чи kubelet убиває контейнер через проби, чи контейнер виходить сам, чи задіяне примусове виконання ресурсів.
Вивід describe показує повторювані події BackOff та стан контейнера Waiting з причиною CrashLoopBackOff. У цей момент поточні журнали менш корисні, ніж попередні журнали, тому що контейнер уже помер щонайменше раз. Ви запускаєте kubectl logs -n payments <pod> --previous і бачите помилку валідації конфігурації біля запуску. Цей єдиний рядок корисний, але це ще не повна хронологія, тому що вам усе ще треба пов’язати його з розгортанням і підтвердити, що та сама помилка з’являється на всіх нових репліках.
Наступний крок — запитати журнали з Деплойменту чи селектора за лейблами з невеликим tail та мітками часу. Якщо всі нові Pod’и показують ту саму помилку валідації невдовзі після запуску, ви можете трактувати збій як проблему конфігурації релізу, а не як специфічну для ноди проблему середовища виконання. Якщо лише один Pod показує помилку, а інші відмовляють інакше, розслідування розгалужується. Ось чому широкий вибір та вузький огляд мають чергуватися: широта каже вам патерн, тоді як деталь каже вам механізм.
Тепер уявіть, що попередні журнали не показують помилки застосунку, але describe pod показує події Unhealthy від проби liveness. Це змінює діагностику. Застосунок може повільно запускатися, шлях проби може бути хибним, або залежність, яку перевіряє проба, може бути недоступною. У цій гілці ви оглядаєте налаштування readiness та liveness, порівнюєте мітки часу з журналами запуску застосунку й вирішуєте, чи виявляє проба справжній збій, чи вбиває процес, який став би здоровим за довшого вікна запуску.
Метрики ресурсів створюють третю гілку. Якщо Pod перезапускається й події показують OOMKilling, kubectl top pod може й не вловити стрибок, тому що контейнер швидко помирає, а метрики вибираються вибірково. Ви все одно порівнюєте запити та ліміти, але не покладаєтеся лише на kubectl top. Попередні журнали, причина завершення та події несуть найсильніші докази вбивства через пам’ять, тоді як Metrics Server надає поточний контекст для Pod’ів, що вижили, та тиску на рівні ноди.
Розміщення на нодах також може змінити шлях. Якщо кожен проблемний Pod потрапляє на ту саму ноду, перевірте умови ноди, події kubelet та журнали середовища виконання контейнерів, перш ніж звинувачувати застосунок. Поганий кеш образів, тиск диску, зламаний стан CNI чи проблема kubelet можуть породити симптоми, які з погляду Деплойменту виглядають як нестабільність застосунку. Стовпець NODE таблиці Pod’ів — тому не оздоблення; це поле співвіднесення, яке допомагає відокремити проблеми робочих навантажень від проблем інфраструктури.
Час — це нитка, яка зв’язує ці спостереження разом. Корисна хронологія могла б казати: новий ReplicaSet створив Pod’и о 10:12, kubelet запустив контейнери о 10:13, застосунок залогував помилку конфігурації о 10:13, kubelet зафіксував BackOff о 10:14, і Деплоймент залишався недоступним після цього. Така послідовність підтримує відкат конфігурації. Інша хронологія, де планування провалилося до того, як запустився будь-який контейнер, підтримувала б натомість виправлення розміщення чи ємності.
Зробіть паузу й передбачте: якщо команда застосунку просить «журнали з провального розгортання», які саме потоки ви зібрали б, і як ви позначили б їх, щоб команда могла міркувати про час? Якісна відповідь включає попередні журнали для кожного проблемного контейнера, поточні журнали для будь-яких реплік, що вижили, релевантні події, відсортовані за міткою часу, та статус Деплойменту чи ReplicaSet, який показує, до якої ревізії належать Pod’и. Сирий текст без міток важко використовувати під час передавання.
Цей приклад також пояснює, чому агрегація журналів не усуває навичок kubectl. Центральна система журналів може зберігати історію та покращувати пошук, але стан об’єкта Kubernetes усе ще є найшвидшим способом зіставити симптом з Pod’ами, контейнерами, нодами, причинами перезапуску та подіями. І навпаки, kubectl може показати лише нещодавні чи локальні для ноди докази, тож надійне логування залишається необхідним для відкладених розслідувань. Ефективні оператори розуміють обидва вигляди й рухаються між ними усвідомлено.
Коли докази вказують на конфігурацію, ви все одно перевіряєте виправлення спостережуваністю, а не припускаєте, що розгортання вилікувано. Після застосування виправленого ConfigMap, Secret чи змінної середовища Деплойменту слідкуйте за подіями на предмет нових збоїв, читайте перші журнали запуску з нових Pod’ів та підтверджуйте готовність. Якщо метрики були частиною симптому, порівняйте використання ресурсів знову після виправлення. Закриття — це не «команда повернула нуль»; закриття — це «попередній режим збою більше не з’являється, і робоче навантаження досягає очікуваного стану».
Коли докази вказують на ресурси, найбезпечніший наступний крок залежить від того, чи проблема в плануванні, в пам’яті середовища виконання чи в насиченні CPU. Pod у стані Pending з FailedScheduling через недостатню пам’ять потребує змін запитів чи ємності, тоді як running Pod, убитий з OOMKilled, потребує перегляду лімітів та поведінки пам’яті. Pod з інтенсивним CPU без перезапусків може потребувати коригування лімітів, горизонтального масштабування чи профілювання застосунку. Усі ці випадки залучають «ресурси», але кожен має іншу першу команду та інший відповідальний шар.
Коли докази вказують на здоров’я ноди, збережіть вигляд Kubernetes, перш ніж заглиблюватися. Зафіксуйте розміщення Pod’ів, умови ноди, події Warning та імена зачеплених робочих навантажень, потім огляньте журнали kubelet чи середовища виконання контейнерів, якщо потрібно. Журнали ноди можуть бути шумними, і без контексту об’єкта ви можете не знати, які помилки мають значення. Послідовність важлива, тому що вона дозволяє вам повернутися від доказів на рівні ноди до конкретного Pod’а, Простору імен та робочого навантаження замість збирання непов’язаних системних повідомлень.
Та сама звичка до хронології застосовна на іспиті CKA, навіть якщо середовище менше. Вас часто винагороджують за вибір найкоротшого валідного шляху доказів: події для планування та монтувань, попередні журнали для падінь, kubectl top для поточного тиску та журнали ноди для проблем kubelet чи середовища виконання. Іспит не вимагає production-платформи спостережуваності, але він вимагає, щоб ви знали, чому команда релевантна, перш ніж її запускати. Це тримає вас швидкими, не будучи випадковими.
Останній урок зі сценарію — що дані спостережуваності мають свіжість та область охоплення. Події свіжі, але короткочасні, журнали контейнерів прив’язані до екземпляра контейнера, метрики нещодавні та вибіркові, а журнали ноди локальні для машини. Діагностика сильніша, коли вона називає ці обмеження прямо. Замість того щоб казати «журнали доводять, що деплоймент зламано», скажіть «попередні журнали для всіх нових контейнерів застосунку показують ту саму помилку валідації запуску після того, як було створено новий ReplicaSet». Це твердження достатньо конкретне, щоб діяти.
Вам також слід думати про аудиторію, збираючи докази. Розробнику застосунку часто потрібен точний виняток, змінна середовища чи збій запиту з міткою часу. Інженеру платформи може знадобитися розміщення Pod’ів, умови ноди, події kubelet та чи з’являється той самий симптом у різних Просторах імен. Менеджеру релізів може знадобитися чітка рекомендація «так чи ні» щодо відкату. Ті самі сирі дані спостережуваності можуть підтримати всі три розмови, але лише якщо ви зберігаєте достатньо контексту, щоб пов’язати докази з дією.
Хороші нотатки про докази компактні й відтворювані. Запишіть Простір імен, ім’я Pod’а, ім’я контейнера, використану команду та часове вікно, яке ви оглянули. Якщо ви використали --previous, скажіть про це явно, тому що це відрізняє завершений екземпляр від поточного. Якщо ви фільтрували журнали, тримайте нефільтровану команду доступною також, тому що іншому рецензенту можуть знадобитися навколишні рядки. Ця дисципліна має значення під час передавання, коли товариш по команді має довіряти вашому висновку, не перезапускаючи кожну команду з пам’яті.
Існує тонка різниця між «моніторингом» та «діагностикою» в цьому модулі. Моніторинг питає, чи система здорова зараз і чи виглядає використання ресурсів аномальним. Діагностика питає, чому стався конкретний симптом. kubectl top nodes може підтримати моніторинг, показуючи поточний тиск, тоді як попередні журнали підтримують діагностику, пояснюючи завершений контейнер. Сильні фахівці з усунення несправностей поєднують їх, але не плутають поточне вимірювання з історичною причиною.
Робочий процес також захищає від переобладнання під знайомі збої. Якщо ви нещодавно виправили проблему завантаження образу, у вас може виникнути спокуса припустити, що наступний збій розгортання має ту саму причину. Цикл доказів змушує вас перевірити стан, події, журнали, метрики та розміщення, перш ніж зобов’язатися до виправлення. Це повільніше за вгадування для першої хвилини, але швидше за відкат здорового образу, коли справжня проблема — це відсутній Secret, провалене монтування чи занадто сувора проба.
Нарешті, трактуйте прибирання як частину практики спостережуваності. Тимчасові діагностичні Pod’и, лабораторні Простори імен та ситуативні скрипти можуть створювати шум, який заплутує пізніші розслідування, якщо вони залишаються в кластері. Видалення лабораторного Простору імен після цієї вправи — це не просто охайність; це тримає майбутній вивід kubectl get pods -A, подій та метрик сфокусованим на справжніх робочих навантаженнях. Чисті середовища роблять сигнал легшим для знаходження, що саме й мають надавати логування та моніторинг.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Наведені нижче патерни розраховані на операційне використання, де швидкість має значення, але передчасна впевненість небезпечна. Кожен патерн працює, тому що він робить межу доказів явною. Журнали, події, метрики та журнали ноди описують різні шари, тож правильний патерн зазвичай той, який звужує шар перед тим, як звузити команду.
| Патерн | Коли використовувати | Чому це працює | Міркування щодо масштабування |
|---|---|---|---|
| Тріаж «події передусім» | Pod’и у стані Pending, ContainerCreating, провалюють проби чи нещодавно перезапустилися | Компоненти Kubernetes пояснюють збої життєвого циклу, перш ніж застосунок зможе залогувати | Експортуйте події для зберігання, бо TTL подій API server короткий |
| Аналіз падіння за попередніми журналами | Контейнери швидко перезапускаються чи показують CrashLoopBackOff | Останній завершений екземпляр містить збій, до якого поточний екземпляр може не дійти | Включайте -c <container> у Pod’ах з кількома контейнерами, щоб не прочитати не той перезапуск |
| Співвіднесення за мітками часу | Події, журнали та метрики показують симптоми приблизно в один період | Збіг часових вікон відділяє причину від подальшого шуму | Використовуйте узгоджені часові зони та централізовано відправляйте журнали для довгих розслідувань |
| Відстеження файлів через sidecar | Застарілі застосунки пишуть у файли й не можуть бути швидко змінені | Спільний том плюс sidecar перетворюють записи у файли на захоплений kubelet stdout | Плануйте міграцію на прямий структурований stdout, щоб зменшити накладні витрати sidecar |
Антипатерни зазвичай походять від трактування одного спостережуваного об’єкта як цілої правди. Потік журналів може бути порожнім, тому що контейнер так і не запустився, а не тому, що нічого не відмовило. Помилка kubectl top може означати, що Metrics Server лежить, а не що кластер не має використання ресурсів. Відсутність подій може означати, що сплинув час зберігання, а не що Kubernetes нічого не побачив. Безпечніша альтернатива — назвати, що інструмент може й не може довести, перш ніж діяти на його основі.
| Антипатерн | Що йде не так | Краща альтернатива |
|---|---|---|
| Стеження за живими журналами до перевірки стану об’єкта | Ви пропускаєте збої планування, завантаження образу, монтування чи проб поза процесом | Спочатку запустіть kubectl describe та нещодавні події Warning для проблем життєвого циклу |
| Читання лише першого контейнера в Pod’і | Збої sidecar, init чи проксі залишаються невидимими | Перелічіть контейнери й усвідомлено використовуйте -c чи --all-containers=true |
| Трактування подій як постійної історії | Аналіз вихідного дня чи відкладеного інциденту втрачає початкові підказки | Експортуйте події в надійну систему журналів і фіксуйте хронології під час інцидентів |
| Використання SSH на ноду як першого діагностичного кроку | Ви втрачаєте контекст об’єкта й підвищуєте операційний ризик | Починайте з API Kubernetes, потім повертайтеся до журналів ноди, коли шару API недостатньо |
Рамка прийняття рішень
Розділ «Рамка прийняття рішень»Використовуйте цю рамку, коли симптом зрозумілий, але наступна команда — ні. Перше рішення — чи запустився контейнер. Якщо ні, журнали вторинні, тому що немає осмисленого виводу процесу. Друге рішення — чи перезапустився контейнер. Якщо так, попередні журнали корисніші за поточні журнали. Третє рішення — чи може симптом бути спричинений тиском на ресурси. Якщо може, метрики та умови ноди слід перевірити, перш ніж змінювати код застосунку.
| Симптом | Перше джерело доказів | Наступне джерело доказів | Загальний напрям виправлення |
|---|---|---|---|
Pod у стані Pending | Події kubectl describe pod | Доступні ресурси ноди, статус PVC, taint’и, affinity | Скоригувати запити, прив’язку сховища, толерантності чи правила розміщення |
Pod у стані CrashLoopBackOff | kubectl logs --previous | Події, причина перезапуску, проби, ліміти ресурсів | Виправити запуск застосунку, конфігурацію, доступ до залежностей чи ліміти |
Pod Running, але не Ready | Події та вивід проб | Поточні журнали з мітками часу | Виправити endpoint readiness, час запуску, перевірки залежностей чи конфігурацію проб |
kubectl top відмовляє | APIService та Pod Metrics Server | Журнали Metrics Server та доступ до kubelet | Встановити, відремонтувати чи переналаштувати Metrics Server |
| Нода показує тиск | Умови node describe | Top Pod’и, відсортовані за CPU чи пам’яттю, журнали kubelet | Налаштувати запити та ліміти, витіснити шумні робочі навантаження чи додати ємність |
┌───────────────────────────┐│ What is the visible state? │└──────────────┬────────────┘ │ ┌─────────▼─────────┐ │ Container started? │ └───────┬─────┬─────┘ │yes │no │ ▼ │ Check Events, scheduling, image pull, mounts ▼ ┌─────────────────────┐ │ Restarted recently? │ └───────┬─────┬───────┘ │yes │no │ ▼ │ Check current logs with timestamps ▼ Check previous logs, restart reason, Events │ ▼ If pressure is plausible, compare top metrics with requests and limitsРамка навмисно консервативна. Вона уникає «читати журнали» як універсального першого кроку, тому що збої Kubernetes часто трапляються до того, як застосунок отримує контроль. Вона також уникає трактування метрик як остаточної відповіді, тому що гарячий Pod може бути симптомом повторних спроб, спричинених збоєм залежності. Найкраща наступна команда — та, яка може усунути гілку дерева рішень з найменшим шумом.
Чи знали ви?
Розділ «Чи знали ви?»- Kubernetes захоплює
stdoutтаstderrза домовленістю: kubelet відкриває потоки контейнера з файлів журналів ноди, ось чому застосунки, які пишуть лише в приватні файли, потребують містка, як-от sidecar. - Події мають короткий стандартний час зберігання: TTL подій API server за замовчуванням становить одну годину, тож події кластера слід експортувати, якщо вашій команді потрібні хронології інцидентів після безпосереднього вікна усунення несправностей.
kubectl topзалежить від агрегованого API: команда потребує Metrics Server та APImetrics.k8s.io, тож збій може бути проблемою конвеєра спостережуваності, а не проблемою застосунку.- Ротація журналів локальна для ноди: налаштування kubelet, такі як максимальний розмір журналу та кількість файлів, захищають дисковий простір, але вони також означають, що локальні для ноди журнали не є надійними архівами інцидентів.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому це трапляється | Як це виправити |
|---|---|---|
Забути --previous під час CrashLoopBackOff | Поточний екземпляр контейнера запускається чисто й приховує рядок, який убив попередній екземпляр | Використовуйте kubectl logs <pod> --previous та додавайте -c <container> для Pod’ів з кількома контейнерами |
| Трактувати порожній журнал як доказ того, що нічого не сталося | Pending Pod’и, збої завантаження образу та збої монтування можуть статися до того, як запуститься код застосунку | Перевіряйте kubectl describe pod та події Warning, перш ніж покладатися на журнали |
| Читати не той контейнер у Pod’і | Sidecar’и, init-контейнери та проксі створюють кілька потоків журналів під одним іменем Pod’а | Перелічіть імена контейнерів і усвідомлено обирайте -c <container> чи --all-containers=true |
| Ігнорувати час зберігання подій | Події короткочасні й можуть зникнути до початку відкладеного аналізу інциденту | Експортуйте події в надійне логування й фіксуйте вивід подій під час інциденту |
Припускати, що kubectl top вбудований усюди | Metrics Server є окремим компонентом і може бути відсутнім чи нездоровим | Перевіряйте Pod Metrics Server та APIService metrics.k8s.io, перш ніж діагностувати використання застосунку |
| Порівнювати метрики лише з лімітами | Запити впливають на планування, ліміти впливають на примусове виконання, і кожен відповідає на інше питання | Порівнюйте поточне використання із запитами, лімітами, ємністю ноди та причинами перезапуску |
| Починати з SSH на ноду для звичайних збоїв Pod’а | Прямий доступ до ноди втрачає контекст об’єкта Kubernetes і може відволікти від простих підказок життєвого циклу | Починайте з подій, виводу describe та журналів; використовуйте журнали ноди, коли вигляду API недостатньо |
| Фільтрувати журнали занадто рано | grep може видалити контекст часу чи пропустити інакше названі повідомлення про збій | Спершу звужуйте за часом, потім шукайте сімейства помилок, такі як exception, fatal, failed та panic |
Тест
Розділ «Тест»Питання 1: Ваша команда розгортає новий образ, і Pod входить у `CrashLoopBackOff`. `kubectl logs my-app` показує лише банер запуску. Що ви перевіряєте далі й чому?
Використайте kubectl logs my-app --previous, додаючи -c <container>, якщо Pod має більше одного контейнера. Звичайна команда журналів читає поточний екземпляр контейнера, який, можливо, лише запустився й ще не дійшов до проблемного рядка. --previous запитує в kubelet останній завершений екземпляр, де зазвичай присутні трасування стека, повідомлення про відсутню конфігурацію чи фатальна помилка запуску. Прочитавши його, співвіднесіть мітку часу з подіями, щоб ви могли відокремити збій застосунку від проби чи примусового виконання ресурсів.
Питання 2: Pod застряг у стані `Pending`, і молодший адміністратор хоче запустити `kubectl logs`, щоб знайти скаргу застосунку. Що вам слід зробити натомість?
Почніть з kubectl describe pod <pod> та нещодавніх подій Warning для Простору імен. Pending Pod зазвичай не запустив контейнер, тож може не бути виводу застосунку для отримання. Події можуть показати FailedScheduling, неприв’язані PVC, taint’и, невідповідності affinity чи недостатній CPU та пам’ять. Щойно Pod досягне стану контейнера, журнали стануть корисними, але до того площина управління є джерелом доказів.
Питання 3: `kubectl top pods -n production` повертає помилку, що метрики недоступні. Ваш kubeconfig та RBAC коректні. Який компонент є ймовірним фокусом?
Огляньте Metrics Server та APIService metrics.k8s.io, перш ніж змінювати маніфести застосунку. kubectl top не читає cgroup’и Pod’а напряму; він запитує агрегований API метрик, який обслуговує Metrics Server. Metrics Server має працювати, бути здатним опитувати endpoint’и ресурсів kubelet та бути зареєстрованим як доступний APIService. Якщо цей конвеєр зламано, kubectl top відмовляє, навіть якщо робочі навантаження споживають CPU та пам’ять.
Питання 4: Pod має основний контейнер застосунку та sidecar-пересилач журналів. Ви підозрюєте, що обидва задіяні в збої. Як уникнути читання лише половини доказів?
Спершу перелічіть контейнери за допомогою kubectl get pod <pod> -o jsonpath='{.spec.containers[*].name}', потім прочитайте релевантні потоки за допомогою kubectl logs <pod> -c <container> чи використайте --all-containers=true, коли співвіднесення має значення. Саме лише ім’я Pod’а не гарантує, що потік, який ви бачите, належить проблемному компоненту. Sidecar’и можуть провалити автентифікацію, проксі можуть відхиляти трафік, а init-контейнери можуть залишити підказки про налаштування, які основний контейнер ніколи не повторює. Вибір контейнера тримає розслідування прив’язаним до межі компонента.
Питання 5: Пакетне завдання провалилося два дні тому, але `kubectl get events` не повертає корисних записів. Чи доводить це, що Kubernetes не видавав подій?
Ні. Події — це короткочасні об’єкти Kubernetes, і стандартний TTL подій становить одну годину, якщо API server не налаштований інакше. До моменту, коли ви розслідуєте дводенний збій, початкові події планування, завантаження, монтування чи проб могли бути зібрані як сміття. Для довгих хронологій інцидентів відправляйте події в надійне логування чи сховище спостережуваності, поки вони свіжі. Для поточного розслідування покладайтеся на збережені журнали застосунку, статус завдання, стан завершення Pod’а та зовнішній моніторинг.
Питання 6: Pod працює, але повільно, `kubectl top pod` показує високий CPU, і перезапусків немає. Який наступний діагностичний напрям?
Порівняйте поточне використання CPU із запитами та лімітами Pod’а, потім перевірте, чи дроселювання, чи насичення пояснюють симптом. Високий CPU без перезапусків указує менше на падіння й більше на продуктивність, ліміти, повторні спроби залежностей чи дисбаланс навантаження. Події все ще можуть мати значення, якщо проби провалюються, але попередні журнали навряд чи допоможуть, якщо контейнер не перезапустився. Корисний шлях — пов’язати метрики, затримку, ліміти та журнали застосунку для одного й того ж часового вікна.
Питання 7: API server тимчасово недосяжний, але у вас є SSH-доступ до ноди, що запускає критичний Pod. Де ви можете шукати журнали контейнерів, і яка пересторога застосовується?
На ноді огляньте /var/log/containers/ на предмет символьних посилань, названих за Pod’ом, Простором імен, контейнером та ID контейнера, потім обережно слідуйте за відповідним файлом. Цими файлами керують kubelet та середовище виконання контейнерів, тож вони корисні, коли звичайний шлях API недоступний. Уникайте редагування чи видалення файлів журналів ноди під час діагностики, тому що ви можете знищити докази чи завадити ротації. Коли доступ до API повернеться, узгодьте докази ноди зі станом об’єкта Kubernetes.
Практична вправа: аналіз журналів та метрик
Розділ «Практична вправа: аналіз журналів та метрик»Сценарій вправи: ви створите Простір імен з одним Pod’ом, що безперервно видає змішані інформаційні повідомлення та повідомлення про помилки, одним Pod’ом, що повторно падає, та необов’язковим логером файлів у застарілому стилі. Вправа змушує вас використати поточні журнали, попередні журнали, фільтрацію, події та метрики в контрольованому середовищі, перш ніж вони знадобляться вам під час іспиту чи production-інциденту. Запускайте ці команди в одноразовому кластері Kubernetes 1.35+, де дозволено створювати Простір імен та тимчасові Pod’и.
Налаштування
Розділ «Налаштування»# Create test namespacekubectl create ns logging-lab
# Create a pod that generates logscat <<'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: log-generator namespace: logging-labspec: containers: - name: logger image: busybox:1.36 command: - sh - -c - | i=0 while true; do echo "$(date '+%Y-%m-%d %H:%M:%S') INFO: Log message $i" if [ $((i % 5)) -eq 0 ]; then echo "$(date '+%Y-%m-%d %H:%M:%S') ERROR: Something went wrong at iteration $i" >&2 fi i=$((i+1)) sleep 2 doneEOF
# Create a crashy pod for --previous democat <<'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: crashy-pod namespace: logging-labspec: containers: - name: crasher image: busybox:1.36 command: - sh - -c - | echo "Starting up..." sleep 5 echo "About to crash!" exit 1EOF
# Wait for log-generator to be ready before proceedingkubectl wait --for=condition=Ready pod/log-generator -n logging-lab --timeout=60sЗавдання 1: базові операції з журналами
Розділ «Завдання 1: базові операції з журналами»Використайте це завдання, щоб довести, що ви можете прочитати поточний потік, недовго слідкувати за ним, обмежити вивід та додати мітки часу. Зупиніть стеження за допомогою Ctrl+C після того, як побачите кілька рядків; мета — підтвердити потік і потім перейти до цілеспрямованого збору доказів, а не дивитися журнали нескінченно.
# View logskubectl logs -n logging-lab log-generator
# Follow logskubectl logs -n logging-lab log-generator -f# (Ctrl+C to stop)
# Last 10 lineskubectl logs -n logging-lab log-generator --tail=10
# With timestampskubectl logs -n logging-lab log-generator --tail=10 --timestampsНотатки до розв'язку Завдання 1
Ви маєте побачити повторювану суміш повідомлень INFO та зрідка повідомлень ERROR від того самого контейнера. Прапорець --tail має зменшити вивід до невеликого нещодавнього вікна, а --timestamps має додати мітки часу журналу Kubernetes перед кожним рядком. Якщо Pod ще не ready, зачекайте кілька секунд та перевірте kubectl describe pod -n logging-lab log-generator, перш ніж припускати, що команда журналів зламана.
Завдання 2: фільтрація журналів
Розділ «Завдання 2: фільтрація журналів»Фільтрація вчить вас зменшувати шум після того, як ви підтвердили потік. Запустіть пошуки помилок, підрахуйте відповідні рядки, а потім виключіть інформаційні рядки. Зауважте, що кожен конвеєр відповідає на інше питання: один знаходить приклади, один вимірює приблизну частоту, а один показує все, що не є рутинним інформаційним виводом.
# Find errors onlykubectl logs -n logging-lab log-generator | grep ERROR
# Count errorskubectl logs -n logging-lab log-generator | grep -c ERROR
# Exclude INFO messageskubectl logs -n logging-lab log-generator | grep -v INFOНотатки до розв'язку Завдання 2
Лічильник помилок має зростати з часом, тому що Pod видає помилку кожні кілька ітерацій. Якщо лічильник дорівнює нулю, Pod, можливо, лише запустився, або ваша команда читає не той Простір імен. У реальному інциденті ви зазвичай поєднували б фільтрацію з --since чи --since-time, щоб лічильник відображав вікно інциденту замість усього часу життя Pod’а.
Завдання 3: попередні журнали контейнера
Розділ «Завдання 3: попередні журнали контейнера»Pod, що падає, розроблений, щоб показати, чому поточний потік та попередній потік різні. Спостерігайте за Pod’ом, доки не побачите перезапуски чи CrashLoopBackOff, потім отримайте попередній екземпляр. Це той самий крок, який ви використовуєте, коли застосунок запускається, друкує банер, виходить і перезапускається занадто швидко, щоб поточний потік журналів виявив фатальний рядок.
# Wait for crashy-pod to crash and restartkubectl get pod -n logging-lab crashy-pod -w# (Press Ctrl+C to stop once you see CrashLoopBackOff)
# When it shows CrashLoopBackOff or restarts, check previous logskubectl logs -n logging-lab crashy-pod --previousНотатки до розв'язку Завдання 3
Попередні журнали мають включати Starting up..., за яким іде About to crash!. Якщо --previous повертає, що попереднього завершеного контейнера не існує, зачекайте на перший перезапуск і спробуйте знову. Ключова звичка — використовувати статус Pod’а та лічильник перезапусків, щоб вирішити, чи поточні чи попередні журнали відповідають екземпляру збою.
Завдання 4: аналіз подій
Розділ «Завдання 4: аналіз подій»Події мають показати життєвий цикл навколо Pod’а, що падає, включно зі створенням, запуском, завершенням та поведінкою backoff. Сортуйте за міткою часу, щоб ви могли прочитати послідовність, а не таблицю, що виглядає випадковою. Потім використайте describe, щоб побачити розділ Events у контексті зі статусом Pod’а та станом контейнера.
# All events in namespacekubectl get events -n logging-lab --sort-by='.lastTimestamp'
# Describe pod for eventskubectl describe pod -n logging-lab crashy-pod | grep -A 10 Events
# Watch for new eventskubectl get events -n logging-lab -wНотатки до розв'язку Завдання 4
Ви маєте побачити події, які відповідають життєвому циклу Pod’а та поведінці backoff. Повідомлення подій не є заміною журналів застосунку, але вони пояснюють, що kubelet робить ззовні. Якщо події не з’являються, підтвердьте, що ви в правильному Просторі імен, і пам’ятайте, що старі події застарівають, тож нещодавню активність легше спостерігати, ніж історичну.
Завдання 5: метрики (якщо встановлено Metrics Server)
Розділ «Завдання 5: метрики (якщо встановлено Metrics Server)»Запускайте команди метрик лише якщо ваш лабораторний кластер має встановлений та здоровий Metrics Server. Якщо вони відмовляють, трактуйте збій як валідну діагностичну гілку: перевірте, чи існує Metrics Server, чи зареєстрований API метрик і чи підтримує його середовище кластера. Не переписуйте запити застосунку на основі відсутніх метрик, доки не дізнаєтеся, що конвеєр метрик працює.
# Node metricskubectl top nodes
# Pod metricskubectl top pods -n logging-lab
# All pods by memorykubectl top pods -A --sort-by=memory | headНотатки до розв'язку Завдання 5
Якщо Metrics Server присутній, ви маєте побачити поточне використання CPU та пам’яті для нод і Pod’ів. Числа можуть бути малими, тому що лабораторні Pod’и легкі. Якщо команда відмовляє з помилкою API метрик, огляньте kubectl -n kube-system get pods | grep metrics-server та kubectl get apiservices | grep metrics замість того, щоб припускати, що робоче навантаження не має використання ресурсів.
Завдання 6: виклик з sidecar-логуванням файлів
Розділ «Завдання 6: виклик з sidecar-логуванням файлів»Цей необов’язковий виклик реалізує місток «файл-до-stdout» з основного уроку. Основний контейнер пише у файл на спільному emptyDir, а sidecar відстежує цей файл командою tail до власного стандартного виводу. Запитайте журнали sidecar, потім поясніть, чому журнали основного контейнера менш корисні для застосунків, що пишуть лише у файли.
cat <<'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: file-logger namespace: logging-labspec: containers: - name: main-app image: busybox:1.36 command: - sh - -c - | i=0 while true; do echo "$(date '+%Y-%m-%d %H:%M:%S') file log $i" >> /var/log/app.log i=$((i+1)) sleep 2 done volumeMounts: - name: shared-logs mountPath: /var/log - name: log-tailer image: busybox:1.36 command: ["sh", "-c", "touch /var/log/app.log 2>/dev/null; tail -n+1 -F /var/log/app.log"] volumeMounts: - name: shared-logs mountPath: /var/log volumes: - name: shared-logs emptyDir: {}EOF
kubectl wait --for=condition=Ready pod/file-logger -n logging-lab --timeout=60skubectl logs -n logging-lab file-logger -c log-tailer --tail=10Нотатки до розв'язку Завдання 6
Корисні рядки журналу файлу мають з’явитися з контейнера log-tailer, а не з основного контейнера застосунку. Це демонструє, чому власне для Kubernetes логування віддає перевагу прямому stdout та stderr, і чому sidecar є лише містком для застарілої поведінки. У production ви також подумали б про ротацію, запити ресурсів для sidecar та надійне відправлення журналів за межі ноди.
Практичні вправи
Розділ «Практичні вправи»Наведені нижче вправи зберігають швидкі патерни команд з оригінального модуля. Запускайте їх після основних завдань, доки не зможете обрати правильну команду за симптомом без паузи. Вони навмисно короткі, але міркування за ними тепер мають бути зрозумілими з розділів робочого процесу вище.
Вправа 1: переглянути останні N журналів (30 сек)
Розділ «Вправа 1: переглянути останні N журналів (30 сек)»# Task: Show last 20 log lineskubectl logs <pod> --tail=20Вправа 2: журнали з мітками часу (30 сек)
Розділ «Вправа 2: журнали з мітками часу (30 сек)»# Task: Show logs with timestampskubectl logs <pod> --timestampsВправа 3: попередні журнали контейнера (30 сек)
Розділ «Вправа 3: попередні журнали контейнера (30 сек)»# Task: Get logs from crashed containerkubectl logs <pod> --previousВправа 4: журнали з кількох контейнерів (1 хв)
Розділ «Вправа 4: журнали з кількох контейнерів (1 хв)»# Task: Get logs from specific containerkubectl get pod <pod> -o jsonpath='{.spec.containers[*].name}'kubectl logs <pod> -c <container-name>Вправа 5: нещодавні події (30 сек)
Розділ «Вправа 5: нещодавні події (30 сек)»# Task: Show events sorted by timekubectl get events --sort-by='.lastTimestamp'Вправа 6: події Warning (30 сек)
Розділ «Вправа 6: події Warning (30 сек)»# Task: Show only warning eventskubectl get events --field-selector type=WarningВправа 7: метрики нод (30 сек)
Розділ «Вправа 7: метрики нод (30 сек)»# Task: Show node resource usagekubectl top nodesВправа 8: відсортовані метрики Pod’ів (30 сек)
Розділ «Вправа 8: відсортовані метрики Pod’ів (30 сек)»# Task: Show top memory-consuming podskubectl top pods -A --sort-by=memory | headКритерії успіху
Розділ «Критерії успіху»- Переглянуто живі журнали зі стеженням і навмисно зупинено потік.
- Відфільтровано журнали на предмет помилок і пояснено, що фільтр приховує.
- Отримано попередні журнали контейнера з Pod’а, що перезапускається.
- Проаналізовано події на предмет інформації про падіння, життєвий цикл чи backoff.
- Використано
kubectl top, коли Metrics Server був доступний, або діагностовано, чому він був недоступний. - Впроваджено логування на основі sidecar для застосунку, що пише у файл.
- Співвіднесено журнали, події та метрики, щоб обрати наступну діагностичну дію.
Прибирання
Розділ «Прибирання»kubectl delete ns logging-labПеревірка для учня
Розділ «Перевірка для учня»Звичайна
kubectl logs deployment/<name>слідує за зв’язком з контролером, але стрімить журнали лише з одного представницького Pod’а в цьому Деплойменті; додайте--all-pods=true, коли вам потрібна кожна репліка.kubectl logs deployment/my-deployment --all-pods=true—usage above requests: under-requested; scheduling/QoS + eviction risk under node pressure—memory near/above limit: OOMKilled—CPU at limit: throttled (not killed).
Джерела
Розділ «Джерела»- Logging Architecture
- kubectl logs
- Resource Metrics Pipeline
- kubectl top
- kubectl top pod
- kubectl top node
- Debug Pods
- Debug Running Pods
- Sidecar Containers
- Event API
- kube-apiserver (
--event-ttl) - Kubelet Configuration
- Metrics Server
Наступний модуль
Розділ «Наступний модуль»Перейдіть до Частини 6: Пробні іспити, щоб перевірити ці прийоми усунення несправностей під тиском часу в стилі іспиту.