本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kubernetes 1.28: 节点 podresources API 进入 GA 阶段
podresources API 是 kubelet 在节点上本地提供的一个 API,用于公开专门分配给容器的计算资源。随着 Kubernetes 1.28 的发布,该 API 现已正式发布(GA)。
它解决了什么问题?
kubelet 可以为容器分配独占资源,例如CPU,授予对完整核心的独占访问权限,或内存,无论是内存区域还是大页。需要高性能或低延迟(或两者兼备)的工作负载会利用这些特性。kubelet 还可以将设备分配给容器。这些支持独占分配的功能统称为“资源管理器”。
如果没有像 podresources 这样的 API,了解资源分配的唯一可能选项是读取资源管理器使用的状态文件。虽然这是出于必要,但这种方法的问题在于这些文件的路径和格式都是内部实现细节。尽管非常稳定,但项目保留自由更改它们的权利。因此,使用状态文件的内容是脆弱且不受支持的,建议这样做项目考虑迁移到 podresources API 或其他受支持的 API。
API 概述
podresources API 最初是为了实现设备监控而提出的。为了启用监控代理,一个关键的前提是能够内省由 kubelet 执行的设备分配。满足这一目的是该 API 的最初目标。API 的第一个迭代版本只实现了一个函数,List
,用于返回有关设备分配给容器的信息。该 API 被 multus CNI 和 GPU 监控工具使用。
自诞生以来,podresources API 的范围已扩展到覆盖除设备管理器之外的其他资源管理器。从 Kubernetes 1.20 开始,List
API 也报告 CPU 核心和内存区域(包括大页);该 API 还报告设备的 NUMA 局部性,而 CPU 和内存的局部性可以从系统中推断出来。
在 Kubernetes 1.21 中,该 API 增加了 GetAllocatableResources
函数。这个更新的 API 补充了现有的 List
API,并使监控代理能够确定未分配的资源,从而支持在 podresources API 之上构建新功能,例如支持 NUMA 的调度器插件。
最后,在 Kubernetes 1.27 中,引入了另一个函数 Get
,以便更好地与 CNI 元插件配合,使其可以更简单地访问分配给特定 Pod 的资源,而不必筛选节点上所有 Pod 的资源。Get
函数目前处于 Alpha 级别。
使用 API
podresources API 由 kubelet 在其运行的同一节点上本地提供。在 Unix 风格的系统上,端点通过 Unix 域套接字提供;默认路径是 /var/lib/kubelet/pod-resources/kubelet.sock
。在 Windows 上,端点通过命名管道提供;默认路径是 npipe://\\.\pipe\kubelet-pod-resources
。
为了让容器化的监控应用程序使用该 API,应将套接字挂载到容器内部。一个好的做法是挂载 podresources 套接字端点所在的目录,而不是直接挂载套接字。这将确保在 kubelet 重启后,容器化的监控应用程序能够重新连接到套接字。
一个假设的监控代理的示例清单,它使用 podresources API 并作为 DaemonSet 部署,可能如下所示
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: podresources-monitoring-app
namespace: monitoring
spec:
selector:
matchLabels:
name: podresources-monitoring
template:
metadata:
labels:
name: podresources-monitoring
spec:
containers:
- args:
- --podresources-socket=unix:///host-podresources/kubelet.sock
command:
- /bin/podresources-monitor
image: podresources-monitor:latest # just for an example
volumeMounts:
- mountPath: /host-podresources
name: host-podresources
serviceAccountName: podresources-monitor
volumes:
- hostPath:
path: /var/lib/kubelet/pod-resources
type: Directory
name: host-podresources
我希望你能发现以编程方式使用 podresources API 是很直接的。kubelet API 包提供了协议文件和 Go 类型定义;然而,项目尚未提供客户端包,并且不应直接使用现有代码。建议的方法是在你的项目中重新实现客户端,复制并粘贴相关函数,例如 multus 项目就是这样做的。
在操作使用 podresources API 的容器化监控应用程序时,有几点值得强调,以防止出现“陷阱”时刻
- 尽管该 API 只公开数据,并且在设计上不允许客户端更改 kubelet 状态,但 gRPC 请求/响应模型需要对 podresources API 套接字具有读写访问权限。换句话说,无法将容器挂载限制为
ReadOnly
。 - 允许多个客户端连接到 podresources 套接字并使用该 API,因为它是无状态的。
- kubelet 具有内置的速率限制,以减轻来自行为不当或恶意消费者的本地拒绝服务攻击。API 的消费者必须容忍服务器返回的速率限制错误。该速率限制目前是硬编码且全局的,因此行为不当的客户端可能会消耗所有配额,并可能导致行为正常的客户端饿死。
未来的增强
由于历史原因,podresources API 的规范没有典型的 Kubernetes API(例如 Kubernetes HTTP API 或容器运行时接口)那么精确。这导致在边缘情况下出现未指定的行为。目前正在进行一项努力来纠正这种情况,并制定更精确的规范。
动态资源分配(DRA)基础设施是对资源管理的重大改革。与 podresources API 的集成已经在进行中。
一项努力正在进行中,旨在推荐或创建一个可供使用的参考客户端包。
参与进来
此功能由 SIG Node 推动。请加入我们,与社区联系,分享您围绕上述功能及其他方面的想法和反馈。我们期待您的声音!