3、K8s核心概念:Pod、Service、Deployment、Namespace、ConfigMap、Secret
说实话,刚接触K8s那会儿,我被这一堆概念搞得有点晕。Pod、Service、Deployment……名字都挺像,到底谁管谁?
后来我总结了一句话:Pod是跑程序的,Deployment是管Pod的,Service是暴露服务的,Namespace是分环境的,ConfigMap和Secret是存配置的。
嗯,就这么简单。咱们一个一个拆开聊。
核心逻辑图:K8s六大概念关系
3.1 Pod:K8s里最小的“小盒子”
Pod 是 K8s 里你能直接操作的最小单元。说白了,它就是一个或多个容器的“合租屋”。
我习惯把 Pod 想象成一个“进程组”。里面可以只住一个容器(最常见),也可以住多个容器(比如一个跑业务,一个做日志收集)。
我的经验:刚开始我总想着一个 Pod 里塞很多容器,觉得省资源。后来发现这样调试特别麻烦,日志混在一起,端口也容易冲突。现在我基本遵循“一个 Pod 一个主容器”的原则,除非有明确的 sidecar 需求。
Pod 有几个关键特点:
- 共享网络:同一个 Pod 里的容器共享 IP 和端口空间,用 localhost 就能互相访问。
- 共享存储:可以挂载同一个 Volume,数据共享很方便。
- 生命周期短暂:Pod 挂了就挂了,K8s 不会自动重启它——这就是为什么我们需要 Deployment。
# 一个最简单的 Pod YAML
apiVersion: v1
kind: Pod
metadata:
name: my-vllm-pod
spec:
containers:
- name: vllm
image: vllm/vllm-openai:latest
ports:
- containerPort: 8000
你看,就这么几行。但实际生产里我几乎不会直接创建 Pod,都是用 Deployment 来管。
3.2 Deployment:Pod 的“保姆”
Deployment 是干嘛的?它负责保证你想要的 Pod 数量一直在线。
我记得有一次,集群里一个节点挂了,上面跑了 3 个 vLLM Pod。如果是裸 Pod,那就全没了。但因为有 Deployment,它自动在另一个节点上重新拉起了 3 个新 Pod。整个过程我连个告警都没收到——嗯,这就是 K8s 的魅力。
核心能力:声明式更新、滚动升级、回滚、自动扩缩容。
# Deployment 示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-deployment
spec:
replicas: 3
selector:
matchLabels:
app: vllm
template:
metadata:
labels:
app: vllm
spec:
containers:
- name: vllm
image: vllm/vllm-openai:latest
ports:
- containerPort: 8000
这里有个坑:selector.matchLabels 必须和 template.metadata.labels 一致。我曾经手抖写错过,结果 Deployment 找不到 Pod,一直报错。排查了半小时才发现是标签没对上。
3.3 Service:稳定的“门牌号”
Pod 是会飘的。今天在 node1,明天可能就在 node2。IP 也会变。那客户端怎么访问?
Service 就是来解决这个问题的。它提供一个固定的虚拟 IP(ClusterIP),不管 Pod 怎么变,客户端只管访问这个 IP 就行。
注意:Service 默认是 ClusterIP 类型,只能在集群内部访问。如果想对外暴露,需要用 NodePort 或 LoadBalancer 类型。
# Service 示例
apiVersion: v1
kind: Service
metadata:
name: vllm-service
spec:
selector:
app: vllm
ports:
- protocol: TCP
port: 80
targetPort: 8000
type: ClusterIP
我个人习惯把 Service 的名字取得有规律,比如 vllm-svc、api-svc。这样在集群里通过 DNS 访问时,直接 http://vllm-svc 就能找到,特别方便。
3.4 Namespace:集群里的“隔间”
Namespace 就是用来做逻辑隔离的。你可以把它理解成一套房子里的不同房间。
我在项目中通常这样划分:
dev:开发环境,随便折腾test:测试环境,跑自动化测试prod:生产环境,严格管控
我的建议:千万别把所有东西都丢在 default 命名空间里。时间一长,你根本分不清哪个 Pod 是干嘛的。我曾经接手过一个项目,default 里躺着 200 多个 Pod……那叫一个乱。
# 创建 Namespace
kubectl create namespace vllm-prod
# 在指定 Namespace 下创建资源
kubectl apply -f deployment.yaml -n vllm-prod
3.5 ConfigMap 与 Secret:配置的“保险柜”
这两个东西都是用来存配置的。区别在于:
| 特性 | ConfigMap | Secret |
|---|---|---|
| 存储内容 | 明文配置(如端口、日志级别) | 敏感信息(如密码、API Key) |
| 编码方式 | 明文 | Base64(仅编码,非加密) |
| 使用场景 | 环境变量、配置文件挂载 | 数据库密码、Token |
我曾经犯过一个错:把数据库密码直接写在了 ConfigMap 里。后来安全审计被点名批评。记住,敏感信息一定要用 Secret。
# ConfigMap 示例
apiVersion: v1
kind: ConfigMap
metadata:
name: vllm-config
data:
MODEL_NAME: "Qwen2.5-7B-Instruct"
MAX_TOKENS: "2048"
# Secret 示例
apiVersion: v1
kind: Secret
metadata:
name: vllm-secret
type: Opaque
data:
API_KEY: bXktc2VjcmV0LWtleQ== # 这是 "my-secret-key" 的 Base64
重要提醒:Secret 只是 Base64 编码,不是加密。如果你需要真正的加密,请使用外部密钥管理工具(如 HashiCorp Vault)或 K8s 的 Encryption at Rest。
好了,这六个概念就是 K8s 的基石。你想想看,Pod 跑服务,Deployment 管生命周期,Service 管网络,Namespace 管隔离,ConfigMap 和 Secret 管配置——一套完整的应用部署体系就搭起来了。
下一章我们会把这些概念串起来,真正部署一个 vLLM 服务。到时候你就知道,这些概念不是孤立的,它们配合起来才叫 K8s。