4. 日志体系概述:结构化日志、日志级别与输出目标

在 Ingress 控制器升级窗口演练中,日志是定位异常的第一手资料。一个设计良好的日志体系需要回答三个问题:记录什么格式(结构化)、记录到什么粒度(日志级别)、记录到哪里(输出目标)。本章从这三个维度展开,为后续的链路追踪与故障排查打下基础。

4.1 结构化日志:从文本到可解析的键值对

传统非结构化日志(如 2025/03/15 10:00:00 [error] upstream timed out)难以被自动化工具解析。结构化日志将每条记录组织为固定的键值对或 JSON 格式,使日志可被程序化查询、过滤和聚合。

特性 非结构化日志 结构化日志
格式 自由文本,无固定字段 JSON / key=value 格式
可解析性 依赖正则表达式,易出错 直接解析,字段明确
查询效率 全文检索,性能低 字段索引,快速过滤
典型示例 [error] upstream connect error {"level":"error","upstream":"10.0.0.1:8080","latency_ms":502}

在 Ingress 控制器(如 NGINX Ingress、Envoy 等)中,结构化日志通常包含以下核心字段:

  • timestamp:事件发生时间,建议使用 RFC3339 格式。
  • level:日志级别,用于快速筛选。
  • logger:日志来源模块(如 controller、proxy、watch)。
  • request_id:关联请求的唯一标识,用于链路追踪。
  • upstream:后端服务地址与端口。
  • status:HTTP 状态码。
  • latency_ms:请求处理耗时(毫秒)。
  • message:人类可读的事件描述。
升级窗口最佳实践:在升级前将日志格式切换为 JSON 结构化输出,并确保 request_id 字段被注入。这样在升级过程中出现 502/503 时,可以快速通过 request_id 关联到具体的后端 Pod 和配置变更。

4.2 日志级别:Error / Warn / Info / Debug

日志级别控制着日志的详细程度。在升级窗口演练中,不同阶段需要切换不同的级别:

级别 含义 升级窗口中的典型场景
Error 发生了错误,需要立即关注 上游连接超时、证书加载失败、配置重载异常
Warn 可能存在问题,但不影响当前请求 重试次数超过阈值、后端 Pod 缓慢、健康检查失败
Info 正常操作信息,用于了解系统状态 配置重载成功、端点更新、Pod 就绪/未就绪
Debug 详细的调试信息,用于问题定位 请求头/响应头详情、路由匹配过程、内部状态机转换
升级窗口日志级别策略:
  • 升级前:保持 Info 级别,监控正常流量。
  • 升级中:临时切换为 Debug 级别,捕获所有配置变更和请求处理细节。
  • 升级后:恢复为 Info 级别,避免磁盘和性能开销。
  • 切勿在生产长期开启 Debug 级别,会导致日志量暴增 10~100 倍。

4.3 日志输出目标:stdout、文件、远程收集

在 Kubernetes 环境中,日志输出目标的选择直接影响可观测性架构的复杂度。以下是三种主流输出方式的对比:

输出目标 优点 缺点 Kubernetes 推荐场景
stdout / stderr 容器原生支持,kubectl logs 可直接查看;无需挂载卷 日志无法持久化;容器重启后丢失;不适合大规模检索 开发调试、临时排查、Sidecar 容器日志
文件 可持久化到宿主机或 PV;支持日志轮转 需要挂载 emptyDir 或 hostPath;增加运维复杂度 需要保留历史日志用于审计的场景
远程收集 集中存储、检索、告警;支持多集群统一视图 依赖网络可达性;增加延迟和资源消耗 生产环境标准配置(如 Fluentd + Elasticsearch)

在 Ingress 控制器升级窗口演练中,推荐采用 stdout + 远程收集 的组合:

  • 控制器容器将结构化日志写入 stdout。
  • DaemonSet 形式的日志采集器(如 Fluent Bit)从 /var/log/containers 读取并转发到 Elasticsearch 或 Loki。
  • 升级期间开启 Debug 级别时,日志量会激增,需确保采集器有足够的缓冲和限流能力。

4.4 日志体系架构总览

下图展示了 Ingress 控制器在升级窗口中的日志流转路径:

Ingress 控制器日志体系架构 Ingress 控制器日志体系架构(升级窗口) Ingress 控制器 结构化日志 (JSON) stdout / stderr 日志文件 (轮转) 远程收集 (Fluent Bit) kubectl logs 本地文件查看 Elasticsearch / Loki 升级窗口建议: • 升级中临时开启 Debug 级别,日志输出到 stdout + 远程收集。 • 升级完成后恢复 Info 级别,避免日志洪峰影响集群性能。

4.5 日志级别与输出目标的组合策略

在升级窗口演练中,不同阶段应采用不同的日志级别与输出目标组合:

阶段 日志级别 输出目标 目的
升级前(基线) Info stdout + 远程收集 记录正常流量模式,建立性能基线
升级中(灰度) Debug stdout + 远程收集 捕获所有配置变更和请求处理细节
升级中(全量) Debug stdout + 远程收集 监控全量流量切换后的异常
升级后(验证) Info stdout + 远程收集 确认系统稳定,关闭 Debug 级别
日志级别动态调整:在 Kubernetes 中,可以通过 ConfigMap 热更新或 Ingress 控制器 API 动态调整日志级别,无需重启 Pod。例如,NGINX Ingress 控制器支持 --v=2 参数调整 verbosity 级别,Envoy 支持通过 admin 接口动态修改日志级别。

4.6 日志配置示例(NGINX Ingress 控制器)

以下是一个生产环境推荐的结构化日志配置片段:

# NGINX Ingress 控制器 ConfigMap 配置
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
data:
  # 启用 JSON 结构化日志
  log-format-escape-json: "true"
  log-format-upstream: '{"time":"$time_iso8601","level":"$log_level",'
    '"request_id":"$req_id","remote_addr":"$remote_addr",'
    '"upstream":"$upstream_addr","status":$status,'
    '"latency_ms":$upstream_response_time,"bytes":$body_bytes_sent,'
    '"method":"$request_method","path":"$uri","message":"$log_message"}'
  
  # 日志级别控制(支持 error/warn/info/debug)
  # 升级窗口期间可临时改为 debug
  log-level: "info"
  
  # 日志输出到 stdout(默认行为)
  # 无需额外配置,容器 stdout 由 kubelet 采集

通过上述配置,每条日志都会以 JSON 格式输出到 stdout,并被集群中的日志采集器(如 Fluent Bit)自动收集到中央存储系统。在升级窗口演练中,只需将 log-level 改为 debug 即可获得更详细的调试信息。