共计 7195 个字符,预计需要花费 18 分钟才能阅读完成。
对于咱们
更多对于云原生的案例和常识,可关注同名【腾讯云原生】公众号~
福利:
①公众号后盾回复【手册】,可取得《腾讯云原生路线图手册》&《腾讯云原生最佳实际》~
②公众号后盾回复【系列】,可取得《15 个系列 100+ 篇超实用云原生原创干货合集》,蕴含 Kubernetes 降本增效、K8s 性能优化实际、最佳实际等系列。
③公众号后盾回复【白皮书】,可取得《腾讯云容器平安白皮书》&《降本之源 - 云原生老本治理白皮书 v1.0》
④公众号后盾回复【光速入门】,可取得腾讯云专家 5 万字精髓教程,光速入门 Prometheus 和 Grafana。
作者
徐蓓,腾讯云容器技术专家,腾讯云异构计算容器负责人,多年云计算一线架构设计与研发教训,长期深耕 Kubernetes、在离线混部与 GPU 容器化畛域,Kubernetes KEP Memory QoS 作者,Kubernetes 踊跃贡献者。
以后存在问题
GPU 具备大量外围和高速内存,善于并行计算,非常适合训练和运行机器学习模型。因为近几年 AI 技术愈发成熟,落地场景越来越多,对 GPU 的需要呈井喷趋势。而在资源管理调度平台上,Kubernetes 已成为事实标准。所以很多客户抉择在 Kubernetes 中应用 GPU 运行 AI 计算工作。
Kubernetes 提供 device plugin 机制,能够让节点发现和上报设施资源,供 Pod 应用。GPU 资源也是通过该形式提供。以 nvidia GPU 为例,用户在 Kubernetes 节点部署 nvidia-device-plugin,插件扫描节点 GPU 卡,会以 extended resource 机制将 GPU 资源以相似 nvidia.com/gpu: 8
的模式注册到节点中。用户创立 Pod 时指定该资源名,通过调度器调度后,Pod 绑定到节点,最终通过 nvidia docker 提供的一系列工具,将所需 GPU 设施挂载到容器里。
Kubernetes device plugin 提供了一种便捷的形式用于集成第三方设施。但利用在 GPU 场景,还是存在以下有余:
- 集群 GPU 资源短少全局视角。没有直观形式可获取集群层面 GPU 信息,比方 Pod / 容器与 GPU 卡绑定关系、已应用 GPU 卡数 等
- 不能很好反对多 GPU 后端。各种 GPU 技术(nvidia docker、qGPU、vCUDA、gpu share、GPU 池化)均需独立部署组件,无奈对立调度和治理
问题一:短少 GPU 资源全局视角
现有 Kubernetes 对 GPU 资源的调配调度是通过 extended resource 实现的,它是基于节点上卡数量的加减调度。用户如果想晓得集群中 GPU 卡的分配情况,须要遍历节点,拿到并计算这些信息。并且因为这个资源是标量的,所以并无奈拿到 Pod / 容器 与卡的绑定关系。这些问题在整卡模式下不是那么凸显,但在细粒度共享模式下,就尤为重大了。
因为 GPU 卡绝对低廉,并且某些 AI 负载吃不满单张 GPU 算力,GPU Sharing 技术应运而生。在 Kubernetes 中,咱们会将一些 AI 负载共享同一张 GPU 卡,通过减少业务部署密度,晋升 GPU 利用率,从而节省成本。以 TKE qGPU 为例,在 GPU Sharing 形式下,扩大资源从 GPU 卡数量变为百分比的 qGPU Core 与 MB 的 qGPU Memory。也就是说,用户可通过 qGPU 容器虚拟化技术,申请小于一张卡的 qGPU 虚构设施。这些设施是在单张物理卡上虚构进去的,资源之间也是强隔离的。除了 qGPU,vCUDA、gpu share 等技术都反对多个 Pod / 容器 共享同一张 GPU 卡。基于现有 Kubernetes 架构,是无奈晓得 GPU 卡所蕴含切片资源(我将之定义为 GPU Core 与 Memory 的组合)的散布状况的。集群资源散布对管理员与用户都是黑盒。管理员无奈晓得整个集群 GPU 切片资源的分配情况,用户也不晓得新部署业务有无资源可用。
问题二:无奈反对多 GPU 后端
除调配挂载整卡的形式外,TKE qGPU、vCUDA、gpu share、GPU 池化 等 GPU 共享技术越来越被用户采纳。每种计划都有本人独立的一套 Kubernetes 集成实现形式。比方在 TKE qGPU 中,咱们自研了 tke-qgpu-scheduler 用于 GPU 细粒度算力与显存调配调度,配套的 tke-qgpu-manager,用于节点初始化、注册上报 qGPU 资源及 qGPU 容器虚拟化。vCUDA、gpu share 也是相似架构,同样是由调度器 + device plugin 组成。这些计划互相独立,没有统一标准,无奈共通。这导致用户在单个集群中很难同时应用多种 GPU 后端技术。比方用户集群有些业务是在线推理,吃不满整卡,想申请 TKE qGPU 切片资源。另一部分业务是训练,须要调配单卡。有些仿真和模型调试业务,为了老本和弹性,想要动静从远端 GPU 池申请资源。现有计划很难同时满足以上诉求,这为基于 Kubernetes 构建对立 AI 基础设施平台减少了很多难度。
以上问题均是 TKE 在基于 Kubernetes 帮忙客户构建 AI 计算平台时遇到的实在困扰。随着 AI 业务的一直精进,客户已不再仅满足于“能应用 Kubernetes GPU 资源”。对 GPU 老本的关注,对 GPU 资源的整体把控,对 GPU 不同后端的精准应用,都成为了客户能用好 GPU 算力的前提条件。既然现有体系无奈满足,那咱们就须要另辟蹊径,从新思考 GPU 在 Kubernetes 中的地位。
一种全新的 Kubernetes GPU 计划
PV / PVC 带来的启发
在 Kubernetes 中,资源个别是围绕 Pod 设计和定义。从重要水平上讲,集群可用资源蕴含两种类型:外围资源和内部资源。外围资源指维持 Pod 失常运行的必不可少的资源,包含 CPU、内存、长期存储、网卡 等。这些会通过 kubelet 扫描节点并上报到集群中。另一部分是内部资源,多指外挂存储和其余设施等,比方数据盘、GPU、FPGA 等。这些设施可能是本地设施挂载、也可能是远端设施挂载。这类资源的存在能够使得 Pod 更好的运行。比方数据盘减少了 Pod 的存储容量、GPU / FPGA 减速了 Pod 的计算能力。从这个角度看,存储与 GPU 有相似之处。
Kubernetes 在存储上形象出了一组资源,如 PV / PVC / StorageClass,并为之提供了一组 API 和交互方式,将存储的供应治理和应用标准化和拆散了进去。
- PV:PV 是集群中的一块理论存储资源,能够由管理员手动创立,或者通过 StorageClass 形式动态创建。PV 相似节点上的 CPU、内存、网卡 等资源。PV 能够有多种后端供应,如前文形容的私有云存储服务、自建共享存储或本地存储。
- PVC:PVC 是用户对 PV 存储资源的申领。它相似于集群中的 Pod。Pod 申请节点上的 CPU、内存、网络 等资源,PVC 申请存储资源,也就是 PV。
- StorageClass:StorageClass 为管理员提供了形容存储“类”的办法。比方 PV 后端创立的办法、挂载的办法 等。
用户通过 PV 在指定后端创立理论存储,用户通过 PVC 申请已创立的 PV 存储资源,或者指定 StorageClass 动静从后端创立 PV。
参照 Kubernetes 存储的设计形式,咱们认为 GPU 也可定义和实现相似形象。
Elastic GPU CRD
咱们定义了三种全新的 Kubernetes CRD,用于代表 GPU 资源的不同形象:
- ElasticGPU:ElasticGPU 是集群中一个理论可应用的 GPU 资源,能够是一块本地 GPU 物理卡、一个 GPU 切片资源(GPU 算力 / 显存 的组合)、一个远端 GPU 设施。
- ElasticGPUClaim:ElasticGPUClaim 是用户对 ElasticGPU 资源的申领,能够申请整卡数量,申请 GPU 核数 / 显存,或者申请 TFLOPS 算力。
- EGPUClass:EGPUClass 提供了生产和挂载 ElasticGPU 的形式,能够应用 qGPU 虚拟化、vCUDA、或是 GPU 远端池化的技术。
type ElasticGPU struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Spec ElasticGPUSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
Status ElasticGPUStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
type ElasticGPUSpec struct {
Capacity v1.ResourceList `json:"capacity,omitempty" protobuf:"bytes,1,rep,name=capacity,casttype=ResourceList,castkey=ResourceName"`
ElasticGPUSource `json:",inline" protobuf:"bytes,2,opt,name=elasticGPUSource"`
ClaimRef v1.ObjectReference `json:"claimRef,omitempty" protobuf:"bytes,3,opt,name=claimRef"`
NodeAffinity GPUNodeAffinity `json:"nodeAffinity,omitempty" protobuf:"bytes,4,opt,name=nodeAffinity"`
NodeName string `json:"nodeName,omitempty" protobuf:"bytes,5,opt,name=nodeName"`
}
type ElasticGPUSource struct {
QGPU *QGPUElasticGPUSource `json:"qGPU,omitempty" protobuf:"bytes,1,opt,name=qGPU"`
PhysicalGPU *PhysicalGPUElasticGPUSource `json:"physicalGPU,omitempty" protobuf:"bytes,2,opt,name=physicalGPU"`
GPUShare *GPUShareElasticGPUSource `json:"gpuShare,omitempty" protobuf:"bytes,3,opt,name=gpuShare"`
}
type ElasticGPUClaim struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Spec ElasticGPUClaimSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
Status ElasticGPUClaimStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
type ElasticGPUClass struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Provisioner string `json:"provisioner" protobuf:"bytes,2,opt,name=provisioner"`
Parameters map[string]string `json:"parameters,omitempty" protobuf:"bytes,3,rep,name=parameters"`
}
上面以 TKE qGPU 为例,形容联合 Elastic GPU 计划的整个资源调度调配流程。
qGPU 资源申请
用户在集群中创立 ElasticGPUClass,指定 qGPU 作为 GPU 后端。
apiVersion: elasticgpu.io/v1alpha
kind: ElasticGPUClass
metadata:
name: qgpu-class
provisioner: elasticgpu.io/qgpu
reclaimPolicy: Retain
eGPUBindingMode: Immediate
创立 ElasticGPUClaim 形容对 qGPU 资源的申领,tke.cloud.tencent.com/qgpu-core
代表申请 10% 的 GPU 算力,tke.cloud.tencent.com/qgpu-memory
代表申请 4GB 显存。
apiVersion: elasticgpu.io/v1alpha
kind: ElasticGPUClaim
metadata:
name: qgpu-egpuc
spec:
storageClassName: qgpu-class
resources:
requests:
tke.cloud.tencent.com/qgpu-core: 10
tke.cloud.tencent.com/qgpu-memory: 4GB
用户在创立 Pod 时指定 ElasticGPUClaim 实现 qGPU 资源申领。
apiVersion: v1
kind: Pod
metadata:
name: qgpu-pod
annotations:
elasticgpu.io/egpuc-<container-name>: qgpu-egpuc
spec:
containers:
- name: test
qGPU 资源调度
思考到 out-tree 的设计,qGPU 资源发现、上报和调度,还是依赖原有 device plugin 与 extended resource 机制。
咱们通过 elastic-gpu-admission-hook 在 Pod 创立时辨认 annotations elasticgpu.io/egpuc-<container-name>
,将申请资源正确设置到 containers 中。
apiVersion: v1
kind: Pod
metadata:
name: qgpu-pod
annotations:
elasticgpu.io/egpuc-test: qgpu-egpuc
spec:
containers:
- name: test
resources:
requests:
tke.cloud.tencent.com/qgpu-core: 10
tke.cloud.tencent.com/qgpu-memory: 4GB
limits:
tke.cloud.tencent.com/qgpu-core: 10
tke.cloud.tencent.com/qgpu-memory: 4GB
qgpu-scheduler 扩大调度器用于 qGPU 资源调度,返回符合要求的节点。当 Pod 绑定到节点上后,qgpu-provisioner 会更新ElasticGPU
CRD 中节点、GPU 卡索引 等信息,实现 qGPU 设施的绑定。
qGPU 资源创立
qgpu-manager 会 watch ElastciGPU
CRD 变动,在绑定节点胜利后,会执行创立 qGPU 设施的操作。qgpu-manager 会依据 CRD 中蕴含的申请算力与显存信息以及调度到的 GPU 卡索引,在底层创立 qGPU 设施。
qGPU 设施挂载
qgpu-manager 是一个 device plugin 插件,kubelet 会在调配 device 时通过标准接口调用插件。在接口 Allocate
和 PreStartContainer
中,咱们会挂载必要的 qGPU、nvidia 设施以及设置环境变量。最初,咱们依赖 qgpu-container-runtime 进行 qGPU 设施与容器的绑定工作。
下一步倒退
随着 AI 业务的大规模落地,越来越多的用户在 Kubernetes 中应用 GPU 进行 AI 计算。现有的 extended resource 与 device plugin 机制很难满足客户对 GPU 资源的精密管制和调配,新的技术框架势在必行。Elastic GPU 在 Kubernetes 集群中形象了一种 native GPU 资源,围绕三种自定义 CRD,在标准化定义了与其余 GPU 技术交互的前提下,同时提供了集群层面全局 GPU 资源视角,让用户能够更好的察看和治理 GPU 资源。
Elastic GPU 第一步会聚焦在 CRD 定义以及交互流程标准化,并首先适配 TKE qGPU。在这个阶段,咱们心愿参照 PV / PVC / CSI 的设计理念,以 Kubernetes native 的形式提供对 GPU 资源的形象,标准化资源分配、调度、挂载等流程,并提供灵便的接口,供其余 GPU 技术集成。通过首先在生产环境反对 TKE qGPU,咱们会继续打磨框架,公布第一个 alpha 版本。接下来,咱们会推动社区实现对支流 GPU 技术的集成反对,包含 nvidia docker、gpu share 以及 vCUDA,横向扩大框架的实用场景。通过规范框架,对立接口和流程,升高客户治理老本。通过 GPU Sharing、Remote GPU 等技术晋升灵活性、减少利用率,升高客户用卡老本。咱们心愿依赖 Elastic GPU 框架,最终能够为客户提供 Kubernetes 开箱即用应用 GPU 资源的能力。
TKE qGPU:https://cloud.tencent.com/doc…
【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!