本部署指南详细介绍了如何在 Google Distributed Cloud (GDC) 气隙环境中,使用开源软件 (OSS) 运行先进的大语言模型 (LLM)。具体而言,本指南介绍了运行最新版 Gemma、DeepSeek 和 Llama 模型所需的所有步骤,同时还介绍了提供其他公开提供的大语言模型的常见程序。我们将利用容器化的服务后端(例如 vLLM 和 Ollama),它们涵盖广泛的功能、不同的配置级别,并且易于部署。
内容摘要
本指南详细介绍了如何在 Google Distributed Cloud (GDC) 隔离环境中部署和运行开源大语言模型 (LLM)。
核心目标和基础设施
- 用途:详细说明如何使用 vLLM 和 Ollama 等优化后端运行前沿 LLM,包括 Gemma 3(多模态)、DeepSeek-R1 和 Llama (3.1/3.2)。
- 最低版本:GDC 网闸隔离配置软件版本 1.15.x*。
- 硬件要求:至少需要 1 个 NVIDIA A100 GPU。建议使用高性能存储空间(500GiB+ PVC),以将模型权重加载时间从 30 分钟缩短到 5 分钟以内。
部署组件
| 组件 | 说明 |
|---|---|
| LLM 后端 | vLLM(使用 PagedAttention 实现高吞吐量服务)和 Ollama(简化本地管理并支持多模态) |
| 模型 | 公开可用的 LLM,包括 Gemma、DeepSeek 和 Llama 系列 |
| 加速器 | 支持完整的 NVIDIA A100 GPU 或 多实例 GPU (MIG) 切片,具体取决于模型的 VRAM 占用空间 |
| GDC 服务 | 使用 GDC 容器服务、负载均衡器 (ELB/ILB)、Harbor Container Registry |
关键操作程序
- 模型管理:LLM 后端会根据使用情况管理模型加载和卸载。vLLM 会将模型固定到内存中,以实现一致的低延迟,而 Ollama 允许动态加载模型,但会在闲置 30 分钟后自动卸载模型。
- 自定义:用户可以从互联网拉取首选 LLM,构建新的 Docker 映像并上传到本地 Harbor 注册表。
前提条件
版本
- GDC 网闸隔离配置 1.15.1 或更高版本。
组件
- 创建的用户集群具有充足的资源(CPU、内存、GPU)。
- 至少需要 1 个 NVIDIA A100 GPU。
- Harbor 实例可用且可访问。
- 已配置
kubectl和gdcloudCLI 以访问用户集群。 - Docker 客户端已安装并配置为推送到 Harbor。
- 已授予必要的 IAM 权限(例如命名空间管理员、集群开发者)。
- 如果使用受限模型,则需要配置 Hugging Face 账号和身份验证。
所需容量
| 资源 | 容量 |
|---|---|
| CPU | 8 个 vCPU |
| RAM 内存 | 32 GiB |
| 临时存储 | 16 Gi |
| GPU | 1 个 NVIDIA A100 GPU |
| 永久性卷 | *500GiB+ |
服务后端需要这些硬件资源才能通过 GPU 加速运行 LLM。例如,一个 a2-ultragpu-1g-gdc 机器类型就可提供足够的资源。
概要图表

此图描绘了一位用户,他正在使用 vLLM 和 Ollama 这两个 LLM 后端公开的 API,以从 Gemma、Llama 和 DeepSeek 等开源模型获取推理响应。根据模型大小(以数十亿参数衡量),每个 LLM 可能需要一个完整的 GPU 或 GPU 的一部分才能运行。
LLM 部署的服务和安全边界示意图
此解决方案依赖于 GDC 网闸隔离配置软件堆栈中已包含的以下服务:
- GDC 容器服务:用于运行所有进程并使用 HPA 扩缩这些进程。
- GDC 负载均衡器:使用 Kubernetes 服务来为该解决方案中的所有后端提供服务,并使客户网络可以访问 LLM,这称为 ELB,代表外部负载均衡器。相反,客户可以选择仅从用户集群内部访问 LLM,这在只有内部代理在其解决方案内部请求推理时可能很有用,这称为 ILB,代表内部负载均衡器。
- GDC CI/CD:Harbor 容器注册表,用于存储 LLM 后端和模型权重。
- GDC 可观测性堆栈:用于收集和搜索后端日志并提供信息中心。
在安全性方面,对 LLM 部署的访问权限取决于哪些用户可以访问公开 LLM 服务后端(在 Kubernetes 项目 / 命名空间中以 pod 形式运行)的负载均衡器服务。

部署
前提条件
在连接到 GDC 网闸隔离配置环境的工作站上安装以下工具:
此文档包含部署 LLM 所需的所有源代码和配置文件。
创建用于从 Harbor 拉取映像的 Secret
如需为 GDC 网闸隔离配置中的容器工作负载配置映像拉取 Secret,您需要创建一个 Kubernetes docker-registry Secret,其中包含用于访问私有 Harbor 项目的凭据。然后,在部署规范中引用此 Secret。
您应使用 Harbor 机器人账号以编程方式访问私有 Harbor 项目中的映像。
请按以下步骤配置映像拉取 Secret:
创建 Harbor 机器人账号:
- 前往 Harbor 实例界面。
- 前往您的 Harbor 项目。
- 选择“机器人账号”标签页。
- 点击 + 新建机器人账号。
- 为其指定名称(例如
oss-llm-puller),并授予其必要的权限(至少是“拉取”访问权限),直到过期时间为止。 - 安全地存储机器人账号名称(例如
robot$oss-llm-puller)和提供的 Secret 令牌。
向 Harbor 验证 Docker 的身份:
在安装了 Docker 且可访问 Harbor 注册表的机器上,使用机器人账号凭据登录:
export INSTANCE_URL="your-harbor-instance-url"
# for example, harbor1-project1.org1.zone1.google.gdc.com
export ROBOT_NAME="your-robot-account-name"
# for example, robot\$oss-llm-puller (note how we escape the $ character)
export ROBOT_SECRET="your-robot-account-secret"
docker login ${INSTANCE_URL} --username ${ROBOT_NAME} --password ${ROBOT_SECRET}
# Sample output:
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your credentials are stored unencrypted in '$HOME/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded
如示例输出所示,此命令会使用身份验证详细信息更新本地 Docker 配置文件 ($HOME/.docker/config.json)。config.json 文件如下所示:
{
"auths": {
"harbor1-project1.org1.zone1.google.gdc.com": {
"auth": "...omitted..."
}
}
}
如果您之前使用 Docker 客户端登录过其他注册中心,您会在“auths”中看到更多条目。
创建 Kubernetes 映像拉取 Secret:
使用 kubectl 在项目命名空间中创建类型为 docker-registry 的 Secret,使用在上一步中更新的 Docker 配置文件:
# Log in to GDC air-gapped using the next commands
gdcloud auth login --login-config-cert {path to your web TLS certificate}
gdcloud clusters get-credentials {Your User Cluster}
kubectl config set-context --current --namespace=NAMESPACE
export SECRET_NAME="oss-llm-pull-secret" # You can choose another name
export NAMESPACE="your-project-namespace"
# Assuming default Docker config path. Adjust if necessary.
export DOCKER_CONFIG_PATH="$HOME/.docker/config.json"
kubectl create secret docker-registry ${SECRET_NAME} \
--from-file=.dockerconfigjson=${DOCKER_CONFIG_PATH} \
-n ${NAMESPACE}
您稍后将在 LLM 后端容器规范中通过添加 imagePullSecrets 字段来引用此 Secret。
按照这些步骤操作后,Kubernetes 集群现在将使用提供的凭据从 GDC 气隙环境中的私有 Harbor 注册表中拉取容器映像。产品文档中也包含这些步骤。
设置 LLM 部署
您可以选择以下 2 种 LLM 后端:
- vLLM
- Ollama
您可以选择其中一个后端,也可以同时部署这两个后端。每个后端都可以运行一个或多个 LLM,例如:
- Gemma 3
- DeepSeek
- Llama
- 其他 LLM
第 1 部分提供了有关如何部署 vLLM 的说明,第 2 部分介绍了如何安装 Ollama。
1. 将 vLLM 部署为 LLM 后端
获取 vLLM Docker 映像
一般来说,vLLM 用于提供从 HuggingFace 下载的模型,正如我们将在本 LLM 部署中展示的那样。部分模型有访问限制,这意味着用户必须明确请求或同意访问 Hugging Face Hub 上的文件和内容,然后才能下载或使用这些文件和内容。
按照文档中的说明,使用 Docker 登录您的 Harbor 实例。在具有互联网访问权限的机器上,拉取 vLLM Docker 映像,然后将其转移到您的 Harbor 项目:
# Pull and Tag vLLM (v0.13.0 recommended for stability)
docker pull vllm/vllm-openai:v0.13.0
docker tag vllm/vllm-openai:v0.13.0 HARBOR_URL/PROJECT/vllm-openai:v0.13.0
docker push HARBOR_URL/PROJECT/vllm-openai:v0.13.0
替换以下内容:
HARBOR_URL:Harbor 实例网址。PROJECT:Harbor 项目名称。
本部署指南使用的 vLLM 版本为:v0.13.0
将 LLM 模型权重存储在 PVC 中
打开新终端,并创建一个用于保存 vLLM 部署文件的文件夹:
mkdir vllm-deployment
cd vllm-deployment
然后,创建一个 YAML 文件(例如 model-pvc.yaml),以使用标准 Kubernetes 原语声明 PersistentVolumeClaim (PVC):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: model-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
storageClassName: standard-rwo
volumeMode: Filesystem
连接到 GDC 网闸隔离配置集群并应用 PVC:
# Log in to GDC air-gapped using the next commands
gdcloud auth login --login-config-cert {path to your web TLS cert}
gdcloud clusters get-credentials {Your User Cluster}
kubectl config set-context --current --namespace=NAMESPACE
# Apply the PVC manifest
kubectl apply -f model-pvc.yaml
从 Hugging Face 下载模型权重:
# Log in to Hugging Face
hf auth login
# Download weights for Gemma 3 (for example, 4B instruction-tuned)
hf download google/gemma-3-4b-it
示例输出:
Fetching 9 files: 100%| 9/9 [00:00<00:00, 19.34it/s]
Downloading (…)7f58a/.gitattributes: 100%| 1.62k/1.62k [00:00<00:00, 7.82MB/s]
Downloading (…)del-00002-of-00002.safetensors: 100%| 3.75G/3.75G [00:46<00:00, 81.3MB/s]
Downloading (…)del-00001-of-00002.safetensors: 100%| 4.90G/4.90G [00:54<00:00, 90.1MB/s]
Downloading (…)-3-4b-it/README.md: 100%| 23.3k/23.3k [00:00<00:00, 48.0MB/s]
Downloading (…)8a/model.safetensors.index.json: 100%| 26.3k/26.3k [00:00<00:00, 39.5MB/s]
Downloading (…)f58a/config.json: 100%| 908/908 [00:00<00:00, 4.41MB/s]
Downloading (…)generation_config.json: 100%| 210/210 [00:00<00:00, 936kB/s]
Downloading (…)tokenizer.json: 100%| 33.1M/33.1M [00:01<00:00, 17.6MB/s]
/Users/rashjab/.cache/huggingface/hub/models--google--gemma-3-4b-it/snapshots/952ec8ffca3adadfd00c6d71b40280ebdbb7f58a
如示例输出中所示,磁盘上的模型占用的存储空间为 8.64 GB,这符合我们之前定义的 500 GiB PVC。请务必确保您选择加载到永久卷 (PV) 中的任何模型都是这种情况,例如,对于 15GB 的模型,使用 500 GiB PVC 可实现 1,500 IOPS,从而将权重加载时间从大约 30 分钟大幅缩短到 5 分钟以内。
通过将模型文件复制到 PV 的卷中来填充 PV。这通常包括:
- 创建用于挂载 PV 的临时“辅助”Pod。
- 使用
kubectl cp将模型文件从工作站复制到辅助 pod 的已挂载卷中。 - 辅助 pod 示例:
helper-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: model-uploader
spec:
containers:
- name: uploader
image: HARBOR_URL/PROJECT/busybox:latest
command: ["sleep", "3600"]
volumeMounts:
- name: model-data
mountPath: /data
imagePullSecrets:
- name: oss-llm-pull-secret
volumes:
- name: model-data
persistentVolumeClaim:
claimName: model-pvc
替换以下内容:
HARBOR_URL:Harbor 实例网址。PROJECT:Harbor 项目名称。oss-llm-pull-secret:如果您选择了其他映像拉取 Secret 名称。model-pvc:替换为您为 PVC 指定的名称。
推送辅助 Docker 映像 (busybox):
docker pull busybox:latest
docker tag busybox HARBOR_URL/PROJECT/busybox:latest
docker push HARBOR_URL/PROJECT/busybox:latest
替换以下内容:
HARBOR_URL:Harbor 实例网址。PROJECT:Harbor 项目名称。
应用 helper-pod.yaml 文件并将模型权重复制到 PV:
kubectl apply -f helper-pod.yaml
# Wait for the pod to be Running
kubectl cp ~/.cache/huggingface/hub/ NAMESPACE/model-uploader:/data/
# After copying, delete the helper pod
kubectl delete pod model-uploader
部署 vLLM 后端
创建部署文件,以便 vLLM 运行模型服务器。以下示例部署了 gemma-3-4b-it 模型。
vllm-gemma-3-4b-it-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gemma-3-4b-it
labels:
app: gemma-3-4b-it
spec:
replicas: 1
selector:
matchLabels:
app: gemma-3-4b-it
template:
metadata:
labels:
app: gemma-3-4b-it
spec:
volumes:
- name: cache-volume
persistentVolumeClaim:
claimName: model-pvc # change with the name you gave initially to your PVC
# vLLM needs to access the host's shared memory for tensor parallel inference.
- name: shm
emptyDir:
medium: Memory
sizeLimit: "16Gi"
containers:
- name: gemma-3-4b-it
image: HARBOR_URL/PROJECT/vllm-openai:v0.13.0
command: ["python3"]
args: [
"-m",
"vllm.entrypoints.openai.api_server",
"--model",
"google/gemma-3-4b-it", # Use the repo ID
"--max-model-len",
"32768",
"--enforce-eager"
]
env:
- name: HF_HUB_OFFLINE
value: "1"
- name: HF_HOME
value: "/model" # Tells vLLM to look for models in /model/hub
# --- PERFORMANCE & STABILITY OPTIMIZATIONS ---
- name: NCCL_P2P_DISABLE
value: "1" # Prevents initialization hangs on P2P checks
- name: NCCL_IB_DISABLE
value: "1" # Prevents initialization hangs on InfiniBand checks
# --- FIPS BYPASS ---
- name: BORINGSSL_FIPS
value: "0"
- name: OPENSSL_FIPS
value: "0"
- name: OPENSSL_CONF
value: "/dev/null"
- name: FIPS_SIG
value: "off"
ports:
- containerPort: 8000
securityContext:
privileged: true
runAsUser: 0
resources:
limits:
nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
cpu: "8" # Increased to handle model weight verification
memory: "64Gi" # Increased to ensure headroom for weight loading
requests:
nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
cpu: "8"
memory: "32Gi"
volumeMounts:
- name: cache-volume
mountPath: /model
- name: shm
mountPath: /dev/shm
imagePullSecrets:
- name: oss-llm-pull-secret
替换以下内容:
HARBOR_URL:Harbor 实例网址。PROJECT:Harbor 项目名称。oss-llm-pull-secret:您在创建映像拉取 Secret 时提供的名称。claimName:您为初始 PVC 创建操作指定的名称。
接下来,创建一个 Kubernetes 服务文件来公开 vLLM 后端 API:
vllm-gemma-3-4b-it-service.yaml
apiVersion: v1
kind: Service
metadata:
name: gemma-3-4b-it
namespace: NAMESPACE
spec:
ports:
- name: http-gemma-3-4b-it
port: 80
protocol: TCP
targetPort: 8000
selector:
app: gemma-3-4b-it
sessionAffinity: None
type: LoadBalancer
应用部署和服务配置:
kubectl apply -f vllm-gemma-3-4b-it-deployment.yaml
kubectl apply -f vllm-gemma-3-4b-it-service.yaml
验证并测试 vLLM 部署
检查 pod 状态:
kubectl get pods等待 pod 处于
Running状态。检查服务:
kubectl get service示例输出:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE # gemma-3-4b-it LoadBalancer 10.201.136.62 136.125.37.198 80:30109/TCP 3d1h记下上一个输出中 vLLM 服务的
EXTERNAL-IP(例如136.125.37.198)。您还可以使用以下方式打印:kubectl get service gemma-3-4b-it \ -o jsonpath='{.status.loadBalancer.ingress[*].ip}'查看日志:
kubectl logs YOUR_VLLM_POD查找指示服务器已启动且模型已加载的消息(例如
INFO: Application startup complete.)。由于没有 Hugging Face 下载,如果文件位于具有高持久卷容量的 PVC 上,则此过程应该很快。使用 curl 测试推理:
验证 vLLM pod 正在运行并获取服务的外部 IP 地址后,您可以使用
curl发送推理请求。由于 vLLM 提供与 OpenAI 兼容的 API,因此您可以使用/v1/chat/completions端点:curl http://EXTERNAL_IP/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "google/gemma-3-4b-it", "messages": [ {"role": "user", "content": "What is Google Distributed Cloud air-gapped?"} ], "max_tokens": 100 }'将
EXTERNAL_IP替换为 vLLM 服务的外部 IP 地址。
2. 将 Ollama 部署为 LLM 后端
Ollama 是一种热门框架,用于在本地和容器化环境中运行开源 LLM。它通过处理权重下载、量化和 GPU 加速来简化模型执行。它包含一个内置 REST API,用于生成补全内容、对话回答和嵌入。
与其他服务引擎不同,Ollama 可动态管理模型执行:
- 动态模型加载:当收到对特定模型的请求时,Ollama 会按需将权重加载到内存(GPU VRAM 或系统 RAM)中。
- 非活动状态卸载:如果模型在 30 分钟内(可通过
OLLAMA_KEEP_ALIVE进行配置)未收到任何推理请求,Ollama 会将其从内存中卸载,以释放硬件资源供其他工作负载使用。 - 每个实例只能有一个有效模型:Ollama 会在每个服务器实例中一次处理一个有效模型的请求。如果并行调用多个模型,Ollama 会将请求排队并按顺序交换模型,这可能会导致延迟。如需同时提供多个模型,而不进行交换,您应为每个模型部署单独的 Ollama 实例。
下载模型权重并创建 Docker 映像
与可以直接从永久性卷加载权重的 vLLM 不同,Ollama 通常要求模型以其内部目录格式 (~/.ollama/models) 存储。
在无法从公共互联网下载模型的隔离环境中,您必须在构建阶段将模型权重预先打包到容器映像本身中。这种方法可确保容器完全自包含,并且在部署后即可立即提供服务,而无需外部网络访问权限。
为 Ollama 部署创建一个文件夹:
mkdir ollama-gemma3
cd ollama-gemma3
创建一个包含以下内容的 Dockerfile:
# Use a standard Linux base image
FROM ubuntu
# Install necessary dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
ca-certificates \
zstd \
&& rm -rf /var/lib/apt/lists/*
# Install Ollama
# This uses Ollama's official installation script, which adds Ollama to /usr/local/bin
RUN curl -fsSL https://ollama.com/install.sh -o install.sh && \
chmod +x install.sh && \
./install.sh && \
rm install.sh
# Set environment variables for Ollama (optional, but a good practice)
# ENV OLLAMA_HOST="0.0.0.0"
# If you want to customize the model storage path within the container, set OLLAMA_MODELS, for example:
# ENV OLLAMA_MODELS="/usr/local/ollama/models"
# The default OLLAMA_MODELS is /root/.ollama
# Then, ensure you create and populate that directory.
# --- Download Gemma 3 model weights ---
# This step starts Ollama server in the background, pulls the model,
# and then kills the server to allow the Docker build to continue.
# This approach works around the Docker RUN command limitations for services.
RUN ollama serve & \
# Give the Ollama server a moment to start up
# Use --retry and --retry-connrefused to handle startup delays
curl --retry 10 --retry-connrefused -s http://localhost:11434 || true && \
# Pull the Gemma 3 model weights
ollama pull gemma3:latest && \
# Stop the background Ollama server process cleanly
pkill ollama || true
# Expose Ollama's default port
EXPOSE 11434
# Command to run Ollama server when the container starts
CMD ["ollama", "serve"]
如果您想尝试其他开源 LLM,例如 Llama 3.2 或 DeepSeek-R1 系列的模型,请修改上一个 Dockerfile 中的此 Ollama 命令:
ollama pull gemma3:latest
例如,如果您想拉取具有 30 亿参数的 Llama 3.2,请使用以下命令:
ollama pull llama3.2:3b
或者,如果您想使用 80 亿参数的 DeepSeek-R1,请使用以下命令:
ollama pull deepseek-r1:8b
您还可以下载多个 LLM,并将其模型权重容器化。这样,当您请求通过不同的预加载模型进行推理时,Ollama 便能够在模型之间切换。例如,您可以将 Gemma 和 Llama 模型都添加到 Docker 映像中。请注意,在无网络连接的环境中,Ollama 后端无法访问 Ollama 库,因此无法随时下载任何模型。
请务必先查看并同意每项模型许可和使用条款,然后再在应用中运行这些模型。Ollama 的库中有许多 LLM。在构建 LLM 后端 Docker 映像时,您只需连接到互联网即可下载模型权重。
构建 Docker 映像并将其推送到 Harbor
按照文档中的说明,使用 Docker 登录您的 Harbor 实例。构建 Gemma 3 Docker 映像并将其上传到您的 Harbor 代码库:
docker build -t ollama-gemma3 .
docker tag ollama-gemma3 HARBOR_URL/PROJECT/ollama-gemma3:latest
docker push HARBOR_URL/PROJECT/ollama-gemma3:latest
替换以下内容:
HARBOR_URL:Harbor 实例网址。PROJECT:Harbor 项目名称。
本部署指南所用的 Ollama 版本:0.14.1
准备 Kubernetes 部署和服务
创建一个名为 ollama-gemma3.yaml 的文件,以定义 Ollama 后端部署及其负载均衡器配置,从而将其公开为服务:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ollama-gemma3
namespace: osd-dev
labels:
app: ollama-gemma3
spec:
replicas: 1
selector:
matchLabels:
app: ollama-gemma3
template:
metadata:
labels:
app: ollama-gemma3
spec:
containers:
- name: ollama-gemma3
image: rashjab-mhs-rashjab-test2.gdc1.us-west6-a.staging.gpcdemolabs.com/rashjab-repo/ollama-gemma3:latest
env:
# This is the crucial fix: Tell Ollama to listen on all network interfaces
- name: OLLAMA_HOST
value: "0.0.0.0"
imagePullPolicy: Always
ports:
- containerPort: 11434
securityContext:
privileged: true
runAsUser: 0
resources:
limits:
nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
requests:
nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
imagePullSecrets:
- name: oss-llm-pull-secret
---
apiVersion: v1
kind: Service
metadata:
name: ollama-gemma3
namespace: osd-dev
spec:
type: LoadBalancer
selector:
app: ollama-gemma3
ports:
- name: ollama-gemma3-port
port: 11434
protocol: TCP
targetPort: 11434
替换以下内容:
HARBOR_URL:Harbor 实例网址。PROJECT:Harbor 项目名称。oss-llm-pull-secret:如果您选择了其他映像拉取 Secret 名称。
验证 GPU 分配
GDC 网闸隔离配置支持 NVIDIA 多实例 GPU (MIG),您可以在公开文档中查看其不同的 MIG 配置文件。如果您要部署小型 LLM,建议检查其大小(以内存为单位),并相应地对 GPU 进行分区。节点池的分区方案在其 Cluster 自定义资源中定义。如需详细了解如何应用 GPU 分区方案,请参阅添加节点池。如果您是应用操作员 (AO),请咨询您的平台管理员 (PA),了解您的项目 / 集群中已安装和可用的加速器。您可以详细了解如何配置容器以使用 GPU 资源以及如何检查 GPU 资源分配。
Gemma 3 4B 模型的默认精度为 16 位。根据 Google 发布的此表格,此 LLM 的 GPU 内存要求为 6.4 GB,使用 BF16(16 位)精度。
在之前的 ollama-gemma3.yaml 中,我们将 10 GB GPU 切片 (NVIDIA A100) 附加到容器,因为此 VRAM 内存量足以加载 Gemma 3 4B 模型并高效运转它,如下所示:
ollama-gemma3.yaml
... omitted ...
resources:
limits:
nvidia.com/mig-1g.10gb-NVIDIA_A100_80GB_PCIE: 1
requests:
nvidia.com/mig-1g.10gb-NVIDIA_A100_80GB_PCIE: 1
... omitted ...
部署 Ollama 后端并将其作为服务公开
连接到集群并将上下文设置为项目命名空间:
# Log in to GDC air-gapped using the next commands
gdcloud auth login --login-config-cert {path to your web TLS certificate}
gdcloud clusters get-credentials {Your User Cluster}
kubectl config set-context --current --namespace=NAMESPACE
应用 Ollama 清单:
kubectl apply -f ollama-gemma3.yaml
确保 Ollama pod 正在运行,并且关联的服务已就位:
kubectl get pods
示例输出:
# NAME READY STATUS RESTARTS AGE
# ollama-gemma3-6fc6fff74b-9qtpf 1/1 Running 0 1h
kubectl get service
示例输出:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# ollama-gemma3 LoadBalancer 172.0.0.1 10.0.0.1 11434:31822/TCP 1d
记下上一个输出中 Ollama 服务的 EXTERNAL-IP(例如 10.0.0.1)。您还可以使用以下方式打印:
kubectl get service ollama-gemma3 \
-o jsonpath='{.status.loadBalancer.ingress[*].ip}'
在检查 Ollama Gemma 3 是否正常运行之前,您需要应用网络政策,例如:
apiVersion: networking.gdc.goog/v1
kind: ProjectNetworkPolicy
metadata:
name: allow-ollama-ingress
namespace: osd-dev
spec:
subject:
subjectType: UserWorkload
policyType: Ingress
ingress:
- from:
- ipBlock:
cidr: 0.0.0.0/0 # Allows traffic from any IP. Restrict this for production.
ports:
- protocol: TCP
port: 11434
应用网络政策:
kubectl apply -f ollama-netpol.yaml
验证并测试 Ollama 部署:
检查 Ollama 是否正在运行:
curl http://EXTERNAL_IP:11434预期响应:“Ollama is running”
发送补全请求:
curl -X POST http://EXTERNAL_IP:11434/v1/completions \ -H "Content-Type: application/json" \ -d '{ "model": "gemma3:latest", "prompt": "Google Distributed Cloud air-gapped is a", "max_tokens": 128, "temperature": 0.90 }'
请求推理
现在,您的 LLM 后端(vLLM 和 Ollama)已部署,并且可以通过各自的 LoadBalancer 服务访问,您可以开始使用它们进行推理了。
根据您的使用场景,您有以下几种选择:
- 交互式 Web 界面:如需进行测试、原型设计或为用户提供类似 ChatGPT 的体验,您可以部署 Open WebUI 或类似的前端。
- 命令行界面 (CLI):如需快速验证、编写脚本或实现自动化,您可以使用
curl或自定义脚本。 - 应用集成:将您的内部应用、AI 代理或 IDE 插件(例如,适用于 VS Code/JetBrains 的 Continue)直接连接到 vLLM (
/v1) 或 Ollama (/v1) 提供的与 OpenAI 兼容的端点。
1. 使用界面与 LLM 互动
如需提供类似 ChatGPT 的界面来与模型互动,请在集群中部署 Open WebUI。
创建 Open WebUI 部署
创建 open-webui-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: open-webui
namespace: osd-dev
labels:
app: open-webui
spec:
replicas: 1
selector:
matchLabels:
app: open-webui
template:
metadata:
labels:
app: open-webui
spec:
containers:
- name: open-webui
image: HARBOR_URL/PROJECT/open-webui:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
env:
- name: OPENAI_API_BASE_URL
value: "http://gemma-3-4b-it/v1" # Point to your vLLM service
- name: OPENAI_API_KEY
value: "EMPTY"
- name: WEBUI_AUTH
value: "False"
imagePullSecrets:
- name: oss-llm-pull-secret
---
apiVersion: v1
kind: Service
metadata:
name: open-webui
namespace: osd-dev
spec:
type: LoadBalancer
selector:
app: open-webui
ports:
- port: 80
targetPort: 8080
应用网络政策
您必须允许您的机器通过端口 80 访问 Open WebUI 服务。
更新您的 PNP 项目网络政策,以包含 open-webui 服务或应用广泛的政策:
apiVersion: networking.gdc.goog/v1
kind: ProjectNetworkPolicy
metadata:
name: allow-webui-ingress
namespace: NAMESPACE
spec:
subject:
subjectType: UserWorkload
policyType: Ingress
ingress:
- from:
- ipBlock:
cidr: 0.0.0.0/0 # Allows traffic from any IP then restrict this for production
ports:
- protocol: TCP
port: 8080
验证
获取 Web 界面 IP:
kubectl get service open-webui -n NAMESPACE访问界面:打开浏览器,然后前往
http://WEB_UI_EXTERNAL_IP配置:首次登录时,创建管理员账号。在设置中,确保 OpenAI 连接指向
http://gemma-3-4b-it/v1选择模型:在对话界面中,从模型下拉菜单中选择
google/gemma-3-4b-it。
2. 使用 CLI 发出 HTTP 请求
- curl:
curl -X POST http://OLLAMA_LOAD_BALANCER_IP:11434/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gemma3:latest",
"prompt": "Google Distributed Cloud air-gapped is a",
"max_tokens": 128,
"temperature": 0.90
}'
验证与确认
检查所有容器和服务是否都在运行:
# Log in to GDC air-gapped using the next commands
gdcloud auth login --login-config-cert {path to your web TLS cert}
gdcloud clusters get-credentials {Your User Cluster}
kubectl config set-context --current --namespace=NAMESPACE
# Pods
kubectl get pods # This command should return results like below
# NAME READY STATUS RESTARTS AGE
# vllm-6fc6fff74b-9qtpf 1/1 Running 0 1h
# ollama-798fbf6ff6-9m7ln 1/1 Running 0 1h
# Services
kubectl get services # This command should return results like below
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# vllm-service LoadBalancer 172.0.0.1 10.0.0.1 11434:31822/TCP 1h
# ollama-service LoadBalancer 172.0.0.2 10.0.0.2 11434:30728/TCP 1h
移除步骤
移除所有 Kubernetes 资源:
kubectl delete -f vllm-gemma-3-4b-it-deployment.yaml kubectl delete -f vllm-gemma-3-4b-it-service.yaml从 Harbor 代码库中手动删除未使用的容器。
操作
vLLM 后端
vLLM 基础知识
vLLM 旨在成为高性能的单模型服务引擎。它不支持在单个服务器进程中提供多个模型,也不支持在单个启动命令中定义多个模型。如需提供多个模型(例如聊天模型和单独的嵌入模型),您必须启动单独的 vLLM 实例,每个实例位于自己的 pod 或容器中,可以选择分配给不同的 GPU 或 GPU 切片。与其他可能会动态交换模型的后端不同,vLLM 实例会在初始化时固定其模型和关联的 KV 缓存内存,以确保始终实现高吞吐量和低延迟。
您可以使用以下命令在任何 vLLM pod 上打开终端:
kubectl exec -it gemma-3-4b-random-string -n NAMESPACE -- /bin/bash
这会显示哪些模型已加载、它们的实参和 PID:
ps aux | grep vllm
预期类似输出:
root 1 0.1 0.8 9436960 1550504 ? Ssl Feb04 9:18 python3 -m vllm.entrypoints.openai.api_server --model google/gemma-3-4b-it --max-model-len 32768 --enforce-eager
root 504 0.0 0.0 3476 1596 pts/0 S+ 02:48 0:00 grep --color=auto vllm
如果您想要更简洁、更“Ollama 式”的视图,而不想看到 grep 命令本身和系统 PID 的杂乱信息,可以使用以下单行命令:
ps aux | grep [v]llm.entrypoints | awk -F'--model ' '{print $2}' | awk '{print $1}'
示例回答:
google/gemma-3-4b-it
您可以使用标准 kubectl 命令并通过查询内部 API 端点来监控 vLLM 部署的状态。
检查 Pod 日志
打开终端以查看初始化日志和服务日志:
kubectl logs -f gemma-3-4b-it-random_string -n NAMESPACE
查找服务器已准备就绪的确认信息:
(APIServer pid=1) INFO: Started server process [1]
(APIServer pid=1) INFO: Waiting for application startup.
(APIServer pid=1) INFO: Application startup complete.
查询内部状态
由于 vLLM 提供与 OpenAI 兼容的 API,因此您可以直接从集群内的终端(例如使用 debug-sh pod)验证已加载的模型和系统健康状况。
您需要先启动调试 pod,以下是相关说明:
启动调试 Pod
运行以下命令,在项目命名空间中启动临时 shell。此配置使用之前推送到 Harbor 注册表的 busybox 映像,并通过 --overrides 标志注入必要的凭据:
kubectl run --rm -it debug-sh \
--image=HARBOR_URL/PROJECT/busybox:latest \
--restart=Never -n osd-dev --overrides='{
"spec": {
"imagePullSecrets": [{"name": "oss-llm-pull-secret"}]
}
}' -- sh
主要参数:
--rm:在退出时自动删除 pod,从而保留集群资源。--overrides:在气隙环境中是必需的,用于允许 pod 向私有 Harbor 注册表进行身份验证。
查询模型服务器状态
进入 pod 后,使用 wget 实用程序查询 vLLM API。由于 vLLM 服务将内部端口 8000 映射到端口 80,因此您可以使用该服务的 DNS 名称:
列出已加载的模型:验证 vLLM 引擎是否已成功初始化并加载 Gemma 3 权重。
wget -qO- http://gemma-3-4b-it/v1/models成功响应:
{"object":"list","data":[{"id":"google/gemma-3-4b-it"}]}检查应用健康状况:确认 API 服务器已准备好处理请求。
wget -qO- http://gemma-3-4b-it/health成功响应:
OK
Ollama 基础知识
Ollama 不支持同时将多个模型加载到内存中。此外,如果您在一段时间内(默认情况下通常为 30 分钟)未使用 LLM,Ollama 会从内存中卸载当前模型。
由于上述行为,该解决方案会根据您的需求和使用情形实现两个或更多 Ollama 后端,以便许多开发者或用户可以并行使用它们,而不会出现只有一个 Ollama 实例频繁加载和卸载模型,从而产生不必要的延迟。
您可以使用以下命令在任何 Ollama pod 上打开终端:
kubectl exec -it ollama-chat-random_string -- sh
kubectl exec -it ollama-autocomplete-random_string -- sh
在 pod 内,您可以使用 Ollama CLI 探索可用的模型,并查看已加载的模型:
在 ollama-chat pod 中,您会找到一个模型:
# ollama list NAME ID SIZE MODIFIED codegemma:7b-instruct 0c96700aaada 5.0 GB 2 hours ago # ollama ps NAME ID SIZE PROCESSOR UNTIL codegemma:7b-instruct 0c96700aaada 10 GB 100% GPU 4 minutes from now在 ollama-autocomplete pod 中,您会找到两个模型:
# ollama list NAME ID SIZE MODIFIED codegemma:2b 926331004170 1.6 GB 2 hours ago codegemma:7b-code aee9a63c13b9 5.0 GB 2 hours ago # ollama ps NAME ID SIZE PROCESSOR UNTIL codegemma:7b-code aee9a63c13b9 7.1 GB 100% GPU 4 minutes from now当 Ollama 卸载其当前模型时,输出为空:
# ollama ps NAME ID SIZE PROCESSOR UNTIL
请注意,当您发送下一个代码辅助请求时,Ollama 会动态加载模型,无需任何手动干预。
GPU 容量的重要性
如果您预配了 10GB 的 GPU 切片,但模型内存占用空间(略)大于该值,您会发现部分 LLM 加载到了 CPU 上,如下所示:
# ollama ps
NAME ID SIZE PROCESSOR UNTIL
codegemma:7b-instruct 0c96700aaada 10 GB 6%/94% CPU/GPU 29 minutes from now
这并非最佳做法,会导致响应延迟时间更长,因此请务必提供本指南中建议的 GPU 大小。
LLM
通过 vLLM 引入其他 LLM 或您偏好的 LLM
如需在 GDC 网闸隔离配置环境中通过 vLLM 运行不同大小的 Gemma 或任何其他开源大语言模型 (LLM),例如 DeepSeek-R1 或 Llama 3.1,您必须将新模型权重注入到您的环境中,并更新部署清单以指向新资源。
根据为此解决方案建立的操作程序,按照以下步骤加载其他模型:
下载新的模型权重:
在可访问互联网的工作站上,使用 Hugging Face CLI 下载所需模型的权重。
- 对于 Gemma 3 (3-12b-it):
hf download google/gemma-3-12b-it- 对于 DeepSeek-R1(7B Distill):
hf download deepseek-ai/DeepSeek-R1-Distill-Qwen-7B- 对于 Llama 3.1 (8B):
hf download meta-llama/Meta-Llama-3.1-8B-Instruct注意:请确保您已在 Hugging Face 上接受模型的许可条款,然后再下载。
填充永久性卷 (PVC):
更新现有
model-pvc或创建一个容量足以支持新模型的新 。使用辅助 Pod 方法从工作站转移权重。 较大的设备规格需要更多的磁盘空间。确保您的 Persistent Volume Claim (PVC) 有足够的容量来存储新的权重。- Gemma 3 4B:约 15.2 GB。
- Gemma 3 27B:约 54 GB 以上。
- 建议:无论模型大小如何,都应保持 500GiB PVC 建议,以确保高 IOPS (1,500),从而加快加载速度。
# Copy the new model's hub directory to the helper pod kubectl cp ~/.cache/huggingface/hub/ osd-dev/model-uploader:/data/更新 vLLM 部署清单:
修改 vLLM 部署 YAML 以引用新的模型 ID。与可以动态交换模型的 Ollama 不同,vLLM 实例专用于单个模型,必须更新或重新部署才能更改模型。
根据您使用的模型(此处以 deepseek 为例)更新部署的 args 部分:
args: [ "-m", "vllm.entrypoints.openai.api_server", "--model", "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B", # Update to new Repo ID "--max-model-len", "32768", "--enforce-eager" # Recommended for GDC stability ]调整 GPU 和内存资源:
较大的模型需要更多 VRAM 来存储权重和 KV 缓存。如果您从 4B 模型改用 8B 或 14B 模型,请确保资源限制足够,以免发生“内存不足”崩溃。
- VRAM 占用空间:在 16 位精度下,一个 80 亿参数的模型仅权重就需要大约 16 GB 的 VRAM,再加上 vLLM
PagedAttention缓存所需的额外内存。 - 建议:对于参数超过 70 亿的模型,请使用完整的 A100 GPU (
nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1),以确保最佳性能并为 KV 缓存留出充足的内存空间。
- VRAM 占用空间:在 16 位精度下,一个 80 亿参数的模型仅权重就需要大约 16 GB 的 VRAM,再加上 vLLM
验证新模型:
部署完成协调后,请使用内部 API 验证新模型是否处于有效状态:
# Inside a debug-sh pod wget -qO- http://gemma-3-4b-it/v1/models成功响应:
{"object":"list","data":[{"id":"deepseek-ai/DeepSeek-R1-Distill-Qwen-7B"}]}
使用 Ollama 引入其他 LLM
如果您想尝试其他开源 LLM,例如 Llama 3.2 或 DeepSeek-R1 系列的模型,请修改上一个 Dockerfile 中的以下 Ollama 命令:
ollama pull gemma3:latest
例如,如果您想拉取具有 30 亿参数的 Llama 3.2,请使用以下命令:
ollama pull llama3.2:3b
或者,如果您想使用 80 亿参数的 DeepSeek-R1,请使用以下命令:
ollama pull deepseek-r1:8b
您还可以下载多个 LLM,并将其模型权重容器化。这样,当您请求通过不同的预加载模型进行推理时,Ollama 便能够在模型之间切换。例如,您可以将 Gemma 和 Llama 模型都添加到 Docker 映像中。请注意,在无网络连接的环境中,Ollama 后端无法访问 Ollama 库,因此无法随时下载任何模型。
请务必先查看并同意每项模型许可和使用条款,然后再在应用中运行这些模型。Ollama 的库中有许多 LLM。在构建 LLM 后端 Docker 映像时,您只需连接到互联网即可下载模型权重。
Open WebUI
检查 Open WebUI pod 是否处于运行状态:
kubectl get pods -n NAMESPACE
预期输出:
NAME READY STATUS RESTARTS AGE
open-webui-69df4664d-przjl 1/1 Running 0 6d3h
检查服务 IP:
kubectl get service -n NAMESPACE
预期输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
open-webui LoadBalancer 10.201.137.164 136.125.37.224 80:30492/TCP 6d3h
以下部分介绍了如何使用主要界面功能。

使用 Ollama 后端扩缩解决方案
垂直
- 为已成为瓶颈的 LLM 分配更大的 GPU 切片,直到使用完整的 GPU。
- 如果您想使用更大的 LLM 来提高回答准确性,例如使用 4,050 亿参数的 LLM 而不是 70 亿参数的 LLM,则可能需要多个 GPU 才能顺畅运行。
- 如果模型适合多个 GPU,则会因 GPU 间通信而产生一些延迟时间。
横向
- 根据需要在给定 LLM 上部署尽可能多的 Ollama pod,以实现目标吞吐量。
- 为此,请增加相应 Ollama 部署 YAML 文件中的 replica 数量。
- Kubernetes 服务(类型为 LoadBalancer)将在端点(即 pod)之间分配代码辅助请求,并通过公开的外部 IP 返回各自的响应。
- 请注意,Continue 插件的每个功能仅指向一个 IP 地址。

如需在 GDC 气隙环境中扩缩 vLLM 后端,您可以遵循与 Ollama 类似的策略,同时侧重于硬件资源分配和 pod 复制。
使用 vLLM 后端扩缩解决方案
垂直
- 升级 GPU 分配:如果推理吞吐量(令牌/秒)成为瓶颈,请分配更大的 GPU 切片,直到使用完整的 NVIDIA A100 GPU。
- 多 GPU 配置:对于无法放入单个 80GB A100 内存中的大型模型(例如,参数数量为 700 亿到 4050 亿),您必须使用张量并行处理扩展到多个 GPU。
- 延迟时间注意事项:请注意,跨多个 GPU 的模型可能会因 GPU 间通信(例如 NCCL 同步)而产生轻微的开销。
横向
- 通过副本提高吞吐量:如需处理针对同一模型的更多并发用户请求,请增加 vLLM 部署 YAML 中的
replicas数量。 - 专用模型实例:由于 vLLM 被设计为单模型服务引擎,并在初始化时固定其 KV 缓存内存,因此您必须为要托管的每个不同的 LLM 部署一组单独的 pod。
- 负载均衡:GDC Kubernetes 服务(类型为
LoadBalancer)会自动将传入的推理请求分配给与该服务关联的所有运行正常的 vLLM pod 端点。
问题排查
| 错误 | 缓解 |
|---|---|
| FIPS 自检失败 | 当 BoringSSL 等库缺少完整性签名时,会发生此错误。通过设置 BORINGSSL_FIPS=0 并利用官方 vLLM 映像来修复 |
| 权重加载停滞 | 检查小型 PVC 是否存在 IOPS 限制。性能模型初始化需要 500GiB 的卷。 |
| 连接遭拒 | 确认 PNP 明确允许 targetPort (8000/8080)。GDC 防火墙不会自动授予对负载均衡器 VIP 的后端端口的访问权限。 |