אתם יכולים להגדיר התאמה אוטומטית לעומס (autoscaling) לעומסי העבודה של מודל שפה גדול (LLM) ב-Google Kubernetes Engine (GKE) שפועל ב-TPU, באמצעות Horizontal Pod Autoscaler (HPA) ו-JetStream במארח יחיד. כך תוכלו לנהל ביעילות עומסי עבודה משתנים של הסקת מסקנות מ-LLM, לבצע אופטימיזציה של ניצול המשאבים ולהבטיח ביצועים עקביים של האפליקציות.
ה-HPA משנה באופן אוטומטי את מספר העותקים של הפוד על סמך ניצול ה-CPU שנצפה או מדדים מותאמים אישית אחרים. JetStream מאפשרת פריסה של מודלים גדולים של שפה (LLM), וכך מאפשרת הרחבה יעילה. למידע על שיטות מומלצות לבחירת מדדים להתאמה אוטומטית של גודל האשכול, אפשר לעיין במאמר שיטות מומלצות להתאמה אוטומטית של גודל האשכול לעומסי עבודה של מודלים גדולים של שפה (LLM) באמצעות TPU ב-GKE.
לפני שמתחילים
לפני שמתחילים, חשוב לוודא שביצעתם את הפעולות הבאות:
- מפעילים את ממשק Google Kubernetes Engine API. הפעלת 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 Adapter של צד שלישי.
Custom Metrics Stackdriver Adapter
החל מגרסה v0.13.1 של המתאם, אפשר להשתמש במתאם Custom Metrics Stackdriver כדי לשלוח שאילתות לגבי מדדים מהשירות המנוהל של Google Cloud ל-Prometheus.
כדי להתקין את המתאם של Stackdriver למדדים מותאמים אישית:
מגדירים אוסף מנוהל באשכול.
מתקינים את 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 בנושא שינוי גודל אוטומטי יש מידע נוסף על האופן שבו נקבע מספר הרפליקות מהערך הזה.
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 תומך בהתאמה לעומס (scaling) של עומס העבודה באמצעות הערך של שאילתות 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 להגדלת הגודל של פריסת המודל.
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 לעומס זמין במסמכי התיעוד של Kubernetes בקוד פתוח.