如何在K8s中处理应用STDOUT日志并对接Graylog?
K8s日志原理澄清
你对Fluent Bit和K8s日志机制的认知存在偏差:K8s默认会将所有容器输出到STDOUT/STDERR的日志,由容器运行时(Docker/containerd)自动持久化到节点本地的/var/log/containers/*.log路径,日志默认包含时间戳、输出流(stdout/stderr)、日志内容三个核心字段。Fluent Bit原生支持监控采集该路径下的日志文件,等于直接采集容器的STDOUT输出,完全不需要你修改现有Java应用的日志输出逻辑。
问题解答
1. 直接读取STDOUT日志发送到Graylog的方案
目前可直接落地的方案有三种:
- 节点级日志代理方案:在K8s集群中以DaemonSet形式部署Fluent Bit,配置
tail输入插件采集/var/log/containers/下的日志,过滤出你需要的Java应用日志后,通过Fluent Bit原生的GELF输出插件直接发往集群内的Graylog实例。该方案无需修改任何业务配置,还能自动给日志附加Pod名、命名空间、节点名等K8s元数据,是和你原有Docker GELF驱动逻辑最接近的方案。 - Sidecar代理方案:如果不想部署集群级的DaemonSet,可以给每个Java应用Pod配置Fluent Bit Sidecar,共享容器的日志输出流直接采集STDOUT,再转发到Graylog,该方案灵活性高但资源开销比节点级方案大。
- 应用直连方案:直接在log4j配置中新增GELF Appender,配置集群内Graylog的Service地址,应用直接把日志发送到Graylog,无需中间代理。但该方案需要每个应用单独配置,还要自行处理Graylog不可用情况下的日志缓冲、丢弃逻辑,维护成本较高。
2. 日志写入文件的滚动策略问题
你完全不需要调整现有应用输出STDOUT的配置,也不需要让应用写本地日志文件,因此不存在应用侧日志文件膨胀的问题。
如果有特殊场景必须让应用写本地日志文件,可通过两个维度控制资源占用:
- 配置log4j的滚动删除策略:开启按大小+按时间滚动,例如单日志文件超过100M自动滚动,每天生成一个新日志文件,仅保留最近7天的日志,超出的自动删除,Log4j原生支持上述配置,无需额外开发。
- 配置K8s存储容量限制:将应用日志挂载路径对应的emptyDir设置容量上限,超出上限后K8s会自动驱逐该Pod,避免日志占满节点磁盘。
3. 行业通用的K8s应用日志处理方案
目前行业内的主流方案是节点级代理采集的三层架构,逻辑如下:
- 应用层:所有业务应用统一将日志输出到STDOUT/STDERR,不自行写入本地日志文件,日志格式建议统一为结构化JSON,降低后续解析成本,你当前的Java应用日志配置完全符合该规范。
- 采集层:在每个K8s节点上以DaemonSet形式部署轻量日志代理(优先选Fluent Bit,资源占用仅几MB,远低于Fluentd),统一采集节点上所有容器的日志,做字段清洗、结构化转换、补充K8s元数据后,统一转发到后端日志系统。
- 存储分析层:用Graylog、ELK、Loki等系统接收采集层上报的日志,提供日志存储、检索、可视化、告警能力。
该方案的优势是和业务完全解耦,不需要业务应用做任何适配,集群层面统一维护即可,资源开销可控。
内容的提问来源于stack exchange,提问作者O. Schnieders
相关产品推荐
相关产品推荐

