2. Kubernetes核心概念回顾:Pod、Deployment、Service、Namespace、资源配额
好,咱们进入第二章。说实话,很多搞AI推理的同学一上来就问我:“老师,我能不能直接跳过K8s基础,直接学vLLM扩缩容?”我的回答永远是——不行。你想想看,HPA自动扩缩容的本质是什么?是K8s在帮你管理Pod的数量。如果你连Pod是什么、Deployment怎么用都不清楚,那后面调参数、排故障的时候,真的会一头雾水。
这一章,我带你快速过一遍K8s最核心的几个概念。都是干货,不废话。我会结合我在生产环境中踩过的坑来讲,保证你听完就能用。
2.1 Pod:K8s里最小的调度单元
Pod是啥?说白了,它就是一组容器的“集合体”。在K8s的世界里,你没法直接跑一个容器,你必须把它包在Pod里。一个Pod可以包含一个或多个容器,这些容器共享网络栈、存储卷,以及一些生命周期管理。
我在项目中遇到过一个问题:有个同事把vLLM的推理进程和日志收集器放在了两个不同的Pod里,结果日志收集器老是连不上推理进程。后来我让他改成同一个Pod里的两个容器,问题瞬间解决。为什么?因为同一个Pod里的容器可以通过localhost互相通信,根本不需要走Service。
- Pod是K8s的最小调度单位,不是容器
- 同一个Pod内的容器共享IP和端口空间
- Pod是“临时”的——它可能随时被销毁和重建
2.2 Deployment:声明式的Pod管理利器
你直接创建一个Pod,万一它挂了怎么办?K8s不会自动帮你重启。这时候就需要Deployment出场了。
Deployment是一个控制器,它负责保证你期望的Pod数量始终存在。你告诉它“我要3个vLLM推理Pod”,它就会一直盯着,少了就补,多了就删。而且它还支持滚动更新——你更新镜像版本时,Pod会逐个替换,不会造成服务中断。
我曾经踩过一个坑:有一次我直接修改了Deployment的replicas从3改成10,结果集群资源不够,Pod一直处于Pending状态。后来我才意识到,资源配额(ResourceQuota)没配好,Deployment根本拉不起那么多Pod。嗯,这里要注意——Deployment只管“声明”,不管“能不能调度成功”。
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-inference
spec:
replicas: 3
selector:
matchLabels:
app: vllm
template:
metadata:
labels:
app: vllm
spec:
containers:
- name: vllm
image: vllm/vllm-openai:latest
ports:
- containerPort: 8000
resources:
requests:
memory: "8Gi"
cpu: "4"
limits:
memory: "16Gi"
cpu: "8"
2.3 Service:稳定的网络入口
Pod是会漂移的——它可能因为节点故障、滚动更新等原因被重建,IP地址也会变。那客户端怎么访问你的vLLM服务呢?靠Service。
Service为一组Pod提供了一个稳定的虚拟IP(ClusterIP)和DNS名称。你访问Service,K8s会自动把流量转发到后端的某个Pod上。说白了,Service就是一个“负载均衡器”。
我个人习惯把Service和Deployment分开定义。虽然可以用kubectl expose命令一键生成,但生产环境我建议手写YAML,因为你可以精确控制端口映射、会话亲和性等细节。
apiVersion: v1
kind: Service
metadata:
name: vllm-service
spec:
selector:
app: vllm
ports:
- protocol: TCP
port: 8000
targetPort: 8000
type: ClusterIP
2.4 Namespace:逻辑隔离的艺术
一个K8s集群里可能有多个团队、多个项目在跑。如果没有隔离,大家互相抢资源、命名冲突,那画面太美我不敢看。Namespace就是用来做逻辑隔离的。
你可以把Namespace理解成一个“虚拟集群”。不同的Namespace里,可以有同名的Deployment、Service,互不干扰。而且你可以给每个Namespace设置资源配额,防止某个团队把集群资源吃光。
我记得有一次,一个同事在default命名空间里直接跑了个大模型推理任务,结果把整个集群的GPU都占满了,其他团队的训练任务全部Pending。后来我强制要求:每个项目必须使用独立的Namespace,并配置ResourceQuota。从那以后,再也没出过类似问题。
- 每个环境(dev/staging/prod)使用独立的Namespace
- 每个团队或项目使用独立的Namespace
- 永远不要在default命名空间里跑生产负载
2.5 资源配额:给Pod戴上“紧箍咒”
资源配额(ResourceQuota)是K8s提供的一种限制机制。你可以限制一个Namespace下所有Pod的总CPU、总内存、总存储等资源上限。没有配额,一个“调皮”的Pod就可能把整个集群搞垮。
在vLLM推理场景下,资源配额尤其重要。因为大模型推理对GPU显存和CPU内存的需求非常高。如果不加限制,一个推理Pod可能吃掉所有可用内存,导致其他Pod被OOM Kill。
apiVersion: v1
kind: ResourceQuota
metadata:
name: vllm-quota
namespace: ai-inference
spec:
hard:
requests.cpu: "40"
requests.memory: "80Gi"
limits.cpu: "80"
limits.memory: "160Gi"
persistentvolumeclaims: "10"
requests.nvidia.com/gpu: "8"
2.6 知识体系总览
为了让你更直观地理解这些概念之间的关系,我画了一张图。你可以看到:Namespace是顶层容器,里面包含Deployment和Service;Deployment管理Pod的生命周期;Pod里运行着容器;Service为Pod提供稳定的访问入口;ResourceQuota则对整个Namespace的资源使用进行约束。
这张图把整个知识体系串起来了。你记住一句话:Namespace是家,Deployment是管家,Pod是员工,Service是前台,ResourceQuota是财务。这样理解起来是不是轻松多了?
好了,这一章的核心概念就讲到这里。下一章我们会深入HPA的原理和配置,到时候你会看到这些基础概念是如何被串联起来的。嗯,先消化一下今天的内容,有问题随时问我。
公众号:蓝海资料掘金营,微信deep3321