L1.7 Kubernetes 核心对象:Pod / Service / Ingress
三维坐标
layer: L1(算力与编排)|level: Engineer|pillar: 硬件架构L1.4 讲 GPU 调度与 Gang 编排时,默认你已经能读懂一份 K8s YAML。本章补齐这块前置:Pod 是什么、Service 怎么暴露、Ingress 怎么接流量——以及 AI 作业里最常见的
Pending/CrashLoopBackOff怎么查。
学习目标
- 前置知识:读过 L0.6 环境基线(装过 Docker / kind);会用命令行。无需自有 K8s 集群。
- 学完产出:① 能画出「Deployment → ReplicaSet → Pod」的控制关系,说清 Pod 为何是 K8s 最小调度单元;② 能区分 ClusterIP / NodePort / LoadBalancer 三种 Service 类型及 AI 推理服务的典型选型;③ 能写一份带
resources.limits与livenessProbe的最小 Deployment + Service YAML;④ 能用kubectl describe pod读懂Events里的 Pending / OOM / ImagePullBackOff 根因;⑤ 在 kind 本地集群亲手部署一个 mock 推理 Pod 并通过 Service 访问。 - 阅读姿势:K8s 对 AI Infra 工程师不是「运维选修课」,而是读调度 YAML、查 Gang Job、对接 GPU Operator 的通用语言。
背景与现状
Kubernetes 把「跑容器」抽象成声明式 API:你描述期望状态(3 副本、每 Pod 1 GPU、镜像 v1.2),控制平面持续 reconcile 直到实际状态匹配。AI 平台(Kubeflow、Volcano Job、vLLM Helm Chart)最终都落在这套对象上。
| 对象 | 职责 | AI 场景举例 |
|---|---|---|
| Pod | 最小调度单元,1+ 容器共享网络/存储 | 单卡训练 Worker、vLLM 推理实例 |
| Deployment | 无状态多副本,滚动升级 | 水平扩展的推理网关 |
| Job / CronJob | 跑完即停 / 定时批任务 | 离线评估、Embedding 回填 |
| Service | 稳定虚拟 IP + DNS,负载均衡到 Pod | 集群内访问推理 API |
| Ingress | HTTP/HTTPS 七层路由 | 对外暴露 /v1/chat/completions |
| ConfigMap / Secret | 非敏感 / 敏感配置注入 | 模型路径、API Key |
业界信号:几乎所有云厂商 AI 平台(EKS/GKE/ACK + Volcano/Kueue)的 GPU 作业最终都是 Pod + 自定义 CRD。不会读 Pod YAML,就无法排查「为什么 8 卡 Job 只起了 6 个」。
原理与架构
2.1 控制平面与数据平面
读图要点:你提交的 YAML 存进 etcd;Deployment 控制器创建 ReplicaSet 再创建 Pod;调度器把 Pod 绑定到节点;kubelet 拉镜像并启动容器。
2.2 Pod 生命周期与常见状态
| 状态 | 含义 | AI 常见根因 |
|---|---|---|
| Pending | 已创建未调度或未拉镜像 | 资源不足(GPU 不够)、节点选择器不匹配、镜像拉取慢 |
| Running | 容器已启动 | 正常 |
| CrashLoopBackOff | 启动后反复退出 | CUDA 版本错、入口命令错、OOM |
| Completed | Job 成功结 束 | 批处理正常 |
| Failed | Job 失败 | 训练脚本非零退出 |
2.3 Service 三种类型
- ClusterIP:集群内 DNS
my-svc.default.svc.cluster.local,Sidecar / 其他微服务互访。 - NodePort:开发调试;生产少用(端口管理混乱)。
- LoadBalancer:云环境对外暴露推理 API 的默认方式;配合 Ingress 做路径路由。
2.4 Ingress:七层路由
Ingress 不替代 Service,而是在 Service 之上做 HTTP 路由:
# 示意:/v1/* → vllm-svc,/metrics → prom-svc
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: llm-ingress
spec:
rules:
- host: infer.example.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: vllm-svc
port:
number: 8000
动手实践:kind 上部署 mock 推理服务
实验目标:用 kind 起集群,部署一个返回 JSON 的 mock 推理 Deployment,通过 ClusterIP Service 在集群内 curl 通。
环境前置
kind create cluster --name k8s-basics 2>/dev/null || true
kubectl cluster-info
步骤 1:Deployment + Service
# mock-infer.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mock-infer
spec:
replicas: 2
selector:
matchLabels:
app: mock-infer
template:
metadata:
labels:
app: mock-infer
spec:
containers:
- name: server
image: python:3.11-slim
command: ["python", "-m", "http.server", "8080"]
ports:
- containerPort: 8080
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: mock-infer-svc
spec:
selector:
app: mock-infer
ports:
- port: 80
targetPort: 8080
type: ClusterIP
kubectl apply -f mock-infer.yaml
kubectl get pods -w # 等到 2/2 Running
kubectl get svc mock-infer-svc
步骤 2:集群内访问
kubectl run curl-test --rm -it --restart=Never --image=curlimages/curl -- \
curl -s http://mock-infer-svc/
# 预期:返回 Simple HTTP server 页面 HTML
步骤 3:排查练习
# 故意改错镜像名,观察 ImagePullBackOff
kubectl set image deployment/mock-infer server=python:nonexistent-tag
kubectl describe pod -l app=mock-infer | tail -20
kubectl rollout undo deployment/mock-infer
踩坑预警
resources不写 limits:在共享集群上容 易被 OOMKill 或挤占邻居;GPU Job 必须写nvidia.com/gpu: 1。- Probe 探针路径错:liveness 失败会无限重启,表现为 CrashLoop;readiness 失败则不会接流量。
- Service selector 与 Pod label 不一致:Service 存在但无 Endpoints,
curl超时。 - kind 默认无 LoadBalancer:
EXTERNAL-IP长期<pending>是正常的,用kubectl port-forward或 Ingress 代替。
配套代码:ai-infra-labs
run_k8s_basics.sh— kind + mock Deployment/Service 一键验收。
深入思考
思考题:为什么 AI 训练 Job 常用 Job 而非 Deployment?
展开参考答案
Deployment 面向长期运行的无状态服务:Pod 挂了会自动重建,期望副本数恒定。分布式训练 Worker 跑完就退出,不应被「自动重建」——否则 checkpoint 语义混乱。
Job(及 Volcano Job / PyTorchJob CRD)面向有终点的批计算:completions 个 Pod 成功即 Completed;失败可按 backoffLimit 重试。Gang 调度(L1.4)在 Job 之上再加 PodGroup,保证 8 卡同时就绪。
推理服务用 Deployment(7×24);训练/评估用 Job。混用是平台设计的第一性选型。
延伸阅读
- 官方文档:Pods、Services
- 下一章:L1.4 资源调度与编排(GPU device plugin、Gang、Volcano)