להגדיר התאמה אוטומטית לעומס (autoscaling) לעומסי עבודה של מודלים גדולים של שפה (LLM) ב-Google Kubernetes Engine (GKE) שפועל ב-TPU, באמצעות Horizontal Pod Autoscaler (HPA) ו-JetStream במארח יחיד. כך תוכלו לנהל ביעילות עומסי עבודה משתנים של הסקת מסקנות ב-LLM, לייעל את ניצול המשאבים ולשמור על ביצועים עקביים באפליקציות שלכם.
ה-HPA משנה אוטומטית את מספר העותקים של הפוד על סמך ניצול ה-CPU שנצפה או מדדים מותאמים אישית אחרים. JetStream מאפשר לפרוס מודלי LLM ולהגדיל את השימוש בהם בצורה יעילה. במאמר שיטות מומלצות להתאמה אוטומטית לעומס של עומסי עבודה של LLM עם יחידות TPU ב-GKE מוסבר איך לבחור מדדים להתאמה אוטומטית לעומס.
לפני שמתחילים
לפני שמתחילים, חשוב לוודא שביצעתם את המשימות הבאות:
- מפעילים את ממשק ה-API של Google Kubernetes Engine. הפעלת Google Kubernetes Engine API
- כדי להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז לאתחל את ה-CLI של gcloud. אם כבר התקנתם את ה-CLI של gcloud, הריצו את הפקודה
gcloud components updateכדי לקבל את הגרסה העדכנית. יכול להיות שבגרסאות קודמות של ה-CLI של gcloud אי אפשר להריץ את הפקודות שבמסמך הזה.
- קוראים את המאמר הצגת Gemma באמצעות יחידות TPU ב-GKE עם JetStream ומבצעים את תהליך העבודה שמתואר בו. מוודאים שהארגומנט PROMETHEUS_PORT מוגדר במניפסט הפריסה של JetStream.
שינוי קנה מידה אוטומטי באמצעות מדדים
אתם יכולים להשתמש במדדי ביצועים ספציפיים לעומס העבודה שמופקים על ידי שרת ההסקה של JetStream או במדדי ביצועים של TPU כדי לכוון את קנה המידה האוטומטי של ה-Pods.
כדי להגדיר התאמה אוטומטית לעומס (automatic scaling) באמצעות מדדים:
ייצוא המדדים משרת 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 יתאים את עצמו למדדים ספציפיים, אפשר להשתמש ב-Custom Metrics Stackdriver Adapter.
- אם רוצים שהמערכת של JetStream תתאים את עצמה לערך של ביטוי שמורכב מכמה מדדים שונים, אפשר להשתמש במתאם Prometheus של צד שלישי.
מתאם של מדדים מותאמים אישית ל-Stackdriver
החל מגרסה 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-adapterמתאם Prometheus
חשוב להביא בחשבון את הנקודות הבאות כשמשתמשים ב-
prometheus-adapterכדי לשנות את קנה המידה באמצעות השירות המנוהל של Google Cloud ל-Prometheus:- מעבירים שאילתות דרך שרת ה-proxy של ממשק המשתמש של Prometheus, בדיוק כמו כששולחים שאילתות לשירות המנוהל של Google Cloud ל-Prometheus באמצעות ה-API או ממשק המשתמש של Prometheus. ההתקנה של ממשק המשתמש הזה מתבצעת בשלב מאוחר יותר.
- כברירת מחדל, הארגומנט
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, אתם צריכים גם להגדיר ולאשר חשבון שירות על ידי הפעלת הפקודות הבאות:
יוצרים חשבון שירות ב-Kubernetes:
kubectl create sa prom-frontend-saמקצים לחשבון השירות של Kubernetes את התפקיד Monitoring Viewer (
roles/monitoring.viewer) בפרויקט: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/default/sa/prom-frontend-sa \ --condition=Noneמחליפים את
PROJECT_IDבמזהה הפרויקט.מגדירים את הפריסה
frontendכך שתשתמש בחשבון השירותprom-frontend-sa: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 בנושא התאמה אוטומטית לעומס מוסבר איך מספר הרפליקות נקבע לפי הערך הזה.
מתאם של מדדים מותאמים אישית ל-Stackdriver
מתאם 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: TARGETמתאם Prometheus
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 בנושא התאמה אוטומטית לעומס (automatic scaling). כדי ליצור מניפסט 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 בקוד פתוח.