本部署指南提供詳細說明,介紹如何在 Google Distributed Cloud (GDC) 實體隔離環境中,使用開放原始碼軟體 (OSS) 執行最先進的大型語言模型 (LLM)。具體來說,本指南會介紹執行最新版 Gemma、DeepSeek 和 Llama 模型的所有必要步驟,同時說明提供其他公開 LLM 服務的常見程序。我們將運用容器化服務後端 (例如 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 系列 |
| 加速器 | 視模型 VRAM 占用空間而定,支援完整的 NVIDIA A100 GPU 或 多執行個體 GPU (MIG) 切片 |
| GDC 服務 | 使用 GDC Container Service、Load Balancer (ELB/ILB)、Harbor Container Registry |
重要作業程序
- 模型管理:LLM 後端會根據用量管理模型的載入和卸載作業。vLLM 會將模型固定在記憶體中,確保延遲時間一致且較短,而 Ollama 則允許動態載入模型,但閒置 30 分鐘後會自動卸載模型。
- 自訂:使用者可以從網際網路提取偏好的 LLM、建構新的 Docker 映像檔,並上傳至本機 Harbor 登錄檔,藉此使用偏好的 LLM。
必要條件
版本
- 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 才能執行。
LLM 部署作業的服務和安全邊界圖表
這項解決方案會使用 GDC 氣隙軟體堆疊中已包含的下列服務:
- GDC 容器服務:執行所有程序,並使用 HPA 調整程序規模。
- GDC 負載平衡器:使用 Kubernetes 服務,為這個解決方案中的所有後端提供服務,並讓客戶網路存取 LLM,這稱為 ELB,代表外部負載平衡器。反之,客戶也可以選擇只允許從使用者叢集內部連線至 LLM,這在只有內部代理程式在解決方案內要求推論時可能很有用,這稱為 ILB,代表內部負載平衡器。
- GDC CI/CD:使用 Harbor Container Registry 儲存 LLM 後端和模型權重。
- GDC Observability Stack:收集及搜尋後端記錄,並提供資訊主頁。
就安全性而言,存取 LLM 部署作業的權限取決於哪些使用者可以連線至負載平衡器服務,該服務會公開 LLM 服務後端,這些後端會以 Pod 形式在 Kubernetes 專案 / 命名空間中執行。

部署作業
必要條件
在連線至 GDC 氣隙環境的工作站上,安裝下列工具:
這份文件包含部署 LLM 所需的所有原始碼和設定檔。
建立密鑰,從 Harbor 提取映像檔
如要在 GDC 實體隔離方案中為容器工作負載設定映像檔提取密碼,您需要建立 Kubernetes docker-registry Secret,其中包含存取私人 Harbor 專案的憑證。然後在部署規格中參照這個密碼。
如要以程式輔助方式存取私人 Harbor 專案中的映像檔,請使用 Harbor 機器人帳戶。
請按照下列步驟設定映像檔提取密鑰:
建立 Harbor 機器人帳戶:
- 前往 Harbor 執行個體 UI。
- 前往 Harbor 專案。
- 選取「機器人帳戶」分頁標籤。
- 按一下「+ NEW ROBOT ACCOUNT」(新增機器人帳戶)。
- 為該權杖命名 (例如
oss-llm-puller),並授予必要權限 (至少要有「pull」存取權),直到權杖到期為止。 - 請妥善保管機器人帳戶名稱 (例如
robot$oss-llm-puller) 和系統提供的密碼權杖。
向 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 映像檔提取密鑰:
使用 kubectl 在專案命名空間中建立 docker-registry 類型的密鑰,並使用上一步更新的 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 欄位來參照這項密鑰。
完成這些步驟後,Kubernetes 叢集就會使用提供的憑證,從 GDC 無網路環境中的私人 Harbor 登錄檔提取容器映像檔。產品說明文件也包含這些步驟。
設定 LLM 部署作業
您可以選擇下列兩種 LLM 後端:
- vLLM
- Ollama
您可以選擇其中一個,或同時部署兩個後端。每個後端都可以執行一或多個 LLM,例如:
- Gemma 3
- DeepSeek
- Llama
- 其他 LLM
第 1 節會說明如何部署 vLLM,第 2 節則會說明如何安裝 Ollama。
1. 將 vLLM 部署為 LLM 後端
取得 vLLM Docker 映像檔
一般來說,vLLM 用於提供從 Hugging Face 下載的模型,我們將在本 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 基本類型宣告 Persistent Volume Claim (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) 的任何模型都是如此。舉例來說,使用 500 GiB PVC 載入 15 GB 模型,可達到 1,500 IOPS,大幅縮短權重載入時間,從約 30 分鐘縮短至 5 分鐘以下。
將模型檔案複製到 PV 的磁碟區,即可填入 PV。這通常包括:
- 建立暫時的「輔助」Pod,掛接 PV。
- 使用
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:如果您選擇了其他映像檔提取密鑰名稱。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:您在建立映像檔提取密鑰時指定的名稱。claimName:您在初始 PVC 建立作業中指定的名稱。
接著,建立 Kubernetes Service 檔案,公開 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 部署作業
檢查廣告連播狀態:
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 正在執行,且您擁有 Service 的外部 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 映像檔
與可直接從 PersistentVolume 載入權重的 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
舉例來說,如要提取 Llama 3.2 (30 億個參數),請使用下列指令:
ollama pull llama3.2:3b
或者,如要使用 80 億參數的 DeepSeek-R1,請使用下列指令:
ollama pull deepseek-r1:8b
您也可以下載多個 LLM,並將其模型權重裝入容器。這樣一來,當您要求以不同預先載入的模型進行推論時,Ollama 就能在模型之間切換。舉例來說,您可以在 Docker 映像檔中同時加入 Gemma 和 Llama 模型。請注意,在無網路連線的環境中,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:如果您選擇了其他映像檔提取密鑰名稱。
驗證 GPU 分配
GDC 實體隔離方案支援 NVIDIA 多重執行個體 GPU (MIG),您可以在公開文件中查看不同的 MIG 設定檔。 如果您要部署小型 LLM,建議檢查其大小 (以記憶體為單位),並據此分割 GPU。節點集區的分割區配置是在其 Cluster 自訂資源中定義。如要進一步瞭解如何套用 GPU 分割配置,請參閱「新增節點集區」。如果您是應用程式操作人員 (AO),請諮詢您的平台管理員 (PA),瞭解專案 / 叢集中已安裝和可用的加速器。如要進一步瞭解如何設定容器使用 GPU 資源,以及如何檢查 GPU 資源分配情形,請參閱這篇文章。
Gemma 3 4B 模型的預設精確度為 16 位元。根據 Google 發布的這份表格,使用 BF16 (16 位元) 精確度時,這個大型語言模型的 GPU 記憶體需求為 6.4 GB。
在先前的 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」(Ollama 正在執行)
傳送完成要求:
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 服務存取,您可以開始使用這些後端進行推論。
視用途而定,您有幾種做法:
- 互動式網頁 UI:如要測試、製作原型,或為使用者提供類似 ChatGPT 的體驗,可以部署 Open WebUI 或類似的前端。
- 指令列介面 (CLI):如要快速驗證、編寫指令碼或自動化,可以使用
curl或自訂指令碼。 - 應用程式整合:將內部應用程式、AI 代理程式或 IDE 外掛程式 (例如 VS Code/JetBrains 的 Continue) 直接連線至 vLLM (
/v1) 或 Ollama (/v1) 提供的 OpenAI 相容端點。
1. 透過 UI 與 LLM 互動
如要提供類似 ChatGPT 的介面,與模型互動,請在叢集中部署 Open WebUI。
建立 Open WebUI Deployment
建立 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
驗證
取得 WebUI 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,操作說明如下:
啟動 Debug Pod
執行下列指令,在專案命名空間中啟動暫時性殼層。這項設定會使用 busybox 映像檔 (先前已推送至 Harbor 登錄檔),並透過 --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 不支援同時將多個模型載入記憶體。此外,如果一段時間未使用 LLM (預設為 30 分鐘),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 nowOllama 卸載目前模型時,輸出內容會空白:
# ollama ps NAME ID SIZE PROCESSOR UNTIL
請注意,當您傳送下一個程式碼輔助要求時,Ollama 會動態載入模型,無須任何手動介入。
GPU 容量的重要性
如果您配置 10 GB 的 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 大小。
大型語言模型
透過 vLLM 導入其他或偏好的 LLM
如要在 GDC air-gapped 上使用 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 方法,從工作站轉移權重。較大的外型規格需要更多磁碟空間。請確認您的永久磁碟區聲明 (PVC) 有足夠容量,可儲存新的權重。- Gemma 3 4B:約 15.2 GB。
- Gemma 3 27B:約 54 GB 以上。
- 建議:維持 500 GiB 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 Deployment 資訊清單:
修改 vLLM 部署 YAML,參照新的模型 ID。與可動態交換模型的 Ollama 不同,vLLM 執行個體專用於單一模型,必須更新或重新部署才能變更模型。
根據您使用的模型更新部署的 args 區段,以下以 deepseek 為例:
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 和記憶體資源:
模型越大,權重和 KV 快取所需的 VRAM 就越多。如果從 4B 模型改用 8B 或 14B 模型,請確保資源限制足夠,以免發生「記憶體不足」當機問題。
- VRAM 占用空間:在 16 位元精確度下,80 億參數模型光是權重就需要約 16 GB,加上 vLLM
PagedAttention快取,還需要額外記憶體。 - 建議:對於參數超過 70 億的模型,請使用完整的 A100 GPU (
nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1),確保 KV 快取有足夠的空間,並發揮最佳效能。
- VRAM 占用空間:在 16 位元精確度下,80 億參數模型光是權重就需要約 16 GB,加上 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
舉例來說,如要提取 Llama 3.2 (30 億個參數),請使用下列指令:
ollama pull llama3.2:3b
或者,如要使用 80 億參數的 DeepSeek-R1,請使用下列指令:
ollama pull deepseek-r1:8b
您也可以下載多個 LLM,並將其模型權重裝入容器。這樣一來,當您要求以不同預先載入的模型進行推論時,Ollama 就能在模型之間切換。舉例來說,您可以在 Docker 映像檔中同時加入 Gemma 和 Llama 模型。請注意,在無網路連線的環境中,Ollama 後端無法存取 Ollama 程式庫,因此無法隨時下載任何模型。
請務必先查看並同意各模型授權和使用條款,再於應用程式中執行模型。Ollama 的程式庫中有很多 LLM。建構 LLM 後端 Docker 映像檔時,只需要連上網際網路下載模型權重。
開啟 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
以下各節說明如何使用主要 UI 功能。

使用 Ollama 後端擴充解決方案
垂直
- 為成為瓶頸的 LLM 分配較大的 GPU 區塊,直到您使用完整的 GPU 為止。
- 如要使用較大的 LLM (例如 405B 參數 LLM,而非 7B 參數 LLM) 提升回覆準確度,可能需要多個 GPU 才能順利執行。
- 如果模型適用於多個 GPU,則會因 GPU 間的通訊而產生延遲。
水平
- 視需要部署任意數量的 Ollama Pod,在特定 LLM 上達到目標處理量。
- 如要達成這個目標,請在對應的 Ollama 部署 YAML 檔案中增加 replica 數量。
- Kubernetes 服務 (LoadBalancer 類型) 會在端點 (即 Pod) 之間分配程式碼輔助要求,並透過公開的外部 IP 傳回各自的回應。
- 請注意,Continue 外掛程式的每個功能只會指向一個 IP 位址。

如要在 GDC vLLM 後端中擴充 air-gapped 環境,可以採用類似 Ollama 的策略,著重於硬體資源分配和 Pod 複製。
使用 vLLM 後端擴充解決方案
垂直
- 升級 GPU 分配:如果推論處理量 (權杖/秒) 成為瓶頸,請分配較大的 GPU 區塊,直到使用完整的 NVIDIA A100 GPU 為止。
- 多 GPU 設定:對於無法容納在單一 80 GB A100 記憶體中的大型模型 (例如 700 億到 4050 億個參數),您必須使用張量平行處理技術,擴充至多個 GPU。
- 延遲考量:請注意,跨越多個 GPU 的模型可能會因 GPU 間通訊 (例如 NCCL 同步) 而產生輕微的額外負擔。
水平
- 透過副本提高輸送量:如要處理相同模型的大量並行使用者要求,請在 vLLM 部署 YAML 中增加
replicas計數。 - 專屬模型執行個體:vLLM 是設計為單一模型服務引擎,且會在初始化時釘選 KV 快取記憶體,因此您必須為要代管的每個不同 LLM 部署一組獨立的 Pod。
- 負載平衡:GDC Kubernetes 服務 (類型
LoadBalancer) 會自動將傳入的推論要求,分配給與該服務相關聯的所有正常 vLLM Pod 端點。
疑難排解
| 錯誤 | 緩解措施 |
|---|---|
| FIPS SELFTEST FAILURE | 如果 BoringSSL 等程式庫缺少完整性簽章,就會發生這種情況。如要修正這個問題,請設定 BORINGSSL_FIPS=0,並使用官方 vLLM 映像檔 |
| 體重載入停滯 | 檢查小型 PVC 是否有 IOPS 節流。初始化效能模型時,需要 500 GiB 的磁碟區。 |
| 連線遭拒 | 確認 PNP 明確允許 targetPort (8000/8080)。GDC 防火牆不會自動授予 Load Balancer VIP 後端通訊埠的存取權。 |