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

简介: extended-resources extended-resources在k8s1.9中是一个stable的特性。可以用一句话来概括这个特性: 通过向apiserver发送一个patch node 的请求,为这个node增加一个自定义的资源类型,用于以该资源的配额统计和相应的QoS的配置。

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...

9c5fd87a455fd44bc2a1156d6ad3be07a2623268

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节点上。

本文转自中文社区-k8s的扩展资源设计和device-plugin

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
23天前
|
运维 Kubernetes 监控
揭秘高效运维:如何用kubectl top命令实时监控K8s资源使用情况?
揭秘高效运维:如何用kubectl top命令实时监控K8s资源使用情况?
30 0
|
1月前
|
存储 Kubernetes 负载均衡
Kubernetes的“厨房”:架构是菜谱,组件是厨具,资源对象是食材(下)
本文深入探讨了Kubernetes(K8s)的架构、核心组件以及资源对象。Kubernetes作为一个开源的容器编排系统,通过其独特的架构设计和丰富的组件,实现了对容器化应用程序的高效管理和扩展。通过本文的介绍,读者可以深入了解Kubernetes的架构、核心组件以及资源对象,从而更好地应用和管理容器化应用程序。Kubernetes的灵活性和可扩展性使得它成为容器编排领域的领先者,为企业提供了强大的容器运行环境。
|
3月前
|
运维 Kubernetes Cloud Native
OpenKruise是一个基于Kubernetes的扩展套件
OpenKruise是一个基于Kubernetes的扩展套件【1月更文挑战第14天】【1月更文挑战第68篇】
19 2
|
4月前
|
Kubernetes 负载均衡 Cloud Native
猿创征文|云原生|kubernetes二进制1.18单master扩展为多master
猿创征文|云原生|kubernetes二进制1.18单master扩展为多master
53 0
|
4月前
|
Kubernetes Cloud Native 应用服务中间件
云原生|kubernetes|ResourceQuota 资源与准入控制器
云原生|kubernetes|ResourceQuota 资源与准入控制器
60 0
|
23天前
|
消息中间件 Kubernetes Kafka
Terraform阿里云创建资源1分钟创建集群一键发布应用Terraform 创建 Kubernetes 集群
Terraform阿里云创建资源1分钟创建集群一键发布应用Terraform 创建 Kubernetes 集群
16 0
|
26天前
|
Kubernetes API 调度
总结归纳Kubernetes | 一站式速查知识,助您轻松驾驭容器编排技术(水平扩展控制)
总结归纳Kubernetes | 一站式速查知识,助您轻松驾驭容器编排技术(水平扩展控制)
55 0
|
1月前
|
Kubernetes API 调度
Kubernetes的“厨房”:架构是菜谱,组件是厨具,资源对象是食材(上)
本文深入探讨了Kubernetes(K8s)的架构、核心组件以及资源对象。Kubernetes作为一个开源的容器编排系统,通过其独特的架构设计和丰富的组件,实现了对容器化应用程序的高效管理和扩展。通过本文的介绍,读者可以深入了解Kubernetes的架构、核心组件以及资源对象,从而更好地应用和管理容器化应用程序。Kubernetes的灵活性和可扩展性使得它成为容器编排领域的领先者,为企业提供了强大的容器运行环境。
|
2月前
|
Kubernetes 调度 微服务
K8s 生产最佳实践 - 限制 NameSpace 资源用量
K8s 生产最佳实践 - 限制 NameSpace 资源用量
|
2月前
|
Kubernetes Linux 调度
「译文」深入了解 Kubernetes 指标 - 第三部分 - 容器资源指标
「译文」深入了解 Kubernetes 指标 - 第三部分 - 容器资源指标

推荐镜像

更多