在云原生架构中,日志系统是 observability(可观测性)的三大支柱之一。日志采集不仅需要标准化,还需要结构化与易于接入采集链路(如 Fluent Bit、Loki、ELK)。Golang 原生支持高性能日志打印,是构建云原生日志模块的理想选择。

本篇将介绍如何用 Golang 构建结构化日志模块,并部署到 Kubernetes 中配合日志收集器进行集中处理。

1. 日志采集模式概述

在 Kubernetes 中,常见的日志采集流程为:

  1. 应用将日志输出到 stdout / stderr
  2. 容器运行时将日志持久化到文件
  3. 日志代理(如 Fluent Bit)读取文件并转发至后端(如 Elasticsearch、Loki)

因此,日志应尽量打印至控制台并保持结构化(JSON 格式)以利采集与索引。

2. 结构化日志库选择

推荐使用以下结构化日志库:

  • uber-go/zap(性能优异,生产可用)
  • sirupsen/logrus(语法友好,学习曲线低)

示例使用 zap

go get go.uber.org/zap

3. 日志模块实现

package logger

import (
  "go.uber.org/zap"
)

var Log *zap.Logger

func InitLogger() {
  cfg := zap.NewProductionConfig()
  cfg.OutputPaths = []string{"stdout"}
  cfg.ErrorOutputPaths = []string{"stderr"}
  cfg.Encoding = "json"

  logger, err := cfg.Build()
  if err != nil {
    panic(err)
  }

  Log = logger
}

在主程序中调用:

func main() {
  logger.InitLogger()
  logger.Log.Info("service starting", zap.String("version", "v1.0.0"))
}

4. 示例日志输出格式(JSON)

{
  "level": "info",
  "ts": 1718946000.123,
  "msg": "service starting",
  "version": "v1.0.0"
}

这类日志格式可被 Fluent Bit、Loki、Logstash 等组件自动识别为结构化字段,便于过滤与查询。

5. 在 Kubernetes 中采集日志

以 Fluent Bit 为例,可通过如下配置采集并过滤日志:

[INPUT]
  Name              tail
  Path              /var/log/containers/*.log
  Parser            docker
  Tag               kube.*

[FILTER]
  Name              kubernetes
  Match             kube.*
  Merge_Log         On
  Keep_Log          Off
  K8S-Logging.Parser On

[OUTPUT]
  Name              stdout
  Match             *

6. 日志字段规范建议

  • 添加 request_idtrace_id 字段以便追踪请求链路
  • 统一字段命名(如 levelservicecomponentmessage
  • 禁止打印敏感信息到日志(如密码、token)

总结

结构化日志是云原生系统中高效排障与监控的重要基础设施。使用 Golang 构建统一的日志模块,并与 Kubernetes 日志采集系统集成,有助于打造可观测、易维护的微服务体系。推荐后续引入 traceID、日志等级控制、动态配置等能力以完善日志系统。