Kubernetes — Как читать журналы, которые записываются в файлы в pods вместо stdout / stderr?

#kubernetes

#kubernetes

Вопрос:

У меня есть pod в состоянии CrashLoopBackOff , журналы, которые я вижу из kubectl logs <pod-name> -p , представляют собой лишь частичную картинку. Другие журналы находятся в других файлах (например, /var/log/something/something.log ).

Поскольку этот pod разбился, я не могу kubectl exec войти в тамошнюю оболочку и посмотреть файлы.

Как я могу просмотреть файлы журналов, созданные контейнером, который больше не запущен?

Чтобы быть более конкретным, я ищу файлы журналов под $HOME/logs/es.log (в контейнере, который потерпел неудачу)

Комментарии:

1. Журналы Docker хранятся на рабочих узлах под /var/log/containers/ . Если у вас не включена ротация, они сохраняются, даже если pods не запущены.

2. Я не ищу журналы docker. возможно, мне следовало быть более ясным. Журналы, которые я ищу, находятся по адресу $HOME/logs /es.log

3. Ах. В этом случае, если журналы не записываются на постоянный том, нет способа получить к ним доступ после удаления контейнера. Однако имейте в виду, что любой вывод stdout и stderr перехватывается docker и записывается в /var/log/containers/ . Итак, если содержимое $HOME/logs/es.log также было записано в stdout, вы должны иметь возможность получить к ним доступ с рабочего узла, на котором он изначально запускался.

Ответ №1:

Я был настолько разочарован отсутствием решения этой, казалось бы, распространенной проблемы, что создал образ docker, который отслеживает файлы журналов и отправляет их в stdout для использования в качестве контейнера sidecar.


Вот что я сделал:

  1. Я добавил том с emptyDir{} в pod
  2. Я подключил этот том к своему основному контейнеру, причем mountPath является каталогом, в который он записывает журналы
  3. Я добавил в pod другой контейнер, называемый «logger», с изображением, являющимся написанным мной средством отслеживания журналов ( lutraman/logger-sidecar:v2 ), и подключил тот же том к /logs (я запрограммировал скрипт для чтения журналов из этого каталога)

затем все журналы, записанные в этот каталог, могут быть доступны kubectl logs <pod-name> -c logger


Вот пример yaml:

 apiVersion: apps/v1
kind: Deployment
metadata:
  name: dummy
  labels:
    app: dummy
spec:
  selector:
    matchLabels:
      app: dummy
  template:
    metadata:
      labels:
        app: dummy
    spec:
      volumes:
        - name: logs
          emptyDir: {}
      containers:
        - name: dummy-app # the app that writes logs to files
          image: lutraman/dummy:v2
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP
          env:
            - name: MESSAGE
              value: 'hello-test'
            - name: LOG_FILE
              value: '/var/log/app.log'
          volumeMounts:
            - name: logs
              mountPath: /var/log
        - name: logger # the sidecar container tracking logs and sending them to stdout
          image: lutraman/logger-sidecar:v2
          volumeMounts:
            - name: logs
              mountPath: /logs
  

Для всех, кому интересно, вот как я создал контейнер sidecar:

Dockerfile:

 FROM alpine:3.9

RUN apk add bash --no-cache

COPY addTail /addTail
COPY logtrack.sh /logtrack.sh

CMD ["./logtrack.sh"]

  

addTail:

 #!/bin/sh

(exec tail -F logs/$3 | sed "s/^/$3: /" ) amp;
echo $! >> /tmp/pids
  

logtrack.sh:

 #!/bin/bash

trap cleanup INT

function cleanup() {
  while read pid; do kill $pid; echo killed $pid; done < /tmp/pids
}

: > /tmp/pids

for log in $(ls logs); do
  ./addTail n logs $log
done

inotifyd ./addTail `pwd`/logs:n 
  

Комментарии:

1. как насчет ‘logrotate’? это было рассмотрено?

2. Спасибо, что поделились! Это похоже на разделы «Использование контейнера sidecar с агентом ведения журнала» в официальной документации k8s. kubernetes.io/docs/concepts/cluster-administration/logging /…

3. Аналогично вопросу @Tun, вы периодически очищали файл журнала? Поскольку теперь файл журнала дублируется в stdout, это удвоит использование диска

4. @yusong вы правы, это удвоит размер на диске за время работы pod. В моем случае это было не очень актуально, поскольку исходные файлы сохранялись в fs контейнера, который является эфемерным и будет удаляться при каждом перезапуске (что в моем случае было достаточно частым, чтобы не беспокоиться). Остальные журналы сохраняются в elastic, для которых у меня есть ротация. Это обоснованная проблема, если у вас большие файлы журналов и между перезапусками проходит много времени

5. Или вы можете поместить стандартный вывод в logback.xml проблема решена

Ответ №2:

В принципе, здесь у вас есть несколько вариантов.

Если вы хотите продолжить, как есть, с вашей настройкой,

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

 $ kubectl get pod my-pod -o custom-columns=Node:{.spec.nodeName} --no-headers
my-worker-node
  

Затем, если у вас есть доступ к этому узлу (например, через shh), вы можете найти контейнер:

 $ ID=$(docker ps -a | grep my-pod | grep -v POD | cut -d" " -f1)
$ docker cp $ID:/my.log .
$ cat my.log
log entry
  

Если у вас нет доступа ssh к узлу, вы можете использовать плагины, подобные этому:https://github.com/kvaps/kubectl-enter

Но, как правило, это не лучшая практика

Вы не должны записывать журналы в файлы, вместо этого ваше приложение должно записывать в stdout / stderr, тогда было бы намного проще отлаживать

Ответ №3:

Вы пробовали использовать --previous флаг?

Это как

 $ kubectl logs <pod-name> <container-name> --previous