Логи приложения

Уровень: expert ~40 мин Практика: Umami (продолжение) (MIT)

Что нужно знать перед уроком

  • M10.02 — Кастомные дашборды и алерты — продолжение серии тем observability модуля M10

Что нужно знать перед уроком

M10 урок 2 — метрики и алерты. Этот урок закрывает третью опору observability — логи, разбирая путь от stdout контейнера до централизованного хранилища.

Теория

Путь лога: от stdout контейнера до log-shipper

Kubernetes по умолчанию собирает stdout/stderr каждого контейнера в файлы на узле (/var/log/containers/) — стандартный механизм container runtime. Модуль log-shipper Deckhouse — это уровень, который читает эти файлы на каждом узле, применяет фильтрацию/трансформацию и отправляет результат в одно или несколько настроенных назначений.

PodLoggingConfig — что собирать (namespace-scoped источник)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: deckhouse.io/v1alpha1
kind: PodLoggingConfig
metadata:
  name: {{.Application.Instance.Name}}-logs
  namespace: {{.Release.Namespace}}
spec:
  labelSelector:
    matchLabels:
      app: {{.Application.Instance.Name}}
  clusterDestinationRefs:
    - loki-storage

PodLoggingConfig — namespaced-ресурс, который Application-разработчик может создавать в своём собственном namespace — это именно та часть логирования, которая находится в зоне ответственности разработчика приложения: указать, какие поды (по labelSelector) собирать, и куда отправлять (clusterDestinationRefs, ссылка на уже существующий, настроенный администратором ClusterLogDestination).

ClusterLogDestination — куда отправлять (cluster-scoped назначение)

1
2
3
4
5
6
7
8
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
  name: loki-storage
spec:
  type: Loki
  loki:
    endpoint: http://loki.loki:3100

ClusterLogDestination — cluster-scoped ресурс, конфигурирующий конкретное назначение: Loki (встроенное краткосрочное хранилище Deckhouse), Socket+GELF (для внешних систем вроде Graylog), и другие типы (Elasticsearch, Kafka и подобные — в зависимости от установленной версии Deckhouse). Пример для Graylog через Socket+GELF-кодек:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
  name: graylog-dest
spec:
  type: Socket
  socket:
    address: graylog.svc.cluster.local:9200
    mode: TCP
    encoding:
      codec: GELF

Разграничение ответственности: разработчик Application vs администратор кластера

РесурсКто настраиваетОбласть
PodLoggingConfigApplication-разработчикNamespace приложения — что собирать
ClusterLogDestinationАдминистратор кластераCluster-wide — куда отправлять

Это то же самое разделение, что и с CustomAlertmanager в M10 уроке 2: конкретные назначения (внешние системы, требующие сетевого доступа и учётных данных) — прерогатива администратора, а конкретизация того, что относится к его приложению — зона ответственности разработчика.

Loki как встроенное краткосрочное хранилище

Loki в составе Deckhouse — обычно предназначен для относительно краткосрочного хранения (retention измеряется днями/неделями, не месяцами/годами) и оперативной отладки через встроенный интерфейс Grafana. Для долгосрочного хранения логов (аудит, соответствие регуляторным требованиям) типично используются внешние назначения (Graylog, Elasticsearch) с собственной, более долговременной retention-политикой, настроенной администратором.

Частые ошибки и подводные камни

  • Пытаться создать ClusterLogDestination из шаблонов Application-пакета. Это cluster-scoped ресурс, требующий административных прав — Application должен только ссылаться на уже существующее назначение через clusterDestinationRefs, а не создавать его самостоятельно.
  • Полагаться на Loki для долгосрочного хранения логов без проверки реальной retention-политики. Встроенный Loki обычно настроен на относительно короткий срок хранения — для требований долгосрочного аудита нужно уточнить у администратора кластера доступные назначения с более длительным retention.
  • Не указывать labelSelector в PodLoggingConfig, собирая логи всех подов namespace без разбора. Если в одном namespace развёрнуто несколько компонентов (например, основное приложение и вспомогательный воркер), без точного labelSelector в целевое назначение попадёт избыточный объём нерелевантных логов.

Практика в кластере

🧩 Практика урока: Umami (продолжение) · лицензия MIT
1
2
d8 k get clusterlogdestination -A
d8 k get podloggingconfig -n course-m10-umami

Найдите доступные в вашем практическом кластере ClusterLogDestination (типично Loki, настроенный по умолчанию Deckhouse CE) и создайте PodLoggingConfig для пакета Umami, ссылающийся на него.

Практика разработки

Добавьте в шаблоны пакета Umami ресурс PodLoggingConfig с labelSelector, точно нацеленным на поды именно этого инстанса приложения (используя .Application.Instance.Name), избегая избыточного захвата логов других компонентов namespace.

Шпаргалка команд урока

1
2
d8 k get clusterlogdestination -A
d8 k logs -n <namespace> -l app=<name> --tail=100    # прямой доступ к логам подов без log-shipper

Вопросы для самопроверки

Какой ресурс Application-разработчик создаёт в своём собственном namespace для настройки логирования?

Это namespace-scoped часть конфигурации, доступная разработчику приложения.

Источник: Deckhouse — Logging

Кто обычно настраивает ClusterLogDestination?

Аналогично CustomAlertmanager — централизованная настройка назначений на уровне кластера.

Источник: Рекомендуемая литература

Подходит ли встроенный Loki для долгосрочного хранения логов с целью регуляторного аудита?

Retention Loki по умолчанию короче, чем требуется для долгосрочного аудита.

Источник: Рекомендуемая литература

Что произойдёт, если не указать labelSelector в PodLoggingConfig?

Точный selector важен при нескольких компонентах в одном namespace.

Источник: Рекомендуемая литература

Рекомендуемая литература

Официальная документация

Статьи и блоги

Книги

  • Brendan Burns, David Oppenheimer. Designing Distributed Systems. 2018. ISBN 978-1491983645.
  • Marko Lukša. Kubernetes in Action. 2nd ed., 2022. ISBN 978-1617297618.

Связанные материалы