同一个 Agent 集群可以按节点池划分运行方式:需要 CUBE 隔离的任务进入 CPU Agent 节点池,GPU 计算任务进入使用标准容器运行时的 GPU 原生节点池。两类任务共享 Kubernetes 集群,通过各自 Pod 的运行时、节点选择和资源申请区分。
GPU/qGPU 在本文中运行于标准容器环境,不运行在 CUBE Guest 内。不要给 GPU Pod 声明
runtimeClassName: cube。这里的“同集群使用”是指两类工作负载分别运行在不同节点池:CUBE 工作负载运行在 CUBE 就绪的 CPU Agent 节点池中;GPU/qGPU 工作负载运行在另建的标准 GPU 原生节点池中,使用标准容器运行时。两者共享集群,但不共享 CUBE 运行环境;GPU/qGPU 计算发生在 GPU 节点的标准容器内,不在 CUBE Guest 内。
节点池如何划分
节点池 | 节点准备 | 工作负载声明 |
CPU Agent 节点池 | 使用符合 Agent 要求的镜像,CUBE 运行时就绪 | runtimeClassName: cube,选择对应节点池。 |
NVIDIA 整卡节点池(按需配置) | 标准 GPU 系统镜像、驱动及 NVIDIA 资源管理组件就绪 | 省略 runtimeClassName,申请 nvidia.com/gpu。 |
qGPU 原生节点池 | 标准 GPU 系统镜像、兼容驱动、qGPU 组件及共享能力就绪 | 省略 runtimeClassName,申请 tke.cloud.tencent.com/qgpu-core,共享时同时申请显存。 |
常用的两池方案是 CPU CUBE 节点池 + qGPU 节点池:qGPU 池既可承载共享任务,也可通过
qgpu-core: 100 分配一张整卡。如果业务还需保留 nvidia.com/gpu 这种分配方式,再使用独立的 NVIDIA 整卡节点池。同一张物理卡应使用一种资源分配方式。不要把同卡的
nvidia.com/gpu: 1 与 qgpu-core: 100 当成两份独立容量;这两种资源名本身不提供跨插件的互斥保障。本次测试先验证 NVIDIA 整卡,再切换为 qGPU,最终由 qGPU 统一分配共享和整卡任务。配置节点与组件
1. 在 Agent 集群控制台创建集群并添加符合要求的 CPU Agent 节点,确认 CUBE 组件和节点就绪。
2. 在该集群对应的 TKE 集群中添加 GPU 原生节点池。使用标准 GPU 系统镜像及兼容驱动,不沿用 CPU Agent 节点的专用镜像或 CUBE/EROX 安装标签。
3. 按分配方式安装 NVIDIA GPU 资源管理组件或 qGPU 隔离组件。使用 qGPU 时,在节点池配置中启用 qGPU 共享,核对现有节点是否也已生效;修改池模板不代表存量节点已更新。
4. 确认 GPU 节点 Ready、驱动可识别设备、设备插件可运行,且节点
allocatable 中出现对应资源。节点开机或节点池显示运行中,不能代替这些检查。以下命令供有相应权限的管理员检查目标集群:
kubectl get nodes -o widekubectl get runtimeclass cube -o yamlkubectl get pods -n kube-system -o widekubectl get node REPLACE_WITH_GPU_NODE_NAME -o jsonpath='{.metadata.labels}{"\\n"}{.status.allocatable}{"\\n"}'
本指南通过
node.tke.cloud.tencent.com/machineset 指定原生节点池。将下面所有 REPLACE_WITH_* 换成自己的节点池 ID 和镜像;镜像必须包含应用及所需 CUDA 用户态依赖、能从目标节点拉取,且与驱动兼容。镜像默认入口应执行计算任务,不能仅靠 nvidia-smi 成功认定计算通过。示例使用 default 命名空间,不依赖测试环境的私有资源。工作负载如何声明
CUBE 任务:显式选择运行时与 CPU Agent 节点池
apiVersion: v1kind: Podmetadata:name: cube-tasknamespace: defaultspec:runtimeClassName: cubenodeSelector:node.tke.cloud.tencent.com/machineset: REPLACE_WITH_CUBE_NODE_POOL_IDagc.cloud.tencent.com/cube-ready: "true"automountServiceAccountToken: falserestartPolicy: Nevercontainers:- name: taskimage: REPLACE_WITH_CPU_TASK_IMAGEresources:requests:cpu: 250mmemory: 256Milimits:cpu: "1"memory: 512Mi
cube 必须是目标环境存在且可用的 RuntimeClass 名称。CPU 和内存配额只是示例,需按业务与 RuntimeClass 开销调整。CUBE 工作负载不申请本文的 GPU 资源。NVIDIA 整卡任务:选择独立 GPU 池,申请一张卡
本示例仅用于采用 NVIDIA 分配方式的节点池;已经切换到 qGPU 的节点使用后面的 qGPU 整卡示例。
apiVersion: v1kind: Podmetadata:name: nvidia-gpu-tasknamespace: defaultspec:# 有意省略 runtimeClassName,使用 GPU 节点的标准默认运行时。nodeSelector:node.tke.cloud.tencent.com/machineset: REPLACE_WITH_NVIDIA_NODE_POOL_IDautomountServiceAccountToken: falserestartPolicy: Nevercontainers:- name: taskimage: REPLACE_WITH_CUDA_TASK_IMAGEresources:requests:cpu: 100mmemory: 128Milimits:memory: 512Minvidia.com/gpu: 1
qGPU 共享任务:同时声明算力和显存
apiVersion: v1kind: Podmetadata:name: qgpu-tasknamespace: defaultspec:# 有意省略 runtimeClassName,不在 CUBE Guest 内使用设备。nodeSelector:node.tke.cloud.tencent.com/machineset: REPLACE_WITH_QGPU_NODE_POOL_IDqgpu-device-enable: enableautomountServiceAccountToken: falserestartPolicy: Nevercontainers:- name: taskimage: REPLACE_WITH_CUDA_TASK_IMAGEresources:requests:cpu: 100mmemory: 128Milimits:memory: 512Mitke.cloud.tencent.com/qgpu-core: 50tke.cloud.tencent.com/qgpu-memory: 4
在显存单位为
1G 的节点上,此例申请半张卡的算力份额和 4GiB 显存。部署前检查节点的 tke.cloud.tencent.com/qgpu.memory-unit 标签,不能把 qgpu-memory: 4 当成跨配置固定的字节数;limits.memory 限制的是容器系统内存,不是显存。算力份额如何执行取决于 qGPU 调度策略。默认
best-effort 不等于每个 Pod 都有 50% 算力硬上限。需要两个任务共享时,将此声明保存为两个名称不同的 Pod,分别申请资源,并核对是否分配到预期的同一物理卡。
qGPU 整卡任务:申请 100 份算力,不填写显存
apiVersion: v1kind: Podmetadata:name: qgpu-fullcard-tasknamespace: defaultspec:# 与共享任务使用同一 qGPU 池,省略 runtimeClassName。nodeSelector:node.tke.cloud.tencent.com/machineset: REPLACE_WITH_QGPU_NODE_POOL_IDqgpu-device-enable: enableautomountServiceAccountToken: falserestartPolicy: Nevercontainers:- name: taskimage: REPLACE_WITH_CUDA_TASK_IMAGEresources:requests:cpu: 100mmemory: 128Milimits:memory: 512Mitke.cloud.tencent.com/qgpu-core: 100
此例通过 qGPU 分配一张整卡及其全部可用显存,需等待有足够空闲资源;不要同时申请
nvidia.com/gpu。使用 Deployment 或 Job 时,把
runtimeClassName、nodeSelector、containers 等 Pod 字段放在 spec.template.spec 下,不放在控制器的顶层 spec 下。如何确认运行结果
对实际创建的 Pod 检查运行时字段、节点、退出码和日志:
kubectl -n default get pod REPLACE_WITH_POD_NAME -o jsonpath='{.spec.runtimeClassName}{"\\n"}{.spec.nodeName}{"\\n"}{.status.containerStatuses[*].state.terminated.exitCode}{"\\n"}'kubectl -n default describe pod REPLACE_WITH_POD_NAMEkubectl -n default logs REPLACE_WITH_POD_NAME -c task
CUBE 任务应使用
cube 且落在 CUBE 就绪节点;GPU/qGPU 任务的 runtimeClassName 应为空,并落在指定的标准 GPU 节点上。若环境的准入策略自动注入 CUBE,应先由管理员配置适用的标准运行时策略,再部署 GPU 工作负载,不能直接照搬省略字段的写法。计算验证应执行真实 CUDA 运算并校验结果。共享验证还应记录并发时间、物理卡分配、每个容器可见显存和超额申请结果。不要把 Pod Running、设备可见、组件安装成功或单次短任务完成等同于完整隔离、性能或稳定性验收。
常见问题
现象 | 检查方法 |
GPU Pod Pending | 核对节点池选择、污点、对应资源的 allocatable 及已申请量;qGPU 整卡需有整卡空闲资源。 |
RuntimeClass 不存在或 GPU Pod 被注入 CUBE | 检查实际 Pod 和准入策略,区分集群默认枚举与 Pod 运行时字段。 |
qGPU 共享开启后无资源 | 核对驱动/内核组合、qgpu-manager 和调度器状态,以及存量节点是否已启用共享。 |
节点池已改驱动,节点仍用旧版本 | 池模板变更可能仅影响新增节点;按 TKE 受支持流程更新,核对节点实际驱动。 |
ImagePullBackOff | 查看仓库连接、凭据和网络;拉取失败不是 CUDA 计算失败,必要时使用可访问仓库中的同内容镜像。 |
CUBE 与 GPU/qGPU 的节点池和运行环境边界
这里的“同集群使用”是指两类工作负载分别运行在不同节点池:CUBE 工作负载运行在 CUBE 就绪的 CPU Agent 节点池中;GPU/qGPU 工作负载运行在另建的标准 GPU 原生节点池中,使用标准容器运行时。两者共享集群,但不共享 CUBE 运行环境;GPU/qGPU 计算发生在 GPU 节点的标准容器内,不在 CUBE Guest 内。
声明工作负载时,CUBE Pod 同时指定
runtimeClassName: cube 和 CPU Agent 节点池;GPU/qGPU Pod 省略 runtimeClassName,并通过 nodeSelector 指定另一个 GPU/qGPU 节点池,再申请相应 GPU 资源。