Fluentd 如何分离 Docker 容器的 stdout 与 stderr 日志?
Docker fluentd 驱动提供 source 字段,json-file 使用 stream,CRI 格式则不同。本文用 rewrite_tag_filter 按 source 改写 tag,分别识别 stdout、stderr 和未知来源,再按需配置输出。本文给出完整配置。
先区分输入格式:Docker fluentd 日志驱动提供 source 字段,json-file 使用 stream,Kubernetes CRI 又有不同格式。下面以 fluentd 驱动的 source 改写 tag,再按 stdout/stderr 分流。
配置示例
<source>
@type forward
bind 0.0.0.0
port 24224
</source>
<filter docker.**>
@type record_transformer
enable_ruby true
<record>
source ${record["source"].to_s.empty? ? "unknown" : record["source"]}
</record>
</filter>
<match docker.**>
@type rewrite_tag_filter
<rule>
key source
pattern ^stdout$
tag stdout.${tag}
</rule>
<rule>
key source
pattern ^stderr$
tag stderr.${tag}
</rule>
<rule>
key source
pattern /^(stdout|stderr)$/
invert true
tag unknown.${tag}
</rule>
</match>
<match stdout.** stderr.** unknown.**>
@type stdout
</match>
Docker 容器需配置 fluentd 日志驱动、可从 daemon 所在网络访问的接收地址,以及 docker.* 标签。安装并确认 fluent-plugin-rewrite-tag-filter 可用;来源为空或未知的事件应通过实际插件版本的缺失字段行为测试,上例先补 unknown 默认值以免被丢弃。TTY 模式可能合并 stdout/stderr,驱动缓冲、断连和丢失行为也需验证。不要把 Docker 内部日志文件当成通用稳定采集接口。
典型玩法
- stderr 单独建来源索引;stderr 不等于 ERROR,仍需解析应用日志级别;
- stdout 全量存档,stderr 额外发通知;
- 只采 stderr,丢弃 stdout 降噪(流量大的服务)。
常见问题(FAQ)
Q:K8s 环境的容器日志路径? 常见路径为 /var/log/containers/,通常是软链;需按实际运行时的 CRI 或其他格式解析,不能直接用 JSON parser。可配合元数据插件关联 Pod。
Q:rewrite_tag_filter 要装插件吗? 是插件(fluent-plugin-rewrite-tag-filter),是否预装取决于发行包和镜像,应检查并显式安装,不能假定所有官方镜像内置。