通过 Helm 安装
从 v2.2.0 起,可以使用官方 Helm Chart 在 Kubernetes 上部署 GPUStack,并使用集群内 Higress API 网关。
说明
使用 Higress 在 Kubernetes 上部署 GPUStack 目前属于实验性功能。继续之前,请查看限制。
前提条件
| 组件 | 版本 |
|---|---|
| Helm | >= v3.18.4 |
| Kubernetes | >= v1.30.0 |
| GPUStack | >= v2.2.0 |
此外:
- 集群必须配置默认
StorageClass,用于 GPUStack Server 数据卷,k3s 中默认为local-path。也可以设置server.dataVolume.hostPath,使用主机路径卷代替 PVC。 - 对于 GPU Worker,确保节点已安装相应 GPU 驱动和容器工具包,见安装要求;同时安装 Node Feature Discovery(NFD),为 GPU 节点添加标签。
限制
- GPUStack Server 部署为
StatefulSet,目前不支持多副本。 - 默认使用内置的内嵌
PostgreSQL数据库。生产环境建议通过server.externalDatabaseURL指定外部数据库。 - Higress 插件由与 GPUStack 一同安装的专用
gpustack/higress-pluginsDeployment 提供。Higress 网关重启时会从此服务下载插件;如果该服务不可用,网关会等待插件可访问后才能启动。 - 内置
higress-core子 Chart 会将 Higress 部署为集群的 Ingress Controller。如果已有其他 Ingress Controller,请设置higress-core.enabled=false,并将gateway.ingressClassname指向已有 Higress 实例。
安装 k3s(可选)
以下步骤以 k3s 作为 Kubernetes 发行版示例。其他符合 CNCF 标准的发行版,如 RKE2、基于 kubeadm 的集群或托管云 Kubernetes,只要满足上述版本要求,也可以使用。
安装 k3s 时禁用 Traefik,因为将使用 Higress 作为 Ingress Controller。高可用 k3s 集群的配置见 k3s 文档。
验证安装:
使用 Helm 安装 GPUStack
Chart 作为 OCI 产物发布在 Docker Hub 的 oci://registry-1.docker.io/gpustack/gpustack-chart。Chart 版本与 GPUStack 发布版本对应,例如 Chart 2.2.0 包含 GPUStack v2.2.0。
安装最新稳定版本。省略 --version 时,Helm 会自动选择最新稳定 Chart 版本,跳过开发版和预发布版:
如需固定版本,请附加 --version <chart-version>,Chart 版本与 GPUStack 发布版本一致,例如 2.2.0:
默认启用 higress-core 子 Chart,并与 GPUStack 一同部署。如果集群中已安装 Higress,请禁用内置 Higress,并将 GPUStack 指向现有实例:
如需自定义参数,请在安装时使用 --set key=value 或 -f your-values.yaml。见下文 Chart 参数。
从克隆的仓库安装
也可以克隆仓库,从本地 Chart 目录安装,适用于离线环境或需要修改 Chart 的场景:
单独安装 Higress
如果设置 higress-core.enabled=false,请在部署 GPUStack 前安装兼容的 Higress 实例:
确认 IngressClass 可用,并且名称与 gateway.ingressClassname 一致:
Higress 自定义配置见 Higress 文档。
访问 GPUStack
等待 GPUStack Server Pod 就绪:
获取初始管理员密码:
如果未设置 server.ingress.hostname,请从 Ingress 获取 GPUStack UI 地址:
在浏览器中打开该地址,使用用户名 admin 和上面获取的密码登录。
常用配置
启用 Worker DaemonSet
Worker DaemonSet 默认禁用(worker.enabled=false)。启用后,Chart 会生成一个 CPU Worker DaemonSet(<release>-worker),并为 worker.gpuVendors 列出的每个 GPU 厂商生成一个 DaemonSet,名称为 <release>-worker-<vendor>。
支持的 worker.gpuVendors 值:nvidia、mthreads、amd、ascend、hygon、metax、iluvatar、cambricon、thead。
说明
每个 GPU DaemonSet 都会自动获得 Node Feature Discovery 上报的 PCI 设备存在性 nodeSelector 标签,例如 NVIDIA 对应 feature.node.kubernetes.io/pci-10de.present: "true"。集群中必须安装 NFD,否则没有节点包含所需标签,所有 Worker Pod 都会停留在 Pending。
只要列出了至少一个 GPU 厂商,即 worker.gpuVendors 非空,每个 Worker Pod 还会获得必需的 podAntiAffinity(topologyKey=hostname),防止两个 Worker 运行在同一节点上,避免 hostNetwork: true 导致端口冲突。
CPU Worker DaemonSet 通过 nodeSelector 条件 feature.gpustack.ai/acceleratable: "false",覆盖未匹配任何 GPU 厂商的节点。设置 worker.cpuEnabled=false 可让这些节点不运行 Worker,通常适用于控制平面与 GPU 节点位于同一集群、且不应运行 Worker 的场景:
此时,worker.gpuVendors 必须指定至少一个受支持的厂商;否则 Release 不会生成任何 Worker DaemonSet,安装会被拒绝。无论是否启用 CPU Worker,GPU DaemonSet 都保留 -<vendor> 后缀,因此关闭 CPU Worker 不会将任何 GPU DaemonSet 重命名为 <release>-worker。
也可以在安装后,通过界面的 Clusters 和 Workers 页面添加 GPU 集群和 Worker。
使用外部数据库
GPUStack 默认使用内嵌 PostgreSQL 数据库。如需使用外部 PostgreSQL 或 MySQL 数据库,请设置 server.externalDatabaseURL:
使用自定义证书启用 HTTPS
通过 server.ingress.tls 提供 PEM 格式的证书和密钥内容。两者均设置后,Ingress 协议将变为 HTTPS:
从私有镜像仓库拉取镜像
如需从私有镜像仓库拉取所有镜像,包括 GPUStack Server/Worker、higress-plugins 和内置 higress-core gateway/controller/pilot,请覆盖 global.hub。Helm 的全局值传播机制可让一个设置应用于所有镜像:
global.hub 还会作为 GPUSTACK_SYSTEM_DEFAULT_CONTAINER_REGISTRY 传入 GPUStack Server,确保 vLLM、llama.cpp 等推理引擎镜像从相同仓库拉取。
为提供拉取凭据,Chart 可以创建名为 gpustack-image-pull-secret 的 docker-registry Secret,并关联到所有 Pod:
如需引用自己预先创建的 Secret,请替换 global.imagePullSecrets:
Chart 参数
下表列出了最常用的参数。完整权威列表见 Chart 的 values.yaml 和 README。
| 参数 | 默认值 | 说明 |
|---|---|---|
debug | false | 启用调试模式。 |
registrationToken | null | Worker 注册令牌;为 null 时生成随机令牌并复用。 |
clusterDomain | cluster.local | Kubernetes 集群服务域名后缀。 |
global.hub | docker.io | 容器镜像仓库主机;使用私有仓库时覆盖此值。 |
global.imagePullSecrets | [gpustack-image-pull-secret] | 关联到所有 Pod 并传播到子 Chart 的镜像拉取 Secret。 |
global.nodeSelector | {} | 所有组件默认使用的 nodeSelector;可由组件级设置替换。 |
image.repository | gpustack/gpustack | 包含命名空间的镜像仓库;最终引用为 {global.hub}/{repository}:{tag}。 |
image.tag | null | 镜像标签;默认为 Chart 的 appVersion。 |
image.pullPolicy | IfNotPresent | 镜像拉取策略。 |
imagePullSecret.credentials.registry | docker.io | Chart 创建镜像拉取 Secret 时使用的仓库主机。 |
imagePullSecret.credentials.username | null | 仓库用户名;与密码同时设置时创建 Secret。 |
imagePullSecret.credentials.password | null | 仓库密码;与用户名同时设置时创建 Secret。 |
server.ingress.hostname | null | Server 的 Ingress 主机名。 |
server.ingress.tls.cert | null | Ingress TLS 证书(PEM);与密钥同时设置时启用 HTTPS。 |
server.ingress.tls.key | null | Ingress TLS 私钥(PEM)。 |
server.externalDatabaseURL | null | 外部数据库连接字符串(PostgreSQL 或 MySQL)。 |
server.dataVolume.hostPath | null | Server 数据卷的主机路径;使用 hostPath 代替 PVC。 |
server.dataVolume.size | 100Gi | Server 数据卷大小(PVC)。 |
server.apiPort | 30080 | API 服务端口。 |
server.metricsPort | 10161 | Server 指标端口。 |
server.environmentConfig | {} | GPUStack Server 的额外环境变量。 |
server.nodeSelector | {} | Server Pod 的 nodeSelector;非空时替换 global.nodeSelector。 |
gateway.ingressClassname | higress | Higress IngressClass 名称;找到对应项时启用集群内网关模式。 |
higress-core.enabled | true | 部署内置 Higress 网关;若已安装,则禁用。 |
worker.enabled | false | 生成 Worker DaemonSet。 |
worker.gpuVendors | [nvidia] | GPU 厂商;每个厂商对应一个 DaemonSet,此外还有 CPU DaemonSet。 |
worker.cpuEnabled | true | 生成 CPU Worker DaemonSet;设为 false 时必须指定 GPU 厂商。 |
worker.nodeSelector | {} | Worker 的基础 nodeSelector;非空时替换 global.nodeSelector。 |
worker.port | 10150 | Worker 服务端口。 |
worker.metricsPort | 10151 | Worker 指标端口。 |
worker.dataDir | /var/lib/gpustack | 在每个 Worker Pod 内挂载到 /var/lib/gpustack 的主机路径。 |
worker.environmentConfig | {} | GPUStack Worker 的额外环境变量。 |
卸载
Release 部署的不仅是 Server:gpustack-operator 子 Chart 还会部署 Kueue 和 Node Feature Discovery 控制器,Operator 创建的自定义资源带有 finalizer。helm uninstall 会将控制器与其他资源一并移除,因此必须先在控制器仍运行时删除自定义资源,否则这些对象会一直停留在 Terminating,gpustack-system 命名空间也无法完成删除。请按以下顺序操作:
-
在所有控制器仍运行时清理工作负载。Operator 会清除其
Instance对象上的 finalizer;而只要已准入的Workload仍占用ClusterQueue,Kueue 就不会释放该队列,因此必须在停止任何控制器之前完成这些清理。Instance属于命名空间级资源,位于各租户的命名空间中,因此请使用-A列出所有对象。从 Server 删除模型,或直接删除其实例;每个实例的 Pod 会随实例终止,Workload 也会随 Instance 删除。不要一次性删除命名空间内的所有 Pod,否则 Operator、Kueue 和 NFD 控制器也会被关闭,而后续清理需要这些控制器完成:如果 Kueue 与其他应用共用,请勿在此处或第 3 步使用
--all,只删除 GPUStack 的对象。Operator 在 Kueue 中创建的所有对象名称均以gpustack开头,例如clusterqueue/gpustack--…、admissioncheck/gpustack-node-devices。集群级资源只需按名称选择;命名空间级资源还需要附带命名空间,因为-o name不包含命名空间: -
停止 Operator 自身的控制器,但保留 Release,让 Kueue 控制器继续运行,以完成下一步的删除。只要
gpustack-operator-worker和gpustack-operator-device-manager-*DaemonSet 仍在运行,它们就会在您删除LocalQueue、ClusterQueue和gpustack-node-devicesAdmissionCheck 后立即重新创建这些资源,使资源数量始终无法归零: -
按依赖顺序删除 Kueue 资源:先删除
LocalQueue,再删除ClusterQueue、AdmissionCheck,最后删除ResourceFlavor。当使用某对象的资源仍存在时,Kueue 会保留该对象上的kueue.x-k8s.io/resource-in-usefinalizer:只有所有 ClusterQueue 都已删除,gpustack-node-devicesAdmissionCheck 才能完成删除;每个 ClusterQueue 也必须等待其 LocalQueue 和已准入的 Workload 删除。确认每类资源均已清空后,再处理下一类。在共享集群中,请对每条命令应用第 1 步的gpustack名称前缀范围限制,不要使用--all: -
卸载 Release。不要传入
--wait:Node Feature Discovery 的 post-delete prune hook 会阻塞删除等待,超过其--timeout;为退出等待而终止 Helm,会留下没有归属的 prune RBAC 资源。第 5 步会手动移除这些资源,即使未使用--wait,也应执行第 5 步: -
移除
helm uninstall未删除的资源。Helm 从不删除 CRD,Operator 注册的准入 Webhook 和 APIService 也不属于任何 Release。这两类资源都会因 Operator Service 已不存在而拒绝请求;在删除 Webhook 之前,它们还会拒绝下文移除 finalizer 的操作:worker.gpustack.ai组始终由 GPUStack 独占,没有其他组件使用,因此可以直接删除该组的 CRD。 -
删除 Release 遗留的 CRD,仅限此 Release 安装的 CRD。删除 CRD 会删除整个集群中该类型的所有对象;如果集群在安装 GPUStack 前已运行 Kueue、Node Feature Discovery 或 Higress(参见上文
higress-core.enabled),且仍有其他组件使用它们,请保留其 CRD,并跳过对应组的清理。请查询此 Release 拥有的资源,不要凭猜测判断:在默认安装中,该命令会列出 Kueue 的 CRD;如果 Chart 还安装了 NFD 和 Higress,也会列出它们的 CRD:
集群提供方自身的 CRD 不属于 GPUStack,不应删除。例如,k3s 集群中的
*.k3s.cattle.io和helm.cattle.io属于集群自身。 -
(可选) 删除命名空间,同时移除其中的 Higress 对象、引导 ConfigMap、ServiceAccount 和注册令牌 Secret。请了解同时会被删除的数据:命名空间中还包含 Server 的 PVC(
gpustack-data-dir-gpustack-server-0,命名规则为<volumeClaimTemplate>-<statefulset>-<ordinal>),其中保存了 Server 的持久化数据,即包含用户、模型和集群信息的内嵌 PostgreSQL 数据库。在Delete回收策略下(local-path的默认策略),底层卷也会被删除。如需保留数据以便重新安装,请保留命名空间;否则可删除命名空间,如果回收策略未自动移除 PVC,请先删除 PVC: