容器日志散落在每个节点的文件系统里,Pod 一重启就丢。本文讲如何用 DaemonSet 部署采集代理、把 stdout 和文件日志统一收进炬鲸 OBSERVE,并注入 Pod、命名空间、容器等元数据,附完整 YAML 与排错要点。
容器的日志采集和虚拟机不一样。第一,日志默认写到每个节点的文件系统里,Pod 漂移到别的节点后,本地日志就断了;第二,Pod 一重启(哪怕只是滚动更新),容器内的日志文件可能直接消失,出事时想查历史记录已经晚了。
所以 Kubernetes 的日志采集标准做法是:每个节点跑一个采集代理,实时把 stdout 和日志文件都推出去,让日志在平台侧集中落盘,而不是留在节点上。代理用 DaemonSet 部署,节点增减自动跟随。
把炬鲸的采集代理以 DaemonSet 形式部署,每个节点一个 Pod,挂载宿主机的日志目录:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: jjhub-agent
spec:
selector:
matchLabels: { app: jjhub-agent }
template:
metadata:
labels: { app: jjhub-agent }
spec:
containers:
- name: agent
image: jjhub/agent:2.5
env:
- name: TOKEN
valueFrom:
secretKeyRef: { name: jjhub-agent, key: token }
- name: ENDPOINT
value: https://ob.example.com
volumeMounts:
- { name: varlog, mountPath: /var/log }
- { name: varlibdocker, mountPath: /var/lib/docker/containers, readOnly: true }
volumes:
- { name: varlog, hostPath: { path: /var/log } }
- { name: varlibdocker, hostPath: { path: /var/lib/docker/containers } }
Token 放 Secret 里,别硬编码进 YAML。代理挂载 /var/log 收系统日志,挂载 Docker/containerd 的容器目录收容器 stdout,两个来源统一推送到平台。
光收日志不够,还得知道每条日志属于哪个 Pod、哪个命名空间、哪个部署。代理会自动给日志打上这些标签:
namespace=prod, pod=order-service-7f8c9, container=order, deployment=order-service
有了这些维度,检索时就能按命名空间、按 Pod、按容器过滤,出问题时直接从告警里的 Pod 名反查日志,不用在几十个节点上挨个翻。
对应用侧只有一个要求:日志走 stdout,别写进容器内部的文件。stdout 会被容器运行时自动采集,日志文件则要额外配置采集路径,还容易漏。
先从一个命名空间试点,跑通采集、检索、告警全流程,再全集群铺开。重点检查三类元数据是否齐全(namespace、pod、container),这是后续所有检索和告警的地基。字段名统一用平台约定,避免各团队各写一套。