בדף הזה מוסבר איך להגדיר את התשתית שלכם להרחבה אוטומטית באמצעות Horizontal Pod Autoscaler (HPA) של GKE כדי לפרוס את המודל הגדול של שפה (LLM) Gemma באמצעות JetStream במארח יחיד.
מידע נוסף על בחירת מדדים להתאמה אוטומטית לעומס זמין במאמר שיטות מומלצות להתאמה אוטומטית לעומס של עומסי עבודה של מודלים גדולים של שפה (LLM) באמצעות TPU ב-GKE.
לפני שמתחילים
לפני שמתחילים, חשוב לוודא שביצעתם את הפעולות הבאות:
- מפעילים את ממשק ה-API של Google Kubernetes Engine. הפעלת Google Kubernetes Engine API
- אם רוצים להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז להפעיל את ה-CLI של gcloud. אם התקנתם בעבר את ה-CLI של gcloud, מריצים את הפקודה
gcloud components updateכדי לקבל את הגרסה העדכנית. יכול להיות שגרסאות קודמות של ה-CLI של gcloud לא יתמכו בהרצת הפקודות שמופיעות במסמך הזה.
- כדאי לעיין בתהליך העבודה במאמר Serve Gemma using TPUs on GKE with JetStream ולבצע אותו. מוודאים שהארגומנט PROMETHEUS_PORT מוגדר במניפסט הפריסה של JetStream.
התאמה אוטומטית של הקיבולת באמצעות מדדים
אתם יכולים להשתמש במדדי הביצועים הספציפיים לעומס העבודה שמופקים על ידי שרת ההיקש של JetStream או במדדי הביצועים של TPU כדי לכוון את ההתאמה האוטומטית לעומס של ה-Pods.
כדי להגדיר התאמה אוטומטית לעומס באמצעות מדדים:
ייצוא המדדים משרת JetStream אל Cloud Monitoring. אתם משתמשים בשירות המנוהל של Google Cloud ל-Prometheus, שמפשט את הפריסה וההגדרה של כלי האיסוף של Prometheus. השירות המנוהל של Google Cloud ל-Prometheus מופעל כברירת מחדל באשכול GKE, אבל אפשר גם להפעיל אותו באופן ידני.
במניפסט לדוגמה הבא מוצג איך מגדירים את ההגדרות של משאב PodMonitoring כדי להנחות את השירות המנוהל של Google Cloud ל-Prometheus לבצע סקריפט של מדדים מה-Pods במרווחי זמן חוזרים של 15 שניות:
אם אתם צריכים לגרד מדדים של שרתים, אתם יכולים להשתמש במניפסט הבא. במדדי שרת, יש תמיכה במרווחי גירוד בתדירות של עד 5 שניות.
apiVersion: monitoring.googleapis.com/v1 kind: PodMonitoring metadata: name: jetstream-podmonitoring spec: selector: matchLabels: app: maxengine-server endpoints: - interval: 15s path: "/" port: PROMETHEUS_PORT targetLabels: metadata: - pod - container - nodeאם אתם צריכים לגרד מדדים של TPU, אתם יכולים להשתמש במניפסט הבא. במדדי מערכת, מרווחי גירוד בתדירות של עד 15 שניות נתמכים.
apiVersion: monitoring.googleapis.com/v1 kind: PodMonitoring metadata: name: tpu-metrics-exporter namespace: kube-system labels: k8s-app: tpu-device-plugin spec: endpoints: - port: 2112 interval: 15s selector: matchLabels: k8s-app: tpu-device-pluginמתקינים מתאם מדדים. המתאם הזה מאפשר לבקר HPA לראות את מדדי השרת שייצאתם ל-Monitoring. פרטים נוספים זמינים במאמר בנושא שינוי אוטומטי של מספר העותקים של הפודים במסמכי התיעוד של השירות המנוהל של Google Cloud ל-Prometheus.
- אם רוצים ש-JetStream יתאים את עצמו למדדים ספציפיים, אפשר להשתמש במתאם Stackdriver למדדים מותאמים אישית.
- אם רוצים שהמערכת של JetStream תתאים את עצמה לערך של ביטוי שמורכב מכמה מדדים שונים, אפשר להשתמש במתאם Prometheus של צד שלישי.
Custom Metrics Stackdriver Adapter
החל מגרסה v0.13.1 של המתאם, אפשר להשתמש במתאם Custom Metrics Stackdriver כדי לשלוח שאילתות לגבי מדדים מהשירות המנוהל של Google Cloud ל-Prometheus.
כדי להתקין את Custom Metrics Stackdriver Adapter:
מגדירים אוסף מנוהל באשכול.
מתקינים את Custom Metrics Stackdriver Adapter באשכול.
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yamlאם הפעלתם איחוד זהויות של עומסי עבודה ל-GKE באשכול Kubernetes ואתם משתמשים באיחוד זהויות של עומסי עבודה ל-GKE, אתם צריכים גם להעניק את התפקיד 'צפייה ב-Monitoring' לחשבון השירות שבו פועל המתאם. מחליפים את
PROJECT_IDבמזהה הפרויקט.
export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format 'get(projectNumber)') gcloud projects add-iam-policy-binding projects/PROJECT_ID \ --role roles/monitoring.viewer \ --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapterPrometheus Adapter
חשוב לקחת בחשבון את הנקודות הבאות כשמשתמשים ב-
prometheus-adapterכדי לשנות את קנה המידה באמצעות השירות המנוהל של Google Cloud ל-Prometheus:- הפניית שאילתות דרך פרוקסי של ממשק המשתמש הקצה של Prometheus, בדיוק כמו כשמבצעים שאילתות בשירות המנוהל של Google Cloud ל-Prometheus באמצעות Prometheus API או ממשק המשתמש. הקצה הקדמי הזה מותקן בשלב מאוחר יותר.
- כברירת מחדל, הארגומנט
prometheus-urlשלprometheus-adapterDeployment מוגדר ל---prometheus-url=http://frontend.default.svc:9090/, כאשרdefaultהוא מרחב השמות שבו פרסתם את חזית האתר. אם פרסתם את חזית האתר במרחב שמות אחר, צריך להגדיר את הארגומנט הזה בהתאם. - בשדה
.seriesQueryבהגדרת הכללים, אי אפשר להשתמש בביטוי רגולרי (regex) להתאמה בשם של מדד. במקום זאת, מציינים את שמות המדדים באופן מלא.
יכול להיות שיעבור קצת יותר זמן עד שהנתונים יהיו זמינים בשירות המנוהל של Google Cloud ל-Prometheus בהשוואה ל-Prometheus במעלה הזרם, ולכן הגדרת לוגיקה של התאמה אוטומטית לעומס שפועלת מהר מדי עלולה לגרום להתנהגות לא רצויה. למרות שאין ערובה לרעננות הנתונים, בדרך כלל הנתונים זמינים לשאילתה 3-7 שניות אחרי שהם נשלחים אל השירות המנוהל של Google Cloud ל-Prometheus, לא כולל חביון ברשת.
כל השאילתות שהונפקו על ידי
prometheus-adapterהן בהיקף גלובלי. המשמעות היא שאם יש לכם אפליקציות בשני מרחבי שמות שפולטות מדדים עם שמות זהים, הגדרת HPA שמשתמשת במדד הזה תבצע שינוי גודל באמצעות נתונים משתי האפליקציות. כדי להימנע מהרחבת קנה מידה באמצעות נתונים שגויים, תמיד משתמשים במסנניםnamespaceאוclusterב-PromQL.כדי להגדיר דוגמה להגדרת HPA באמצעות
prometheus-adapterואוסף מנוהל, פועלים לפי השלבים הבאים:- מגדירים אוסף מנוהל באשכול.
פורסים את שרת ה-Proxy של ממשק המשתמש הקדמי של Prometheus באשכול. יוצרים את קובץ המניפסט הבא בשם
prometheus-frontend.yaml:apiVersion: apps/v1 kind: Deployment metadata: name: frontend spec: replicas: 2 selector: matchLabels: app: frontend template: metadata: labels: app: frontend spec: automountServiceAccountToken: true affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/arch operator: In values: - arm64 - amd64 - key: kubernetes.io/os operator: In values: - linux containers: - name: frontend image: gke.gcr.io/prometheus-engine/frontend:v0.8.0-gke.4 args: - "--web.listen-address=:9090" - "--query.project-id=PROJECT_ID" ports: - name: web containerPort: 9090 readinessProbe: httpGet: path: /-/ready port: web securityContext: allowPrivilegeEscalation: false capabilities: drop: - all privileged: false runAsGroup: 1000 runAsNonRoot: true runAsUser: 1000 livenessProbe: httpGet: path: /-/healthy port: web --- apiVersion: v1 kind: Service metadata: name: prometheus spec: clusterIP: None selector: app: frontend ports: - name: web port: 9090לאחר מכן, מחילים את המניפסט:
kubectl apply -f prometheus-frontend.yamlכדי לוודא ש-
prometheus-adapterמותקן באשכול, מתקינים את תרשים ה-Helmprometheus-community/prometheus-adapter. יוצרים את הקובץvalues.yamlהבא:rules: default: false external: - seriesQuery: 'jetstream_prefill_backlog_size' resources: template: <<.Resource>> name: matches: "" as: "jetstream_prefill_backlog_size" metricsQuery: avg(<<.Series>>{<<.LabelMatchers>>,cluster="CLUSTER_NAME"}) - seriesQuery: 'jetstream_slots_used_percentage' resources: template: <<.Resource>> name: matches: "" as: "jetstream_slots_used_percentage" metricsQuery: avg(<<.Series>>{<<.LabelMatchers>>,cluster="CLUSTER_NAME"}) - seriesQuery: 'memory_used' resources: template: <<.Resource>> name: matches: "" as: "memory_used_percentage" metricsQuery: avg(memory_used{cluster="CLUSTER_NAME",exported_namespace="default",container="jetstream-http"}) / avg(memory_total{cluster="CLUSTER_NAME",exported_namespace="default",container="jetstream-http"})לאחר מכן משתמשים בקובץ הזה כקובץ הערכים לפריסת תרשים ה-Helm:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts && helm repo update && helm install example-release prometheus-community/prometheus-adapter -f values.yaml
אם אתם משתמשים ב-איחוד זהויות של עומסי עבודה ל-GKE, אתם צריכים גם להגדיר ולאשר חשבון שירות על ידי הפעלת הפקודות הבאות:
קודם יוצרים את חשבונות השירות Google Cloud בתוך האשכול:
gcloud iam service-accounts create prom-frontend-sa && kubectl create sa prom-frontend-saלאחר מכן, מקשרים בין שני חשבונות השירות. חשוב להחליף את
PROJECT_IDבמזהה הפרויקט:gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:PROJECT_ID.svc.id.goog[default/prom-frontend-sa]" \ jetstream-iam-sa@PROJECT_ID.iam.gserviceaccount.com \ && kubectl annotate serviceaccount \ --namespace default \ prom-frontend-sa \ iam.gke.io/gcp-service-account=jetstream-iam-sa@PROJECT_ID.iam.gserviceaccount.comלאחר מכן, מקצים לחשבון השירות
monitoring.viewerאת התפקידmonitoring.viewer: Google Cloudgcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:jetstream-iam-sa@PROJECT_ID.iam.gserviceaccount.com \ --role=roles/monitoring.viewerלבסוף, מגדירים את חשבון השירות של פריסות ה-frontend כחשבון השירות החדש בתוך האשכול:
kubectl set serviceaccount deployment frontend prom-frontend-sa
מגדירים את משאב ה-HPA שמבוסס על מדדים. פורסים משאב HPA שמבוסס על מדד השרת המועדף. פרטים נוספים זמינים במאמר בנושא שינוי אוטומטי של מספר העותקים של הפודים במאמרי העזרה של השירות המנוהל של Google Cloud ל-Prometheus. ההגדרה הספציפית של HPA תלויה בסוג המדד (שרת או TPU) ובמתאם המדדים שהותקן.
יש כמה ערכים שנדרשים בכל ההגדרות של HPA, וצריך להגדיר אותם כדי ליצור משאב HPA:
- MIN_REPLICAS: מספר הרפליקות המינימלי של פודים של JetStream שמותר. אם לא משנים את מניפסט הפריסה של JetStream מהשלב Deploy JetStream, מומלץ להגדיר את הערך הזה כ-1.
- MAX_REPLICAS: המספר המקסימלי של רפליקות של פודים של JetStream שמותר להשתמש בהן. הפריסה לדוגמה של JetStream דורשת 8 שבבים לכל עותק, ומאגר הצמתים מכיל 16 שבבים. אם רוצים לשמור על זמן אחזור נמוך של הגדלת הקיבולת, מגדירים את הערך הזה ל-2. ערכים גדולים יותר מפעילים את התכונה Cluster Autoscaler ליצירת צמתים חדשים במאגר הצמתים, וכך מגדילים את זמן האחזור של הגדלת הקיבולת.
TARGET: הממוצע הממוקד של המדד הזה בכל המופעים של JetStream. במסמכי התיעוד של Kubernetes בנושא התאמה אוטומטית לעומס (automatic scaling) יש מידע נוסף על האופן שבו נקבע מספר הרפליקות מהערך הזה.
Custom Metrics Stackdriver Adapter
מתאם Stackdriver של מדדים בהתאמה אישית תומך בהרחבת עומס העבודה באמצעות הערך הממוצע של שאילתות מדדים נפרדות מהשירות המנוהל של Google Cloud ל-Prometheus בכל ה-Pods. כשמשתמשים במתאם Stackdriver של מדדים מותאמים אישית, מומלץ להשתמש במדדי השרת
jetstream_prefill_backlog_sizeו-jetstream_slots_used_percentageובמדד TPUmemory_usedכדי להגדיל את קנה המידה.כדי ליצור מניפסט HPA לצורך שינוי גודל באמצעות מדדי שרת, יוצרים את הקובץ
hpa.yamlהבא:apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: jetstream-hpa namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: maxengine-server minReplicas: MIN_REPLICAS maxReplicas: MAX_REPLICAS metrics: - type: Pods pods: metric: name: prometheus.googleapis.com|jetstream_METRIC|gauge target: type: AverageValue averageValue: TARGETכשמשתמשים במתאם Stackdriver של מדדים מותאמים אישית עם מדדי TPU, מומלץ להשתמש רק במדד
kubernetes.io|node|accelerator|memory_usedלצורך שינוי קנה מידה. כדי ליצור מניפסט HPA לצורך שינוי קנה מידה באמצעות המדד הזה, יוצרים את הקובץhpa.yamlהבא:apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: jetstream-hpa namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: maxengine-server minReplicas: MIN_REPLICAS maxReplicas: MAX_REPLICAS metrics: - type: External external: metric: name: prometheus.googleapis.com|memory_used|gauge selector: matchLabels: metric.labels.container: jetstream-http metric.labels.exported_namespace: default target: type: AverageValue averageValue: TARGETPrometheus Adapter
Prometheus Adapter תומך בהרחבת נפח העבודה באמצעות הערך של שאילתות PromQL מהשירות המנוהל של Google Cloud ל-Prometheus. קודם לכן הגדרתם את מדדי השרת
jetstream_prefill_backlog_sizeו-jetstream_slots_used_percentageשמייצגים את הערך הממוצע בכל ה-Pods.כדי ליצור מניפסט HPA לצורך שינוי גודל באמצעות מדדי שרת, יוצרים את הקובץ
hpa.yamlהבא:apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: jetstream-hpa namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: maxengine-server minReplicas: MIN_REPLICAS maxReplicas: MAX_REPLICAS metrics: - type: External external: metric: name: jetstream_METRIC target: type: AverageValue averageValue: TARGETכדי ליצור מניפסט HPA לצורך שינוי קנה מידה באמצעות מדדי TPU, מומלץ להשתמש רק ב-
memory_used_percentageשמוגדר בקובץ הערכים של prometheus-adapter helm. memory_used_percentageהוא השם שניתן לשאילתת PromQL הבאה, שמשקפת את ממוצע הזיכרון הנוכחי שנעשה בו שימוש בכל המאיצים:avg(kubernetes_io:node_accelerator_memory_used{cluster_name="CLUSTER_NAME"}) / avg(kubernetes_io:node_accelerator_memory_total{cluster_name="CLUSTER_NAME"})כדי ליצור מניפסט HPA לצורך שינוי גודל באמצעות
memory_used_percentage, יוצרים את קובץhpa.yamlהבא:apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: jetstream-hpa namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: maxengine-server minReplicas: MIN_REPLICAS maxReplicas: MAX_REPLICAS metrics: - type: External external: metric: name: memory_used_percentage target: type: AverageValue averageValue: TARGET
התאמה באמצעות כמה מדדים
אפשר גם להגדיר שינוי גודל על סמך כמה מדדים. מידע על האופן שבו נקבע מספר הרפליקות באמצעות מדדים שונים זמין במאמרי העזרה של Kubernetes בנושא התאמה אוטומטית לעומס. כדי ליצור מניפסט HPA מהסוג הזה, צריך לאסוף את כל הערכים מהשדה spec.metrics של כל משאב HPA למשאב HPA יחיד. בקטע הקוד הבא אפשר לראות דוגמה לאופן שבו אפשר לאגד את משאבי ה-HPA:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: jetstream-hpa-multiple-metrics
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: maxengine-server
minReplicas: MIN_REPLICAS
maxReplicas: MAX_REPLICAS
metrics:
- type: Pods
pods:
metric:
name: jetstream_METRIC
target:
type: AverageValue
averageValue: JETSTREAM_METRIC_TARGET
- type: External
external:
metric:
name: memory_used_percentage
target:
type: AverageValue
averageValue: EXTERNAL_METRIC_TARGET
מעקב ובדיקה של התאמה אוטומטית לעומס
אתם יכולים לראות איך עומסי העבודה של JetStream משתנים בהתאם להגדרות של HPA.
כדי לראות את מספר העותקים בזמן אמת, מריצים את הפקודה הבאה:
kubectl get hpa --watch
הפלט של הפקודה הזו אמור להיראות כך:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
jetstream-hpa Deployment/maxengine-server 0/10 (avg) 1 2 1 1m
כדי לבדוק את היכולת של HPA לבצע שינוי גודל, משתמשים בפקודה הבאה ששולחת פרץ של 100 בקשות לנקודת הקצה של המודל. הפעולה הזו תגרום לניצול מלא של משבצות הפענוח הזמינות, וליצירת עומס של בקשות בתור למילוי מראש. כתוצאה מכך, ה-HPA יגדיל את גודל ה-Deployment (פריסה) של המודל.
seq 100 | xargs -P 100 -n 1 curl --request POST --header "Content-type: application/json" -s localhost:8000/generate --data '{ "prompt": "Can you provide a comprehensive and detailed overview of the history and development of artificial intelligence.", "max_tokens": 200 }'
המאמרים הבאים
- איך מבצעים אופטימיזציה של התאמה אוטומטית לעומס של Pod על סמך מדדים מ-Cloud Monitoring
- מידע נוסף על התאמה אופקית של קבוצות Pod לעומס זמין במסמכי התיעוד של Kubernetes בקוד פתוח.