From 4e8fb7278a168f44ee5ca2d9d0543d8b0207c12d Mon Sep 17 00:00:00 2001 From: bryan Date: Tue, 31 Mar 2020 15:25:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20device-plugins=E4=B8=AD?= =?UTF-8?q?=E6=96=87=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compute-storage-net/device-plugins.md | 400 ++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 content/zh/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md diff --git a/content/zh/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md b/content/zh/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md new file mode 100644 index 0000000000..329731f623 --- /dev/null +++ b/content/zh/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md @@ -0,0 +1,400 @@ +--- +reviewers: +title: 设备插件 +description: 使用 Kubernetes 设备插件框架来实现适用于 GPU,NIC,FPGA,InfiniBand 以及需要特定于供应商设置的类似资源的插件。 +content_template: templates/concept +weight: 20 +--- + +{{% capture overview %}} +{{< feature-state for_k8s_version="v1.10" state="beta" >}} + + +Kubernetes 提供了一个[设备插件框架](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/resource-management/device-plugin.md),您可以用来将系统硬件资源发布到 {{< glossary_tooltip term_id="kubelet" >}}。 + +供应商可以实现您手动部署或作为 {{< glossary_tooltip term_id="daemonset" >}} 部署的设备插件,而不必为 Kubernetes 本身定制代码。目标设备包括 GPU、高性能NIC、FPGA、InfiniBand 适配器以及其他类似的计算资源,可能需要特定于供应商的初始化和设置。 + +{{% /capture %}} + +{{% capture body %}} + +## 注册设备插件 + + +kubelet 输出了一个 `Registration` 的 gRPC 服务: + +```gRPC +service Registration { + rpc Register(RegisterRequest) returns (Empty) {} +} +``` + + +设备插件可以通过此 gRPC 服务在 kubelet 进行注册。在注册期间,设备插件需要发送下面几样内容: + + * 设备插件的 Unix 套接字。 + * 设备插件的 API 版本。 + * `ResourceName` 是需要公布的。这里 `ResourceName` 需要遵循[扩展资源命名方案](/docs/concepts/configuration/manage-compute-resources-container/#extended-resources),类似于 `vendor-domain/resourcetype`。(比如 NVIDIA GPU 就被公布为 `nvidia.com/gpu`。) + +成功注册后,设备插件就向 kubelet 发送他所管理的设备列表,然后 kubelet 负责将这些资源发布到 API 服务器,作为 kubelet 节点状态更新的一部分。 + +比如,设备插件在 kubelet 中注册了 `hardware-vendor.example/foo` 并报告了节点上的两个运行状况良好的设备后,节点状态将更新以通告该节点已安装2个 `Foo` 设备并且是可用的。 + + +然后用户需要去请求其他类型的资源的时候,就可以请求[容器](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core)规范中的设备,但是有以下的限制: + * 扩展资源支持整数资源,并且不能被过量使用 + * 设备不能在容器之间共享 + + +假设 Kubernetes 集群正在运行一个设备插件,该插件在一些节点上公布的资源为 `hardware-vendor.example/foo`,下面就是一个 pod 运行请求此资源的示例: + +```yaml +--- +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 服务,该服务实现以下接口: + + ```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) {} + } + ``` + + * 插件通过 Unix socket 在主机路径 `/ var / lib / kubelet / device-plugins / kubelet.sock` 处向 kubelet 注册自身。 + * 成功注册自身后,设备插件将以服务模式运行,在此期间,它将持续监控设备运行状况,并在设备状态发生任何变化时向 kubelet 报告。它还负责`分配` gRPC 请求。在`分配`期间,设备插件可能还会做一些设备特定的准备;例如 GPU 清理或 QRNG 初始化。如果操作成功,则设备插件将返回 `AllocateResponse`,其中包含用于访问被分配的设备容器运行时的配置。kubelet将此信息传递到容器运行时。 + + +### 处理 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](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core) 中声明作为 {{< glossary_tooltip term_id="volume" >}} 被 mount 到插件中。 + +如果你选择 DaemonSet 方法,你可以通过 Kubernetes 进行以下操作:将设备插件的 Pod 放置在节点上,在出现故障后重新启动 daemon Pod,来进行自动进行升级。 + + +## API 兼容性 + +Kubernetes 设备插件支持还处于 beta 版本。所以在稳定版本出来之前 API 会以不兼容的方式进行更改,作为一个项目,Kubernetes 建议设备插件开发者: + +* 注意未来版本的更改 +* 支持多个版本的设备插件 API,以实现向后/向前兼容性。 + +如果你启用 DevicePlugins 功能,并在需要升级到 Kubernetes 版本来获得较新的设备插件 API 版本的节点上运行设备插件,请在升级这些节点之前先升级设备插件以支持这两个版本。采用该方法将确保升级期间设备分配的连续运行。 + + +## 监控设备插件资源 + +{{< feature-state for_k8s_version="v1.15" state="beta" >}} + +为了监控设备插件提供的资源,监控代理程序需要能够发现节点上正在使用的设备,并获取元数据来描述哪个指标与容器相关联。设备监控代理暴露给 [Prometheus](https://prometheus.io/) 的指标应该遵循 [Kubernetes Instrumentation Guidelines](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/instrumentation.md),使用 `pod`、`namespace` 和 `container` 标签来标识容器。 + + +kubelet 提供了gRPC服务来使得正在使用中的设备被发现,并且还未这些设备提供了元数据: + +```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 socket 来提供服务。设备插件资源的监控代理程序可以部署为守护进程或者 DaemonSet。规范的路径 `/var/lib/kubelet/pod-resources` 需要特权来进入,所以监控代理程序必须要在获得授权的安全的上下文中运行。如果设备监控代理以 DaemonSet 形式运行,必须要在插件的 [PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core) 中声明将 `/var/lib/kubelet/pod-resources` 目录以 {{< glossary_tooltip term_id="volume" >}} 形式被 mount 到容器中。 + +对“PodResources 服务”的支持要求启用“KubeletPodResources”[feature gate](/docs/reference/command-line-tools-reference/feature-gates/)。从 Kubernetes 1.15 开始默认启用。 + + +## 设备插件与拓扑管理器的集成 + +{{< feature-state for_k8s_version="v1.17" state="alpha" >}} + +拓扑管理器是 Kubelet 的一个组件,它允许以拓扑对齐方式来调度资源。为了做到这一点,设备插件 API 进行了扩展来包括一个 `TopologyInfo` 结构体。 + +```gRPC +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,},}}} +``` + + +## 设备插件示例 {#examples} + +下面是一些设备插件实现的示例: + +* [AMD GPU device plugin](https://github.com/RadeonOpenCompute/k8s-device-plugin) +* [Intel device plugins](https://github.com/intel/intel-device-plugins-for-kubernetes) 支持 Intel GPU、FPGA 和 QuickAssist 设备 +* [KubeVirt device plugins](https://github.com/kubevirt/kubernetes-device-plugins) 用于硬件辅助的虚拟化 +* The [NVIDIA GPU device plugin](https://github.com/NVIDIA/k8s-device-plugin) + * 需要 [nvidia-docker](https://github.com/NVIDIA/nvidia-docker) 2.0,允许运行 Docker 容器的时候开启 GPU。 +* [NVIDIA GPU device plugin for Container-Optimized OS](https://github.com/GoogleCloudPlatform/container-engine-accelerators/tree/master/cmd/nvidia_gpu) +* [RDMA device plugin](https://github.com/hustcat/k8s-rdma-device-plugin) +* [Solarflare device plugin](https://github.com/vikaschoudhary16/sfc-device-plugin) +* [SR-IOV Network device plugin](https://github.com/intel/sriov-network-device-plugin) +* [Xilinx FPGA device plugins](https://github.com/Xilinx/FPGA_as_a_Service/tree/master/k8s-fpga-device-plugin/trunk) + +{{% /capture %}} +{{% capture whatsnext %}} + + +* 查看 [scheduling GPU resources](/docs/tasks/manage-gpus/scheduling-gpus/) 来学习使用设备插件 +* 查看在 node 上如何 [advertising extended resources](/docs/tasks/administer-cluster/extended-resource-node/) +* 阅读如何在 Kubernetes 中如何使用 [hardware acceleration for TLS ingress](https://kubernetes.io/blog/2019/04/24/hardware-accelerated-ssl/tls-termination-in-ingress-controllers-using-kubernetes-device-plugins-and-runtimeclass/) +* 学习 [Topology Manager] (/docs/tasks/adminster-cluster/topology-manager/) + +{{% /capture %}}