Kubernetes 1.28:节点 podresources API 正式发布

作者:Francesco Romani (Red Hat)

译者:Wilson Wu (DaoCloud)

podresources API 是由 kubelet 提供的节点本地 API,它用于公开专门分配给容器的计算资源。 随着 Kubernetes 1.28 的发布,该 API 现已正式发布。

它解决了什么问题?

kubelet 可以向容器分配独占资源,例如 CPU,授予对完整核心的独占访问权限内存,包括内存区域或巨页。 需要高性能或低延迟(或者两者都需要)的工作负载可以利用这些特性。 kubelet 还可以将设备分配给容器。 总的来说,这些支持独占分配的特性被称为“资源管理器(Resource Managers)”。

如果没有像 podresources 这样的 API,了解资源分配的唯一可能选择就是读取资源管理器使用的状态文件。 虽然这样做是出于必要,但这种方法的问题是这些文件的路径和格式都是内部实现细节。 尽管非常稳定,但项目保留自由更改它们的权利。因此,使用状态文件内容的做法是不可靠的且不受支持的, 建议这样做的项目考虑迁移到使用 podresources API 或其他受支持的 API。

API 概述

podresources API 最初被提出是为了实现设备监控。 为了支持监控代理,一个关键的先决条件是启用由 kubelet 执行的设备分配自省(Introspection)。 API 的最初目标就是服务于此目的。API 的第一次迭代仅实现了一个函数 List,用于返回有关设备分配给容器的信息。 该 API 由 multus CNIGPU 监控工具使用。

自推出以来,podresources API 扩大了其范围,涵盖了设备管理器之外的其他资源管理器。 从 Kubernetes 1.20 开始,List API 还报告 CPU 核心和内存区域(包括巨页); 在能够从系统中推断 CPU 和内存的位置时,API 还报告设备的 NUMA 位置。

在 Kubernetes 1.21 中,API 增加了 GetAllocatableResources 函数。这个较新的 API 补充了现有的 List API, 并使监控代理能够辨识尚未分配的资源,从而支持在 podresources API 之上构建新的特性, 例如 NUMA 感知的调度器插件

最后,在 Kubernetes 1.27 中,引入了另一个函数 Get,以便对 CNI 元插件(Meta-Plugins)更加友好, 简化对已分配给特定 Pod 的资源的访问,而不必过滤节点上所有 Pod 的资源。Get 函数目前处于 Alpha 级别。

使用 API

podresources API 由本地 kubelet 提供,位于 kubelet 运行所在的同一节点上。 在 Unix 风格的系统上,通过 Unix 域套接字提供端点;默认路径是 /var/lib/kubelet/pod-resources/kubelet.sock。 在 Windows 上,通过命名管道提供端点;默认路径是 npipe://\\.\pipe\kubelet-pod-resources

为了让容器化监控应用使用 API,套接字应挂载到容器内。 一个好的做法是挂载 podresources 套接字端点所在的目录,而不是直接挂载套接字。 这种做法将确保 kubelet 重新启动后,容器化监视器应用能够重新连接到套接字。

在下面的 DaemonSet 示例清单中,包含一个假想的使用 podresources API 的监控代理:

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  # 仅作为样例
        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 是允许的,因为 API 是无状态的。
  • kubelet 具有内置限速机制, 用以缓解来自行为不当或恶意用户的本地拒绝服务攻击。API 的使用者必须容忍服务器返回的速率限制错误。 速率限制目前是硬编码的且作用于全局的,因此行为不当的客户端可能会耗光所有配额,进而导致行为正确的客户端挨饿。

未来的增强

由于历史原因,podresources API 的规范不如典型的 kubernetes API(例如 Kubernetes HTTP API 或容器运行时接口)精确。 这会导致在极端情况下出现未指定的行为。我们正在努力纠正这种状态并制定更精确的规范。

动态资源分配(DRA)基础设施是对资源管理的重大改革。 与 podresources API 的集成已经在进行中。

我们正在努力推荐或创建可供使用的参考客户端包。

参与其中

此功能由 SIG Node 驱动。 请加入我们,与社区建立联系,并分享你对上述功能及其他功能的想法和反馈。我们期待你的回音!