前言
在 AI Infra 领域,Kubernetes(简称 K8s)已经成为管理 GPU 集群和 AI 训练/推理工作负载的事实标准。无论是训练一个 7B 模型需要调度 8 张 A100,还是部署一个 vLLM 推理服务需要自动扩缩容,背后都是 K8s 在做资源分配和生命周期管理。
但对于非运维背景的同学来说,K8s 的概念体系很容易让人晕头转向:Pod、Deployment、Service、ConfigMap、DaemonSet......这些东西之间是什么关系?为什么需要这么多层抽象?
这篇文章从 AI Infra 的视角出发,把 K8s 的核心概念讲清楚,重点放在你需要理解到什么程度才能做好 AI 基础设施的工作。
一、Kubernetes 是什么,为什么需要它
K8s 是一个容器编排系统。你可以把它理解为一个"自动化的运维工程师":你告诉它"我需要 3 个 nginx 实例始终运行",它就帮你保证这件事------如果有实例挂了,它自动拉起新的;如果节点资源不够,它把实例调度到更合适的节点上。
在 AI 场景下,K8s 解决的核心问题是:
- GPU 资源调度:集群里有几十张 GPU,谁来决定哪个训练任务用哪几张卡?
- 工作负载管理:训练任务挂了怎么办?推理服务需要自动扩缩容怎么办?
- 环境一致性:不同人的训练环境怎么保证一致?容器镜像解决了这个问题。
二、集群架构:控制平面 + 工作节点

图1:K8s 集群架构。左侧是控制平面(Control Plane),负责决策和状态管理;右侧是工作节点(Worker Node),负责实际运行容器。
一个 K8s 集群由两部分组成:
控制平面(Control Plane / Master)
控制平面是集群的"大脑",做所有决策。它有四个核心组件:
kube-apiserver :集群的统一入口。你对 K8s 的所有操作(kubectl apply、kubectl get)都是发给 API Server 的 RESTful 请求。它负责认证、授权和准入控制。
etcd:集群的唯一状态存储,一个高可用的 Key-Value 数据库。集群的所有"真相"都存在这里------有哪些 Pod、哪些 Node、配置是什么。etcd 挂了,整个集群就失去了记忆。
kube-scheduler:调度器。当一个新 Pod 被创建但还没有分配到节点时,调度器根据资源需求(CPU、内存、GPU)、亲和性规则、节点负载等因素,选出一个最合适的节点。
kube-controller-manager :控制器管理器。运行一系列控制器进程,持续把集群的当前状态 往期望状态对齐。比如你声明"需要 3 个副本",但实际只有 2 个,控制器就会创建一个新的。
工作节点(Worker Node)
工作节点是真正干活的地方,每个节点上有三个组件:
kubelet:节点上的代理。接收控制平面的指令(Pod Spec),确保本节点上的容器按预期运行。它定期向 API Server 汇报节点状态。
kube-proxy:网络代理。维护节点上的网络规则(iptables/IPVS),实现 Service 的负载均衡和流量转发。
容器运行时:实际运行容器的软件,如 containerd 或 CRI-O。早期 K8s 用 Docker,现在 Docker 已被弃用,直接使用 containerd。
三、核心资源对象
K8s 中的一切都是"资源对象",用 YAML 文件声明,通过 kubectl apply -f 提交给 API Server。下面按重要性排序讲解。

图2:K8s 核心资源对象的关系。Deployment 管理 ReplicaSet,ReplicaSet 管理 Pod,Service 通过标签选择器关联 Pod,对外暴露稳定的访问入口。
3.1 Pod ------ 最小调度单元
Pod 是 K8s 中最小的、不可再分的部署单元。一个 Pod 包含一个或多个紧密关联的容器,它们共享网络命名空间(同一个 IP)和存储卷。
你可以把 Pod 想象成一台"虚拟机"------里面有你的应用容器,它们可以通过 localhost 互相通信,共享同一个 IP 地址。
yaml
apiVersion: v1
kind: Pod
metadata:
name: training-job
labels:
app: llm-train
spec:
containers:
- name: trainer
image: pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime
command: ["python", "train.py"]
resources:
limits:
nvidia.com/gpu: 1 # 请求 1 块 GPU
memory: "32Gi"
cpu: "8"
重要认知:Pod 是临时的,随时可能被创建、销毁、重启。永远不要直接依赖 Pod IP------它每次重建都会变。这就是为什么需要 Service。
3.2 Deployment ------ 管理 Pod 的期望状态
你不会手动创建 Pod(那太累了)。Deployment 帮你管理一组 Pod 的期望状态:需要几个副本、用什么镜像、怎么更新。
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: llm-inference
spec:
replicas: 3 # 始终保持 3 个 Pod 运行
selector:
matchLabels:
app: llm-inference
template: # Pod 模板
metadata:
labels:
app: llm-inference
spec:
containers:
- name: vllm
image: vllm/vllm-openai:latest
ports:
- containerPort: 8000
resources:
limits:
nvidia.com/gpu: 1
Deployment 的工作方式是:创建 ReplicaSet → ReplicaSet 创建和管理 Pod。当你更新镜像版本时,Deployment 会做滚动更新(Rolling Update)------逐步替换旧 Pod,保证服务不中断。
3.3 Service ------ 稳定的访问入口
Pod 有 IP,但 IP 会变。Service 给一组 Pod 提供一个稳定的 IP 和 DNS 名称,并通过标签选择器(Label Selector)自动发现后端 Pod。
yaml
apiVersion: v1
kind: Service
metadata:
name: llm-inference-svc
spec:
selector:
app: llm-inference # 关联标签为 app=llm-inference 的 Pod
ports:
- port: 80 # Service 暴露的端口
targetPort: 8000 # Pod 上容器的端口
type: ClusterIP # 集群内访问
Service 有几种类型:
| 类型 | 说明 | 场景 |
|---|---|---|
| ClusterIP | 集群内部 IP,外部无法访问 | 内部服务间通信 |
| NodePort | 在每个节点上开一个固定端口(30000-32767) | 简单的外部访问 |
| LoadBalancer | 由云厂商提供外部负载均衡器 | 生产环境对外暴露服务 |
3.4 ConfigMap 与 Secret ------ 配置与密钥
把配置从容器镜像中解耦出来,做到"一次构建镜像,多处使用不同配置"。
yaml
# ConfigMap: 存储非敏感配置
apiVersion: v1
kind: ConfigMap
metadata:
name: training-config
data:
learning_rate: "0.001"
batch_size: "32"
model_name: "llama-7b"
---
# Secret: 存储敏感信息(Base64 编码)
apiVersion: v1
kind: Secret
metadata:
name: wandb-secret
type: Opaque
data:
api-key: d2FuZGIua2V5Lnh4eA== # echo -n 'wandb.key.xxx' | base64
在 Pod 中可以通过环境变量或挂载文件的方式使用它们。
3.5 Namespace ------ 逻辑隔离
Namespace 把集群划分成多个逻辑空间,不同 Namespace 的资源互相隔离(但不完全隔离网络)。
bash
kubectl create namespace training # 训练任务
kubectl create namespace inference # 推理服务
kubectl create namespace monitoring # 监控组件
在企业环境中,Namespace 常用来隔离不同团队或项目,配合 ResourceQuota 限制每个空间的资源上限。
四、一个完整的 AI 推理服务部署示例
把上面的概念串起来,看一个部署 LLM 推理服务的完整 YAML:
yaml
# 1. ConfigMap: 推理参数
apiVersion: v1
kind: ConfigMap
metadata:
name: vllm-config
data:
model: "meta-llama/Llama-2-7b-hf"
max-model-len: "4096"
gpu-memory-utilization: "0.9"
---
# 2. Secret: HuggingFace Token
apiVersion: v1
kind: Secret
metadata:
name: hf-token
type: Opaque
data:
token: aGZfeHh4eA==
---
# 3. Deployment: 管理推理 Pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: llama-inference
spec:
replicas: 2
selector:
matchLabels:
app: llama-inference
template:
metadata:
labels:
app: llama-inference
spec:
containers:
- name: vllm
image: vllm/vllm-openai:latest
args:
- --model
- $(MODEL_NAME)
- --max-model-len
- $(MAX_LEN)
env:
- name: MODEL_NAME
valueFrom:
configMapKeyRef:
name: vllm-config
key: model
- name: MAX_LEN
valueFrom:
configMapKeyRef:
name: vllm-config
key: max-model-len
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token
key: token
ports:
- containerPort: 8000
resources:
limits:
nvidia.com/gpu: 1
memory: "32Gi"
cpu: "8"
---
# 4. Service: 暴露稳定的 API 端点
apiVersion: v1
kind: Service
metadata:
name: llama-api
spec:
selector:
app: llama-inference
ports:
- port: 80
targetPort: 8000
type: LoadBalancer
部署命令:
bash
kubectl apply -f llm-inference.yaml
kubectl get pods # 查看 Pod 状态
kubectl get svc llama-api # 获取外部 IP
curl http://<EXTERNAL-IP>/v1/chat/completions -d '...'
五、GPU 调度:AI Infra 的核心话题
在 AI 场景中,GPU 是最稀缺的资源。K8s 原生不识别 GPU,需要通过插件机制来支持。
5.1 NVIDIA Device Plugin
K8s 通过 Device Plugin 机制 扩展硬件支持。NVIDIA 提供了一个 DaemonSet,在每个 GPU 节点上运行,向 kubelet 注册 nvidia.com/gpu 资源:

图3:K8s GPU 管理与 Device Plugin 工作机制。Device Plugin 以 DaemonSet 形式运行在每个 GPU 节点上,探测 GPU 资源并向 kubelet 注册,kubelet 上报给 API Server,调度器据此做调度决策。
GPU 节点启动
→ NVIDIA Device Plugin Pod 启动(DaemonSet 自动部署)
→ 探测本节点的 GPU 数量和型号
→ 向 kubelet 注册扩展资源: nvidia.com/gpu = 8
→ kubelet 上报给 API Server: "本节点有 8 块 GPU"
→ 调度器就能根据 Pod 的 GPU 请求做调度决策
在 Pod 中请求 GPU 只需在 resources.limits 中声明:
yaml
resources:
limits:
nvidia.com/gpu: 2 # 请求 2 块 GPU
注意 :GPU 只能在
limits中声明,不能只在requests中。K8s 规定扩展资源(extended resources)必须 limits = requests,不支持超卖。
5.2 节点选择与 GPU 型号
集群里可能有不同型号的 GPU(A100、H100、V100)。通过**节点标签(Node Labels)**和 nodeSelector / nodeAffinity 让 Pod 调度到特定 GPU 的节点上:
bash
# 给节点打标签
kubectl label nodes gpu-node-01 gpu-model=a100-80g
kubectl label nodes gpu-node-02 gpu-model=h100-80g
yaml
# Pod 中选择节点
spec:
nodeSelector:
gpu-model: a100-80g
NVIDIA 的 GPU Feature Discovery(GFD)工具可以自动给节点打上 GPU 型号、显存大小、互联拓扑等标签。
5.3 多 GPU 分布式训练
分布式训练需要多个 Pod 协同工作,每个 Pod 使用若干 GPU。K8s 原生的 Deployment 不适合这种场景(Pod 之间没有协调机制),通常使用 Job 或 StatefulSet ,配合 Volcano 等批调度器实现 Gang Scheduling:
yaml
# Gang Scheduling: 所有 Pod 要么一起启动,要么一起等
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: distributed-training
spec:
minAvailable: 4 # 4 个 Pod 必须同时调度成功才启动
tasks:
- replicas: 4
template:
spec:
containers:
- name: trainer
image: my-training-image:latest
resources:
limits:
nvidia.com/gpu: 8 # 每个 Pod 用 8 卡
# 总共 4 Pod × 8 GPU = 32 卡分布式训练
Gang Scheduling 解决了分布式训练的一个关键问题:如果 4 个 Worker 需要同时启动才能做 AllReduce,但 K8s 只调度了 3 个,那这 3 个就会一直等着------死锁。minAvailable: 4 保证 4 个都准备好了才一起启动。
5.4 GPU 共享与切分
一张 A100 80GB 可能跑多个小推理任务。K8s 支持两种方式在多个 Pod 之间共享一张 GPU:
时间分片(Time Slicing):NVIDIA Device Plugin 把一张物理 GPU 虚拟成多份。多个 Pod 轮流使用,通过时间片切换。适合推理场景,不适合训练(性能损耗大)。
MIG(Multi-Instance GPU):A100/H100 硬件级支持,把一张 GPU 物理切分成多个独立实例(如 7 个 5GB 实例),每个实例有独立的显存、缓存和计算单元,互不干扰。
六、存储与网络基础
持久化存储(PVC)
AI 训练需要读取大量数据集、保存模型 checkpoint。Pod 重启后本地文件会丢失,需要持久化存储。
K8s 通过 PV(PersistentVolume)+ PVC(PersistentVolumeClaim) 模式管理存储:
yaml
# 声明需要 500GB 存储
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dataset-storage
spec:
accessModes:
- ReadWriteMany # 多 Pod 同时读
resources:
requests:
storage: 500Gi
storageClassName: nfs # 使用 NFS 后端
然后在 Pod 中挂载:
yaml
volumes:
- name: dataset
persistentVolumeClaim:
claimName: dataset-storage
containers:
- name: trainer
volumeMounts:
- name: dataset
mountPath: /data # Pod 内 /data 目录对应 PVC
常见的存储后端:NFS(简单通用)、Ceph(高性能分布式)、云厂商 CSI 驱动(EBS、GCE PD)。
网络模型
K8s 的网络设计遵循三个原则:
- 每个 Pod 有独立 IP------不需要端口映射(Docker 的痛点)
- Pod 之间可以直接通信------跨节点也能直连
- Node 上的代理可以和该 Node 上的所有 Pod 通信
网络实现由 CNI 插件负责(Calico、Cilium、Flannel 等)。对 AI Infra 来说,Pod 间通信主要用于分布式训练的梯度同步,性能敏感场景通常配合 RDMA 网络。
七、常用 kubectl 命令速查
bash
# 集群信息
kubectl cluster-info # 集群状态
kubectl get nodes -o wide # 节点列表(含 GPU 信息)
kubectl describe node gpu-node-01 # 节点详情(GPU 分配情况)
# 资源管理
kubectl apply -f deployment.yaml # 创建/更新资源
kubectl delete -f deployment.yaml # 删除资源
kubectl get pods -o wide # Pod 列表(含节点和 IP)
kubectl get svc # Service 列表
kubectl get events --sort-by=.metadata.creationTimestamp # 集群事件
# 调试
kubectl logs <pod-name> # 查看容器日志
kubectl logs -f <pod-name> # 实时跟踪日志
kubectl exec -it <pod-name> -- bash # 进入容器
kubectl describe pod <pod-name> # Pod 详情(含事件和调度信息)
kubectl top pods # Pod 资源使用率
# GPU 相关
kubectl get nodes -L nvidia.com/gpu.product # 查看各节点 GPU 型号
kubectl get pods -o custom-columns=NAME:.metadata.name,GPU:.spec.containers[*].resources.limits.nvidia\.com/gpu
# 查看各 Pod 的 GPU 请求量
八、AI Infra 面试常见 K8s 问题
Q:Pod 和容器的区别是什么?
Pod 是 K8s 的调度单元,可以包含多个容器。容器是实际运行的进程。一个 Pod 里的容器共享网络和存储,彼此可以通过 localhost 通信。K8s 不直接管理容器,只管理 Pod。
Q:Deployment 的滚动更新是怎么工作的?
Deployment 创建新的 ReplicaSet,逐步增加新 Pod 数量,同时减少旧 ReplicaSet 的 Pod 数量。通过 maxSurge(最多多出的 Pod 数)和 maxUnavailable(最多不可用的 Pod 数)控制节奏,保证服务不中断。
Q:如何在 K8s 上调度 GPU 任务?
通过 NVIDIA Device Plugin 注册 nvidia.com/gpu 扩展资源,Pod 在 resources.limits 中声明 GPU 需求,调度器根据节点可用 GPU 数量做调度。用 nodeSelector 或 nodeAffinity 选择特定 GPU 型号的节点。
Q:什么是 Gang Scheduling?为什么 AI 训练需要它?
Gang Scheduling 保证一组 Pod 要么全部被调度成功、要么全部等待。分布式训练(如 8 卡 AllReduce)要求所有 Worker 同时在线才能通信,如果只启动了一部分就会死锁。Gang Scheduling 通过 minAvailable 解决这个问题。
Q:Service 的 ClusterIP 和 NodePort 有什么区别?
ClusterIP 只在集群内部可访问,适合服务间内部通信。NodePort 在每个节点上开一个固定端口(30000-32767),外部可以通过 NodeIP:NodePort 访问。生产环境通常用 LoadBalancer 类型,由云厂商提供外部负载均衡。
九、总结
K8s 的概念体系虽然庞大,但核心逻辑很清晰:声明式 API + 控制器模式。你声明"我要什么"(YAML),控制器持续工作把现实往你的声明对齐。Pod 是最小运行单元,Deployment 管理 Pod 的副本和更新,Service 提供稳定访问入口,ConfigMap/Secret 管理配置。
对于 AI Infra 工程师来说,最重要的能力是:理解 GPU 调度机制(Device Plugin、节点标签、Gang Scheduling),能写训练/推理的 YAML 配置,知道怎么用 PVC 管理数据和模型存储,会用 kubectl 排查问题。这些是日常工作中每天都在用的东西。