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

使用节点仪表板可视化 Kubelet 性能

自本文发布以来,节点性能仪表板已停用,不再可用。

此停用发生在 2019 年初,是 kubernetes/contrib 存储库弃用的一部分。

在 Kubernetes 1.4 中,我们引入了一个新的节点性能分析工具,称为节点性能仪表板,以更详细地可视化和探索 Kubelet 的行为。这项新功能将使 Kubelet 开发人员更容易理解和改进代码性能,并使集群维护人员能够根据提供的服务水平目标 (SLO) 设置配置。

背景

Kubernetes 集群由主节点和工作节点组成。主节点管理集群的状态,而工作节点执行运行和管理 Pod 的实际工作。为此,在每个工作节点上,一个名为 Kubelet 的二进制文件会监视 Pod 配置中的任何更改,并采取相应的操作以确保容器成功运行。Kubelet 的高性能,例如与新 Pod 配置的低延迟收敛以及低资源使用的高效内务处理,对于整个 Kubernetes 集群至关重要。为了衡量此性能,Kubernetes 使用 端到端 (e2e) 测试来持续监控最新构建版本中具有新功能的基准变化。

Kubernetes SLO 由以下基准定义 :

* API 响应速度:99% 的 API 调用在 1 秒内返回。
* Pod 启动时间:99% 的 Pod 及其容器(具有预拉取的镜像)在 5 秒内启动。

在 1.4 版本之前,我们仅在集群级别测量和定义了这些指标,这增加了其他因素可能影响结果的风险。除此之外,我们还希望拥有更多与性能相关的 SLO,例如特定机器类型的最大 Pod 数量,以最大程度地利用您的集群。为了正确进行测量,我们希望引入一组与节点性能隔离的测试。此外,我们的目标是从新测试中收集更精细的资源使用情况和 Kubelet 操作跟踪数据。

数据收集

自 1.4 版本以来,节点特定的密度和资源使用情况测试现在已添加到 e2e-node 测试集中。资源使用情况由独立的 cAdvisor Pod 测量,以便实现灵活的监控间隔(与 Kubelet 集成的 cAdvisor 相比)。性能数据,例如延迟和资源使用百分位数,记录在持久性测试结果日志中。测试还记录时间序列数据,例如 Pod 的创建时间、运行时间以及实时资源使用情况。Kubelet 操作的跟踪数据记录在其日志中,并与测试结果一起存储。

节点性能仪表板

自 Kubernetes 1.4 以来,我们一直在持续构建最新的 Kubelet 代码并运行节点性能测试。数据由我们新的性能仪表板收集,可在 node-perf-dash.k8s.io 上访问。图 1 给出了仪表板的预览。您可以开始通过选择测试来探索它,可以使用短测试名称的下拉列表(区域 (a))或逐个选择测试选项(区域 (b))。测试详细信息显示在区域 (c) 中,其中包含来自 Ginkgo 的完整测试名称(Kubernetes 使用的 Go 测试框架)。然后在区域 (d) 中选择节点类型(镜像和机器)。

| | | 图 1. 在节点性能仪表板中选择要显示的测试。 |

“构建”页面显示了不同构建版本之间的性能数据(图 2)。这些图包括 Pod 启动延迟、Pod 创建吞吐量以及 Kubelet 和运行时(当前为 Docker)的 CPU/内存使用率。这样可以很容易地监控新功能签入后性能随时间的变化。

| | | 图 2. 不同构建版本之间的性能数据。 |

比较不同的节点配置

比较不同配置之间的性能总是很有趣的,例如比较不同机器类型的启动延迟、不同 Pod 的数量,或比较托管不同 Pod 数量的资源使用情况。仪表板提供了一种方便的方式来执行此操作。只需单击测试选择菜单右上角的“比较”按钮(图 1 中的区域 (e))。选定的测试将添加到“比较”页面中的比较列表中,如图 3 所示。一系列构建版本的数据聚合为一个值,以方便比较,并以条形图显示。

| | | 图 3. 比较不同的测试配置。 |

时间序列和跟踪:深入了解性能数据

Pod 启动延迟是 Kubelet 的一个重要指标,尤其是在每个节点创建大量 Pod 时。使用仪表板,您可以看到延迟的变化,例如,在创建 105 个 Pod 时,如图 4 所示。当您看到高度可变的线条时,您可能会认为方差是由于不同的构建版本造成的。然而,由于这里的这些测试是针对相同的 Kubernetes 代码运行的,因此我们可以得出结论,方差是由于性能波动造成的。当我们比较构建版本 #162 和 #173 的 99% 延迟时,方差接近 40 秒,这非常大。为了深入了解波动的来源,让我们查看“时间序列”页面。

| | | 图 4. 创建 105 个 Pod 时的 Pod 启动延迟。 |

具体查看构建版本 #162,我们可以看到在 Pod 创建延迟图中绘制的跟踪数据(图 5)。每条曲线是已到达特定跟踪探针的 Pod 操作数量的累积直方图。跟踪 Pod 的时间戳要么从性能测试中收集,要么通过解析 Kubelet 日志获得。目前,我们收集以下跟踪数据

  • “create”(在测试中):测试通过 API 客户端创建 Pod;
  • “running”(在测试中):测试监视来自 API 服务器的 Pod 是否正在运行;
  • “pod_config_change”:Kubelet SyncLoop 检测到的 Pod 配置更改;
  • “runtime_manager”:运行时管理器开始创建容器;
  • “infra_container_start”:Pod 的基础容器启动;
  • “container_start”:Pod 的容器启动;
  • “pod_running”:Pod 正在运行;
  • “pod_status_running”:状态管理器更新正在运行的 Pod 的状态;

时间序列图表明,状态管理器更新 Pod 状态需要很长时间(由于“running”与“pod_status_running”重叠,因此未显示“running”的数据)。我们发现此延迟是由于 Kubelet 对 API 服务器的每秒查询次数 (QPS) 限制(默认为 5)而引入的。在意识到这一点后,我们在其他测试中发现,通过增加 QPS 限制,曲线“running”逐渐与“pod_running”收敛,从而导致更低的延迟。因此,之前的 e2e 测试 Pod 启动结果反映了 Kubelet 和上传状态时间的综合延迟,因此低估了 Kubelet 的性能。

| | | 图 5. 使用构建版本 #162 的数据的时间序列页面。 |

此外,通过比较构建版本 #162(图 5)和构建版本 #173(图 6)的时间序列数据,我们发现性能 Pod 启动延迟波动实际上发生在更新 Pod 状态期间。构建版本 #162 有几个延迟较长的“pod_status_running”事件。因此,它为未来的优化提供了有用的想法。 

| | | 图 6. 构建版本 #173 的 Pod 启动延迟。 |

未来,我们计划使用 Kubernetes 中具有固定日志格式的事件来更方便地收集跟踪数据。您可以将自己的跟踪探针插入 Kubelet 中,而不是提取现有的日志条目,然后获得每个段的分解延迟。 

您可以在“TRACING”页面中查看不同构建版本中任意两个探针之间的延迟,如图 7 所示。例如,选择 “pod_config_change” 作为起始探针, “pod_status_running” 作为结束探针,可以获得 Kubelet 在连续构建中的延迟变化,而无需考虑状态更新的开销。借助此功能,开发人员可以监控 Kubelet 内部特定代码部分的性能变化。

| | | 图 7. 绘制任意两个探针之间的延迟。 |

未来工作

节点性能仪表板是一项全新的功能。目前仍处于积极开发中的 alpha 版本。我们将继续优化数据收集和可视化,为开发人员和集群维护人员提供更多的测试、指标和工具。

请加入我们的社区,帮助我们构建 Kubernetes 的未来!如果您对节点或性能测试特别感兴趣,请在我们的 Slack 频道中与我们聊天,或加入我们每周二太平洋时间上午 10 点在此 SIG-Node Hangout 举行的会议。