Kubernetes Cluster-level logging architectures
Kubernetes 官方不提供原生的集群日志方案,但是提供了一些解决思路:
- 在每个 Node 上运行一个日志客户端。
- 在应用的 Pod 里以 sidecar 形式运行一个日志容器。
- 应用直接把日志推送到后端日志存储里。
Using a node logging agent
一台 Node 上所有容器的 stdout/stderr 日志会被统一保存到宿主机的目录,只需要以 DaemonSet 的形式在每个 Node 上运行一个日志收集客户端即可将这台 Node 上所有容器的 标准输出/标准错误 日志收集起来存到后端存储里。
这里的日志收集客户端建议 fluentd。
Using a sidecar container with the logging agent
使用 Sidecar 方式有两种方案:
- Sidecar 容器将应用日志导流到标准输出或标准错误。
这种方式有利于适配 kubelet,或每台 Node 已经运行日志收集客户端的情况。Sidecar 容器可以从文件、socket 或 journald 收集日志,为应用里的每个日志模块运行一个特定的 sidecar 容器,整个 Pod 共享一个共享目录,最终把每个日志模块的日志对应的输出到各自的 sidecar 容器的标准输出或标准错误。
这是一个在容器内部写两个日志文件的应用范例,然后是同一个 Pod 里运行两个 sidecar 容器分别对两个日志文件进行收集:
two-files-counter-pod-streaming-sidecar.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| apiVersion: v1 kind: Pod metadata: name: counter spec: containers: - name: count image: busybox args: - /bin/sh - -c - > i=0; while true; do echo "$i: $(date)" >> /var/log/1.log; echo "$(date) INFO $i" >> /var/log/2.log; i=$((i+1)); sleep 1; done volumeMounts: - name: varlog mountPath: /var/log - name: count-log-1 image: busybox args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log'] volumeMounts: - name: varlog mountPath: /var/log - name: count-log-2 image: busybox args: [/bin/sh, -c, 'tail -n+1 -f /var/log/2.log'] volumeMounts: - name: varlog mountPath: /var/log volumes: - name: varlog emptyDir: {}
|
然后,你就可以使用 kubectl logs counter count-log-1
查看 1.log 的内容。同理2。
Node 上的日志客户端会自动采集这两个 sidecar容器的标准输出/标准错误,实际也就是采集了 1.log 和 2.log 两个日志文件。
- Sidecar 容器运行一个日志收集客户端,主动去收集应用日志。
这种方式适用于 Node 上没有日志收集客户端的情况。需要注意的是这种方式存在过多资源消耗的问题,而且无法使用 kubectl logs 命令直接查看应用日志。
这里举例使用 fluentd 作为 sidecar logging agent 收集日志:
fluentd-sidecar-config.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| apiVersion: v1 kind: ConfigMap metadata: name: fluentd-config data: fluentd.conf: | <source> type tail format none path /var/log/1.log pos_file /var/log/1.log.pos tag count.format1 </source> <source> type tail format none path /var/log/2.log pos_file /var/log/2.log.pos tag count.format2 </source> <match **> type google_cloud </match>
|
two-files-counter-pod-agent-sidecar.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| apiVersion: v1 kind: Pod metadata: name: counter spec: containers: - name: count image: busybox args: - /bin/sh - -c - > i=0; while true; do echo "$i: $(date)" >> /var/log/1.log; echo "$(date) INFO $i" >> /var/log/2.log; i=$((i+1)); sleep 1; done volumeMounts: - name: varlog mountPath: /var/log - name: count-agent image: k8s.gcr.io/fluentd-gcp:1.30 env: - name: FLUENTD_ARGS value: -c /etc/fluentd-config/fluentd.conf volumeMounts: - name: varlog mountPath: /var/log - name: config-volume mountPath: /etc/fluentd-config volumes: - name: varlog emptyDir: {} - name: config-volume configMap: name: fluentd-config
|
Exposing logs directly from the application
这是最简单的方式,不过涉及应用的改造。