במדריך הפריסה הזה מוסבר בפירוט איך להריץ מודלי שפה גדולים (LLM) מתקדמים באמצעות תוכנת קוד פתוח (OSS) בסביבות מבודדות של Google Distributed Cloud (GDC). במדריך הזה מפורטים כל השלבים שנדרשים להפעלת הגרסאות האחרונות של מודלי Gemma, DeepSeek ו-Llama, ומוצגים בו תהליכים נפוצים להפעלת מודלים אחרים של LLM שזמינים לציבור. נשתמש בשרתי קצה עורפיים מבוססי-קונטיינר, כמו vLLM ו-Ollama, שמכסים מגוון רחב של פונקציות, רמות שונות של הגדרה ופריסה קלה.
סיכום התוכן
במדריך הזה מוסבר איך לפרוס ולהפעיל מודלי שפה גדולים (LLM) בקוד פתוח בסביבות מבודדות של Google Distributed Cloud (GDC).
מטרות ותשתית ליבה
- המטרה: הוראות מפורטות להפעלת מודלים מתקדמים של שפה גדולה (LLM), כולל Gemma 3 (מולטימודאלי), DeepSeek-R1 ו-Llama (3.1/3.2) באמצעות עורפי קצה מותאמים כמו vLLM ו-Ollama.
- גרסה מינימלית: גרסת תוכנה של GDC עם air gap 1.15.x*.
- דרישות חומרה: נדרש לפחות מעבד GPU אחד מסוג NVIDIA A100. מומלץ להשתמש באחסון עם ביצועים גבוהים (PVC של 500GiB ומעלה) כדי לשפר את זמני הטעינה של משקלי המודל מ-30 דקות לפחות מ-5 דקות.
רכיבי פריסה
| רכיב | תיאור |
|---|---|
| בקשות קצה של LLM | vLLM (מילוי בקשות עם תפוקה גבוהה באמצעות PagedAttention) ו-Ollama (ניהול מקומי פשוט ותמיכה בריבוי מודאלי) |
| מודלים | מודלים של LLM שזמינים לציבור, כולל משפחות המודלים Gemma, DeepSeek ו-Llama |
| מאיצים | תמיכה מלאה במעבדי GPU של NVIDIA A100 או בפרוסות של Multi-Instance GPU (MIG), בהתאם לשימוש ב-VRAM של המודל |
| שירותי GDC | משתמש ב-GDC Container Service, Load Balancer (ELB/ILB), Harbor Container Registry |
נוהלי תפעול מרכזיים
- ניהול מודלים: קצה העורפי של ה-LLM מנהל את הטעינה והפריקה של המודלים על סמך השימוש. vLLM מצמיד מודלים לזיכרון כדי להבטיח זמן אחזור נמוך ועקבי, ואילו Ollama מאפשר טעינה דינמית של מודלים, אבל פורק את המודלים באופן אוטומטי אחרי 30 דקות של חוסר פעילות.
- התאמה אישית: משתמשים יכולים להשתמש במודלים מועדפים של LLM על ידי משיכתם מהאינטרנט, יצירת קובצי אימג' חדשים של Docker והעלאה למאגר המקומי של Harbor.
דרישות מוקדמות
גרסה
- GDC עם air gap מגרסה 1.15.1 ואילך.
רכיבים
- נוצר אשכול משתמשים עם מספיק משאבים (CPU, זיכרון, GPU).
- נדרש לפחות GPU אחד מסוג NVIDIA A100.
- מופע Harbor זמין ונגיש.
- ממשקי ה-CLI
kubectlו-gdcloudמוגדרים לגישה לאשכול המשתמשים. - לקוח Docker מותקן ומוגדר להעברה בדחיפה אל Harbor.
- ההרשאות הנדרשות ב-IAM הוענקו (לדוגמה, Namespace Admin, Cluster Developer).
- אם משתמשים במודלים עם גישה מוגבלת, צריך להגדיר חשבון ואימות ב-Hugging Face.
הקיבולת הנדרשת
| משאב | קיבולת |
|---|---|
| CPU | 8 vCPU |
| זיכרון RAM | 32 GiB |
| שטח אחסון זמני | 16 Gi |
| יחידות GPU | 1 NVIDIA A100 GPU |
| נפח אחסון מתמיד | *500GiB ומעלה |
משאבי החומרה האלה נדרשים כדי שהעורפים (back-end) של שרתים יוכלו להריץ מודלים גדולים של שפה (LLM) עם האצת GPU. לדוגמה, סוג המכונה a2-ultragpu-1g-gdc יספק מספיק משאבים.
תרשים כללי

בתרשים הזה מוצג משתמש שצורך ממשקי API שנחשפים על ידי שני עורפי LLM, vLLM ו-Ollama, כדי לקבל תגובות היקש ממודלים בקוד פתוח, כמו Gemma, Llama ו-DeepSeek. בהתאם לגודל המודל, שנמדד במיליארדי פרמטרים, יכול להיות שכל מודל שפה גדול יצטרך GPU מלא או חלק ממנו כדי לפעול.
תרשים של גבולות השירות והאבטחה לפריסת מודל שפה גדול (LLM)
הפתרון הזה מסתמך על השירותים הבאים שכבר כלולים בחבילת התוכנה של GDC עם air gap:
- GDC Container Service: כדי להריץ את כל התהליכים ולהגדיל את ההיקף שלהם באמצעות HPA.
- מאזן עומסים של GDC: באמצעות שירות Kubernetes, כדי להציג את כל הקצה העורפי בפתרון הזה ולאפשר גישה למודלים של שפה גדולה (LLM) מהרשת של הלקוח. זה נקרא ELB, קיצור של External Load Balancer (מאזן עומסים חיצוני). לעומת זאת, הלקוח יכול לבחור להשאיר את ה-LLM נגיש רק מתוך אשכול משתמשים. זה יכול להיות שימושי אם יש רק סוכן פנימי שמבקש מסקנות בתוך הפתרון שלו. זה נקרא ILB, קיצור של Internal Load Balancer (מאזן עומסים פנימי).
- GDC CI/CD: Harbor Container Registry לאחסון של קצה עורפי של LLM ומשקלים של מודלים.
- חבילת כלי ה-Observability של GDC: לאיסוף ולחיפוש של יומני קצה עורפיים ולמתן לוחות בקרה.
מבחינת אבטחה, הגישה לפריסת ה-LLM תלויה במשתמשים שיכולים להגיע לשירות איזון העומסים שחושף את העורפים של שרת ה-LLM, שפועלים כ-pods בפרויקט או במרחב שמות של Kubernetes.

פריסה
דרישות מוקדמות
מתקינים את הכלים הבאים בתחנת עבודה שמחוברת לסביבת GDC עם air gap:
במסמך הזה מפורטים כל קוד המקור וקבצי ההגדרות שנדרשים לפריסת מודלים של שפה גדולה (LLM).
יצירת סוד למשיכת תמונות מ-Harbor
כדי להגדיר סוד למשיכת תמונה עבור עומס עבודה של קונטיינר ב-GDC עם air gap, צריך ליצור סוד של Kubernetesdocker-registry שמכיל פרטי כניסה לגישה לפרויקט Harbor הפרטי. הסוד הזה מוזכר במפרט הפריסה.
מומלץ להשתמש בחשבון רובוט של Harbor לגישה פרוגרמטית לתמונות בפרויקטים פרטיים של Harbor.
כדי להגדיר את סוד משיכת התמונה:
יצירת חשבון רובוט של Harbor:
- עוברים לממשק המשתמש של מופע Harbor.
- עוברים לפרויקט Harbor.
- בוחרים בכרטיסייה חשבונות רובוט.
- לוחצים על + חשבון רובוט חדש.
- נותנים לו שם (לדוגמה,
oss-llm-puller) ומעניקים לו את ההרשאות הנדרשות (לפחות גישת 'משיכה') עד לתאריך התפוגה. - שומרים בצורה מאובטחת את השם של חשבון הרובוט (לדוגמה,
robot$oss-llm-puller) ואת האסימון הסודי שסופק.
אימות Docker ב-Harbor:
במחשב שבו מותקן 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 ישתמש עכשיו בפרטי הכניסה שסיפקתם כדי לשלוף קובץ אימג' של קונטיינר ממאגר Harbor הפרטי בסביבת GDC עם air gap. השלבים האלה מופיעים גם בתיעוד המוצר.
הגדרת פריסת LLM
יש שתי אפשרויות ל-LLM Backend:
- vLLM
- Ollama
אתם יכולים לבחור אחת מהן או לפרוס את שתי מערכות ה-Backend. כל קצה עורפי יכול להריץ מודל שפה גדול אחד או יותר, לדוגמה:
- Gemma 3
- DeepSeek
- Llama
- מודלים אחרים של LLM
בקטע 1 מוסבר איך לפרוס את vLLM, ובקטע 2 מוסבר איך להתקין את Ollama.
1. פריסת vLLM כקצה עורפי של LLM
קבלת קובץ האימג' של Docker ל-vLLM
באופן כללי, משתמשים ב-vLLM כדי להכניס לשימוש בסביבת הייצור מודלים שהורדו מ-HuggingFace, כמו שיוצג בהמשך במאמר הזה על פריסת LLM. חלק מהמודלים חסומים, כלומר המשתמשים צריכים לבקש במפורש גישה לקבצים ולתוכן שלהם ב-Hugging Face Hub או לאשר את הגישה אליהם לפני שהם יכולים להוריד אותם או להשתמש בהם.
נכנסים למופע Harbor באמצעות Docker כמו שמוסבר במסמכים. במחשב עם גישה לאינטרנט, מושכים את קובץ האימג' של 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: כתובת ה-URL של מופע Harbor. -
PROJECT: שם הפרויקט ב-Harbor.
הגרסה של vLLM שבה השתמשנו במדריך הפריסה הזה היא: v0.13.0
שמירת משקלי המודל של LLM ב-PVC
פותחים טרמינל חדש ויוצרים תיקייה שבה ישמרו קובצי הפריסה של vLLM:
mkdir vllm-deployment
cd vllm-deployment
לאחר מכן יוצרים קובץ YAML (לדוגמה, model-pvc.yaml) כדי להצהיר על בקשה ל-PersistentVolume (PVC) באמצעות פרימיטיבים סטנדרטיים של Kubernetes:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: model-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
storageClassName: standard-rwo
volumeMode: Filesystem
מתחברים לאשכול GDC עם air gap ומחילים את ה-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.64GB, שמתאים ל-PVC של 500GiB שהגדרנו קודם. חשוב לוודא שזה המצב בכל מודל שבוחרים לטעון ל-Persistent Volume (PV). לדוגמה, אם משתמשים ב-PVC בגודל 500GiB כדי לטעון מודל בגודל 15GB, אפשר להשיג 1,500 IOPS, וכך לקצר משמעותית את זמן הטעינה של המשקלים מכ-30 דקות לפחות מ-5 דקות.
מאכלסים את ה-PV על ידי העתקת קובצי המודל לנפח שלו. לרוב זה כולל:
- יצירת פוד זמני מסוג helper שמבצע mount של ה-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: כתובת ה-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: כתובת ה-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: כתובת ה-URL של מופע Harbor. -
PROJECT: שם הפרויקט ב-Harbor. -
oss-llm-pull-secret: השם שנתתם במהלך יצירת הסוד של משיכת התמונה. -
claimName: השם שנתתם ליצירת ה-PVC הראשונית.
לאחר מכן, יוצרים קובץ שירות של Kubernetes כדי לחשוף את ממשקי ה-API של ה-Backend של vLLM:
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מהפלט הקודם, כדאי לשמור את
EXTERNAL-IPשל שירות vLLM (לדוגמה,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 עם קיבולת גבוהה של Persistent Volume.בדיקת ההסקה באמצעות curl:
אחרי שמוודאים שתרמיל vLLM פועל ושיש לכם את כתובת ה-IP החיצונית של השירות, אפשר לשלוח בקשת הסקה באמצעות
curl. מכיוון ש-vLLM מספק API שתואם ל-OpenAI, אפשר להשתמש בנקודת הקצה/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בכתובת ה-IP החיצונית של שירות ה-vLLM.
2. פריסת Ollama כקצה עורפי של LLM
Ollama היא מסגרת פופולרית להרצת מודלים גדולים של שפה (LLM) בקוד פתוח באופן מקומי ובסביבות בקונטיינרים. הוא מפשט את הרצת המודל על ידי טיפול בהורדות של משקלים, בכימות ובהאצת GPU. הוא כולל API בארכיטקטורת REST מובנה ליצירת השלמות, תשובות בצ'אט והטמעות.
בניגוד למנועי הצגה אחרים, Ollama מנהל את הביצוע של המודל באופן דינמי:
- טעינה דינמית של מודלים: כשמתקבלת בקשה למודל ספציפי, Ollama טוען את המשקלים לזיכרון (VRAM של GPU או RAM של המערכת) לפי דרישה.
- הסרת טעינה של חוסר פעילות: אם לא מתקבלות בקשות הסקה עבור מודל במשך 30 דקות (אפשר להגדיר את זה באמצעות
OLLAMA_KEEP_ALIVE), Ollama מסיר את הטעינה שלו מהזיכרון כדי לפנות משאבי חומרה לעומסי עבודה אחרים. - מודל פעיל יחיד לכל מופע: Ollama מעבד בקשות למודל פעיל אחד בכל פעם לכל מופע שרת. אם קוראים לכמה מודלים במקביל, Ollama מכניס את הבקשות לתור ומחליף בין המודלים באופן עקבי, מה שעלול לגרום לזמן אחזור. כדי להפעיל כמה מודלים בו-זמנית בלי להחליף ביניהם, צריך לפרוס מופעי Ollama נפרדים לכל מודל.
הורדת משקלים של מודלים ויצירת קובץ אימג' של Docker
בניגוד ל-vLLM, שיכול לטעון משקלים ישירות מנפח אחסון קבוע, בדרך כלל Ollama מצפה שהמודלים יאוחסנו בפורמט של ספרייה פנימית (~/.ollama/models).
בסביבה עם air gap, שבה קונטיינרי זמן הריצה לא יכולים להוריד מודלים מהאינטרנט הציבורי, צריך לארוז מראש את משקלי המודל בקובץ אימג' של קונטיינר עצמו במהלך שלב ה-build. הגישה הזו מבטיחה שהקונטיינר יהיה עצמאי לחלוטין ומוכן להפעלה מיידית אחרי הפריסה, בלי לדרוש גישה לרשת חיצונית.
יוצרים תיקייה לפריסת 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, צריך לשנות את פקודת Ollama הזו בקובץ Dockerfile הקודם:
ollama pull gemma3:latest
לדוגמה, אם רוצים למשוך את Llama 3.2 עם 3 מיליארד פרמטרים, משתמשים בפקודה הבאה:
ollama pull llama3.2:3b
לחלופין, אם אתם מעדיפים להשתמש ב-DeepSeek-R1 עם 8 מיליארד פרמטרים, תוכלו להשתמש בפקודה הזו:
ollama pull deepseek-r1:8b
אפשר גם להוריד יותר ממודל LLM אחד ולכלול את משקלי המודל שלהם במאגר. לאחר מכן, Ollama יוכל לעבור בין מודלים כשמבקשים מסקנות על ידי מודלים שונים שנטענו מראש. לדוגמה, אפשר להוסיף גם את מודל Gemma וגם את מודל Llama לקובץ האימג' של Docker. כפי שציינו, בסביבה עם פער אוויר, ל-Ollama backend אין גישה לספריית Ollama כדי להוריד מודל כלשהו בכל שלב.
חשוב לזכור לבדוק את הרישיון ואת תנאי השימוש של כל מודל ולאשר אותם לפני שמריצים את המודלים באפליקציות. יש הרבה מודלי שפה גדולים בספרייה של Ollama. תצטרכו חיבור לאינטרנט רק כדי להוריד את משקלי המודל בזמן בניית קובץ אימג' של Docker של ה-LLM backend.
יצירת קובץ אימג' של Docker והעברה שלו בדחיפה ל-Harbor
נכנסים למופע Harbor באמצעות Docker כמו שמוסבר במסמכים. יוצרים את קובץ האימג' של 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: כתובת ה-URL של מופע Harbor. -
PROJECT: שם הפרויקט ב-Harbor.
גרסת Ollama שבה נעשה שימוש במדריך הפריסה הזה: 0.14.1
הכנת פריסה ושירות של Kubernetes
יוצרים קובץ בשם ollama-gemma3.yaml כדי להגדיר את הפריסה של ה-backend של 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: כתובת ה-URL של מופע Harbor. -
PROJECT: שם הפרויקט ב-Harbor. -
oss-llm-pull-secret: אם בחרתם שם אחר של סוד משיכת התמונה.
אימות הקצאת ה-GPU
GDC עם air gap תומך ב-NVIDIA Multi-Instance GPUs (MIG), ואפשר לעיין בפרופילים השונים של MIG בתיעוד הציבורי. אם אתם פורסים מודלים קטנים של LLM, מומלץ לבדוק את הגודל שלהם (בזיכרון) ולחלק את מעבדי ה-GPU בהתאם. סכמת החלוקה למחיצות של מאגר צמתים מוגדרת במשאב המותאם אישית Cluster שלו. מידע נוסף על אופן ההחלה של סכימת חלוקה למחיצות של GPU זמין במאמר בנושא הוספת מאגר צמתים. אם אתם אופרטור של אפליקציות (AO), כדאי להתייעץ עם אדמין הפלטפורמה (PA) לגבי המאיצים שמותקנים בפרויקט או באשכול שלכם וזמינים לשימוש. כאן אפשר לקרוא פרטים נוספים על הגדרת קונטיינר לשימוש במשאבי GPU ועל בדיקת הקצאת משאבי GPU.
דיוק ברירת המחדל של מודל Gemma 3 4B הוא 16 ביט. לפי הטבלה הזו שפורסמה על ידי Google, דרישת הזיכרון של ה-GPU עבור מודל ה-LLM הזה היא 6.4GB, באמצעות דיוק BF16 (16 ביט).
בדוגמה הקודמת ollama-gemma3.yaml, צירפנו לקונטיינר פרוסת GPU של 10GB (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
מוודאים שרכיב ה-pod של Ollama פועל ושקיים השירות המשויך:
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
שימו לב ל-EXTERNAL-IP של שירות Ollama (לדוגמה, 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
החלת מדיניות רשת ב-Kubernetes:
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 המתאימים, אתם יכולים להתחיל להשתמש בהם להסקת מסקנות.
בהתאם לתרחיש לדוגמה שלכם, יש לכם כמה אפשרויות:
- ממשק משתמש אינטראקטיבי באינטרנט: כדי לבדוק, ליצור אב טיפוס או לספק למשתמשים חוויה דומה ל-ChatGPT, אפשר לפרוס את Open WebUI או קצה קדמי דומה.
- ממשק שורת הפקודה (CLI): כדי לבצע אימות מהיר, לכתוב סקריפטים או להגדיר אוטומציה, אפשר להשתמש ב-
curlאו בסקריפטים מותאמים אישית. - שילוב אפליקציות: אפשר לחבר את האפליקציות הפנימיות, סוכני ה-AI או הפלאגינים לסביבת הפיתוח המשולבת (IDE) (לדוגמה, Continue ל-VS Code או ל-JetBrains) ישירות לנקודות הקצה שתואמות ל-OpenAI שמסופקות על ידי vLLM (
/v1) או Ollama (/v1).
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
החלת מדיניות הרשת
אתם צריכים לאפשר למכונה שלכם להגיע לשירות Open WebUI ביציאה 80.
מעדכנים את מדיניות הרשת של הפרויקט שלכם ב-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
אימות
קבלת כתובת ה-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. שליחת בקשות HTTP באמצעות CLI
- 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, כל אחד בתא או במאגר משלו, שאפשר להקצות אותם ל-GPU או לחלקים שונים של GPU. בניגוד למערכות עורפיות אחרות שעשויות להחליף מודלים באופן דינמי, מופע vLLM מצמיד את המודל שלו ואת זיכרון מטמון ה-KV המשויך לו עם ההפעלה, כדי להבטיח תפוקה גבוהה ועקבית וזמן אחזור נמוך.
אפשר לפתוח טרמינל בכל אחד מהפודים של vLLM באמצעות הפקודות הבאות:
kubectl exec -it gemma-3-4b-random-string -n NAMESPACE -- /bin/bash
יוצגו לכם הדגמים שנטענו, הארגומנטים שלהם ומזהי התהליך שלהם :
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
אתם יכולים לעקוב אחרי הסטטוס של פריסת vLLM באמצעות פקודות kubectl סטנדרטיות ובאמצעות שאילתות של נקודות הקצה של ה-API הפנימי.
בדיקת היומנים של ה-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 מספקת API שתואם ל-OpenAI, כך שאפשר לאמת את המודלים שנטענו ואת תקינות המערכת ישירות ממסוף בתוך האשכול (לדוגמה, באמצעות פוד debug-sh).
קודם צריך להפעיל את ה-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: חובה בסביבות מבודדות כדי לאפשר לאמצעי ההגנה לאמת את עצמו מול מרשם 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 מבטל את הטעינה של המודל הנוכחי מהזיכרון.
בגלל ההתנהגות שתוארה קודם, הפתרון מטמיע שני עורפי קצה (backend) או יותר של Ollama, בהתאם לצרכים ולתרחיש השימוש, כדי שמפתחים או משתמשים רבים יוכלו להשתמש בהם במקביל בלי שרק מופע אחד של Ollama יטען ויבטל טעינה של מודלים לעיתים קרובות, מה שיוצר חביון מיותר.
אפשר לפתוח טרמינל בכל אחד מה-pods של Ollama באמצעות הפקודות הבאות:
kubectl exec -it ollama-chat-random_string -- sh
kubectl exec -it ollama-autocomplete-random_string -- sh
בתוך ה-pods, אפשר להשתמש ב-Ollama CLI כדי לראות את המודלים הזמינים ולבדוק איזה מודל נטען:
ב-pod ollama-chat מופיע מודל אחד:
# 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 יש שני מודלים:
# 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
אם אתם מקצים פרוסת GPU עם 10GB, אבל הזיכרון שבשימוש של המודל גדול יותר (אפילו קצת), תשימו לב שחלק מה-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 אחר או את המודל המועדף
כדי להריץ גרסאות שונות של Gemma או כל מודל שפה גדול (LLM) אחר בקוד פתוח באמצעות vLLM ב-GDC עם air gap, כמו 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.
מאכלסים את Persistent Volume (PVC):
מעדכנים את
model-pvcהקיים או יוצרים חדש עם קיבולת מספקת לדגם החדש. אפשר להשתמש בשיטה של פודים מסייעים כדי להעביר את המשקלים מתחנת העבודה. גורמי צורה גדולים יותר דורשים הרבה יותר מקום בדיסק. מוודאים שלתביעת הנפח המתמשך (PVC) יש מספיק קיבולת לאחסון המשקלים החדשים.- Gemma 3 4B: ~15.2 GB.
- Gemma 3 27B: ~54 GB+.
- המלצה: כדי להבטיח IOPS גבוה (1,500) לטעינה מהירה יותר, בלי קשר לגודל המודל, מומלץ לשמור על ההמלצה לגבי PVC של 500GiB.
# Copy the new model's hub directory to the helper pod kubectl cp ~/.cache/huggingface/hub/ osd-dev/model-uploader:/data/מעדכנים את מניפסט הפריסה של vLLM:
משנים את קובץ ה-YAML של פריסת vLLM כדי להפנות למזהה המודל החדש. בניגוד ל-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 והזיכרון:
מודלים גדולים יותר דורשים יותר VRAM למשקלים ולמטמון KV. אם עוברים ממודל 4B למודל 8B או 14B, צריך לוודא שמגבלות המשאבים מספיקות כדי למנוע קריסות של 'אין זיכרון פנוי (OOM)'.
- השימוש בזיכרון VRAM: בדיוק של 16 ביט, מודל של 8B דורש כ-16GB רק בשביל המשקלים, בנוסף לזיכרון נוסף בשביל מטמון ה-vLLM
PagedAttention. - המלצה: כדי להבטיח ביצועים אופטימליים ומרחב פעולה למטמון KV, מומלץ להשתמש ב-GPU מלא מסוג A100 (
nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1) למודלים עם יותר מ-7 מיליארד פרמטרים.
- השימוש בזיכרון VRAM: בדיוק של 16 ביט, מודל של 8B דורש כ-16GB רק בשביל המשקלים, בנוסף לזיכרון נוסף בשביל מטמון ה-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"}]}
שימוש במודל שפה גדול (LLM) אחר עם Ollama
אם רוצים לנסות מודל שפה גדול (LLM) אחר בקוד פתוח, כמו מודל מהמשפחות Llama 3.2 או DeepSeek-R1, צריך לשנות את פקודת Ollama הזו ב-Dockerfile הקודם:
ollama pull gemma3:latest
לדוגמה, אם רוצים למשוך את Llama 3.2 עם 3 מיליארד פרמטרים, משתמשים בפקודה הבאה:
ollama pull llama3.2:3b
לחלופין, אם אתם מעדיפים להשתמש ב-DeepSeek-R1 עם 8 מיליארד פרמטרים, תוכלו להשתמש בפקודה הזו:
ollama pull deepseek-r1:8b
אפשר גם להוריד יותר ממודל LLM אחד ולכלול את משקלי המודל שלהם במאגר. לאחר מכן, Ollama יוכל לעבור בין מודלים כשמבקשים מסקנות על ידי מודלים שונים שנטענו מראש. לדוגמה, אפשר להוסיף גם את מודל Gemma וגם את מודל Llama לקובץ האימג' של Docker. כפי שציינו, בסביבה עם פער אוויר, ל-Ollama backend אין גישה לספריית Ollama כדי להוריד מודל כלשהו בכל שלב.
חשוב לזכור לבדוק את הרישיון ואת תנאי השימוש של כל מודל ולאשר אותם לפני שמריצים את המודלים באפליקציות. יש הרבה מודלי שפה גדולים בספרייה של Ollama. תצטרכו חיבור לאינטרנט רק כדי להוריד את משקלי המודל בזמן בניית קובץ אימג' של Docker של ה-LLM backend.
פתיחת ממשק משתמש באינטרנט
בודקים אם ה-pod של Open WebUI נמצא במצב פעיל :
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
אנכית
- כדאי להקצות פרוסה גדולה יותר של GPU למודל שפה גדול שהפך לצוואר בקבוק, עד שתשתמשו ב-GPU מלא.
- אם רוצים להשתמש ב-LLM גדול יותר כדי לקבל תשובות מדויקות יותר, למשל LLM עם 405 מיליארד פרמטרים במקום 7 מיליארד, יכול להיות שתצטרכו יותר מ-GPU אחד כדי להריץ אותו בצורה חלקה.
- מודלים שמתאימים ליותר מיחידת GPU אחת חווים השהיה שקשורה לתקשורת בין יחידות ה-GPU.
אופקית
- פורסים כמה פודים של Ollama שצריך כדי להשיג את קצב העברת הנתונים הרצוי במודל שפה גדול (LLM) נתון.
- כדי לעשות את זה, מגדילים את מספר העותקים בקובץ ה-YAML של פריסת Ollama המתאים.
- שירות Kubernetes, מסוג LoadBalancer, יפיץ בקשות לעזרה בכתיבת קוד בין נקודות קצה (כלומר, pods) ויחזיר את התגובות המתאימות דרך כתובת ה-IP החיצונית שנחשפת.
- חשוב לזכור שהתוסף Continue מצביע רק על כתובת IP אחת לכל פונקציונליות.

כדי לשנות את קנה המידה של קצה העורפי (backend) של vLLM בסביבת GDC עם בידוד פיזי, אפשר לפעול לפי אסטרטגיה דומה לזו שמשמשת ל-Ollama, ולהתמקד בהקצאת משאבי חומרה ובשכפול של פודים.
הרחבת הפתרון באמצעות קצה עורפי של vLLM
אנכית
- שדרוג הקצאת ה-GPU: אם קצב העברת הנתונים של ההסקה (טוקנים/שנייה) הופך לצוואר בקבוק, צריך להקצות פרוסת GPU גדולה יותר עד לשימוש ב-GPU מלא של NVIDIA A100.
- תצורות של כמה מעבדי GPU: כדי להשתמש במודלים גדולים מאוד (לדוגמה, פרמטרים של 70B עד 405B) שלא נכנסים לזיכרון של A100 יחיד בנפח 80GB, צריך להגדיל את מספר מעבדי ה-GPU באמצעות מקביליות טנסורית.
- שיקולים לגבי זמן האחזור: שימו לב שייתכן שיהיה תקורה קלה בדגמים שמשתרעים על יותר מ-GPU אחד, שקשורה לתקשורת בין ה-GPU (לדוגמה, סנכרון NCCL).
אופקית
- הגדלת התפוקה באמצעות רפליקות: כדי לטפל בנפח גדול יותר של בקשות משתמשים
בו-זמניות עבור אותו מודל, מגדילים את
replicasמספר הרפליקות בקובץ ה-YAML של פריסת vLLM. - מופעים ייעודיים של מודלים: מכיוון ש-vLLM מתוכנן כמנוע להצגת מודל יחיד ומצמיד את זיכרון מטמון KV שלו במהלך האתחול, צריך לפרוס קבוצה נפרדת של פודים לכל LLM שרוצים לארח.
- איזון עומסים: שירות GDC Kubernetes (סוג
LoadBalancer) יפיץ באופן אוטומטי בקשות הסקה נכנסות בין כל נקודות הקצה של vLLM pod שמשויכות לשירות הזה.
פתרון בעיות
| שגיאה | צמצום הפגיעה |
|---|---|
| FIPS SELFTEST FAILURE | השגיאה הזו מתרחשת כשחסרים חתימות שלמות בספריות כמו BoringSSL. תיקון באמצעות הגדרת BORINGSSL_FIPS=0 ושימוש בתמונות vLLM רשמיות |
| טעינת משקל מושהית | בודקים אם יש הגבלת IOPS ב-PVC קטנים. נדרש נפח אחסון של 500GiB כדי לאתחל את מודל הביצועים. |
| החיבור נדחה | מוודאים ש-PNP מאפשר באופן מפורש את targetPort (8000/8080). חומות האש של GDC לא מעניקות אוטומטית גישה ליציאות של השרתים העורפיים עבור כתובות ה-VIP של מאזן העומסים. |