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 控制器在升级窗口中的日志流转路径:
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 即可获得更详细的调试信息。