סקירה כללית
המסמך הזה הוא מדריך ליישום הפתרון (SRI), שמתאר את השלבים הנדרשים לפריסה, להכניס לשימוש בסביבת הייצור ולבדיקה של הפתרון Open Model Serving on Distributed Cloud software only.
במדריך הזה נסביר איך לפרוס את מנוע הפרסום האופטימלי של vLLM שמריץ את Gemma 4 (google/gemma-4-31B-it) בתוכנה של Distributed Cloud בלבד, בהגדרת אשכול עם צומת יחיד שמיועד לפריסה בקצה הרשת, תוך שימוש במשאבי GPU פיזיים של NVIDIA (לדוגמה, RTX PRO 6000).
ההדרכה המפורטת הזו מיועדת לביצוע מלקוח טרמינל של CLI עם גישת kubectl רק לאשכול התוכנה של Distributed Cloud.
מטרות
בסיום ההטמעה של הפתרון הזה, תוכלו:
- הגדרת פרמטרים של סביבת ההצגה באמצעות קובץ
.envמקומי. - פריסת דרישת נפח אחסון מתמיד (PVC) באמצעות מחלקת האחסון
local-sharedכדי לשמור את משקלי המודל. - פריסת מנוע האופטימיזציה vLLM באמצעות קונטיינרים שעומדים בדרישות של Vertex AI, מיפוי משאבים פיזיים
nvidia.com/gpu. - פורסים את ממשק המשתמש האינטרנטי של Gradio כדי לספק ממשק צ'אט אינטראקטיבי.
- יצירת מנהרות מקומיות להעברת נתונים דרך יציאות כדי לאמת את מהירות התגובה של ההצגה באמצעות ממשקי API וממשק המשתמש באינטרנט.
- מאמתים את השילוב של ניראות (observability) על ידי אישור של הכנסת נתונים של יומנים ומדדים (כולל טלמטריית GPU) ל-Cloud Logging ול-Cloud Monitoring.
לפני שמתחילים
דרישות מוקדמות (הגדרת אשכול)
המדריך הזה מבוסס על ההנחה שיש לכם אשכול תוכנה פעיל של Distributed Cloud בלבד, עם תמיכה ב-GPU. להתקנת האשכול, עיין במאמרי העזרה הרשמיים בנושא תוכנת Distributed Cloud ל-Bare Metal בלבד. הגדרת ה-GPU צריכה להיות בהתאם למסמכים הרשמיים Google Cloud בנושא הגדרה ושימוש ב-GPU של NVIDIA.
דרישות סף לתחנת עבודה של לקוח
מוודאים שהכלים הבאים מותקנים ומוגדרים בסביבת המסוף המקומית:
- ה-CLI של gcloud: נדרש להגדרת הפרויקט ולשליחת שאילתות יומנים.
צריך להיות מאומת (
gcloud auth login) ומוגדר לפרויקט הפעילGoogle Cloud שבו רשום האשכול של תוכנת Distributed Cloud בלבד. - kubectl: נדרש לניהול משאבי אשכול. צריך להגדיר אותו עם ההקשר המתאים כדי לגשת רק לאשכול התוכנה המבוזרת של יעד Cloud (למשל, דרך שער חיבור או גישה ישירה לרשת המקומית).
- curl: נדרש לשליחת בקשות בדיקה לנקודת הקצה של הצגת המודעות.
- jq: נדרש לניתוח פלט JSON מנקודת הקצה של ההצגה.
גישה למודל של Hugging Face
כדי להוריד ולפרוס את מודל Gemma 4, צריך לקבל גישה למאגר Hugging Face:
- חשבון ב-Hugging Face: צריך לוודא שיש לכם חשבון רשום ב-Hugging Face.
- מאשרים את רישיון המודל: עוברים אל הדף של מודל Gemma 4 31B IT ומאשרים את תנאי הרישיון כדי לקבל גישה למשקלים של המודל המוגבל.
- יצירת אסימון גישה: יוצרים אסימון גישה למשתמש עם הרשאות קריאה בהגדרות החשבון ב-Hugging Face (הגדרות > אסימוני גישה). הטוקן הזה ישמש כ-
HF_TOKENבהגדרה שלכם.
הגדרת הפניה מרכזית
כל פרמטרי הפריסה מנוהלים באמצעות קובץ .env מרכזי שנמצא בכתובת
<local-config-dir>/.env. צריך לוודא שהקובץ הזה קיים ומכיל את הפרמטרים הספציפיים שלכם (טוקן Hugging Face, מרחב שמות, שם המודל וכו').
מבנה .env לדוגמה:
# GDCso Cluster Namespace
NAMESPACE_NAME="your-custom-namespace"
# Hugging Face Token (Required to download gated Gemma models)
HF_TOKEN="your-hf-token-here"
# Model Sizing Parameters
MODEL_NAME="google/gemma-4-31B-it"
SAFE_MODEL_NAME="google-gemma-4-31B-it"
# Hyperparameters
MAX_MODEL_LEN=8192
GPU_MEMORY_UTILIZATION=0.95
MAX_NUM_SEQS=512
MAX_NUM_BATCHED_TOKENS=4096
DTYPE="bfloat16"
# Pod Sizing Requests
CPU_REQUEST="4"
MEMORY_REQUEST="80"
הגדרת הסביבה ופרטי הכניסה
יצירת מרחב שמות וסוד של Hugging Face
לפני הפריסה, צריך ליצור את מרחב השמות ואת סוד הטוקן של Hugging Face:
# Navigate to your project root
cd <local-working-dir>
# Sourced from your local .env file
source <local-config-dir>/.env
# Create namespace
kubectl create namespace ${NAMESPACE_NAME} --dry-run=client -o yaml | kubectl apply -f -
# Create Hugging Face token secret
kubectl create secret generic hf-token-secret \
--from-literal=token="${HF_TOKEN}" \
-n "${NAMESPACE_NAME}" --dry-run=client -o yaml | kubectl apply -f -
פריסת vLLM ב-Kubernetes
הפריסה מורכבת משלושה מניפסטים עיקריים: PVC, Service ו-Deployment. התבניות האלה משתמשות במשתני סביבה שמוחלפים בזמן הפריסה.
דרישת נפח אחסון מתמיד (PVC)
ה-PVC מבטיח שמשקלי המודל יישמרו גם אחרי הפעלה מחדש של הפוד, באמצעות מחלקת האחסון local-shared של תוכנת Distributed Cloud בלבד.
יוצרים קובץ בשם vllm-pvc.yaml עם התוכן הבא:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: model-cache-pvc
namespace: ${NAMESPACE_NAME}
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-shared
resources:
requests:
storage: 100Gi
שירות
חושף את שרת vLLM API באופן פנימי ביציאה 8000.
יוצרים קובץ בשם vllm-service.yaml עם התוכן הבא:
apiVersion: v1
kind: Service
metadata:
name: vllm-service
namespace: ${NAMESPACE_NAME}
labels:
app: vllm
annotations:
prometheus.io/scrape: "true"
prometheus.io/path: "/metrics"
prometheus.io/port: "8000"
spec:
ports:
- name: http
port: 8000
targetPort: 8000
selector:
app: vllm
type: ClusterIP
פריסה
מריצים את קונטיינר vLLM, טוענים את נפח מטמון המודל ומבקשים משאבי GPU פיזיים. אף על פי ש-96GB של VRAM מתאימים למשקלים לא מכומתים של BF16 (~62GB), יישום ההפניה הזה מאפשר כימות של Blackwell FP8 (--quantization=fp8, משקלים של ~31GB) כדי להרחיב את מטמון KV ל-56.53GiB (61,728 טוקנים) לשיפור התפוקה המקבילית.
יוצרים קובץ בשם vllm-deployment.yaml עם התוכן הבא:
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-deployment
namespace: ${NAMESPACE_NAME}
labels:
app: vllm
ai.gke.io/inference-server: vllm
ai.gke.io/model: ${SAFE_MODEL_NAME}
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: vllm
template:
metadata:
labels:
app: vllm
examples.ai.gke.io/source: user-guide
ai.gke.io/inference-server: vllm
ai.gke.io/model: ${SAFE_MODEL_NAME}
spec:
runtimeClassName: nvidia
containers:
- name: vllm-container
image: us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:gemma4
imagePullPolicy: IfNotPresent
command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
args:
- --model=$(MODEL_ID)
- --host=0.0.0.0
- --port=8000
- --tensor-parallel-size=1
- --enable-log-requests
- --max-model-len=${MAX_MODEL_LEN}
- --gpu-memory-utilization=${GPU_MEMORY_UTILIZATION}
- --max-num-seqs=${MAX_NUM_SEQS}
- --max-num-batched-tokens=${MAX_NUM_BATCHED_TOKENS}
- --dtype=${DTYPE}
- --trust-remote-code
- --enable-prefix-caching
- --enable-chunked-prefill
- --quantization=fp8
env:
- name: MODEL_ID
value: ${MODEL_NAME}
- name: HUGGING_FACE_HUB_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
- name: LD_LIBRARY_PATH
value: "/usr/local/nvidia/lib64"
ports:
- name: http
containerPort: 8000
resources:
requests:
cpu: ${CPU_REQUEST}
memory: "${MEMORY_REQUEST}Gi"
nvidia.com/gpu: "1"
limits:
cpu: ${CPU_REQUEST}
memory: "${MEMORY_REQUEST}Gi"
nvidia.com/gpu: "1"
volumeMounts:
- mountPath: /root/.cache/huggingface
name: cache-volume
- mountPath: /dev/shm
name: dshm
volumes:
- name: cache-volume
persistentVolumeClaim:
claimName: model-cache-pvc
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 16Gi
פריסת ממשק המשתמש של Gradio
ממשק המשתמש של Gradio מספק ממשק אינטרנטי אינטראקטיבי לשיחה עם המודל. הוא נפרס באשכול ומתחבר לשירות vLLM דרך רשת Kubernetes הפנימית.
פריסת Gradio
יוצרים קובץ בשם gradio-deployment.yaml עם התוכן הבא:
apiVersion: apps/v1
kind: Deployment
metadata:
name: gradio-deployment
namespace: ${NAMESPACE_NAME}
labels:
app: gradio
spec:
replicas: 1
selector:
matchLabels:
app: gradio
template:
metadata:
labels:
app: gradio
spec:
containers:
- name: gradio
image: us-docker.pkg.dev/google-samples/containers/gke/gradio-app:v1.0.4
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "500m"
memory: "512Mi"
env:
- name: CONTEXT_PATH
value: "/v1/chat/completions"
- name: HOST
value: "http://vllm-service:8000"
- name: MODEL_ID
value: "${MODEL_NAME}"
ports:
- containerPort: 7860
שירות Gradio
יוצרים קובץ בשם gradio-service.yaml עם התוכן הבא:
apiVersion: v1
kind: Service
metadata:
name: gradio-service
namespace: ${NAMESPACE_NAME}
spec:
selector:
app: gradio
ports:
- protocol: TCP
port: 8080
targetPort: 7860
type: ClusterIP
הגדרת ניראות (observability)
לפרטים על הגדרת רישום ביומן ומעקב באפליקציה, אפשר לעיין במדריך הרשמי בנושא רישום ביומן ומעקב באפליקציה.
מעקב אחרי vLLM
כדי להפעיל גירוד של מדדי vLLM באמצעות השירות המנוהל של Google Cloud ל-Prometheus (GMP), אנחנו פורסים משאב PodMonitoring שמטרגט את ה-pods של vLLM.
יוצרים קובץ בשם vllm-pod-monitoring.yaml עם התוכן הבא:
apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
name: vllm-pod-monitoring
namespace: ${NAMESPACE_NAME}
spec:
selector:
matchLabels:
app: vllm
endpoints:
- port: http
interval: 30s
מעקב אחר GPU
כדי להפעיל גירוד של מדדי GPU מ-NVIDIA DCGM Exporter באמצעות השירות המנוהל של Google Cloud ל-Prometheus (GMP), אנחנו פורסים משאב PodMonitoring במרחב השמות gpu-operator. פרטים נוספים זמינים במאמר שליחת מדדי GPU אל Cloud Monitoring.
יוצרים קובץ בשם gpu-pod-monitoring.yaml עם התוכן הבא:
apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
name: dcgm-gmp
namespace: gpu-operator
spec:
selector:
matchLabels:
app: nvidia-dcgm-exporter
endpoints:
- port: metrics
interval: 30s
שלבי הביצוע
פריסת מניפסטים
מחילים את המניפסטים על האשכול. מכיוון שקובצי ה-YAML מכילים placeholders של משתני סביבה, צריך להשתמש ב-envsubst כדי להחליף את המשתנים מקובץ .env לפני שמחילים אותם.
עוברים לספריית העבודה שמכילה את קובצי ה-YAML:
cd <local-working-dir>מפעילים את משתני הסביבה:
source <local-config-dir>/.envמחילים את המניפסטים ברצף:
# Apply core serving manifests envsubst < vllm-pvc.yaml | kubectl apply -f - envsubst < vllm-service.yaml | kubectl apply -f - envsubst < vllm-deployment.yaml | kubectl apply -f - # Apply observability manifests envsubst < vllm-pod-monitoring.yaml | kubectl apply -f - kubectl apply -f gpu-pod-monitoring.yaml # Apply Gradio UI manifests envsubst < gradio-deployment.yaml | kubectl apply -f - envsubst < gradio-service.yaml | kubectl apply -f -
אימות
מעקב אחר רצף האתחול של ה-pod
מזרימים את היומנים של מאגר התגים כדי לעקוב אחרי רצף ההפעלה:
# 1. Check pod status (wait until it is Running)
kubectl get pods -n ${NAMESPACE_NAME} -l app=vllm
# 2. Stream logs to verify model loading
kubectl logs -f -l app=vllm -n ${NAMESPACE_NAME}
מחכים עד שרואים ביומנים את האות שההצגה הפעילה מוכנה:
INFO: Application startup complete.
יצירת מנהרה להעברה ליציאה אחרת
כדי לבדוק את נקודת הקצה באופן מקומי, מעבירים את יציאת השירות 8000:
kubectl port-forward service/vllm-service 8000:8000 -n ${NAMESPACE_NAME}
משאירים את חלון ה-Terminal פתוח או מריצים אותו ברקע.
נקודת קצה (endpoint) להצגת שאילתות
ממסוף נפרד, בודקים את מהירות התגובה של ה-API:
1. רשימת מודלים של שאילתות
curl -s http://localhost:8000/v1/models | jq
2. שאילתות להשלמת צ'אט
curl -s http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "'"${MODEL_NAME}"'",
"messages": [
{"role": "user", "content": "What is AGI in 100 words"}
],
"max_tokens": 150
}' | jq
אימות ההקצאות של ה-GPU וה-VRAM
כדי לוודא שהמודל משתמש בחומרה בצורה יעילה ושהזיכרון תואם, אפשר להריץ ביקורת על ה-GPU.
בדיקת ה-GPU באמצעות nvidia-smi בתוך ה-pod
מאחזרים את השם של ה-pod הפעיל של vLLM ומריצים את הפקודה nvidia-smi בתוך המאגר:
# Dynamically get the pod name
export VLLM_POD_NAME=$(kubectl get pods -n ${NAMESPACE_NAME} -l app=vllm -o jsonpath='{.items[0].metadata.name}')
# Run nvidia-smi inside the container
kubectl exec ${VLLM_POD_NAME} -n ${NAMESPACE_NAME} -- nvidia-smi
פלט צפוי: הפלט צריך לדווח על ניצול זיכרון ה-VRAM הפיזי שתואם לפרמטר GPU_MEMORY_UTILIZATION. לדוגמה, בתחנת עבודה עם NVIDIA RTX PRO 6000 (כ-96GB VRAM) שמופעלת עם google/gemma-4-31B-it, אמור להיות מוקצה ל-VLLM::EngineCore נפח של כ-95,800MiB:GPU_MEMORY_UTILIZATION=0.95
+-----------------------------------------------------------------------------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA RTX PRO 6000 Blac... On | 00000000:05:00.0 Off | 0 |
| N/A 36C P0 85W / 600W | 95805MiB / 97887MiB | 0% Default |
+-----------------------------------------+------------------------+----------------------+
אימות ההקצאה של מטמון KV ביומנים
אפשר גם לבדוק את יומני ההקצאה הפנימיים של vLLM כדי לוודא את גודל מטמון KV ואת מספר האסימונים המקבילים:
kubectl logs ${VLLM_POD_NAME} -n ${NAMESPACE_NAME} | grep -E "Available KV cache|GPU KV cache size"
הפלט הצפוי:
(EngineCore pid=362) INFO 06-18 15:03:43 [gpu_worker.py:456] Available KV cache memory: 56.53 GiB
(EngineCore pid=362) INFO 06-18 15:03:43 [kv_cache_utils.py:1316] GPU KV cache size: 61,728 tokens
הנתון הזה מאשר ש-56.53 GiB של VRAM שמורים למטמון KV של ההקשר, מה שמאפשר מספר גדול של טוקנים במקביל.
אימות הפריסה של ממשק המשתמש של Gradio
אחרי שה-pod של Gradio פועל, אפשר לגשת לממשק המשתמש על ידי יצירת מנהרת העברת נתונים (port-forwarding).
מעקב אחרי הסטטוס של פוד Gradio
מוודאים שרכיב ה-Gradio פועל:
kubectl get pods -n ${NAMESPACE_NAME} -l app=gradio
הפלט הצפוי:
NAME READY STATUS RESTARTS AGE
gradio-deployment-yyyyyyyy-yyyyy 1/1 Running 0 1m
הקמת מנהרת העברת נתונים ליציאה אחרת ל-Gradio
מעבירים את יציאת שירות Gradio 8080 ליציאה המקומית 7860:
kubectl port-forward service/gradio-service 7860:8080 -n ${NAMESPACE_NAME}
משאירים את הטרמינל פתוח או מפעילים אותו ברקע:
kubectl port-forward service/gradio-service 7860:8080 -n ${NAMESPACE_NAME} > pf_gradio.log 2>&1 & sleep 3
גישה לממשק המשתמש באינטרנט
- אם מריצים את הכלי בתחנת עבודה מקומית: פותחים את הדפדפן ועוברים ישירות לכתובת:
http://localhost:7860 - אם מריצים ב-Cloud Shell: לוחצים על הלחצן תצוגה מקדימה באינטרנט, בוחרים באפשרות שינוי יציאה, מזינים
7860ולוחצים על שינוי ותצוגה מקדימה.
אמור להופיע ממשק הצ'אטבוט של Gradio. אתם יכולים להקליד הודעה כדי ליצור אינטראקציה עם מודל Gemma. ה-pod של Gradio ינתב את הבקשה באופן פנימי לנקודת הקצה vllm-service.
ניקוי מנהרות
כדי להפסיק את מנהרת העברת הפורטים:
pkill -f "port-forward service/gradio-service"
מעקב אחרי האימות
אחרי שפורסים את vLLM ומחילים את המשאב PodMonitoring, אפשר לוודא שהמדדים מוזנים ל-Cloud Monitoring.
אימות הסטטוס של PodMonitoring
מוודאים שמשאב PodMonitoring נוצר ופעיל:
kubectl get podmonitoring -n ${NAMESPACE_NAME}
אימות ההטמעה של מדדים באמצעות מסוף Google Cloud
כדי לוודא שהמדדים נקלטים, אפשר להשתמש ב Google Cloud מסוף (Metrics Explorer):
- פותחים את Metrics Explorer במסוף Google Cloud :
- עוברים אל
https://console.cloud.google.com/monitoring/metrics-explorer(חשוב לבחור את הפרויקט${GCP_PROJECT_ID}).
- עוברים אל
- בתפריט הנפתח בחירת מדד, מחפשים ובוחרים את המדדים הבאים:
-
prometheus.googleapis.com/vllm:num_requests_running/gaugeכדי לאמת את מדדי ה-vLLM. -
prometheus.googleapis.com/DCGM_FI_DEV_GPU_UTIL/gaugeכדי לאמת את מדדי השימוש ב-GPU.
-
- בודקים את התרשים כדי לוודא שנקודות הנתונים מוצגות באופן פעיל.
אימות רישום
אחרי שעומס העבודה יפעל, תוכלו לוודא שהיומנים מיוצאים ל-Cloud Logging.
אימות של הטמעת יומנים ב-vLLM
מוודאים שיומני מאגרי vLLM מיוצאים ל-Cloud Logging:
project_id=$(gcloud config get-value project)
gcloud logging read "resource.type=\"k8s_container\" AND resource.labels.namespace_name=\"${NAMESPACE_NAME}\" AND resource.labels.container_name=\"vllm-container\"" --limit=10 --project=${project_id}
אימות ההטמעה של יומן ייצוא ה-GPU
מוודאים שיומני הקונטיינר של כלי הייצוא של ה-GPU מיוצאים ל-Cloud Logging:
project_id=$(gcloud config get-value project)
gcloud logging read "resource.type=\"k8s_container\" AND resource.labels.namespace_name=\"gpu-operator\" AND resource.labels.container_name=\"nvidia-dcgm-exporter\"" --limit=10 --project=${project_id}
אימות יומנים באמצעות מסוף Google Cloud (Logs Explorer)
אפשר גם לאמת את ההעברה של היומן באמצעות Google Cloud המסוף:
- פותחים את Logs Explorer במסוף Google Cloud :
- עוברים אל
https://console.cloud.google.com/logs/query(חשוב לבחור את הפרויקט${GCP_PROJECT_ID}).
- עוברים אל
בתיבה Query, מזינים את השאילתה הבאה כדי להציג את יומני vLLM:
resource.type="k8s_container" resource.labels.namespace_name="<NAMESPACE_NAME>" resource.labels.container_name="vllm-container"(מחליפים את
<NAMESPACE_NAME>במרחב השמות בפועל, לדוגמה:your-custom-namespace).לוחצים על Run query. אמורות להופיע רשומות ביומן מהמאגר vLLM.
כדי לבדוק את היומנים של כלי הייצוא של GPU, מריצים את השאילתה הבאה:
resource.type="k8s_container" resource.labels.namespace_name="gpu-operator" resource.labels.container_name="nvidia-dcgm-exporter"