kubectl logs и многоконтейнерный Pod
Откуда kubectl берёт логи, какие флаги реально используют и почему --previous иногда возвращает пустоту.
Как Kubernetes собирает логи
Контейнер пишет в 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 его
не увидит. В образе должен быть либо вывод в stdout/stderr, либо
symlink на
/dev/stdout. - Файл логов на ноде ротируется (дефолт 10 МБ на файл, 5 файлов на контейнер). Старее этого окна kubectl logs ничего не отдаст. Для долгого хранения нужен внешний коллектор (Loki, ELK, Fluent Bit), но это уже за пределами базового kubectl.
kubectl logs: основные флаги
Базовая команда:
kubectl logs <pod>
Если в Pod несколько контейнеров, команда вернёт ошибку:
error: a container name must be specified for pod <pod>
Решение, флаг -c:
kubectl logs <pod> -c <container>
Полезные флаги:
-f(follow) стримит логи в реальном времени, пока не нажать Ctrl+C.--tail=Nпоказывает последние N строк. По умолчанию kubectl отдаёт всё, для долгоживущих Pod это большой объём.--since=10mпоказывает только записи за последние 10 минут. Можно--since-time=2026-01-01T00:00:00Z.--previousпоказывает логи предыдущего instance контейнера (детали и ограничения в секции ниже).--timestampsпрефиксит каждую строку временной меткой.-l app=webзабирает логи со всех Pod по селектору. Удобно для Deployment с несколькими репликами.
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
Стандартные паттерны:
- Sidecar. Помощник к основному контейнеру. Например, nginx и рядом
log-shipper, который читает access.log из общего тома и отправляет
в Loki. С 1.33 такой sidecar принято описывать как initContainer с
restartPolicy: Always: он стартует раньше основного и гасится после него. Дляkubectl logsразницы нет,-c <имя>работает одинаково. - Adapter. Преобразует выход основного контейнера в нужный формат.
- Ambassador. Прокси к внешним сервисам.
Когда 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 # проверить текущий шаг
Коротко
- Логи это stdout и stderr контейнера, сложенные runtime в файл на ноде; kubectl logs читает их через API kubelet.
- Запись в файл внутри контейнера в
kubectl logsне попадёт. - Ротация на ноде (по умолчанию 10 МБ × 5 файлов) ограничивает глубину истории, дальше нужен внешний коллектор.
- В многоконтейнерном Pod контейнер выбирают через
-c, всё разом забирают через--all-containers --prefix. --previousпокажет логи упавшего instance, только если Pod перезапустился на той же ноде и файл ещё не ротирован.
Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс