← Kubernetes: наблюдаемость
7 мин · средне · Урок 1 из 3

kubectl logs и многоконтейнерный Pod

Откуда kubectl берёт логи, какие флаги реально используют и почему --previous иногда возвращает пустоту.

Как Kubernetes собирает логи

контейнер stdout, stderr пишет runtime 0.log на ноде читает kubelet отдаёт через API отдаёт kubectl logs то, что видно вам
kubectl logs показывает файл на ноде, а не живой поток из контейнера.

Контейнер пишет в stdout и stderr. Container runtime (containerd или cri-o) перехватывает потоки и складывает в файл на ноде: /var/log/pods/<namespace>_<pod>_<uid>/<container>/0.log. Kubelet читает этот файл и отдаёт через API на запросы вида GET /api/v1/namespaces/.../pods/.../log. kubectl logs это тонкая обёртка над этим API.

Из этого следует две вещи:

kubectl logs: основные флаги

Базовая команда:

kubectl logs <pod>

Если в Pod несколько контейнеров, команда вернёт ошибку:

error: a container name must be specified for pod <pod>

Решение, флаг -c:

kubectl logs <pod> -c <container>

Полезные флаги:

kubectl logs <pod> --tail=50 --timestamps
kubectl logs <pod> -c <container> --previous
kubectl logs -l app=web --tail=20

Многоконтейнерный Pod

В одном Pod может быть несколько контейнеров. Они шарят сеть и тома, но stdout у каждого свой.

Pod my-pod
 ├─ app      свой stdout   -c app
 └─ sidecar  свой stdout   -c sidecar

Стандартные паттерны:

Когда kubectl logs вызывают без -c, kubectl требует явно указать контейнер:

kubectl logs my-pod -c app
kubectl logs my-pod -c sidecar

Если нужно сразу всё со всех контейнеров Pod, есть --all-containers:

kubectl logs my-pod --all-containers --prefix

--prefix добавит к каждой строке имя контейнера, иначе они смешаются и не разобрать, где чьё.

--previous и зачем он нужен

Логи живут не в API, а в файлах на ноде. Когда kubelet перезапускает контейнер, он создаёт новый файл (0.log, потом 1.log). Текущий kubectl logs отдаёт самый свежий. Чтобы посмотреть, что писал контейнер в прошлой жизни, перед падением, нужен --previous:

kubectl logs my-pod --previous
kubectl logs my-pod -c app --previous

Это работает, только пока контейнер был перезапущен на той же ноде и файл предыдущего instance ещё не ротирован. Если Pod пересоздался полностью (Deployment поднял новый Pod на другом узле), --previous уже ничего не покажет: новый Pod это новые файлы логов с нуля.

Домашка

Теорию закрепляет задание на своём кластере: 2 шага с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.

./run.sh start k8s-logging     # развернуть стартовое состояние
./run.sh verify k8s-logging    # проверить текущий шаг

Коротко

Прошли материал до конца? Отметьте урок пройденным.