Black lives matter.
We stand in solidarity with the Black community.
Racism is unacceptable.
It conflicts with the core values of the Kubernetes project and our community does not tolerate it.
We stand in solidarity with the Black community.
Racism is unacceptable.
It conflicts with the core values of the Kubernetes project and our community does not tolerate it.
Kubernetes v1.10 [beta]
Kubernetes 提供了一个设备插件框架,您可以用来将系统硬件资源发布到 Kubelet一个在集群中每个节点上运行的代理。它保证容器都运行在 Pod 中。 。
供应商可以实现设备插件,由您手动部署或作为 DaemonSet确保 Pod 的副本在集群中的一组节点上运行。 来部署,而不必定制 Kubernetes 本身的代码。目标设备包括 GPU、高性能 NIC、FPGA、InfiniBand 适配器以及其他类似的、可能需要特定于供应商的初始化和设置的计算资源。
kubelet 输出了一个 Registration
的 gRPC 服务:
service Registration {
rpc Register(RegisterRequest) returns (Empty) {}
}
设备插件可以通过此 gRPC 服务在 kubelet 进行注册。在注册期间,设备插件需要发送下面几样内容:
ResourceName
是需要公布的。这里 ResourceName
需要遵循扩展资源命名方案,类似于 vendor-domain/resourcetype
。(比如 NVIDIA GPU 就被公布为 nvidia.com/gpu
。)成功注册后,设备插件就向 kubelet 发送他所管理的设备列表,然后 kubelet 负责将这些资源发布到 API 服务器,作为 kubelet 节点状态更新的一部分。
比如,设备插件在 kubelet 中注册了 hardware-vendor.example/foo
并报告了节点上的两个运行状况良好的设备后,节点状态将更新以通告该节点已安装2个 Foo
设备并且是可用的。
然后用户需要去请求其他类型的资源的时候,就可以在Container规范请求这类设备,但是有以下的限制:
假设 Kubernetes 集群正在运行一个设备插件,该插件在一些节点上公布的资源为 hardware-vendor.example/foo
。
下面就是一个 Pod 示例,请求此资源以运行某演示负载:
---
apiVersion: v1
kind: Pod
metadata:
name: demo-pod
spec:
containers:
- name: demo-container-1
image: k8s.gcr.io/pause:2.0
resources:
limits:
hardware-vendor.example/foo: 2
#
# 这个 pod 需要两个 hardware-vendor.example/foo 设备
# 而且只能够调度到满足需求的 node 上
#
# 如果该节点中有2个以上的设备可用,其余的可供其他 pod 使用
设备插件的常规工作流程包括以下几个步骤:
/var/lib/kubelet/device-plugins/
下的 Unix socket 启动一个 gRPC 服务,该服务实现以下接口:service DevicePlugin {
// ListAndWatch returns a stream of List of Devices
// Whenever a Device state change or a Device disappears, ListAndWatch
// returns the new list
rpc ListAndWatch(Empty) returns (stream ListAndWatchResponse) {}
// Allocate is called during container creation so that the Device
// Plugin can run device specific operations and instruct Kubelet
// of the steps to make the Device available in the container
rpc Allocate(AllocateRequest) returns (AllocateResponse) {}
}
/var/lib/kubelet/device-plugins/kubelet.sock
处向 kubelet 注册自身。Allocate
gRPC 请求。在Allocate
期间,设备插件可能还会做一些设备特定的准备;例如 GPU 清理或 QRNG 初始化。如果操作成功,则设备插件将返回 AllocateResponse
,其中包含用于访问被分配的设备容器运行时的配置。kubelet 将此信息传递到容器运行时。设备插件应能监测到 kubelet 重启,并且向新的 kubelet 实例来重新注册自己。在当前实现中,当 kubelet 重启的时候,新的 kubelet 实例会删除 /var/lib/kubelet/device-plugins
下所有已经存在的 Unix sockets。设备插件需要能够监控到它的 Unix socket 被删除,并且当发生此类事件时重新注册自己。
你可以将你的设备插件作为节点操作系统的软件包来部署、作为 DaemonSet 来部署或者手动部署。
规范目录 /var/lib/kubelet/device-plugins
是需要特权访问的,所以设备插件必须要在被授权的安全的上下文中运行。如果你将设备插件部署为 DaemonSet,/var/lib/kubelet/device-plugins
目录必须要在插件的 PodSpec 中声明作为 卷包含可被 Pod 中容器访问的数据的目录。
被 mount 到插件中。
如果你选择 DaemonSet 方法,你可以通过 Kubernetes 进行以下操作:将设备插件的 Pod 放置在节点上,在出现故障后重新启动 daemon Pod,来进行自动进行升级。
Kubernetes 设备插件支持还处于 beta 版本。所以在稳定版本出来之前 API 会以不兼容的方式进行更改。作为一个项目,Kubernetes 建议设备插件开发者:
如果你启用 DevicePlugins 功能,并在需要升级到 Kubernetes 版本来获得较新的设备插件 API 版本的节点上运行设备插件,请在升级这些节点之前先升级设备插件以支持这两个版本。采用该方法将确保升级期间设备分配的连续运行。
Kubernetes v1.15 [beta]
为了监控设备插件提供的资源,监控代理程序需要能够发现节点上正在使用的设备,并获取元数据来描述哪个指标与容器相关联。设备监控代理暴露给 Prometheus 的指标应该遵循 Kubernetes Instrumentation Guidelines,使用 pod
、namespace
和 container
标签来标识容器。
kubelet 提供了 gRPC 服务来使得正在使用中的设备被发现,并且还未这些设备提供了元数据:
// PodResourcesLister is a service provided by the kubelet that provides information about the
// node resources consumed by pods and containers on the node
service PodResourcesLister {
rpc List(ListPodResourcesRequest) returns (ListPodResourcesResponse) {}
}
gRPC 服务通过 /var/lib/kubelet/pod-resources/kubelet.sock
的 UNIX 套接字来提供服务。设备插件资源的监控代理程序可以部署为守护进程或者 DaemonSet。规范的路径 /var/lib/kubelet/pod-resources
需要特权来进入,所以监控代理程序必须要在获得授权的安全的上下文中运行。如果设备监控代理以 DaemonSet 形式运行,必须要在插件的 PodSpec 中声明将 /var/lib/kubelet/pod-resources
目录以 卷包含可被 Pod 中容器访问的数据的目录。
形式被 mount 到容器中。
对“PodResources 服务”的支持要求启用 KubeletPodResources
特性门控。从 Kubernetes 1.15 开始默认启用。
Kubernetes v1.17 [alpha]
拓扑管理器是 Kubelet 的一个组件,它允许以拓扑对齐方式来调度资源。为了做到这一点,设备插件 API 进行了扩展来包括一个 TopologyInfo
结构体。
message TopologyInfo {
repeated NUMANode nodes = 1;
}
message NUMANode {
int64 ID = 1;
}
设备插件希望拓扑管理器可以将填充的 TopologyInfo 结构体作为设备注册的一部分以及设备 ID 和设备的运行状况发送回去。然后设备管理器将使用此信息来咨询拓扑管理器并做出资源分配决策。
TopologyInfo
支持定义 nodes
字段,允许为 nil
(默认)或者是一个 NUMA nodes 的列表。这样就可以使设备插件可以跨越 NUMA nodes 去发布。
下面是一个由设备插件为设备填充 TopologyInfo
结构体的示例:
pluginapi.Device{ID: "25102017", Health: pluginapi.Healthy, Topology:&pluginapi.TopologyInfo{Nodes: []*pluginapi.NUMANode{&pluginapi.NUMANode{ID: 0,},}}}
下面是一些设备插件实现的示例: