Логи в Kubernetes

Приложения и системы, регистрирующие выходные данные в каком-то волшебном месте, которое мы в конечном итоге находим в операционной системе или по системному пути, были спасителями каждого системного администратора и разработчика с момента появления компьютеров.

В Kubernetes все по-другому.

Без надлежащего ведения журналов и общего потребления журналов вы никогда не сможете устранять неполадки, происходящие в вашей среде Kubernetes.

В этом посте вы узнаете, что такое ведение журнала, различные методологии ведения журнала в Kubernetes и как их можно реализовать в рабочей среде.

Что такое ведение журнала

Вы когда-нибудь видели всплывающую ошибку на экране, когда вы пытались что-то установить или использовать определенный инструмент/платформу?

Вам когда-нибудь приходилось садиться за компьютер и смотреть на вывод определенного приложения? Это журналы.

Журналы содержат информацию о системе, операционной системе, приложении и многих других аспектах, при условии, что везде, где вы просматриваете журналы, поддерживается ведение журнала. Это означает, что каждое приложение имеет возможность отправлять журналы, но иногда они этого не делают. Разработчик должен реализовать функциональность для сохранения/вывода журналов для приложения.

Ведение журнала было спасением почти для всех в технологическом пространстве. Независимо от того, являетесь ли вы системным администратором, облачным инженером, разработчиком или кем-то еще, почти гарантировано, что в какой-то момент вы просматривали журналы для решения конкретной проблемы.

Короче говоря, журналы — это события, которые происходят на компьютере или в приложении.

Типы журналов логов в Kubernetes

В Kubernetes вы будете заботиться о двух разных типах журналов:

  • Журналы кластера
  • Журналы ресурсов/объектов Kubernetes

Журналы кластера относятся к тому, как работает кластер. Исправна ли плоскость управления, исправны ли рабочие узлы, и в зависимости от того, как они установлены, как работают компоненты Kubernetes (и т. д., планировщик, сервер API и т. д.). Например, в стандартных развертываниях Kubeadm Etcd будет работать как Pod, поэтому он будет считаться «журналом ресурсов/объектов Kubernetes». Однако, если Etcd настроен для кластеров, работающих на собственном сервере, он может не загружаться как под и, следовательно, будет считаться «кластерным журналом».

Журналы ресурсов/объектов Kubernetes — это любой запущенный ресурс Kubernetes. Вы можете получать журналы и события для различных ресурсов Kubernetes, но основная часть того, на что обычно обращают внимание инженеры, — это журналы Pod и контейнеров, поскольку это основное место, где вы можете получить информацию о запущенном приложении.

Самый быстрый способ проверить журналы для модулей — с помощью kubectl logs pod_nameкоманды. Однако kubectl logsработайте только над проверкой журналов для модулей и никаких других ресурсов Kubernetes.

Различные типы методов ведения журнала в Kubernetes

Когда вы думаете о своей стратегии ведения журналов для среды Kubernetes, существует несколько различных способов вывода журналов:

  • Переадресация приложений
  • Коляска
  • Агент узла вперед

Давайте сломаем их.

Переадресация приложений выполняется внутри кода приложения. Например, предположим, вы пишете фронтальное приложение. Внутри приложения вы можете указать логику, которая говорит «отправлять журналы отсюда в эту систему». Хотя это может показаться простым, возможно, это худший способ управления журналами. Почему?

Потому что вы ставите зависимость от кода и системы ведения журнала. Что делать, если система ведения журналов изменится? Собираетесь ли вы реализовать это для каждого приложения и части каждого приложения? Этого метода следует избегать всегда, если только у вас нет какой-то смехотворно убедительной причины для вас.

Например, веская причина сделать это — если у вас есть устаревшее приложение, в которое уже встроены функции ведения журнала (хотя вы должны планировать, как изменить эту функциональность в будущем).

Метод sidecar будет, если вы внедрите агрегатор журналов в модуль Kubernetes. В итоге у вас есть два контейнера в одном поде. Один из контейнеров — это само приложение, а другой — используемая вами система ведения журналов. Это «хороший» метод, и его определенно следует использовать вместо перенаправления приложений, но есть и лучший метод — перенаправление агента узла.

Метод Node Agent Forwarding — это Pod, который запускается на каждом рабочем узле Kubernetes. Работа Pod заключается в чтении файлов журналов контейнерного приложения и отправке их на любой инструмент/платформу ведения журнала, которую вы используете. Это лучший метод по нескольким причинам. 1) Вы не реализуете sidecar, который удаляет дополнительные функции для Pod, которые технически должны выполнять одну работу. 2) Разделяет процессы рабочей нагрузки и наличие зависимостей, и, в свою очередь, у вас есть один ресурс Kubernetes (Pod), который выполняет одну работу (отправляет журналы).

Журналы аудита Kubernetes

Дело в том, что журналы могут рассматриваться практически как любые выходные данные.

События, журналы приложений, вывод терминала, события выхода и многое другое. Из-за этого мы не можем охватить все без того, чтобы этот пост в блоге не превратился в технический документ, поэтому давайте остановимся на самом важном.

Чтобы начать практическую часть этой записи в блоге, вы начнете с журналов аудита Kubernetes.

Журналы аудита Kubernetes дают вам возможность собирать и просматривать любые выходные данные, которые создает ресурс Kubernetes. Например, когда вы создаете развертывание Kubernetes, происходит много всего.

  • Образ контейнера извлекается из реестра.
  • Поды планируются на рабочих узлах.
  • Модули либо запускаются, либо выходят из строя, и если они выходят из строя, на это есть причина.
  • Масштабирование на модулях выполнено.

Из-за этой детали вы можете захотеть собрать определенные журналы или, может быть, вы хотите их все.

Например, ниже Policyресурс Kubernetes используется для создания политики аудита, которая буквально собирает все, что возможно, из каждого отдельного ресурса Kubernetes.

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata

Во-первых, давайте посмотрим, как это делается в локальном кластере Kubernetes. Например, загрузился с помощью Kubeadm, так как он сильно отличается от облачных сервисов. Затем вы увидите, как настраивается аудит для облачных служб.

Kubeadm

Сначала создайте новый YAML для политики, которую вы хотите создать.

sudo vim /etc/kubernetes/kubeadmpolicy.yaml

Далее укажите политику. Например, вы можете использовать приведенную ниже политику, которая собирает журналы аудита для модулей и всех, кто проходит аутентификацию в API.

apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
  - "RequestReceived"
rules:
  - level: RequestResponse
    resources:
    - group: ""
      resources: ["pods"]

  - level: Metadata
    resources:
    - group: ""
      resources: ["pods/log", "pods/status"]

  - level: None
    userGroups: ["system:authenticated"]
    nonResourceURLs:
    - "/api*"
    - "/version"

После сохранения вам необходимо обновить сервер API. При начальной загрузке кластера Kubernetes с помощью Kubeadm все манифесты для модулей, составляющих плоскость управления, находятся в разделе /etc/kubernetes/manifests.

Откройте kube-apiserver.yamlМанифест.

sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml

Сохраните следующие строки в kube-apiserverконфигурации, которые будут указывать, куда вы хотите вести журналы, и политику, которую вы создали выше.

- --audit-log-path=/var/log/audit.log
- --audit-policy-file=/etc/kubernetes/kubeadmpolicy.yaml

Описание изображения

Далее укажите политику аудита и журнал в качестве точки монтирования.

*- mountPath: /etc/kubernetes/kubeadmpolicy.yaml*
  *name: audit*
  *readOnly: true*
*- mountPath: /var/log/audit.log*
  *name: audit-log*
  *readOnly: false*

Описание изображения

Последним шагом является указание пути хоста томов для ранее созданных путей монтирования.

*- hostPath:
    path: /etc/kubernetes/kubeadmpolicy.yaml
    type: File
  name: audit
- hostPath:
    path: /var/log/audit.log
    type: FileOrCreate
  name: audit-log*

Описание изображения

После завершения перезапустите Kubelet.

sudo systemctl restart kubelet

Теперь вы должны увидеть журналы в следующем месте.

tail -f /var/log/audit.log

Служба Azure Kubernetes

По умолчанию аудит включен в AKS, и существует политика аудита для сбора всего со всех ресурсов Kubernetes.

Однако функция просмотра журналов аудита не включена по умолчанию. Чтобы включить его, сделайте следующее.

Сначала перейдите в свой кластер AKS и в разделе «Мониторинг» нажмите «Параметры диагностики» . Затем нажмите синюю кнопку + Добавить параметры диагностики .

Описание изображения

В настройках диагностики щелкните категорию «Аудит Kubernetes» . На этом этапе у вас будет возможность выбрать, где вы хотите сохранить журналы. Для целей этого раздела вы можете выбрать параметр «Отправить в рабочую область Log Analytics» .

Описание изображения

Теперь, когда аудит включен, вы можете открыть рабочую область аналитики и выполнить запрос для получения событий.

Например, приведенный ниже запрос будет запрашивать все журналы аудита Kubernetes.

AzureDiagnostics
| where Category == "kube-audit"
| project log_s

Вы можете увидеть пример вывода ниже.

Описание изображения

Сервис AWS Elastic Kubernetes

Для AWS ведение журнала аудита по умолчанию не включено. Вы можете включить его при создании кластера Kubernetes, и тогда журналы аудита по умолчанию будут отправляться в CloudWatch.

Описание изображения

События Kubernetes

В этом разделе вы узнаете, как получать события Kubernetes, которые сами по себе являются журналами.

Событие — это ресурс/объект Kubernetes. это происходит, когда происходит изменение с другим ресурсом/объектом Kubernetes, будь то модули, службы, узлы и т. д.…

Вы можете запустить kubectl get eventsкоманду, чтобы увидеть, что происходит внутри кластера.

kubectl get events
LAST SEEN   TYPE     REASON                    OBJECT              MESSAGE
5m1s        Normal   NodeHasSufficientMemory   node/stdkubeadmwn   Node stdkubeadmwn status is now: NodeHasSufficientMemory
5m1s        Normal   NodeHasNoDiskPressure     node/stdkubeadmwn   Node stdkubeadmwn status is now: NodeHasNoDiskPressure
5m1s        Normal   NodeHasSufficientPID      node/stdkubeadmwn   Node stdkubeadmwn status is now: NodeHasSufficientPID
5m1s        Normal   NodeReady                 node/stdkubeadmwn   Node stdkubeadmwn status is now: NodeReady
5m11s       Normal   NodeNotReady              node/stdkubeadmwn   Node stdkubeadmwn status is now: NodeNotReady

Однако ничего особенного не происходит, потому что kubectl get eventsкоманда была запущена в новом кластере. Давайте бросим на него немного трафика, чтобы сгенерировать некоторые события.

Запустите следующий YAML, который развернет развертывание Nginx Kubernetes.

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginxdeployment
  replicas: 2
  template:
    metadata:
      labels:
        app: nginxdeployment
    spec:
      containers:
      - name: nginxdeployment
        image: nginx:latest
        ports:
        - containerPort: 80
EOF

Если вы снова запустите kubectl get eventsкоманду, вы увидите еще несколько событий, так как были созданы модули для развертывания Nginx, а образ контейнера Nginx был извлечен для реестра Docker.

mike@stdkubeadmcp:~$ kubectl get events
LAST SEEN   TYPE     REASON                    OBJECT                                   MESSAGE
1s          Normal   Scheduled                 pod/nginx-deployment-574db6c95f-fr8qb    Successfully assigned default/nginx-deployment-574db6c95f-fr8qb to stdkubeadmwn
1s          Normal   Pulling                   pod/nginx-deployment-574db6c95f-fr8qb    Pulling image "nginx:latest"
1s          Normal   Scheduled                 pod/nginx-deployment-574db6c95f-llzzd    Successfully assigned default/nginx-deployment-574db6c95f-llzzd to stdkubeadmwn
1s          Normal   Pulling                   pod/nginx-deployment-574db6c95f-llzzd    Pulling image "nginx:latest"
1s          Normal   SuccessfulCreate          replicaset/nginx-deployment-574db6c95f   Created pod: nginx-deployment-574db6c95f-fr8qb
1s          Normal   SuccessfulCreate          replicaset/nginx-deployment-574db6c95f   Created pod: nginx-deployment-574db6c95f-llzzd
1s          Normal   ScalingReplicaSet         deployment/nginx-deployment              Scaled up replica set nginx-deployment-574db6c95f to 2
6m16s       Normal   NodeHasSufficientMemory   node/stdkubeadmwn                        Node stdkubeadmwn status is now: NodeHasSufficientMemory
6m16s       Normal   NodeHasNoDiskPressure     node/stdkubeadmwn                        Node stdkubeadmwn status is now: NodeHasNoDiskPressure
6m16s       Normal   NodeHasSufficientPID      node/stdkubeadmwn                        Node stdkubeadmwn status is now: NodeHasSufficientPID
6m16s       Normal   NodeReady                 node/stdkubeadmwn                        Node stdkubeadmwn status is now: NodeReady
6m26s       Normal   NodeNotReady              node/stdkubeadmwn                        Node stdkubeadmwn status is now: NodeNotReady

Как вы можете себе представить, выполнение в kubectl get eventsконечном итоге приведет к извлечению тонны данных в зависимости от того, насколько новый кластер.

Чтобы получить более конкретный список событий, вы можете настроить таргетинг на конкретный ресурс Kubernetes.

В приведенном ниже примере видно, что describeкоманда используется для просмотра событий (и многих других компонентов) развертывания Kubernetes.

kubectl describe deployment nginx-deployment

Если вы прокрутите вывод команды вниз describe, вы увидите вывод, аналогичный приведенному ниже выводу, в котором показаны события для ресурса.

Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  38s   deployment-controller  Scaled up replica set nginx-deployment-574db6c95f to 2

Заключение

Ведение журнала логов в Kubernetes очень похоже на любой другой метод ведения журнала — собирайте события, просматривайте их и используйте их для устранения неполадок или понимания того, что происходит в системе и в приложении. Здесь следует помнить, что вы должны отправлять журналы в правильное место, которое может быть использовано всей командой.