k8s的扩展资源设计和device-plugin

本文深入探讨Kubernetes 1.9版本中稳定特性的Extended Resources,讲解如何通过自定义资源类型进行资源配额管理和QoS配置。同时,解析Device Plugin的功能,包括其注册、实施及在Pod创建流程中的作用,以及如何通过DaemonSet部署。

extended-resources

extended-resources在k8s1.9中是一个stable的特性。可以用一句话来概括这个特性:

通过向apiserver发送一个patch node 的请求,为这个node增加一个自定义的资源类型,用于以该资源的配额统计和相应的QoS的配置。

patch node 的请求:

举例:

curl --header "Content-Type: application/json-patch+json" \
--request PATCH \
--data '[{"op": "add", "path": "/status/capacity/example.com~1dongle", "value": "4"}]' \
http://localhost:8001/api/v1/nodes/10.123.123.123/status

如上,我们为10.123.123.123这个node增加了一个resource:example.com/dongle (命令中的 ~1 会转化为 / ) ,这个node的capicity/allocable中会展示其有4个example.com/dongle资源:

"capacity": {
  "alpha.kubernetes.io/nvidia-gpu": "0",
  "cpu": "2",
  "memory": "2049008Ki",
  "example.com/dongle": "4",

如果我们要清除这个资源可以使用:

curl --header "Content-Type: application/json-patch+json" \
--request PATCH \
--data '[{"op": "remove", "path": "/status/capacity/example.com~1dongle"}]' \
http://localhost:8001/api/v1/nodes/<your-node-name>/status

QoS配置:

如果对QoS的含义不了解,可以参考我之前的文章

先假设整个k8s集群中我们只对10.123.123.123这个node动了手脚,当我们创建pod时,在spec.containers.resources.requests/limits中可以设置

 "example.com/dongle": "2"

从而让pod被调度到10.123.123.123上并消耗其2个example.com/dongle资源。这个资源将与cpu、memory一样,被调度器进行统计,并用在pod的调度算法中。如果node上的example.com/dongle资源耗尽,这类pod将无法成功调度。

device-plugin插件

设备插件从1.8版本开始加入,到1.9目前仍是alpha特性,设备插件的作用是在不更改k8s代码的情况下,向k8s提供各种资源的统计信息和使用预备工作。这里说的资源如GPU、高性能NIC、FPGA、infiniBand或其他。

device-plugin的注册和实施

device-plugin功能由DevicePlugins这个参数控制,默认是禁用的,启用这个参数后就可以令kubelet开放Register 的grpc服务。 device-plugin可以通过这个服务向kubelet注册自己,注册时要告知kubelet:

  • 本device-plugin的Unix socket 名称。用于kubelet作为grpc 客户端向本device-plugin发请求;
  • 本device-plugin的API版本;
  • 本device-plugin要开放的资源名,此处资源名必须遵循一定格式,形如:nvidia.com/gpu

注册成功后,kubelet会向device-plugin调用Listandwatch方法获取设备的列表,此处设备的列表以该资源所有设备的描述信息(id、健康状态)组成数组返回。kubelet将这个资源及其对应的设备个数记录到node.status.capicity/allocable 更新到apiserver。该方法会一直循环检查,一旦设备异常或者从机器上拔出,会将最新的设备列表返回给kubelet。

如此一来,创建pod时,spec.containers.resource.limits/requests 中就可以增加如 "nvidia.com/gpu" : 2 这样的字段,来告知k8s将pod调度到有超过2个nvidia.com/gpu资源余量的nodes上(这里与上文的extended-resources中QoS是一个道理)。当node上要运行该pod时,kubelet会向device-plugin调用Allocate方法,device-plugin在这里可能会做一些初始化的操作,比如GPU清理或QRNG初始化之类。如果初始化成功。该方法会返回分配给该pod使用的设备在容器创建时需要如何配置,这个配置会被传递到container runtime。用于run 容器时作为参数进行配置。

完整的使用流程如下图(图片来源:https://github.com/kubernetes...

clipboard.png

device-plugin 使用的代码解析

我们从创建pod的整个流程中一步步解析代码执行:

创建带特殊资源设备的pod;
调度器从cache中选择满足要求的node;
node收到ADD POD, 对pod执行admit方法进行可运行的判断。

kubelet初始化时增加了一个admitHandler

klet.admitHandlers.AddPodAdmitHandler(lifecycle.NewPredicateAdmitHandler(klet.getNodeAnyWay, criticalPodAdmissionHandler, klet.containerManager.UpdatePluginResources))

其中就包括了klet.containerManager.UpdatePluginResources方法,该方法会执行devicepluginManager中的Allocate方法:

func (cm *containerManagerImpl) UpdatePluginResources(node *schedulercache.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error {
      return cm.devicePluginManager.Allocate(node, attrs)
}

上述的Allocate方法,会将kubelet本身缓存记录的资源可用量进行判断和计算;
然后选定要使用的设备,向device-plugin发送Allocate调用,device-plugin会针对request中的设备id,检查是否可用,并将使用这几个设备需要的使用参数返回给kubelet,返回的格式是:

type AllocateResponse struct {
 // List of environment variable to be set in the container to access one of more devices.
 Envs map[string]string
 // Mounts for the container.
 Mounts []*Mount
 // Devices for the container.
 Devices []*DeviceSpec
}

最后将要这个pod要使用哪几个资源设备(设备id、以及deviceplugin返回的设备使用参数)记录在podDevices中,podDevices就是一个从pod到资源设备详细信息的映射,是一个多层次的map结构。

kubelet要创建pod的容器时,会调用到GenerateRunContainerOptions方法,用于生成容器runtime要的参数,该方法中会首先调用:

opts, err := kl.containerManager.GetResources(pod, container)

containerManagerGetResources会调用devicePluginManager中的GetDeviceRunContainerOptions方法,最后执行deviceRunContainerOptions方法,从podDevices中获取这个pod相应的容器需要使用的设备,并组织成容器运行时参数的对象opts,最终run container时会被用到。比如gpu容器,会在opts中增加devices参数的指定,最后容器创建时会带有需要的设备。

device-plugin的部署

部署device-plugin插件最佳的方法是使用k8s的daemonset,因为daemonset可以在插件失败是重新启动之,且会自动分布到满足条件的所有node节点上。

社区参考文档
https://kubernetes.io/docs/ta...

<think>好的,用户想了解Kubernetes扩展资源的概念使用方法,包括定义、使用场景示例。首先,我需要整理一下Kubernetes中扩展资源的基本概念。扩展资源主要分为两种:自定义资源定义(CRD)第三方资源(已弃用)。现在主要使用CRD,所以重点应该放在CRD上。 根据引用[3],CRD是Kubernetes API的扩展机制,允许用户添加新的资源类型,而无需修改核心代码。CRD的核心组成包括API组与版本、结构定义命名空间作用域。用户需要了解如何定义CRD,可能涉及到YAML文件的编写,比如定义apiVersion、kind、metadata等部分,特别是spec中的结构,如组名、版本、作用域等。 接下来是使用场景。CRD通常用于抽象自定义业务逻辑,比如数据库实例管理、批处理任务工作流等。比如在引用[1]的示例项目中,可能展示了如何用CRD管理应用配置。需要结合引用中的信息,说明CRD在哪些具体情况下适用,比如当原生资源无法满足需求时,或者需要统一管理自定义应用配置时。 然后是示例部分。用户可能需要一个具体的CRD定义示例,比如定义一个名为“MyAppConfig”的资源,包含一些字段如replicas、image等。同时,还需要展示如何使用这个CRD创建资源实例,比如通过kubectl apply应用YAML文件。另外,结合引用[2],可能需要提到资源请求限制,虽然这更多是关于Pod资源管理,但可以说明CRD如何与其他资源管理结合使用。 用户可能还关心扩展资源的实际应用,比如如何通过CRD扩展集群功能,或者如何与Operator模式结合实现自动化管理。比如,引用[3]提到CRD的行为与原生资源一致,可以使用kubectl管理,这点需要强调。同时,引用[4]中的监控命令,如kubectl top nodes,可能与资源使用情况有关,但扩展资源更多是定义新资源类型,而不是直接监控资源使用,这点需要注意区分。 此外,需要确保回答结构清晰,分点说明定义、使用场景示例,并生成相关问题。注意使用中文回答,正确使用LaTeX格式,比如变量用$...$包裹。例如,当提到API组时,可以写成$stable.example.com/v1$。同时,检查是否有需要引用的地方,比如CRD的定义引用[3],示例项目引用[1],资源请求引用[2]等。 可能还需要注意用户的问题是否涉及其他类型的扩展资源,比如设备插件管理的资源,如GPU。但根据引用内容,主要讨论的是CRD,所以应集中在CRD上。不过,如果用户提到扩展资源,可能需要简要说明其他类型,但根据现有引用,可能没有足够信息,因此可能需要专注于CRD部分。 最后,生成相关问题时要围绕CRD的定义、使用场景、示例以及与其他Kubernetes功能的结合,比如如何验证CRD的有效性,或者CRD与Operator的关系等。确保问题具有针对性,帮助用户深入理解。</think>### Kubernetes 扩展资源详解 #### 一、扩展资源定义 Kubernetes 扩展资源(Extended Resources)分为两类: 1. **自定义资源定义(CRD)** 通过 CRD 机制扩展 Kubernetes API,定义新的资源类型,语法格式如下[^3]: ```yaml apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: myappconfigs.stable.example.com spec: group: stable.example.com versions: - name: v1 served: true storage: true schema: # 结构定义 openAPIV3Schema: type: object properties: spec: type: object properties: replicas: {type: integer} image: {type: string} scope: Namespaced # 命名空间级资源 ``` 2. **设备插件扩展资源** 例如 GPU、FPGA 等硬件资源,需通过设备插件(Device Plugin)实现资源上报与管理。 #### 二、使用场景 1. **抽象业务逻辑** 如管理数据库实例(MySQLCluster)、批处理任务(BatchJob)等复杂业务对象[^1] 2. **统一配置管理** 封装应用配置模板,实现多环境配置复用 3. **扩展调度策略** 自定义资源配额管理,例如限制每个租户的 GPU 使用量 4. **集成外部系统** 对接云服务资源(如 AWS S3 Bucket)或传统中间件 #### 三、完整示例 1. **定义 CRD** ```yaml # myappconfig-crd.yaml apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: myappconfigs.stable.example.com spec: group: stable.example.com versions: - name: v1 served: true storage: true schema: openAPIV3Schema: type: object properties: spec: type: object properties: replicas: {type: integer, minimum: 1} image: {type: string, pattern: '^.+:.+$'} scope: Namespaced ``` 创建命令: ```bash kubectl apply -f myappconfig-crd.yaml ``` 2. **创建资源实例** ```yaml # demo-app.yaml apiVersion: stable.example.com/v1 kind: MyAppConfig metadata: name: demo-app spec: replicas: 3 image: nginx:1.21 ``` 应用配置: ```bash kubectl apply -f demo-app.yaml ``` 3. **结合原生资源使用** ```yaml # deployment-with-crd.yaml apiVersion: apps/v1 kind: Deployment metadata: name: crd-integration-demo spec: replicas: 3 template: spec: containers: - name: app image: nginx:1.21 resources: requests: cpu: 100m memory: 128Mi limits: cpu: 200m # 资源限制定义[^2] memory: 256Mi ``` #### 四、监控与管理 1. 查看自定义资源: ```bash kubectl get myappconfigs.stable.example.com ``` 2. 监控 API 请求速率: ```bash kubectl logs -n kube-system <apiserver-pod> | grep 'REJECT' [^4] ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值