首页
/ 使用 Helm 在 Kubernetes 上部署 vLLM 推理服务:安装步骤、values 配置详解与模型自动下载原理

使用 Helm 在 Kubernetes 上部署 vLLM 推理服务:安装步骤、values 配置详解与模型自动下载原理

2026-09-04 21:40:48作者:魏侃纯Zoe

本篇基于 vLLM 仓库中的 Helm 部署文档 与官方示例 chart examples/deployment/chart-helm,完整讲解如何用 Helm 在 Kubernetes 上部署 vLLM 推理服务:包括前置条件、安装与卸载命令、全部 values 参数、部署架构,以及结合 chart 模板源码剖析"模型自动下载 + init 容器等待"这套默认机制的底层实现。读完后,你可以直接复制命令在自己集群中部署 vLLM,并理解每个 K8s 资源对象是由哪个模板、依据哪些参数渲染出来的。

vLLM Helm 部署架构:PVC 存储模型,Job 下载模型,Deployment 运行 vLLM 服务

部署架构概览

Helm 是 Kubernetes 的包管理器。借助它,vLLM 可以把整套 K8s 资源(Deployment、Service、PVC、Job、HPA 等)打包为一个 chart,以不同配置下发到多个 namespace。

chart 目录结构 可以看到,这个 chart(Chart.yaml 中声明 name: chart-vllmtype: application)由一组 Go Template 模板渲染而成:

模板文件 渲染出的 K8s 资源 作用
templates/deployment.yaml Deployment 运行 vllm serve 主容器,含 init 容器、健康探针、GPU 亲和性
templates/job.yaml Job 用 aws-cli 把模型权重从 S3 同步到 PVC(默认启用)
templates/pvc.yaml PersistentVolumeClaim 存放模型权重的持久化存储(ReadWriteOnce
templates/service.yaml Service ClusterIP 类型,对外暴露推理端口
templates/hpa.yaml HorizontalPodAutoscaler 按 CPU/内存利用率自动扩缩容(默认关闭)
templates/poddisruptionbudget.yaml PodDisruptionBudget 自愿中断时限制不可用副本数
templates/configmap.yaml / templates/secrets.yaml ConfigMap / Secret 通过 envFrom 注入环境变量与 S3 凭据
templates/custom-objects.yaml 任意自定义对象 以 Helm 模板语法渲染任意 K8s 资源

整体数据流是:Job 先把模型权重从 S3 写入 PVC,Deployment 主容器把 PVC 挂载到 /data,容器内执行 vllm serve /data/ 启动 OpenAI 兼容服务,Service 将流量导入 Pod。

前置条件

在开始之前,确保你具备以下条件(引自 Helm 文档):

  • 一个可用的 Kubernetes 集群;
  • NVIDIA Kubernetes Device Plugin(k8s-device-plugin),用于向 K8s 注册 GPU 资源;
  • 集群中有可用的 GPU 资源;
  • (可选)存放模型权重的 S3 桶或其他存储 —— 仅在使用"自动模型下载"时需要。

S3 凭据会在安装时以 --set secrets.* 的方式传入,最终由 templates/secrets.yaml 渲染为一个 Opaque Secret(值经 b64enc 编码),命名规则为 {{ .Release.Name }}-secrets

安装与卸载 Chart

文档以 examples/deployment/chart-helm 目录中的 chart 为例。helm upgrade --install 命令在 chart 所在目录(即 examples/deployment/chart-helm)下执行,安装一个 release 名为 test-vllm 的部署:

helm upgrade --install --create-namespace \
  --namespace=ns-vllm test-vllm . \
  -f values.yaml \
  --set secrets.s3endpoint=$ACCESS_POINT \
  --set secrets.s3bucketname=$BUCKET \
  --set secrets.s3accesskeyid=$ACCESS_KEY \
  --set secrets.s3accesskey=$SECRET_KEY

要点说明:

  • --create-namespace --namespace=ns-vllm:自动创建并使用独立 namespace,便于把同一 chart 部署到多个 namespace 做不同配置;
  • -f values.yaml:使用 chart 自带 values.yaml 作为基线值,也可以用自定义文件覆盖;
  • 四个 --set secrets.* 覆盖 S3 凭据,供默认启用的模型下载 Job 使用;values.yaml 中的 secrets 默认为空对象 {},即 S3 地址/桶名/密钥必须显式提供,否则 wait-download-model 与下载 Job 无法工作。

卸载命令:

helm uninstall test-vllm --namespace=ns-vllm

文档特别强调:该命令会删除 chart 关联的所有 Kubernetes 组件,包括持久卷(PVC),并删除 release。也就是说 test-vllm-storage-claim 这个 PVC 会被一并移除,模型权重不会保留,重新部署时需要再次下载。

主容器与 Deployment:源码级细节

渲染逻辑集中在 templates/deployment.yamltemplates/_helpers.tpl 中,几个关键实现细节:

  1. 镜像与启动命令。主容器镜像为 {{ .Values.image.repository }}:{{ .Values.image.tag }},默认 vllm/vllm-openai:latestimage.repositoryimage.tag 使用 required 强制校验,未定义会渲染失败。仓库 values.yaml 中默认的启动命令为:

    command: ["vllm", "serve", "/data/", "--served-model-name", "opt-125m",
              "--enforce-eager", "--dtype", "bfloat16", "--block-size", "16",
              "--host", "0.0.0.0", "--port", "8000"]
    

    即从 PVC 挂载目录 /data/ 加载模型、以 125M 参数的小模型 opt-125m 为例做演示,并显式指定 --enforce-eager(禁用 CUDA Graph 以便在资源受限环境启动)、bfloat16 精度与 16 的 block size。实际部署时替换为你的模型路径与参数即可。

  2. 模型存储挂载。主容器把 {{ .Release.Name }}-storage 卷(指向 PVC {{ .Release.Name }}-storage-claim)挂载到 /data,与 vllm serve /data/ 形成闭环。

  3. GPU 调度。当 resources.requestsresources.limitsnvidia.com/gpu 均大于 0 时,模板会自动追加 runtimeClassName: nvidia,并生成基于节点标签 nvidia.com/gpu.productnodeAffinity,候选值取自 gpuModels 列表(默认占位符 TYPE_GPU_USED,必须替换成实际卡型,如 A10G/H100 对应的 product 标签值)。这也解释了前置条件中要求安装 NVIDIA Device Plugin——没有插件就没有 nvidia.com/gpu 资源可请求。

  4. 副本数与更新策略replicas 来自 replicaCount(默认 1);deploymentStrategy 未配置时,helpers 中的 chart.strategy 默认使用 rollingUpdate: maxSurge 100% / maxUnavailable 0 的零中断滚动更新,且 Deployment 的 progressDeadlineSeconds 为 1200 秒,为 vLLM 这类大模型容器拉镜像、加载权重的慢启动留出余量。

  5. 环境变量注入。若配置了 configs / secrets / externalConfigs,模板通过 envFrom 引用 {{ .Release.Name }}-configs ConfigMap 与 {{ .Release.Name }}-secrets Secret。这意味着所有 S3 凭据最终都以环境变量形式进入容器(见下一节),也可以借此注入 VLLM_* 系列环境变量给 vLLM 主进程。

模型自动下载机制:Job + 等待 init 容器

这是该 chart 默认开启(extraInit.modelDownload.enabled: true)的核心机制,由两个协作者构成:

下载 Jobtemplates/job.yaml):当 modelDownload.enabled 为真时渲染出名为 {{ .Release.Name }}-init-vllm 的 Job,其容器 job-download-model 使用 aws-cli 镜像(默认 amazon/aws-cli:2.6.4)执行:

aws --endpoint-url $S3_ENDPOINT_URL s3 sync s3://$S3_BUCKET_NAME/$S3_PATH /data

把桶内 s3modelpath 指定的模型目录同步到 PVC 的 /data。Job 的 restartPolicy: OnFailure,完成后 100 秒内自动清理(ttlSecondsAfterFinished: 100),资源请求/上限仅为 200m/500m CPU、1Gi/2Gi 内存——下载任务本身很轻。

等待 init 容器templates/deployment.yaml 第 75–98 行附近):Deployment 的 wait-download-model init 容器在主容器之前运行,通过轮询"干跑"同步结果来阻塞,直到模型文件就绪:

while aws --endpoint-url $S3_ENDPOINT_URL s3 sync --dryrun s3://$S3_BUCKET_NAME/$S3_PATH /data | grep -q download; do sleep 10; done

即:只要 --dryrun 输出中还有 download 条目(说明 /data 里还缺文件),就每 10 秒重试一次。这样主容器启动时模型必然已就位,避免了 vllm serve 因权重缺失而反复崩溃。

凭据如何流转。init 容器与 Job 的环境变量由 helpers 中的 chart.extraInitEnv 统一生成:S3_ENDPOINT_URLS3_BUCKET_NAMEAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 四个变量分别通过 secretKeyRef{{ .Release.Name }}-secrets 中读取 s3endpoints3bucketnames3accesskeyids3accesskey 四个键——这正是安装命令里那四个 --set secrets.* 的落点;S3_PATH 则直接取自 extraInit.s3modelpath。此外,若 extraInit.awsEc2MetadataDisabled 有定义(默认 true),还会注入 AWS_EC2_METADATA_DISABLED,避免在 EKS 之外的云环境(如自建集群、GCP/Azure)上 aws-cli 反复查询 EC2 元数据服务导致启动变慢。注意:一旦显式配置了 waitContainer.envdownloadJob.env,模板会整体替换默认的 S3 变量组,适合改用 Hugging Face 等其它下载方式。

PVC、Service、HPA 与 PDB

  • PVCtemplates/pvc.yaml):只要 extraInit 有值就渲染,容量取自 extraInit.pvcStorage(默认 "1Gi",只够 opt-125m 演示模型;部署 7B 级以上模型务必调大,如 10Gi),访问模式固定为 ReadWriteOnce
  • Servicetemplates/service.yaml):固定 ClusterIP 类型,servicePort(默认 80)映射到容器端口名 container-port(即 containerPort,默认 8000,与 --port 8000 对应)。serviceName 为空时默认命名 {{ .Release.Name }}-service
  • HPAtemplates/hpa.yaml):autoscaling.enabled: true 时渲染 autoscaling/v2 HPA,支持 CPU(targetCPUUtilizationPercentage,默认 80)与内存(targetMemoryUtilizationPercentage,values 中默认注释)两个 Resource 指标,副本数在 minReplicas(默认 1)到 maxReplicas(默认 100)之间伸缩。
  • PDBtemplates/poddisruptionbudget.yaml):maxUnavailable 默认 1,保障节点维护等自愿中断期间的服务可用性。
  • ConfigMap / Secretsconfigs(默认 {})渲染为 {{ .Release.Name }}-configssecrets 渲染为 base64 编码的 Opaque Secret。
  • 自定义资源customObjects 列表中的每一项都会以 Helm 模板语法渲染成独立 K8s 对象,方便追加 Ingress、InferenceService 等任意资源。

values 参数完整说明

以下表格完整收录 Helm 文档values.yaml 的可配置参数:

Key Type Default Description
autoscaling object {"enabled":false,"maxReplicas":100,"minReplicas":1,"targetCPUUtilizationPercentage":80} Autoscaling configuration
autoscaling.enabled bool false Enable autoscaling
autoscaling.maxReplicas int 100 Maximum replicas
autoscaling.minReplicas int 1 Minimum replicas
autoscaling.targetCPUUtilizationPercentage int 80 Target CPU utilization for autoscaling
configs object {} Configmap
containerPort int 8000 Container port
customObjects list [] Custom Objects configuration
deploymentStrategy object {} Deployment strategy configuration
externalConfigs list [] External configuration
extraContainers list [] Additional containers configuration
extraInit object {"modelDownload":{"enabled":true},"initContainers":[],"pvcStorage":"1Gi"} Additional configuration for init containers
extraInit.modelDownload object {"enabled":true} Model download functionality configuration
extraInit.modelDownload.enabled bool true Enable automatic model download job and wait container
extraInit.modelDownload.image object {"repository":"amazon/aws-cli","tag":"2.6.4","pullPolicy":"IfNotPresent"} Image for model download operations
extraInit.modelDownload.waitContainer object {} Wait container configuration (command, args, env)
extraInit.modelDownload.downloadJob object {} Download job configuration (command, args, env)
extraInit.initContainers list [] Custom init containers (appended after model download if enabled)
extraInit.pvcStorage string "1Gi" Storage size for the PVC
extraInit.s3modelpath string "relative_s3_model_path/opt-125m" (Optional) Path of the model on S3
extraInit.awsEc2MetadataDisabled bool true (Optional) Disable AWS EC2 metadata service
extraPorts list [] Additional ports configuration
gpuModels list ["TYPE_GPU_USED"] Type of gpu used
image object {"command":["vllm","serve","/data/","--served-model-name","opt-125m","--host","0.0.0.0","--port","8000"],"repository":"vllm/vllm-openai","tag":"latest"} Image configuration
image.command list ["vllm","serve","/data/","--served-model-name","opt-125m","--host","0.0.0.0","--port","8000"] Container launch command
image.repository string "vllm/vllm-openai" Image repository
image.tag string "latest" Image tag
livenessProbe object {"failureThreshold":3,"httpGet":{"path":"/health","port":8000},"initialDelaySeconds":15,"periodSeconds":10} Liveness probe configuration
livenessProbe.failureThreshold int 3 Number of times after which if a probe fails in a row, Kubernetes considers that the overall check has failed: the container is not alive
livenessProbe.httpGet object {"path":"/health","port":8000} Configuration of the kubelet http request on the server
livenessProbe.httpGet.path string "/health" Path to access on the HTTP server
livenessProbe.httpGet.port int 8000 Name or number of the port to access on the container, on which the server is listening
livenessProbe.initialDelaySeconds int 15 Number of seconds after the container has started before liveness probe is initiated
livenessProbe.periodSeconds int 10 How often (in seconds) to perform the liveness probe
maxUnavailablePodDisruptionBudget string "" Disruption Budget Configuration
readinessProbe object {"failureThreshold":3,"httpGet":{"path":"/health","port":8000},"initialDelaySeconds":5,"periodSeconds":5} Readiness probe configuration
readinessProbe.failureThreshold int 3 Number of times after which if a probe fails in a row, Kubernetes considers that the overall check has failed: the container is not ready
readinessProbe.httpGet object {"path":"/health","port":8000} Configuration of the kubelet http request on the server
readinessProbe.httpGet.path string "/health" Path to access on the HTTP server
readinessProbe.httpGet.port int 8000 Name or number of the port to access on the container, on which the server is listening
readinessProbe.initialDelaySeconds int 5 Number of seconds after the container has started before readiness probe is initiated
readinessProbe.periodSeconds int 5 How often (in seconds) to perform the readiness probe
replicaCount int 1 Number of replicas
resources object {"limits":{"cpu":4,"memory":"16Gi","nvidia.com/gpu":1},"requests":{"cpu":4,"memory":"16Gi","nvidia.com/gpu":1}} Resource configuration
resources.limits."nvidia.com/gpu" int 1 Number of GPUs used
resources.limits.cpu int 4 Number of CPUs
resources.limits.memory string "16Gi" CPU memory configuration
resources.requests."nvidia.com/gpu" int 1 Number of GPUs used
resources.requests.cpu int 4 Number of CPUs
resources.requests.memory string "16Gi" CPU memory configuration
secrets object {} Secrets configuration
serviceName string "" Service name
servicePort int 80 Service port
labels.environment string test Environment name

结合仓库源码补充几点文档表格之外的实现事实:

  • 两个探针(readinessProbe / livenessProbe)整体通过 helpers 中的 chart.probestoYaml 透传,因此可以按 K8s 标准探针语法追加 timeoutSecondssuccessThreshold 等字段;探针对应的是 vLLM OpenAI 兼容服务的 /health 端点。
  • resources.requests.memorycpulimits 对应字段在 helpers 的 chart.resources 中均为 required,缺失会导致渲染直接报错。
  • deployment.yaml 的结构看,chart 还支持 nodeSelectortolerationsimage.securityContext / image.runAsUser 等透传字段(image 未显式给出 securityContext 时,默认 runAsNonRoot: false),便于把 vLLM 钉到带 GPU 污点容忍的专用节点池。
  • chart 附带 values.schema.json 用于 helm 侧的值校验,tests/ 目录下的 deployment_test.yamljob_test.yaml 等基于 chart-testing 的测试文件验证了 Deployment/Job/PVC 等模板的输出契约,可参考其断言来确认自己 values 的渲染结果是否符合预期。

配置示例

示例一:S3 模型下载(默认方式)

将模型存放在 S3 并调整存储配额:

extraInit:
  modelDownload:
    enabled: true
  pvcStorage: "10Gi"
  s3modelpath: "models/llama-7b"

安装命令中通过 --set secrets.s3endpoint / s3bucketname / s3accesskeyid / s3accesskey 提供凭据后,models/llama-7b 目录会在 Pod 启动前同步进 /data。记得把 image.command 里的 --served-model-name 与模型路径改成你的真实模型,并把 gpuModels 换成节点上 nvidia.com/gpu.product 标签的实际取值。

示例二:仅使用自定义 Init 容器(如 llm-d 场景)

当不需要 chart 内置的 S3 下载、而要注入自定义 sidecar/init 容器时:

extraInit:
  modelDownload:
    enabled: false
  initContainers:
    - name: llm-d-routing-proxy
      image: ghcr.io/llm-d/llm-d-routing-sidecar:v0.2.0
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 8080
          name: proxy
      securityContext:
        runAsUser: 1000
      restartPolicy: Always
  pvcStorage: "10Gi"

deployment.yaml 的条件 {{- if and .Values.extraInit (or .Values.extraInit.modelDownload.enabled .Values.extraInit.initContainers) }} 看,只要 modelDownload.enabledinitContainers 任一有值就会渲染 init 容器段;自定义 init 容器追加在 wait-download-model 之后,PVC 依然会创建并挂载,模型可以通过其它方式(镜像自带、节点预置、对象存储挂载卷等)提前写入。

小结

vLLM 仓库自带的 Helm chart 覆盖了 LLM 服务在 K8s 上落地的完整链路:PVC 承载模型权重、aws-cli Job 拉取权重、init 容器轮询等待、GPU 节点亲和调度、健康探针、滚动更新策略与 HPA/PDB。所有可调项都收敛在 values.yaml 中,配合 --set secrets.* 注入凭据即可用一条 helm upgrade --install 完成部署;需要深度定制时,直接阅读 templates 下的对应模板文件就能定位渲染逻辑。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384