2. K8s核心概念回顾:快速回顾Pod、Deployment、Service、Ingress、ConfigMap、Secret等核心资源

好,咱们直接进入正题。这一章我打算带大家快速过一遍Kubernetes里最常用的几个核心资源。你可能会觉得「这些我早就知道了」,但别急——我挑几个我踩过坑的点,结合vLLM部署的实际场景来讲,保证有收获。

一句话总结本章价值:搞懂这些资源,你就能在K8s里把vLLM服务跑起来,并且让外界能访问到它。

2.1 Pod:最小调度单元,也是vLLM进程的家

Pod是K8s里你能创建的最小单位。说白了,一个Pod就是一个或多个容器的组合。我习惯把Pod想象成一个「进程盒子」——里面跑着你的应用进程,共享网络和存储。

在vLLM的场景下,一个Pod里通常只跑一个容器,就是vLLM推理服务本身。但注意,如果你需要边推理边做日志采集,那就可以在同一个Pod里加一个sidecar容器,专门负责日志上传。

我的经验:我曾经在部署vLLM时,把模型加载和推理放在同一个Pod的两个容器里,结果发现模型加载容器先退出,Pod就重启了——其实应该用InitContainer来做模型预热。这个后面实战章节会细讲。

Pod的YAML长这样,很简单:

apiVersion: v1
kind: Pod
metadata:
  name: vllm-pod
  namespace: ai-namespace
spec:
  containers:
  - name: vllm
    image: vllm/vllm-openai:latest
    ports:
    - containerPort: 8000
    resources:
      requests:
        memory: "8Gi"
        nvidia.com/gpu: 1
      limits:
        memory: "16Gi"
        nvidia.com/gpu: 1

嗯,这里要注意:Pod是临时性的。如果节点挂了,Pod就没了。所以生产环境我们很少直接创建Pod,而是用Deployment来管理。

2.2 Deployment:让vLLM服务永不掉线

Deployment是K8s里最常用的工作负载控制器。它的核心能力就三个字:自愈。你告诉它「我要跑3个vLLM实例」,它就会一直维持3个。哪个Pod挂了,它立刻再起一个。

我个人觉得,Deployment是K8s最伟大的设计之一。你想想看,以前运维一个推理服务,节点宕机了得手动重启容器,现在Deployment自动搞定。

避坑指南:我曾经在更新vLLM镜像时,直接改了Deployment的镜像版本,结果新版本有bug,所有Pod都CrashLoopBackOff。幸好Deployment支持回滚——kubectl rollout undo deployment/vllm-deployment 一键回到上一个版本。所以,永远不要手动删Pod来更新版本,用Deployment的滚动更新策略。

Deployment的YAML示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-deployment
  namespace: ai-namespace
spec:
  replicas: 3
  selector:
    matchLabels:
      app: vllm
  template:
    metadata:
      labels:
        app: vllm
    spec:
      containers:
      - name: vllm
        image: vllm/vllm-openai:latest
        ports:
        - containerPort: 8000

2.3 Service:给vLLM Pod一个稳定的入口

Pod的IP是动态的。今天这个Pod的IP是10.1.1.5,明天重启后就变成10.1.1.8了。那客户端怎么访问?Service就是来解决这个问题的。

Service为一组Pod提供一个固定的虚拟IP(ClusterIP)和DNS名称。客户端只要访问Service的名字,K8s会自动把请求转发到后端的某个Pod上。

在vLLM场景下,我们通常用ClusterIP类型的Service,让集群内部的其他服务(比如你的前端应用)通过Service名来调用vLLM的推理接口。

关键点:Service的selector必须和Pod的labels匹配。我见过很多新手在这里栽跟头——Service配好了,但就是转发不到Pod,一查发现label写错了。

Service YAML:

apiVersion: v1
kind: Service
metadata:
  name: vllm-service
  namespace: ai-namespace
spec:
  selector:
    app: vllm
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8000
  type: ClusterIP

2.4 Ingress:让外部世界访问你的vLLM

Service的ClusterIP只能在集群内部访问。如果想让外部用户调用vLLM的API,就需要Ingress。

Ingress是K8s的七层负载均衡器。它负责把外部的HTTP/HTTPS请求,根据域名和路径,路由到集群内部的Service上。

举个例子:你有一个域名 api.mymodel.com,想让它指向vLLM的推理接口。Ingress就可以配置:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: vllm-ingress
  namespace: ai-namespace
spec:
  rules:
  - host: api.mymodel.com
    http:
      paths:
      - path: /v1/completions
        pathType: Prefix
        backend:
          service:
            name: vllm-service
            port:
              number: 80

我的建议:生产环境一定要配TLS证书。我曾经在测试环境忘了配,结果API被爬虫扫到,白白浪费了GPU算力。Ingress支持自动签发Let's Encrypt证书,配合cert-manager用起来很爽。

2.5 ConfigMap & Secret:配置与敏感信息管理

这两个资源经常一起出现,我就放一块讲了。

ConfigMap 用来存非敏感配置,比如vLLM的模型路径、日志级别、最大并发数等。你可以把它挂载到Pod里作为环境变量或配置文件。

Secret 用来存敏感信息,比如API密钥、数据库密码、Hugging Face的token等。它的内容会被base64编码(注意,不是加密,只是编码),但K8s会保证它在传输和存储时是加密的。

我曾经踩过的坑:有一次我把Hugging Face的token直接写在了Deployment的YAML里,然后不小心把YAML提交到了公开的Git仓库。结果第二天发现有人用我的token下载了付费模型……从那以后,我所有敏感信息都走Secret,而且用Sealed Secrets或External Secrets来做加密存储。

ConfigMap示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: vllm-config
  namespace: ai-namespace
data:
  model_name: "meta-llama/Llama-2-7b-chat-hf"
  max_model_len: "4096"
  gpu_memory_utilization: "0.9"

Secret示例:

apiVersion: v1
kind: Secret
metadata:
  name: hf-secret
  namespace: ai-namespace
type: Opaque
data:
  hf_token: aGZfxxxxxxxxxxxxxxxxxxxxx  # base64编码后的token

2.6 本章知识体系总览

下面这张图,是我用SVG画的本章核心资源关系图。你看一眼就能明白它们是怎么协作的:

K8s核心资源关系图(vLLM部署场景) 外部用户 Ingress Service Deployment Pod (vLLM) ConfigMap Secret 图例: 外部实体 网络入口 服务发现 工作负载 运行实例 配置/密钥 实线箭头 = 流量方向 | 虚线箭头 = 配置注入

从这张图可以清晰看到:外部用户请求 → Ingress(域名路由) → Service(负载均衡) → Deployment(管理Pod) → Pod(运行vLLM)。同时ConfigMap和Secret把配置和密钥注入到Pod里。

2.7 快速总结

好了,这一章我们快速回顾了6个核心资源。我再用一句话帮你记住它们:

  • Pod:跑vLLM进程的盒子
  • Deployment:保证Pod数量正确、版本可回滚
  • Service:给Pod一个稳定的内部访问入口
  • Ingress:让外部用户通过域名访问vLLM
  • ConfigMap:存模型路径、日志级别等配置
  • Secret:存API密钥、Hugging Face token等敏感信息

我的个人习惯:每次部署新服务前,我都会先画一张类似上面的资源关系图。画完图,整个架构就清晰了,写YAML的时候基本不会漏东西。你也可以试试。

下一章,我们会把这些资源组合起来,真正搭建一个带命名空间隔离的vLLM推理服务。到时候你会看到这些概念是怎么落地的。


专注资料整理