Ringkasan
Dokumen ini memberikan petunjuk langkah demi langkah untuk men-deploy Model Bahasa Besar (LLM) open weight seperti Gemma, Llama, dan DeepSeek di lingkungan air-gapped Google Distributed Cloud (GDC). Codelab ini membahas penggunaan vLLM untuk penyajian dengan throughput tinggi dan Ollama untuk kemudahan penggunaan, dengan memanfaatkan kemampuan platform GDC, termasuk Kubernetes, Harbor, dan resource GPU.
Arsitektur
Solusinya melibatkan deployment backend penyajian LLM dalam container (vLLM, Ollama) sebagai Deployment dalam cluster pengguna. Bobot model disimpan di Persistent Volumes, yang diisi dari image di registry Harbor. Layanan Kubernetes jenis LoadBalancer mengekspos API backend. Kebijakan jaringan project mengamankan akses ke layanan ini.

Sebelum memulai
Pastikan prasyarat berikut terpenuhi:
- GDC dengan air gap versi 1.15.1 atau yang lebih tinggi.
- Cluster pengguna dibuat dengan resource yang memadai (CPU, Memori, GPU).
- Minimal diperlukan 1 GPU NVIDIA A100.
- Instance Harbor tersedia dan dapat diakses.
- CLI
kubectldangdcloudyang dikonfigurasi untuk mengakses cluster pengguna. - Klien Docker diinstal dan dikonfigurasi untuk mengirim ke Harbor.
- Izin IAM yang diperlukan telah diberikan (misalnya, Namespace Admin, Cluster Developer**).
- Akun dan autentikasi Hugging Face dikonfigurasi jika menggunakan model yang dibatasi.
Bagian 1: Penyiapan umum
1.1 Buat secret penarikan gambar
Untuk mengonfigurasi secret penarikan image untuk workload container di GDC dengan air gap, Anda perlu membuat secret docker-registry Kubernetes yang berisi kredensial untuk mengakses project Harbor pribadi Anda. Secret ini kemudian dirujuk dalam spesifikasi deployment Anda.
Anda harus menggunakan akun robot Harbor untuk akses terprogram ke image dalam project Harbor pribadi.
Ikuti langkah-langkah berikut untuk mengonfigurasi secret penarikan image:
Buat akun robot Harbor:
- Buka UI instance Harbor Anda.
- Buka project Harbor Anda.
- Pilih tab Akun Robot.
- Klik New Robot Account.
- Beri nama (misalnya,
oss-llm-puller) dan beri izin yang diperlukan (setidaknya akses tarik) hingga waktu habis masa berlaku. - Simpan nama akun robot (misalnya,
robot$oss-llm-puller) dan token rahasia yang diberikan dengan aman.
Mengautentikasi Docker ke Harbor:
Di komputer Anda yang telah menginstal Docker dan memiliki akses jaringan ke registry Harbor, login menggunakan kredensial akun robot:
export INSTANCE_URL="HARBOR_INSTANCE_URL"
# for example, harbor1-project1.org1.zone1.google.gdc.com
export ROBOT_NAME="ROBOT_ACCOUNT_NAME"
# for example, robot\$oss-llm-puller (note how we escape the $ character)
export ROBOT_SECRET="ROBOT_ACCOUNT_SECRET"
docker login ${INSTANCE_URL} --username ${ROBOT_NAME} --password ${ROBOT_SECRET}
Buat secret penarikan image Kubernetes:
Gunakan kubectl untuk membuat secret jenis docker-registry di namespace project Anda, menggunakan file konfigurasi Docker yang diperbarui pada langkah sebelumnya:
# Log in into GDC environment using the next commands
gdcloud auth login --login-config-cert WEB_TLS_CERT_PATH
gdcloud clusters get-credentials KUBERNETES_CLUSTER
kubectl config set-context --current --namespace=NAMESPACE
export SECRET_NAME="OSS_LLM_PULL_SECRET"
export NAMESPACE="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}
Bagian 2: Men-deploy dengan vLLM
2.1 Mendapatkan image Docker vLLM
Di komputer dengan akses internet, tarik image Docker vLLM, lalu transfer ke project Harbor Anda:
# 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
Ganti HARBOR_URL dan PROJECT dengan URL instance Harbor dan nama project Anda.
2.2 Menyiapkan bobot model di PVC
Buat file YAML (misalnya, model-pvc.yaml):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: model-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
storageClassName: standard-rwo
volumeMode: Filesystem
Terapkan PVC: kubectl apply -f model-pvc.yaml
Download bobot dari Hugging Face:
hf auth login
hf download google/gemma-3-4b-it
Gunakan pod helper (misalnya, helper-pod.yaml) untuk mentransfer bobot ke PVC.
Pastikan Anda memiliki image busybox di Harbor.
# Push busybox if not present
docker pull busybox:latest
docker tag busybox HARBOR_URL/PROJECT/busybox:latest
docker push HARBOR_URL/PROJECT/busybox:latest
# Contents of 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
Terapkan pod dan salin file:
kubectl apply -f helper-pod.yaml
# Wait for pod to be Running
kubectl cp ~/.cache/huggingface/hub/ NAMESPACE/model-uploader:/data/
kubectl delete pod model-uploader
2.3 Men-deploy backend vLLM
Buat file deployment 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
- 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",
"--max-model-len",
"32768",
"--enforce-eager"
]
env:
- name: HF_HUB_OFFLINE
value: "1"
- name: HF_HOME
value: "/model"
- name: NCCL_P2P_DISABLE
value: "1"
- name: NCCL_IB_DISABLE
value: "1"
- 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"
memory: "64Gi"
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
Buat file layanan 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
Terapkan konfigurasi:
kubectl apply -f vllm-gemma-3-4b-it-deployment.yaml
kubectl apply -f vllm-gemma-3-4b-it-service.yaml
2.4 Mengonfigurasi kebijakan jaringan
Terapkan resource ProjectNetworkPolicy untuk mengizinkan traffic masuk ke port layanan vLLM (8000). Buat vllm-netpol.yaml:
apiVersion: networking.gdc.goog/v1
kind: ProjectNetworkPolicy
metadata:
name: allow-vllm-ingress
namespace: NAMESPACE
spec:
subject:
subjectType: UserWorkload
policyType: Ingress
ingress:
- from:
- ipBlock:
cidr: 0.0.0.0/0 # Restrict this in production
ports:
- protocol: TCP
port: 8000
Terapkan kebijakan: kubectl apply -f vllm-netpol.yaml
Bagian 3: Men-deploy dengan Ollama
3.1 Siapkan Dockerfile
Buat Dockerfile untuk membangun image Ollama dengan model Anda yang sudah dimuat sebelumnya:
FROM ubuntu
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates zstd
RUN curl -fsSL https://ollama.com/install.sh -o install.sh
RUN chmod +x install.sh
RUN ./install.sh && \
rm -rf /var/lib/apt/lists/*
# Pre-pull gemma3 model
RUN ollama serve & \
sleep 5 && \
curl --retry 10 --retry-connrefused -s http://localhost:11434 || true && \
ollama pull gemma3:latest && \
pkill ollama || true
EXPOSE 11434
CMD ["ollama", "serve"]
3.2 Membangun dan mengirim image
Build dan kirim image:
docker build -t ollama-gemma3 .
docker tag ollama-gemma3 HARBOR_URL/PROJECT/ollama-gemma3:latest
docker push HARBOR_URL/PROJECT/ollama-gemma3:latest
3.3 Deploy backend Ollama
Buat ollama-gemma3.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ollama-gemma3
namespace: NAMESPACE
labels:
app: ollama-gemma3
spec:
replicas: 1
selector:
matchLabels:
app: ollama-gemma3
template:
metadata:
labels:
app: ollama-gemma3
spec:
containers:
- name: ollama-gemma3
image: HARBOR_URL/PROJECT/ollama-gemma3:latest
env:
- 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: NAMESPACE
spec:
type: LoadBalancer
selector:
app: ollama-gemma3
ports:
- name: ollama-gemma3-port
port: 11434
protocol: TCP
targetPort: 11434
Terapkan manifes: kubectl apply -f ollama-gemma3.yaml
3.4 Mengonfigurasi kebijakan jaringan
Buat ollama-netpol.yaml:
apiVersion: networking.gdc.goog/v1
kind: ProjectNetworkPolicy
metadata:
name: allow-ollama-ingress
namespace: NAMESPACE
spec:
subject:
subjectType: UserWorkload
policyType: Ingress
ingress:
- from:
- ipBlock:
cidr: 0.0.0.0/0 # Restrict this for production.
ports:
- protocol: TCP
port: 11434
Terapkan kebijakan: kubectl apply -f ollama-netpol.yaml
Bagian 4: Validasi
Verifikasi deployment dengan memeriksa status pod, alamat IP layanan, dan
mengirim permintaan inferensi pengujian menggunakan curl ke alamat IP LoadBalancer
untuk vLLM dan Ollama.
Pastikan semua penampung dan layanan Running:
# Login into GDC air-gapped using the next commands
gdcloud auth login --login-config-cert WEB_TLS_CERT_PATH
gdcloud clusters get-credentials KUBERNETES_CLUSTER
kubectl config set-context --current --namespace=NAMESPACE
# Pods
kubectl get pods
# Services
kubectl get services
Menguji vLLM:
export VLLM_IP=$(kubectl get service gemma-3-4b-it -n NAMESPACE -o jsonpath='{.status.loadBalancer.ingress[*].ip}')
curl http://${VLLM_IP}/v1/chat/completion \
-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
}'
Menguji Ollama:
export OLLAMA_IP=$(kubectl get service ollama-gemma3 -n NAMESPACE -o jsonpath='{.status.loadBalancer.ingress[*].ip}')
# Check if Ollama is running
curl http://${OLLAMA_IP}:11434
# Send a completion request
curl -X POST http://${OLLAMA_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,
"stream": false
}'
Bagian 5: Operasi dan pemecahan masalah
5.1 Operasi vLLM
Periksa Log: kubectl logs -f -n NAMESPACE
Kueri Status Internal (dari pod debug):
wget -qO- http://gemma-3-4b-it/v1/models
wget -qO- http://gemma-3-4b-it/health
5.2 Operasi Ollama
Akses CLI: kubectl exec -it -n NAMESPACE -- sh
Di dalam pod: ollama list, ollama ps
5.3 Penskalaan
Menskalakan solusi dengan backend Ollama
Secara vertikal
- Alokasikan slice GPU yang lebih besar untuk LLM Anda yang menjadi hambatan hingga Anda menggunakan GPU penuh.
- Jika ingin menggunakan LLM yang lebih besar untuk akurasi respons yang lebih baik, misalnya, LLM dengan parameter 405B, bukan 7B, Anda mungkin memerlukan lebih dari satu GPU agar dapat berjalan dengan lancar.
- Model yang cocok dengan lebih dari satu GPU mengalami beberapa latensi terkait dengan komunikasi antar-GPU.
Secara horizontal
- Deploy pod Ollama sebanyak yang Anda perlukan untuk mencapai target throughput pada LLM tertentu.
- Untuk melakukannya, tingkatkan jumlah replika dalam file YAML deployment Ollama yang sesuai.
- Layanan Kubernetes, yang berjenis LoadBalancer, akan mendistribusikan permintaan bantuan kode di antara endpoint (yaitu pod) dan menampilkan respons masing-masing melalui IP eksternal yang terekspos.
- Ingat, plugin Lanjutkan hanya mengarah ke satu alamat IP per fungsi.

Untuk menskalakan backend vLLM dalam lingkungan air-gapped GDC, Anda dapat mengikuti strategi yang serupa dengan yang digunakan untuk Ollama, dengan berfokus pada alokasi resource hardware dan replikasi pod.
Menskalakan solusi dengan backend vLLM
Secara vertikal
- Mengupgrade Alokasi GPU: Jika throughput inferensi (token/dtk) menjadi penghambat, alokasikan slice GPU yang lebih besar hingga Anda menggunakan GPU NVIDIA A100 penuh.
- Konfigurasi Multi-GPU: Untuk model berukuran sangat besar (misalnya, parameter 70B hingga 405B) yang tidak muat dalam memori satu A100 80 GB, Anda harus menskalakan ke beberapa GPU menggunakan paralelisme tensor.
- Pertimbangan Latensi: Perhatikan bahwa model yang mencakup lebih dari satu GPU mungkin mengalami sedikit overhead terkait komunikasi antar-GPU (misalnya, sinkronisasi NCCL).
Secara horizontal
- Meningkatkan Throughput melalui Replika: Untuk menangani volume permintaan pengguna serentak yang lebih tinggi untuk model yang sama, tingkatkan jumlah replika di YAML deployment vLLM Anda.
- Instance Model Khusus: Karena vLLM dirancang sebagai mesin penayangan model tunggal dan menyematkan memori cache KV-nya saat inisialisasi, Anda harus men-deploy serangkaian pod terpisah untuk setiap LLM berbeda yang ingin dihosting.
- Load Balancing: Layanan Kubernetes GDC (jenis LoadBalancer) akan otomatis mendistribusikan permintaan inferensi masuk di antara semua endpoint pod vLLM yang sehat dan terkait dengan layanan tersebut.
5.4 Pemecahan masalah
Error umum dan mitigasi.
| Error | Mitigasi |
|---|---|
| FIPS SELFTEST FAILURE | Terjadi saat library seperti BoringSSL tidak memiliki tanda tangan integritas. Perbaiki dengan menyetel BORINGSSL_FIPS=0 dan menggunakan image vLLM resmi |
| Pemuatan Berat yang Tertunda | Periksa apakah ada throttling IOPS pada PVC kecil. Volume 500 GiB diperlukan untuk inisialisasi model performa. |
| Koneksi Ditolak | Pastikan PNP secara eksplisit mengizinkan targetPort (8000/8080). Firewall GDC tidak otomatis memberikan akses ke port backend untuk VIP Load Balancer. |