创建 AI 应用
给 Pod 模板加一个标签和几个注解,让 AI 应用跑在 TensorFusion vGPU 上
让工作负载用上 TensorFusion vGPU,只需在 Pod 模板上加标签 tensor-fusion.ai/enabled: "true" 和几个资源注解。TensorFusion webhook 会注入 Pod 需要的组件,TensorFusion 调度器负责把它放到合适的 GPU 上。镜像和业务代码都不用改。
本文用一个 Deployment 走完四步:估算资源、选 QoS、加注解、验证。
前置条件
- 已安装 TensorFusion,且至少有一个
GPUPool处于运行状态。参考在 Kubernetes 安装。 - 能用
kubectl访问工作负载所在的 namespace。 - GPU 池里已经发现了 GPU。用下面的命令确认:
kubectl get gpupool
kubectl get gpu -o custom-columns='NAME:.metadata.name,MODEL:.status.gpuModel,CAPACITY:.status.capacity,AVAILABLE:.status.available'CAPACITY 一列是每张卡的 TFLOPS 和显存,第 1 步要用到。
第 1 步:估算资源
一个 vGPU 由两种资源描述。每种资源都有 request(调度器为它预留的量)和 limit(工作负载不能超过的量)。
| 资源 | 注解 | 怎么估 |
|---|---|---|
| 显存(VRAM) | vram-request、vram-limit | 模型权重加运行时开销。权重在 8 位精度下约为每 10 亿参数 1 GiB,FP16 下约 2 GiB。上下文长度、batch 大小和 KV cache 还要另算,定值之前先实际跑一次量一下。 |
| 算力 | tflops-request、tflops-limit | 让工作负载独占一张卡跑一遍,记下平均利用率和峰值利用率,分别乘以 CAPACITY 里这张卡的 TFLOPS:平均值作 request,峰值作 limit。 |
如果池里只有一种 GPU 型号,也可以用 compute-percent-request 和 compute-percent-limit 按单卡百分比写算力。百分比不计入 namespace 的 GPU 配额,也不能和 tflops-* 写在同一个 Pod 上。
没法提前测量时,先给一个偏大的 request,再打开自动扩缩容,让 TensorFusion 按实际用量修正。
第 2 步:选择 QoS 等级
| QoS | 适用场景 |
|---|---|
low | 实验、可以等待或被打断的批处理任务 |
medium | 离线任务,例如 embedding、批量推理 |
high | 在线推理 |
critical | 对延迟敏感、不能被饿死的服务 |
QoS 等级影响三件事:
- 调度优先级。
high和critical的 Pod 如果没有自己的priorityClassName,会被设为tensor-fusion-high或tensor-fusion-critical,GPU 不够时可以抢占低优先级的 Pod。 - 自动扩缩容。 打开自动扩缩容后,
low和medium的 request 取用量的下界,high取目标值,critical取上界。 - 计费。 池管理员可以给每个 QoS 等级定价,见QoS 级别与计价。
不写 tensor-fusion.ai/qos 时,webhook 按下面的顺序取值:两种资源的 request 都等于 limit 时为 high;否则取池的 qosConfig.defaultQoS;池也没配时为 medium。
第 3 步:添加标签和注解
标签和注解要写在 Pod 模板上,不是 Deployment 自身的 metadata 上。
# pytorch-vgpu.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pytorch-vgpu
spec:
replicas: 1
selector:
matchLabels:
app: pytorch-vgpu
template:
metadata:
labels:
app: pytorch-vgpu
tensor-fusion.ai/enabled: "true"
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"
tensor-fusion.ai/qos: "medium"
spec:
containers:
- name: pytorch
image: pytorch/pytorch:2.4.1-cuda12.1-cudnn9-runtime
command: ["sh", "-c", "sleep infinity"]kubectl apply -f pytorch-vgpu.yaml没写的注解按下表取默认值:
| 配置项 | 默认值 |
|---|---|
| GPU 池 | 集群的默认池。用 tensor-fusion.ai/gpupool 指定其他池。 |
| GPU 数量 | 1。用 tensor-fusion.ai/gpu-count 申请多张,此时 request 和 limit 对每张卡分别生效。 |
| 本地还是远程 | 池的 defaultUsingLocalGPU。管理员没改过的话是本地模式,Pod 运行在 GPU 节点上。 |
| 隔离模式 | soft |
| 注入的容器 | Pod 里唯一的容器。多容器 Pod 必须用 tensor-fusion.ai/inject-container 写明哪些容器使用 GPU。 |
全部注解见注解参考。远程 vGPU、指定 GPU 型号、多卡等其他情况的清单见注解使用场景。
可选:用 WorkloadProfile 复用配置
多个工作负载配置相同时,把配置写进工作负载所在 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
gpuCount: 1 template:
metadata:
labels:
tensor-fusion.ai/enabled: "true"
annotations:
tensor-fusion.ai/workload-profile: small-inferenceGPU 池、本地或远程模式、隔离模式只从注解或池的默认值读取,不从 profile 读取。
第 4 步:验证
-
确认 Pod 在运行,并且已被 TensorFusion 接管:
kubectl get pod -l app=pytorch-vgpu -o wide kubectl get tensorfusionworkload pytorch-vgpuPod 状态为
Running,并且存在一个与 Deployment 同名的TensorFusionWorkload。 -
查看分到了哪张 GPU。本地模式下,调度器会把结果写在 Pod 上:
POD=$(kubectl get pod -l app=pytorch-vgpu -o jsonpath='{.items[0].metadata.name}') kubectl get pod "$POD" -o jsonpath='{.metadata.annotations.tensor-fusion\.ai/gpu-ids}{"\n"}' -
进容器检查 GPU:
kubectl exec "$POD" -c pytorch -- nvidia-smi kubectl exec "$POD" -c pytorch -- python3 -c 'import torch; print(torch.cuda.device_count()); print(torch.ones(1024, device="cuda").sum().item())'nvidia-smi能正常执行,显示的总显存接近vram-limit,而不是整卡显存。PyTorch 能看到 1 个设备并完成计算。Pod 处于Running不代表 GPU 链路是通的,一定要实际调用一次 CUDA。 -
确认池里已经扣减了这份资源:
kubectl get gpu -o custom-columns='NAME:.metadata.name,CAPACITY:.status.capacity,AVAILABLE:.status.available'被分配的那张 GPU,
AVAILABLE减少了 request 的量。
出错时怎么办
不合法的 Pod 会在创建时被 webhook 拒绝。对 Deployment 来说,报错出现在 ReplicaSet 的事件里:kubectl describe rs -l app=pytorch-vgpu。
| 现象 | 原因和处理 |
|---|---|
gpu pool not found | 集群没有默认池,或 tensor-fusion.ai/gpupool 写了不存在的池。把注解改成 kubectl get gpupool 里列出的池。 |
inject container has to be specified when Pod containers > 1 | 加上 tensor-fusion.ai/inject-container,写明使用 GPU 的容器名。 |
tflops request is not set ... | 没找到任何资源注解。至少设置 tflops-request、compute-percent-request、vram-request 中的一个。 |
get workload profile(...) | 引用的 WorkloadProfile 不在 Pod 所在的 namespace。 |
Pod 一直 Pending | 没有 GPU 放得下这份请求。对比 request 和上面的 AVAILABLE,再看 kubectl describe pod 里的事件。 |
| Pod 里没有 GPU,也没有被注入容器 | Pod 模板上缺少标签 tensor-fusion.ai/enabled: "true",或者把它写成了注解。 |
更多情况见问题处理手册。
TensorFusion 文档