Модуль 3.2: Логування контейнерів
Складність:
[QUICK]— Необхідна щоденна навичка, прості командиЧас на виконання: 25–30 хвилин
Передумови: Модуль 1.1 (Поди), базове розуміння stdout/stderr
Що ви зможете робити
Розділ «Що ви зможете робити»Після завершення цього модуля ви зможете:
- Діагностувати проблеми застосунків шляхом запитів логів контейнерів за допомогою
kubectl logsта його опцій фільтрації - Реалізувати паттерни логування, що записують структурований вивід у stdout/stderr для збору Kubernetes
- Пояснити архітектуру логування Kubernetes і чому контейнери повинні писати логи в stdout, а не у файли
- Налаштувати доступ до логів для Підів з кількома контейнерами, вказавши правильне ім’я контейнера
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Логи — це ваше вікно у те, що відбувається всередині контейнерів. Коли щось іде не так, логи — зазвичай перше місце, куди ви дивитесь. Kubernetes не зберігає логи постійно — він надає доступ до stdout/stderr з працюючих контейнерів.
Іспит CKAD перевіряє вашу здатність:
- Переглядати логи контейнерів
- Отримувати логи попередніх екземплярів контейнерів
- Працювати з подами з кількома контейнерами
- Фільтрувати та шукати у виводі логів
Аналогія з бортовим самописцем
Логи контейнерів — як чорна скринька літака. Вони записують усе, що застосунок каже (stdout/stderr). Коли щось іде не так, ви витягуєте запис, щоб зрозуміти, що сталося. Але на відміну від чорної скриньки, Kubernetes зберігає лише нещодавні логи — якщо «літак» знищено і відбудовано, старий запис зникає.
Базові команди для логів
Розділ «Базові команди для логів»Перегляд логів
Розділ «Перегляд логів»# Базові логиk logs pod-name
# Слідкувати за логами (потік)k logs -f pod-name
# Останні N рядківk logs --tail=100 pod-name
# Логи з певного часуk logs --since=1h pod-namek logs --since=30m pod-namek logs --since=10s pod-name
# Логи з конкретного моментуk logs --since-time=2024-01-15T10:00:00Z pod-name
# Показати мітки часуk logs --timestamps pod-nameПоди з кількома контейнерами
Розділ «Поди з кількома контейнерами»# Вказати контейнер (обов'язково для кількох контейнерів)k logs pod-name -c container-name
# Усі контейнериk logs pod-name --all-containers=true
# Перелічити контейнери в подіk get pod pod-name -o jsonpath='{.spec.containers[*].name}'Попередній екземпляр контейнера
Розділ «Попередній екземпляр контейнера»# Логи попереднього контейнера, що впав/перезапустивсяk logs pod-name --previousk logs pod-name -p
# Попередній екземпляр конкретного контейнераk logs pod-name -c container-name --previousДжерела логів
Розділ «Джерела логів»Що записується в логи
Розділ «Що записується в логи»Kubernetes захоплює:
- stdout: Стандартний вивід процесів контейнера
- stderr: Стандартний потік помилок процесів контейнера
Застосунки МУСЯТЬ писати логи в stdout/stderr, щоб kubectl logs працював.
Що НЕ записується в логи
Розділ «Що НЕ записується в логи»- Файли, записані всередині контейнера (наприклад,
/var/log/app.log) - Системні логи вузла
- Логи init-контейнерів (використовуйте
-c init-container-name)
Логи на основі Deployment та міток
Розділ «Логи на основі Deployment та міток»Логи подів Deployment
Розділ «Логи подів Deployment»# Логи всіх подів з міткоюk logs -l app=myapp
# Слідкувати за логами всіх відповідних подівk logs -l app=myapp -f
# Обмежити кількість подівk logs -l app=myapp --max-log-requests=5
# З обмеженням рядківk logs -l app=myapp --tail=50Комбінування фільтрів
Розділ «Комбінування фільтрів»# Мітка + контейнер + tailk logs -l app=myapp -c nginx --tail=100
# Мітка + часk logs -l app=myapp --since=30mШаблони роботи з логами
Розділ «Шаблони роботи з логами»Потокове читання логів для налагодження
Розділ «Потокове читання логів для налагодження»# Потік з мітками часуk logs -f --timestamps pod-name
# Потік лише помилок (grep)k logs -f pod-name | grep -i error
# Потік з кількох подівk logs -f -l app=myapp --all-containersЕкспорт логів
Розділ «Експорт логів»# Зберегти у файлk logs pod-name > pod-logs.txt
# Зберегти з мітками часуk logs --timestamps pod-name > pod-logs-$(date +%s).txt
# Усі контейнериk logs pod-name --all-containers > all-logs.txtСценарії логування з кількома контейнерами
Розділ «Сценарії логування з кількома контейнерами»Шаблон Sidecar
Розділ «Шаблон Sidecar»apiVersion: v1kind: Podmetadata: name: sidecar-demospec: containers: - name: app image: nginx - name: sidecar image: busybox command: ['sh', '-c', 'while true; do echo sidecar running; sleep 10; done']# Переглянути логи основного застосункуk logs sidecar-demo -c app
# Переглянути логи sidecark logs sidecar-demo -c sidecar
# Усі контейнериk logs sidecar-demo --all-containersЛоги Init-контейнерів
Розділ «Логи Init-контейнерів»apiVersion: v1kind: Podmetadata: name: init-demospec: initContainers: - name: init-setup image: busybox command: ['sh', '-c', 'echo Init complete'] containers: - name: app image: nginx# Переглянути логи init-контейнераk logs init-demo -c init-setupВізуалізація логування
Розділ «Візуалізація логування»┌─────────────────────────────────────────────────────────────┐│ Логування контейнерів │├─────────────────────────────────────────────────────────────┤│ ││ Застосунок ││ │ ││ ▼ ││ stdout/stderr ─────────────▶ Container Runtime ││ │ ││ ▼ ││ /var/log/containers/ ││ /var/log/pods/ ││ │ ││ ▼ ││ kubectl logs ││ ││ ┌─────────────────────────────────────────────────────┐ ││ │ Під: my-pod │ ││ │ ┌──────────────┐ ┌──────────────┐ │ ││ │ │ Контейнер A │ │ Контейнер B │ │ ││ │ │ (stdout) │ │ (stdout) │ │ ││ │ │ (stderr) │ │ (stderr) │ │ ││ │ └──────────────┘ └──────────────┘ │ ││ │ │ │ │ ││ │ ▼ ▼ │ ││ │ k logs -c a k logs -c b │ ││ └─────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────┘Швидка довідка
Розділ «Швидка довідка»# Основні командиk logs POD # Базові логиk logs POD -f # Слідкувати/потікk logs POD --tail=100 # Останні 100 рядківk logs POD --since=1h # За останню годинуk logs POD -c CONTAINER # Конкретний контейнерk logs POD --previous # Попередній екземплярk logs POD --all-containers # Усі контейнериk logs -l app=myapp # За міткоюk logs POD --timestamps # З мітками часуЧи знали ви?
Розділ «Чи знали ви?»-
Логи зберігаються на вузлі за шляхами
/var/log/containers/та/var/log/pods/. Коли під видаляється, ці логи врешті-решт очищуються. -
У Kubernetes немає вбудованої агрегації логів. Для продакшну команди використовують такі інструменти, як Fluentd, Fluent Bit, Loki або Elasticsearch, щоб збирати та зберігати логи централізовано.
-
Ротацію логів виконує середовище виконання контейнерів. Типово Docker/containerd ротує логи, щоб запобігти переповненню диска, але це означає, що старі логи зникають.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому це шкодить | Рішення |
|---|---|---|
Забули -c для кількох контейнерів | Помилка: потрібно вказати контейнер | Спочатку перелічіть контейнери, потім вкажіть |
| Шукаєте логи видаленого пода | Логи зникли | Використовуйте --previous до перезапуску пода |
| Застосунок пише логи у файли, а не stdout | kubectl logs нічого не показує | Налаштуйте застосунок писати в stdout |
Не використовуєте --tail для великих логів | Термінал заливає потоком даних | Завжди обмежуйте початковий вивід |
| Ігнорування логів init-контейнерів | Пропуск помилок налаштування | Перевіряйте init-контейнери з -c |
Тест
Розділ «Тест»-
Як переглянути логи попереднього екземпляра контейнера?
Відповідь
`kubectl logs pod-name --previous` або `kubectl logs pod-name -p` -
Як переглянути логи конкретного контейнера в поді з кількома контейнерами?
Відповідь
`kubectl logs pod-name -c container-name` -
Як переглянути останні 50 рядків логів за останню годину?
Відповідь
`kubectl logs pod-name --since=1h --tail=50` -
Як слідкувати за логами всіх подів з міткою
app=web?Відповідь
`kubectl logs -l app=web -f` (додайте `--max-log-requests=N`, якщо подів багато)
Практична вправа
Розділ «Практична вправа»Завдання: Попрактикуватися в отриманні логів з різних конфігурацій подів.
Підготовка:
# Створити під, що генерує логиcat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: log-demo labels: app: log-demospec: containers: - name: logger image: busybox command: ['sh', '-c', 'i=0; while true; do echo "$(date) - Log entry $i"; i=$((i+1)); sleep 2; done']EOFЧастина 1: Базові логи
# Переглянути логиk logs log-demo
# Слідкувати за логами (Ctrl+C для зупинки)k logs log-demo -f
# Останні 5 рядківk logs log-demo --tail=5
# З мітками часуk logs log-demo --timestamps --tail=5Частина 2: Кілька контейнерів
# Створити під з кількома контейнерамиcat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: multi-logspec: containers: - name: app image: nginx - name: sidecar image: busybox command: ['sh', '-c', 'while true; do echo Sidecar log; sleep 5; done']EOF
# Перелічити контейнериk get pod multi-log -o jsonpath='{.spec.containers[*].name}'
# Переглянути кожний контейнерk logs multi-log -c appk logs multi-log -c sidecar
# Усі контейнериk logs multi-log --all-containersЧастина 3: Попередній екземпляр
# Створити під, що падаєcat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: crasherspec: containers: - name: app image: busybox command: ['sh', '-c', 'echo "Starting..."; echo "About to crash!"; exit 1']EOF
# Зачекати на перезапуск, потім перевірити попередні логиk get pod crasher -wk logs crasher --previousОчищення:
k delete pod log-demo multi-log crasherПрактичні вправи
Розділ «Практичні вправи»Вправа 1: Базові логи (Ціль: 1 хвилина)
Розділ «Вправа 1: Базові логи (Ціль: 1 хвилина)»# Створити підk run drill1 --image=nginx
# Переглянути логиk logs drill1
# Очищенняk delete pod drill1Вправа 2: Слідкування за логами (Ціль: 2 хвилини)
Розділ «Вправа 2: Слідкування за логами (Ціль: 2 хвилини)»# Створити під з логуваннямk run drill2 --image=busybox -- sh -c 'while true; do echo tick; sleep 1; done'
# Слідкувати (Ctrl+C після кількох тіків)k logs drill2 -f
# Очищенняk delete pod drill2Вправа 3: Кілька контейнерів (Ціль: 3 хвилини)
Розділ «Вправа 3: Кілька контейнерів (Ціль: 3 хвилини)»cat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: drill3spec: containers: - name: web image: nginx - name: monitor image: busybox command: ['sh', '-c', 'while true; do echo monitoring; sleep 5; done']EOF
# Отримати логи з кожногоk logs drill3 -c webk logs drill3 -c monitor
# Очищенняk delete pod drill3Вправа 4: Вибір за мітками (Ціль: 2 хвилини)
Розділ «Вправа 4: Вибір за мітками (Ціль: 2 хвилини)»# Створити кілька подівk run drill4a --image=nginx -l app=drill4k run drill4b --image=nginx -l app=drill4
# Логи всіх з міткоюk logs -l app=drill4
# Очищенняk delete pod -l app=drill4Вправа 5: Попередній екземпляр (Ціль: 3 хвилини)
Розділ «Вправа 5: Попередній екземпляр (Ціль: 3 хвилини)»# Створити під, що падаєcat << 'EOF' | k apply -f -apiVersion: v1kind: Podmetadata: name: drill5spec: containers: - name: app image: busybox command: ['sh', '-c', 'echo "Run at $(date)"; sleep 5; exit 1']EOF
# Спостерігати за падіннямk get pod drill5 -w
# Після перезапуску отримати попередні логиk logs drill5 --previous
# Очищенняk delete pod drill5Вправа 6: Повний сценарій логування (Ціль: 4 хвилини)
Розділ «Вправа 6: Повний сценарій логування (Ціль: 4 хвилини)»Сценарій: Відлагодити застосунок, що не працює, використовуючи логи.
# Створити «зламаний» 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: app image: busybox command: ['sh', '-c', 'echo "Starting app"; echo "ERROR: Database connection failed"; exit 1']EOF
# Знайти подиk get pods -l app=drill6
# Перевірити логи одного подаk logs -l app=drill6 --tail=10
# Отримати логи попереднього екземпляраPOD=$(k get pods -l app=drill6 -o jsonpath='{.items[0].metadata.name}')k logs $POD --previous
# Очищенняk delete deploy drill6Наступний модуль
Розділ «Наступний модуль»Модуль 3.3: Налагодження в Kubernetes — Усунення несправностей подів, контейнерів та проблем кластера.