本文已发布超过一年。较旧的文章可能包含过时内容。请检查页面中的信息自发布以来是否仍是正确的。

Kubernetes 1.29 中的上下文日志记录:更好的故障排除和增强的日志功能

代表 结构化日志工作组SIG Instrumentation,我们很高兴宣布,Kubernetes v1.24 中引入的上下文日志功能已成功迁移到两个组件(kube-scheduler 和 kube-controller-manager)以及一些目录。此功能旨在提供更有用的日志,以便更好地排查 Kubernetes 问题,并赋予开发者增强 Kubernetes 的能力。

什么是上下文日志?

上下文日志 基于 go-logr API。其核心思想是,库通过调用者传递一个日志记录器实例,并使用该实例进行日志记录,而不是访问全局日志记录器。二进制文件决定了日志记录实现,而不是库。go-logr API 围绕结构化日志记录设计,支持向日志记录器附加额外信息。

这开启了额外的用例

  • 调用者可以向日志记录器附加额外信息

    • WithName 添加一个 "logger" 键,其值为用点连接的名称
    • WithValues 添加键/值对

    当将此扩展的日志记录器传递给函数时,如果函数使用它而不是全局日志记录器,则所有日志条目中都会包含附加信息,而无需修改生成日志条目的代码。这对于高度并行的应用程序非常有用,因为不同操作的输出会交错在一起,很难识别某个操作的所有日志条目。

  • 运行单元测试时,日志输出可以与当前测试相关联。然后,当测试失败时,go test 只会显示失败测试的日志输出。默认情况下,此输出也可以更详细,因为它不会显示给成功的测试。测试可以并行运行,而不会交错它们的输出。

上下文日志记录的设计决策之一是允许将日志记录器作为值附加到 context.Context。由于日志记录器封装了调用所需日志记录的所有方面,因此它是上下文的一部分,而不仅仅是使用上下文。一个实际的优势是许多 API 已经具有 ctx 参数或可以添加一个。这带来了额外的优势,例如能够在函数内部摆脱 context.TODO() 调用。

如何使用它

上下文日志功能从 Kubernetes v1.24 开始处于 Alpha 阶段,因此需要启用 ContextualLogging 特性门。如果您想在 Alpha 阶段测试此功能,需要在 kube-controller-managerkube-scheduler 上启用此特性门。

对于 kube-scheduler,需要注意一点,除了启用 ContextualLogging 特性门外,检测还依赖于日志详细程度。为了避免因 1.29 版本添加的上下文日志记录检测而降低调度器的速度,仔细选择何时添加额外信息非常重要。

  • -v3 或更低级别,每个调度周期只使用一次 WithValues("pod")。这具有预期的效果,即该周期的所有日志消息都包含 Pod 信息。一旦上下文日志记录达到 GA 阶段,可以从所有日志调用中移除 "pod" 键/值对。
  • -v4 或更高级别,会产生更丰富的日志条目,其中 WithValues 也用于节点(适用时),并且 WithName 用于当前操作和插件。

这里有一个示例展示了效果

I1113 08:43:37.029524 87144 default_binder.go:53] "尝试将 Pod 绑定到节点" logger="Bind.DefaultBinder" pod="kube-system/coredns-69cbfb9798-ms4pq" node="127.0.0.1"

直接的好处是操作和插件名称在 logger 中可见。podnodekube-scheduler 代码的单个日志调用中已经作为参数记录。一旦 kube-scheduler 之外的更多包支持上下文日志记录,它们也将在那里可见(例如,client-go)。一旦达到 GA 阶段,日志调用可以简化,以避免重复这些值。

kube-controller-manager 中,使用 WithName 将用户可见的控制器名称添加到日志输出中,例如

I1113 08:43:29.284360 87141 graph_builder.go:285] "垃圾收集控制器监视器未同步:没有监视器" logger="garbage-collector-controller"

logger=”garbage-collector-controller” 是由 kube-controller-manager 核心在实例化该控制器时添加的,并出现在其所有日志条目中——至少只要它调用的代码支持上下文日志记录。还需要进一步的工作来转换像 client-go 这样的共享包。

性能影响

在包中支持上下文日志记录,即接受调用者传递的日志记录器,开销很小。对 kube-scheduler 未观察到性能影响。如上所述,添加 WithNameWithValues 需要更谨慎地进行。

在 Kubernetes 1.29 中,在生产详细程度(-v3 或更低)启用上下文日志记录对 kube-scheduler 没有造成可测量的减速,对 kube-controller-manager 预计也不会。在调试级别,某些测试用例的 28% 的减速仍然是合理的,考虑到生成的日志使调试更容易。详情请参见 关于将此特性提升到 Beta 阶段的讨论

对下游用户的影响

日志输出不是 Kubernetes API 的一部分,并且在每个版本中都会定期更改,无论是由于开发人员的代码工作还是由于正在进行的结构化和上下文日志转换。

如果下游用户依赖于特定的日志,他们需要了解此更改如何影响他们。

进一步阅读

参与进来

如果您有兴趣参与进来,我们随时欢迎新的贡献者加入我们。上下文日志记录为您贡献 Kubernetes 开发并产生有意义的影响提供了绝佳的机会。通过加入 结构化日志工作组,您可以积极参与 Kubernetes 的开发并做出您的第一个贡献。这是学习、与社区互动并获得宝贵经验的好方法。

我们鼓励您探索代码仓库,熟悉正在进行的讨论和项目。这是一个协作环境,您可以在其中交流想法、提问并与其他贡献者一起工作。

如果您有任何问题或需要指导,请随时联系我们,您可以在我们的 公共 Slack 频道 上进行。如果您尚未加入该 Slack 工作区,可以访问 https://slack.k8s.io/ 获取邀请。

我们要感谢所有为该功能的实现提供了优秀评审、分享了宝贵见解并给予协助的贡献者(按字母顺序排列)