一、前言¶
集群级/应用日志通过将日志数据从容器或节点中解耦,并将其发送到集中的日志存储或处理系统,使日志数据在整个集群中可见。
优势:即使容器或节点发生故障,仍然可以访问日志数据以进行故障排查和监控。
二、应用日志分析¶
应用容器标准输出流:
[root@master01 9]# vim podstdr.yaml
apiVersion: v1
kind: Pod
metadata:
name: podstdr
spec:
containers:
- name: podstdr
image: registry.cn-hangzhou.aliyuncs.com/abroad_images/busybox:1.30
args:
[
/bin/sh,
-c,
'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done',
]
# 应用
[root@master01 9]# kaf podstdr.yaml
# 验证
[root@master01 9]# kgp | grep podstdr
podstdr 1/1 Running 0 14s
创建完成后,可以使用 kubectl logs 命令查看日志信息:
$ kubectl logs podstdr
0: Mon Apr 14 23:52:56 UTC 2025
1: Mon Apr 14 23:52:57 UTC 2025
2: Mon Apr 14 23:52:58 UTC 2025
...
...
三、Pod日志收集¶
Kubernetes 集群本身不提供日志收集的解决方案,一般主要有 4 种方案来做日志收集:
- 在节点上运行一个 agent 来收集日志;
- 在 Pod 中包含一个 sidecar 容器来收集应用日志;
- 在 Pod 中启动一个 sidecar Agent容器来收集应用日志;
- 直接在应用程序中将日志信息推送到采集后端;
3.1 节点代理方式日志采集¶

- DaemonSet 控制器运行该应用程序,每个节点上运行一个日志收集的agent来采集日志数据;
- 日志agent用一个容器来运行,可以访问该节点上所有应用程序容器的日志文件所在目录。
- 对应用程序没有任何侵入性,仅适用于收集输出到 stdout 和 stderr 的应用程序日志。
3.2 Sidecar 方式收集容器日志¶
如果应用程序的日志是输出到容器中的某个日志文件呢?
在 Pod 中启动另外一个 sidecar 容器,直接将应用程序的日志通过这个容器重新输出到 stdout,即可完成日志收集。
主要逻辑:将应用程序中的日志进行重定向打印,逻辑非常简单,开销很小,由于输出 到了 stdout 或者 stderr,故也可使用 kubectl logs来查看日志。
示例:Pod 中将日志记录在容器的两个本地文件之中
apiVersion: v1
kind: Pod
metadata:
name: podstdr
spec:
containers:
- name: podstdr
image: registry.cn-hangzhou.aliyuncs.com/abroad_images/busybox:1.30
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
volumes:
- name: varlog
emptyDir: {}
利用另外一个 sidecar 容器去获取容器中的日志文件,然后将日志重定向到自己的 stdout 流中。
可以将上面的 YAML 文件做如下修改: two-files-pod-sidecar.yaml
[root@master01 9]# vim two-files-pod-sidecar.yaml
apiVersion: v1
kind: Pod
metadata:
name: podstdr2
spec:
containers:
- name: podstdr2
image: registry.cn-hangzhou.aliyuncs.com/abroad_images/busybox:1.30
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: registry.cn-hangzhou.aliyuncs.com/abroad_images/busybox:1.30
args: [/bin/sh, -c, "tail -n+1 -f /var/log/1.log"]
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-log-2
image: registry.cn-hangzhou.aliyuncs.com/abroad_images/busybox:1.30
args: [/bin/sh, -c, "tail -n+1 -f /var/log/2.log"]
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
运行成功后,我们可以通过下面的命令来查看日志的信息:
$ kubectl logs -f podstdr2 count-log-1
0: Sat Jul 1 11:34:56 UTC 2023
1: Sat Jul 1 11:34:57 UTC 2023
2: Sat Jul 1 11:34:58 UTC 2023
3: Sat Jul 1 11:34:59 UTC 2023
...
$ kubectl logs -f podstdr2 count-log-2
Sat Jul 1 11:34:56 UTC 2023 INFO 0
Sat Jul 1 11:34:57 UTC 2023 INFO 1
Sat Jul 1 11:34:58 UTC 2023 INFO 2
Sat Jul 1 11:34:59 UTC 2023 INFO 3
...
# 环境复原
[root@master01 9]# k delete -f two-files-pod-sidecar.yaml
这样前面节点上的日志采集 agent 就可以自动获取这些日志信息,而不需要其他配置。
这种方法虽然可以解决上面的问题,但是也有一个明显的缺陷,就是日志不仅会在原容器文件中保留下来,还会通过 stdout 输出后占用磁盘空间,这样无形中就增加了一倍磁盘空间。
3.3 Sidecar 运行日志采集 agent¶
主要流程:
- 部署:在同一个宿主机上部署主应用程序的容器和 Sidecar 容器。主应用程序容器 负责运行应用程序本身,而Sidecar 容器则专门负责运行日志采集 agent。
- 连接:Sidecar 容器与主应用程序容器之间建立连接,以获取需要采集的日志数据。 通过共享文件系统方式实现。
- 日志采集:Sidecar 容器中运行的日志采集 agent 监听主应用程序容器的日志输 出,并将日志数据收集起来。可使用特定的方式来解析不同的日志格式。
- 存储或转发:采集到的日志数据根据需求进行转发。推送到消息队列或直接推送到ES服务等。
下面是 Kubernetes 官方的一个 fluentd 的配置文件示例,使用 ConfigMap 对象来保存:
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>
上面的配置文件是配置收集原文件 /var/log/1.log 和 /var/log/2.log 的日志数据,然后通过 google_cloud 这个插件将数据推送到 EFK 后端。
下面是我们使用上面的配置文件在应用程序中运行一个 fluentd 的容器来读取日志数据:
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: registry.cn-hangzhou.aliyuncs.com/abroad_images/busybox:1.30
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: registry.cn-hangzhou.aliyuncs.com/github_images1024/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
如上主要功能:容器 count-agent 就会将 count 容器中的日志进行收集然后上传。
3.4 直接从应用程序收集日志¶

通过在应用程序代码中添加日志输出语句,将应用程序的关键信息记录下来。这种方式有以下几个主要步骤:
- 添加日志库:在应用程序中引入适合的日志库或框架,如Logback、Log4j、或是应 用程序特定的日志库。
- 配置日志属性:根据需要,配置日志属性,如日志的级别(如DEBUG、INFO、 ERROR等)、输出格式、输出位置等。
- 在应用程序中添加日志语句:在关键的代码块、重要的事件或异常处理中添加合适 的日志输出语句。日志语句应该包含相关的上下文信息,如时间戳、请求参数、业 务数据等,以便更好地理解日志内容。
- 输出和存储:当应用程序执行到日志语句时,日志库会根据配置将日志输出到指定 的目标,如控制台、文件、数据库等。
- 日志级别控制:通过设置日志级别,可以控制哪些级别的日志会被输出和记录。
直接从应用程序收集日志的好处:
- 应用程序开发者可以更精确地控制日志输出内容和格式。
- 日志与应用程序的关联更紧密,方便定位和排查问题。
- 可以根据不同的环境和需求调整日志级别和目标,以达到最佳的日志记录效果。
四、总结¶
- 节点代理方式:使用节点代理来采集日志。独立的代理程序,负责监控和收集该节点上运行的容器或应用程序的日志。
- Sidecar 方式收集容器日志:在容器编排平台(例如 Kubernetes)中,可以使用 Sidecar 容器模式来收集主要应用程序容器的日志。这种方式中,一个专门的 Sidecar 容器与主应用程序容器一起部署在同一个 Pod 中,并负责收集主应用程序容器的日志。
- Sidecar 运行日志采集 Agent:类似于上述的 Sidecar 方式,但不仅仅收集主应用程 序容器的日志,还负责运行日志采集。利用容器的特性(如共享卷或网络通信)来获取主应用程序的日志,并将其发送到中央日志存储或分析系统。
- 直接从应用程序收集日志:应用程序本身负责进行日志的记录和发送。将日志数据直接发送到中央日志存储或分析系统。