【Kubernetes从入门到精通】第89篇:K8s + AI/ML——在K8s上运行机器学习工作负载
上一篇【第88篇】多集群管理实战——从单集群到联邦集群的进化之路下一篇【第90篇】K8s的未来——Serverless、WASM、eBPF和AI原生的新篇章摘要大模型火了之后一个反直觉的事实是搞AI的同学最后都成了K8s运维。训练要几十张GPU、推理要弹性扩缩、实验要可复现——这些恰恰是K8s的强项。这篇从GPU怎么插进K8s讲起Device Plugin把显卡暴露成可调度资源MIG把一张卡切成几张小的。然后上Kubeflow看它怎么用Notebook/Pipeline/Katib/Training Operator把ML全生命周期搬上K8s。最后给一份分布式训练Job和推理服务的实战YAML。AI时代K8s就是那个底座。一、GPU怎么进K8sDevice Plugin普通节点只有CPU和内存K8s原生不认识GPU。要让调度器知道这台机器有显卡靠的是Device Plugin机制本质是K8s的device-plugin扩展点。NVIDIA官方提供nvidia-device-plugin【GPU 接入流程】 GPU 物理卡 │ (节点上) ▼ nvidia-device-plugin (DaemonSet, 每节点一个) │ 向 kubelet 上报: 我有 nvidia.com/gpu 8 ▼ kubelet → 写入 Node 状态 (Extended Resource) │ ▼ Scheduler 就能按 nvidia.com/gpu 调度 Pod安装后节点会多出一个扩展资源kubectl describenodegpu-node-01|grep-A2Allocatable# nvidia.com/gpu: 8Pod申请GPU就这么写apiVersion:v1kind:Podmetadata:name:train-gpuspec:containers:-name:trainerimage:pytorch/pytorch:2.1.0-cuda12.1resources:limits:nvidia.com/gpu:1# 要1张卡# 注意: GPU 目前只能放 limits, 不能只放 requests# 且申请 N 张就是 N 张整卡(除非用MIG, 见下)要点GPU是不可压缩、不可分割的扩展资源目前只能写在limits里且默认整卡分配。想一张卡分给多个任务得上MIG或time-slicing下面讲。二、一张卡分给多人MIG 与 Time-SlicingA100/H100支持MIGMulti-Instance GPU把一张物理卡切成多个独立小卡彼此隔离、各有显存【MIG 切分 A100】 1张 A100 (40GB) ├── MIG 实例1: 1g.10gb (1/7算力, 10GB显存) ├── MIG 实例2: 1g.10gb ├── MIG 实例3: 2g.20gb └── ... 最多7个 每个MIG实例在K8s里是独立的 nvidia.com/gpu → 小模型/推理用 1g.10gb 刚好, 不浪费整卡配置MIG模式后Pod可以只申请一小块resources:limits:nvidia.com/gpu:1# 实际是1个MIG实例(如1g.10gb)如果不支持MIG老卡可以用Time-Slicing时间片复用让多Pod共享一张卡但显存不隔离适合开发调试# 通过 ConfigMap 配置 device-plugin 的 sharing 策略# 适合多人共用一张卡做实验, 不适合生产推理方式隔离性适合整卡完全大模型训练MIG显存算力硬件隔离推理、小训练Time-Slicing仅时间复用显存共享开发调试三、KubeflowML全生命周期平台单个GPU Pod能跑训练但真实ML工作是一整套流水线写代码→调参数→分布式训练→部署推理。Kubeflow就是架在K8s上的ML平台把这些都变成K8s原生资源。【Kubeflow 组件全景】 ┌─────────────────────────────────────────┐ │ Kubeflow on K8s │ │ │ │ Notebook → 交互式开发(Jupyter) │ │ Pipeline → 工作流编排(Argo底层) │ │ Katib → 自动调参(HPO) │ │ Training Op → TFJob/PyTorchJob/MPIJob │ │ KServe → 模型推理服务化 │ │ Model Registry→ 模型版本管理 │ └─────────────────────────────────────────┘ 全都是 K8s CRD Operator核心几个Notebook基于CRD起一个带GPU的Jupyter开发直接在集群里跑数据不用下载到本地。Training Operator把分布式训练封装成PyTorchJob/TFJob你只声明几机几卡它帮你起Worker/PS/Master并组网。Pipeline用Python SDK定义DAG流水线数据预处理→训练→评估→部署底层跑Argo Workflows。Katib自动超参搜索帮你试几百组参数找最优。KServe把模型包装成推理服务带自动扩缩甚至缩到0。要点Kubeflow的本质是把ML工程的所有环节都变成K8s的CRD。它重但对大团队值得——否则每个算法工程师都在自己的机器上野跑实验结果根本没法复现和共享。四、分布式训练PyTorchJob 实战用Training Operator起一个多机多卡训练不用自己写MPI启动脚本apiVersion:kubeflow.org/v1kind:PyTorchJobmetadata:name:resnet-trainspec:pytorchReplicaSpecs:Master:replicas:1template:spec:containers:-name:pytorchimage:registry.example.com/train:torch2resources:limits:{nvidia.com/gpu:1}command:[python,train.py]Worker:replicas:3# 3个Worker, 共 134 张卡template:spec:containers:-name:pytorchimage:registry.example.com/train:torch2resources:limits:{nvidia.com/gpu:1}command:[python,train.py]Training Operator会自动设置MASTER_ADDR、WORLD_SIZE、RANK等分布式环境变量你的train.py直接用torch.distributed即可不用管节点发现。# 看训练状态kubectl get pytorchjob kubectl logs resnet-train-worker-0-f# 挂了会自动重启(Job的backoff, 第024篇)五、推理服务Deployment GPU 暴露训练完的模型要对外提供服务本质就是一个带GPU的Deployment Service。轻量的可以用KServe简单的直接写apiVersion:apps/v1kind:Deploymentmetadata:name:infer-servicespec:replicas:2selector:matchLabels:{app:infer}template:metadata:labels:{app:infer}spec:containers:-name:inferimage:registry.example.com/infer:llama-7bresources:limits:nvidia.com/gpu:1memory:16GireadinessProbe:httpGet:{path:/health,port:8080}initialDelaySeconds:30ports:-containerPort:8080---apiVersion:v1kind:Servicemetadata:name:infer-servicespec:selector:{app:infer}ports:-port:80targetPort:8080推理场景的扩缩容有坑GPU Pod启动慢要加载模型权重HPA基于CPU不准。常见做法用KEDA基于队列长度/自定义指标扩缩比HPA灵活第025篇思路延伸。用KServe的缩容到零没有请求时Pod缩到0省显卡钱。显存够就一卡多实例或用MIG提高单卡利用率。要点推理服务最贵的不是CPU而是占着的显卡。一个7B模型可能只占半张卡却申请整卡→另一半闲着烧钱。MIG或一卡多实例是降本关键也呼应第085篇成本优化。六、GPU节点调度与规划GPU节点贵调度要精打细算【GPU 节点池规划】 节点池A (训练型): 8×A100, 大显存 → 只接 training job, 打 taint 防误用 → toleration 只有 Training Operator 能进 节点池B (推理型): 4×T4/L4, 便宜 → 接推理服务, 可缩容/用Spot(第085篇) 节点池C (开发型): 2×A10 MIG, 切片 → Notebook 开发调试# 训练节点打污点, 推理Pod进不去kubectl taint nodes gpu-train-01 dedicatedgpu-training:NoSchedule# 训练Job加对应toleration(第028篇污点和容忍)考量建议GPU型号选型训练用A100/H100推理用L4/T4更划算抢占/Spot容错训练任务用Spot省一半钱(第085篇)显存碎片用MIG避免小任务占整卡拓扑感知NVLINK跨卡快调度尽量放同节点(利用nodeAffinity)本篇小结大模型时代K8s成了AI训练与推理的默认底座。GPU通过Device Plugin暴露成nvidia.com/gpu扩展资源MIG/Time-Slicing解决整卡浪费Kubeflow用一套CRD把Notebook、Pipeline、Katib、Training Operator、KServe串成ML全生命周期分布式训练交给PyTorchJob推理服务就是带GPU的DeploymentService靠KEDA/缩容到零省显卡钱。核心经验训练节点和推理节点分池、用taint隔离、显存碎片的 killer 是MIG、最贵的是占着不用的卡。下篇收官聊聊K8s自己的未来——Serverless、WASM、eBPF和AI原生。上一篇【第88篇】多集群管理实战——从单集群到联邦集群的进化之路下一篇【第90篇】K8s的未来——Serverless、WASM、eBPF和AI原生的新篇章