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

Kubernetes v1.22 中的 Alpha 功能:API Server Tracing

在分布式系统中,找出问题所在可能很困难。你可能 grep 一个组件的日志,却发现问题根源在另一个组件。你在那里搜索,却发现你需要启用调试日志才能弄清楚真正出了什么问题……如此循环往复。你的请求路径越复杂,就越难回答它去了哪里。我个人花费了很多时间与各种 Kubernetes 组件进行这种“舞蹈”。分布式跟踪是一种旨在帮助解决这些情况的工具,而 Kubernetes API Server 也许是调试起来最重要的 Kubernetes 组件。在 Kubernetes 的 Sig Instrumentation 中,我们的使命是让用户更容易了解集群中发生的情况,我们很高兴地宣布,Kubernetes API Server 中的分布式跟踪已在 1.22 版本中达到 Alpha 阶段。

什么是跟踪?

分布式跟踪将来自多个不同源的大量超详细信息链接起来,并将这些遥测数据构建成该请求的单一树结构。与日志记录不同,日志记录通过使用日志级别来限制摄取的数据量,而跟踪则收集所有详细信息,并使用采样只收集一小部分请求。这意味着一旦你有一个能说明问题的跟踪信息,你就应该拥有定位问题根源所需的所有信息——无需 grep 对象 UID!不过,我最喜欢的一点是跟踪信息的可视化有多么有用。即使你不理解 API Server 的内部工作原理,或者不知道 etcd 的“Transaction”是什么,我敢打赌你(是的,就是你!)也能大致告诉我事件的顺序是什么,以及哪些组件参与了请求。如果某个步骤花费了很长时间,很容易就能看出问题出在哪里。

为什么选择 OpenTelemetry?

重要的是 Kubernetes 能为所有人良好地工作,无论你管理的是谁的基础设施,也无论你选择与哪些供应商集成。对于 Kubernetes 与遥测解决方案的集成来说尤其如此。OpenTelemetry 作为 CNCF 项目,拥有这些核心价值观,并且正在创建 Kubernetes 正需要的东西:一套用于跟踪客户端库 API 的开放标准和一种标准的跟踪格式。通过使用 OpenTelemetry,我们可以确保用户可以自由选择其后端,并确保供应商有一个公平的竞争环境。时机再好不过了:OpenTelemetry golang API 和 SDK 非常接近其 1.0 版本发布,并将很快为这些开放标准提供向后兼容性。

为什么对 API Server 进行埋点?

Kubernetes API Server 是进行跟踪的绝佳候选对象,原因如下:

  • 它遵循标准的“RPC”模型(通过向下游组件发出请求来服务一个请求),这使得埋点变得容易。
  • 用户对延迟敏感:如果一个请求需要超过 10 秒才能完成,许多客户端会超时。
  • 它具有复杂的服务拓扑:一个请求可能需要咨询十几个 webhook,或者涉及对 etcd 的多个请求。

使用 webhook 试用 APIServer 跟踪

启用 API Server 跟踪

  1. 启用 APIServerTracing feature-gate

  2. 通过将 kube-apiserver 上的 --tracing-config-file 标志指向我们的配置文件来设置跟踪配置,配置文件中包含:

apiVersion: apiserver.config.k8s.io/v1alpha1
kind: TracingConfiguration
# 1% sampling rate
samplingRatePerMillion: 10000

启用 Etcd 跟踪

更新:以下内容是在博文发布后添加的 向 etcd 添加 --experimental-enable-distributed-tracing--experimental-distributed-tracing-address=0.0.0.0:4317--experimental-distributed-tracing-service-name=etcd 标志来启用跟踪。请注意,这会跟踪每个请求,因此如果启用它,可能会生成大量跟踪。所需 etcd 版本为 3.5 至 3.5.4

从 3.5.5 版本到 3.5.10 版本,跟踪的默认采样率设置为 0%,这意味着默认情况下不会收集任何跟踪。遗憾的是,没有提供选项来配置更高的采样率。(参阅详情

3.5.11 版本中,可以使用新引入的 --experimental-distributed-tracing-sampling-rate=1000000 标志配置每百万个 Span 收集的样本数量。

跟踪示例:列出节点

我可以使用任何跟踪后端,但决定使用 Jaeger,因为它是最流行的开源跟踪项目之一。我在集群中部署了Jaeger 一体化容器,在我的控制平面节点上部署了OpenTelemetry 收集器示例),并捕获了如下跟踪:

Jaeger screenshot showing API server and etcd trace

青色线条来自 API Server,包括它为 /api/v1/nodes 的请求提供服务,并向 ETCD 发出 grpc Range RPC。黄色线条来自 ETCD 处理 Range RPC。

跟踪示例:使用 Mutating Webhook 创建 Pod

我使用 OpenTelemetry 对示例 webhook 进行了埋点(我不得不修改 controller-runtime,但这制作了一个不错的演示),并将跟踪路由到了 Jaeger。我收集了如下跟踪:

Jaeger screenshot showing API server, admission webhook, and etcd trace

与之前的跟踪相比,这里有两个新的 Span:一个是来自 API Server 调用准入 webhook 的青色 Span,另一个是来自准入 webhook 处理请求的棕色 Span。即使你没有对你的 webhook 进行埋点,你仍然会获得 API Server 调用该 webhook 的 Span。

参与进来!

由于这是我们首次尝试向 Kubernetes 组件添加分布式跟踪,可能有很多地方可以改进!如果我的困境与你产生共鸣,或者你只是想尝试 Kubernetes 最新的特性,请试用该功能,并在遇到任何问题以及认为该功能可以改进的地方提交 Issue。

这仅仅是我们在 Kubernetes 中使用分布式跟踪的开端。如果你认为还有其他组件可以从分布式跟踪中受益,或者想帮助将 API Server 跟踪推向 GA 阶段,请参加 sig-instrumentation 的例会并参与进来!