Go应用应输出结构化JSON日志至stdout,由Fluentd或Logstash采集并注入Kubernetes元数据后发往ES等后端;禁用文件轮转与敏感信息输出,统一格式与采集入口是关键。

Go 语言本身不直接处理日志收集或转发,但作为容器化服务(如微服务、CLI 工具、后台任务)的主力开发语言,它需要与日志采集系统(如 Fluentd、Logstash)良好协作。关键在于:让 Go 程序以结构化、可解析的方式输出日志,并适配标准输入/文件路径等采集入口。
Go 应用日志输出规范
避免使用 fmt.Println 或未格式化的 log.Printf。推荐使用支持 JSON 输出的日志库,便于 Fluentd/Logstash 解析。
- 用 logrus 或 zap(高性能场景)并启用 JSON 格式
- 确保日志包含必要字段:
level、time、service、trace_id(如有)、message - 将日志写入
os.Stdout(而非文件),由容器运行时(Docker / containerd)捕获为 stdout/stderr 流
示例(logrus + JSON):
log := logrus.New()
log.SetFormatter(&logrus.JSONFormatter{})
log.SetOutput(os.Stdout) // 关键:输出到 stdout
log.WithFields(logrus.Fields{"user_id": 123}).Info("user login succeeded")Fluentd 配置采集容器日志
Fluentd 常以 DaemonSet 方式部署在 Kubernetes 节点,或作为独立容器监听 Docker 日志目录。
立即学习“go语言免费学习笔记(深入)”;
- Docker 默认日志驱动为
json-file,日志存于/var/lib/docker/containers// -json.log - Fluentd 的
使用tail插件读取这些 JSON 文件 - 用
parser解析原始 JSON,并添加 Kubernetes 元信息(如 namespace、pod_name) - 通过
补充 service 标签、重命名字段、过滤 debug 日志等 - 最终用
将日志发往 Elasticsearch、Kafka 或 S3
简化的 fluent.conf 片段:
@type tail path /var/lib/docker/containers/**/*-json.log pos_file /var/log/fluentd-containers.log.pos tag kubernetes.* format json time_key time time_format %Y-%m-%dT%H:%M:%S.%NZ
@type kubernetes_metadata
@type elasticsearch host elasticsearch port 9200 logstash_format true logstash_prefix myapp
ELK 中 Logstash 替代 Fluentd 的方式
若选择 Logstash,通常用 docker logs --since 或 file 输入插件读取容器日志文件,逻辑类似 Fluentd。
- Logstash 配置中用
json编解码器解析 Go 输出的 JSON 日志 - 用
dissect或grok处理非 JSON 日志(不推荐,应优先统一为 JSON) - 通过
kubernetes插件注入 Pod 元数据(需运行在集群内) - 输出到 Elasticsearch 时建议开启
pipeline进行字段标准化(如统一时间字段名、level 映射)
额外建议与避坑点
- 禁止 Go 程序自己轮转日志文件(如用 lumberjack),这会干扰容器日志采集机制
- 避免在日志中打印敏感信息(密码、token),可在中间件或 filter 层脱敏
- K8s 环境下,用
container_name和pod_name替代硬编码服务名,方便关联追踪 - 测试时可用
docker logs确认输出是否为合法 JSON,无控制字符或换行截断
基本上就这些。Go 日志本身轻量,难点在对接和一致性 —— 统一格式、统一采集入口、统一元数据补充,比选哪个工具更重要。










