注解使用场景
按需求找到对应的注解写法,每个常见 vGPU 场景给出一份最小的 Pod 模板
下面每一节对应一个需求,给出满足它所需的最少注解。找到你的场景,把片段复制到工作负载的 Pod 模板里即可。
开始之前
- 已安装 TensorFusion 并有一个运行中的
GPUPool,并且已经在上面部署过一个工作负载。还没有的话,先看创建 AI 应用。 - 每个片段替换的都是下面这个 Deployment 的
template.metadata部分。标签和注解写在 Pod 模板上,不是 Deployment 自身的 metadata 上。
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
spec:
replicas: 1
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
tensor-fusion.ai/enabled: "true"
annotations: {} # 下面的片段写在这里
spec:
containers:
- name: app
image: pytorch/pytorch:2.4.1-cuda12.1-cudnn9-runtime
command: ["sh", "-c", "sleep infinity"]- 有些片段要用到准确的 GPU 型号或池名,用下面的命令查:
kubectl get gpupool
kubectl get gpu -o custom-columns='NAME:.metadata.name,VENDOR:.status.vendor,MODEL:.status.gpuModel,CAPACITY:.status.capacity,AVAILABLE:.status.available'| 我想…… | 看这一节 |
|---|---|
| 给 Pod 分一部分 GPU | 多个 Pod 共用一张 GPU |
| 不想换算 TFLOPS | 用百分比表示算力 |
| 给 Pod 一整张 GPU | 独占整卡 |
| 给 Pod 多张 GPU | 使用多张 GPU |
| 控制 Pod 落在哪里 | 指定池、型号、厂商或卡号 |
| 让 Pod 跑在没有 GPU 的节点上 | 使用其他节点上的 GPU |
| 加强租户之间的隔离 | 选择隔离模式 |
| 保护重要的工作负载 | 设置优先级 |
| Pod 里有 sidecar | 指定哪些容器使用 GPU |
| 不想再猜资源大小 | 让 TensorFusion 自动调整大小 |
| 分布式训练要么全起要么不起 | 让一组 Pod 一起启动 |
| 复用同一份配置 | 多个工作负载共用配置 |
| 逐步接入 TensorFusion | 只启用部分副本 |
| 排除某个 Pod | 让 Pod 不使用 TensorFusion |
多个 Pod 共用一张 GPU
适合每个实例只需要一部分显卡的推理服务。给每个 Pod 写上 TFLOPS 和显存的 request(调度器预留的量)和 limit(Pod 不能超过的量)。
annotations:
tensor-fusion.ai/tflops-request: "10"
tensor-fusion.ai/tflops-limit: "20"
tensor-fusion.ai/vram-request: "4Gi"
tensor-fusion.ai/vram-limit: "4Gi"只要 request 之和放得下,多个 Pod 就可以放在同一张 GPU 上;具体选哪张卡取决于池的调度策略。在容器里,nvidia-smi 显示的总显存约为 4 GiB。
用百分比表示算力
池里只有一种 GPU 型号时,按单卡百分比写算力比 TFLOPS 更直观。
annotations:
tensor-fusion.ai/compute-percent-request: "20"
tensor-fusion.ai/compute-percent-limit: "50"
tensor-fusion.ai/vram-request: "4Gi"
tensor-fusion.ai/vram-limit: "4Gi"compute-percent-* 不能和 tflops-* 混用。百分比不计入 namespace 的 GPU 配额,多租户集群请用 TFLOPS。
独占整卡
适合训练任务,或任何不应该与别人共用显卡的工作负载。isolation: shared 表示每张 GPU 整卡分配、不注入限流组件;dedicated-gpu 会按型号自动补全整卡容量。
annotations:
tensor-fusion.ai/isolation: "shared"
tensor-fusion.ai/dedicated-gpu: "true"
tensor-fusion.ai/gpu-model: "<gpu-model>" # 与 status.gpuModel 完全一致
tensor-fusion.ai/gpu-count: "1"调度完成后,被分配的 GPU 可用 TFLOPS 和显存都为 0,不会再有其他 Pod 落到这张卡上。
使用多张 GPU
gpu-count 是每个 Pod 使用的 GPU 数量,这些 GPU 都来自同一个节点。request 和 limit 对每张 GPU 分别生效,所以下面这个 Pod 预留的显存是 2 × 8Gi。
annotations:
tensor-fusion.ai/gpu-count: "2"
tensor-fusion.ai/tflops-request: "30"
tensor-fusion.ai/tflops-limit: "60"
tensor-fusion.ai/vram-request: "8Gi"
tensor-fusion.ai/vram-limit: "8Gi"在容器里,torch.cuda.device_count() 返回 2。取值范围是 1 到 128。
指定池、型号、厂商或卡号
下面每个注解都会缩小调度器可选的 GPU 范围,可以按需组合。没有 GPU 满足条件时,Pod 保持 Pending。
annotations:
tensor-fusion.ai/gpupool: "<gpupool-name>" # 默认:集群的默认池
tensor-fusion.ai/gpu-model: "<gpu-model>" # 与 status.gpuModel 完全一致
tensor-fusion.ai/vendor: "NVIDIA" # 与 status.vendor 完全一致
tensor-fusion.ai/tflops-request: "10"
tensor-fusion.ai/tflops-limit: "20"
tensor-fusion.ai/vram-request: "4Gi"
tensor-fusion.ai/vram-limit: "4Gi"想把 Pod 固定到节点上的某几张卡,就列出它们的设备序号。此时 GPU 数量等于序号的个数。
annotations:
tensor-fusion.ai/gpu-indices: "0,1"
tensor-fusion.ai/tflops-request: "10"
tensor-fusion.ai/tflops-limit: "20"
tensor-fusion.ai/vram-request: "4Gi"
tensor-fusion.ai/vram-limit: "4Gi"节点层面的约束照常生效:TensorFusion 调度器会遵守 Pod spec 里的 nodeSelector、节点亲和性、污点和容忍。
使用其他节点上的 GPU
Pod 默认运行在本地 GPU 模式:它被调度到 GPU 节点上,直接使用显卡。在远程 vGPU 模式下,Pod 可以运行在任意节点(包括没有 GPU 的节点),GPU 调用通过网络转发到 GPU 节点上的 worker Pod。
annotations:
tensor-fusion.ai/is-local-gpu: "false"
tensor-fusion.ai/tflops-request: "10"
tensor-fusion.ai/tflops-limit: "20"
tensor-fusion.ai/vram-request: "4Gi"
tensor-fusion.ai/vram-limit: "4Gi"检查结果:
kubectl get tensorfusionconnection
kubectl get pods -A -l tensor-fusion.ai/component=worker,tensor-fusion.ai/workload=demo -o wide可以看到这个 Pod 对应的 TensorFusionConnection,以及运行在 GPU 节点上的 worker Pod。tensor-fusion.ai/gpu-ids 注解写在 worker Pod 上,不在你的 Pod 上。
对延迟敏感时选本地模式;业务必须留在 CPU 节点上,或者 GPU 节点紧张时选远程模式。池的默认模式由它的 defaultUsingLocalGPU 决定。
选择隔离模式
tensor-fusion.ai/isolation 决定 Pod 与同一张 GPU 上其他 Pod 的隔离方式,默认是 soft。
| 模式 | 什么时候选 |
|---|---|
soft | 工作负载之间互相信任,希望共享方式最灵活。限额可以在 Pod 运行期间修改,所以能配合自动扩缩容。 |
hard | 需要租户之间有更严格的性能隔离。限额在 Pod 启动时确定。 |
shared | Pod 要独占整卡。见独占整卡。 |
partitioned | 需要 NVIDIA MIG 这类硬件级分区,并且管理员已经为此配置好集群。 |
hard 隔离:
annotations:
tensor-fusion.ai/isolation: "hard"
tensor-fusion.ai/tflops-request: "20"
tensor-fusion.ai/tflops-limit: "20"
tensor-fusion.ai/vram-request: "4Gi"
tensor-fusion.ai/vram-limit: "4Gi"本地模式下,hard 隔离的 Pod 会多出一个 tensorfusion-worker 容器。默认安装下,一张 GPU 同一时间只服务一种隔离模式,所以 soft 和 hard 的 Pod 会落在不同的卡上。
使用指定分区模板的 partitioned 隔离:
annotations:
tensor-fusion.ai/isolation: "partitioned"
tensor-fusion.ai/partition-id: "<partition-template-id>"
tensor-fusion.ai/gpu-model: "<gpu-model>"
tensor-fusion.ai/vendor: "<vendor>"partitioned 模式在默认的 isolationModePolicy: dynamic 下不可用。集群是否支持、有哪些模板 ID,请咨询管理员。
设置优先级
annotations:
tensor-fusion.ai/qos: "critical" # low | medium | high | critical
tensor-fusion.ai/tflops-request: "20"
tensor-fusion.ai/tflops-limit: "20"
tensor-fusion.ai/vram-request: "8Gi"
tensor-fusion.ai/vram-limit: "8Gi"high 和 critical 的 Pod 如果没有自己的 priorityClassName,会被设为 tensor-fusion-high 或 tensor-fusion-critical,GPU 不够时可以抢占低优先级的 Pod。怎么选等级、不写时取什么值,见创建 AI 应用。
指定哪些容器使用 GPU
多容器 Pod 必须写明哪些容器使用 GPU。其他容器保持原样,看不到 GPU。
annotations:
tensor-fusion.ai/inject-container: "app" # 多个容器用逗号分隔
tensor-fusion.ai/tflops-request: "10"
tensor-fusion.ai/tflops-limit: "20"
tensor-fusion.ai/vram-request: "4Gi"
tensor-fusion.ai/vram-limit: "4Gi"多个容器都用 GPU、并且要各用各的卡时,再写上每个容器的数量。数量之和不能超过 gpu-count。
annotations:
tensor-fusion.ai/inject-container: "trainer,eval"
tensor-fusion.ai/gpu-count: "3"
tensor-fusion.ai/container-gpu-count: '{"trainer":2,"eval":1}'
tensor-fusion.ai/tflops-request: "30"
tensor-fusion.ai/tflops-limit: "60"
tensor-fusion.ai/vram-request: "8Gi"
tensor-fusion.ai/vram-limit: "8Gi"不写 container-gpu-count 时,列出的每个容器都能看到 Pod 的全部 GPU。
让 TensorFusion 自动调整大小
先给一个估计值,再让自动扩缩容按实际用量修正 request 和 limit。
annotations:
tensor-fusion.ai/autoscale: "true"
tensor-fusion.ai/autoscale-target: "all" # compute | vram | all
tensor-fusion.ai/tflops-request: "10"
tensor-fusion.ai/tflops-limit: "20"
tensor-fusion.ai/vram-request: "4Gi"
tensor-fusion.ai/vram-limit: "4Gi"工作负载创建后的前 30 分钟不会做任何调整。定时规则、分位数配置以及要观察的 status 字段,见配置自动扩缩容。
让一组 Pod 一起启动
分布式训练里,4 个 worker 只起来 3 个是在浪费 GPU。开启 Gang 调度后,只有足够多的成员都能放下时,这组 Pod 才会被绑定到节点。
spec:
replicas: 4
template:
metadata:
labels:
app: demo
tensor-fusion.ai/enabled: "true"
annotations:
tensor-fusion.ai/gang-enabled: "true"
tensor-fusion.ai/gang-min-members: "4" # 可选,默认为全部副本
tensor-fusion.ai/gang-timeout: "5m" # 可选,默认一直等待
tensor-fusion.ai/tflops-request: "100"
tensor-fusion.ai/tflops-limit: "100"
tensor-fusion.ai/vram-request: "10Gi"
tensor-fusion.ai/vram-limit: "10Gi"工作负载至少要有 2 个副本,gang-min-members 必须在 2 和副本数之间。进度写在 TensorFusionWorkload 的 status.gang 里。
多个工作负载共用配置
把公共配置写进同一个 namespace 的 WorkloadProfile,再引用它。Pod 上的注解会覆盖 profile 里的值。
apiVersion: tensor-fusion.ai/v1
kind: WorkloadProfile
metadata:
name: small-inference
spec:
resources:
requests:
tflops: "10"
vram: 4Gi
limits:
tflops: "20"
vram: 4Gi
qos: medium annotations:
tensor-fusion.ai/workload-profile: "small-inference"
tensor-fusion.ai/vram-limit: "6Gi" # 覆盖 profile 里的值只启用部分副本
想先在 Deployment 的一部分副本上试用 TensorFusion,可以限制它接管的 Pod 数量。其余 Pod 原样创建。
annotations:
tensor-fusion.ai/enabled-replicas: "1"
tensor-fusion.ai/tflops-request: "10"
tensor-fusion.ai/tflops-limit: "20"
tensor-fusion.ai/vram-request: "4Gi"
tensor-fusion.ai/vram-limit: "4Gi"完整流程见迁移现有应用。
让 Pod 不使用 TensorFusion
没有标签 tensor-fusion.ai/enabled: "true" 的 Pod 不会被处理。如果管理员开启了自动迁移,申请 nvidia.com/gpu 的 Pod 即使没有这个标签也会被接管;把标签设为 "false" 可以排除某个 Pod。
labels:
app: demo
tensor-fusion.ai/enabled: "false"
TensorFusion 文档