מאגרים זמניים למשאבי מחשוב משפרים את מהירות התגובה והאמינות של עומסי עבודה קריטיים, על ידי ניהול יזום של קיבולת אשכולות פנויה ומצבים מושהים של קיבולת שהוקצתה והוגדרה מראש באמצעות CapacityBuffers. באמצעות מאגרים זמניים למשאבי מחשוב, אתם יכולים להגדיר במפורש כמות ספציפית של קיבולת צומת לא מנוצלת באשכול. הקיבולת הפנויה הזו עוזרת לצמצם את זמן התזמון של Pods.
כשצריך להגדיל עומס עבודה בעדיפות גבוהה, אפשר להשתמש בקיבולת הריקה בלי לחכות להקצאת הצמתים. הגישה הזו מפחיתה את זמן האחזור ומונעת תחרות על משאבים במהלך עליות פתאומיות בביקוש.
בדף הזה מוסבר איך להגדיר מאגרים זמניים למשאבי מחשוב עם רפליקה קבועה, מגבלת משאבים ואחוזים, להקצות מאגר זמני לעומס עבודה ספציפי, להתאים אישית את ההתנהגות של המאגר הזמני במצב המתנה ולטעון מראש קובצי אימג' של קונטיינרים. אם אתם משתמשים ב-ComputeClasses בהתאמה אישית ולא צריכים גדלים מותאמים אישית של יחידות מאגר, שינוי גודל לפי רפליקה או אחוזים, או זמני התחלה ורענון מותאמים אישית של מצב המתנה, הגדירו מאגרים זמניים למשאבי מחשוב ב-ComputeClasses בהתאמה אישית.
לפני שמתחילים
לפני שמתחילים, חשוב לוודא שביצעתם את המשימות הבאות:
- מפעילים את Google Kubernetes Engine API. הפעלת Google Kubernetes Engine API
- כדי להשתמש ב-Google Cloud CLI למשימה הזו, מתקינים ואז מאתחלים את ה-CLI של gcloud. אם כבר התקנתם את ה-CLI של gcloud, הריצו את הפקודה
gcloud components updateכדי להוריד את הגרסה העדכנית. יכול להיות שגרסאות קודמות של ה-CLI של gcloud לא תומכות בהרצת הפקודות שבמסמך הזה.
- ליצור או לקבל גישה לאשכול GKE שפועל בגרסה 1.37.1-gke.3020000 ואילך. כדי להשתמש במאגרי המתנה באשכולות במצב Autopilot, צריך ComputeClasses בהתאמה אישית.
- להפעיל יצירה אוטומטית של מאגרי צמתים באשכולות הרגילים. באשכולות Autopilot, היצירה האוטומטית של מאגרי צמתים כבר מופעלת. יצירה אוטומטית של מאגרי צמתים היא אופציונלית, אבל מומלצת למאגרים פעילים ונדרשת למאגרים במצב המתנה.
יצירת אובייקטים של Kubernetes שנדרשים מראש
כדי להגדיר CapacityBuffer, צריך מרחב שמות שמכיל את כל האובייקטים הנדרשים (CapacityBuffer עצמו ומשאבים נוספים כמו PodTemplate או עומס עבודה). ה-PodTemplate וה-CapacityBuffer צריכים להיות באותו מרחב שמות. אתם יכולים ליצור מרחב שמות או להשתמש במרחב שמות קיים, כולל מרחב השמות default.
בהתאם לסוג של CapacityBuffer שאתם מגדירים, תצטרכו גם אחת מהאפשרויות הבאות:
- PodTemplate: מגדיר את דרישות המשאבים ליחידה אחת של קיבולת מאגר. ההגדרה שצוינה באובייקט CapacityBuffer מפנה לתבנית Pod.
עומס עבודה: עומס עבודה קיים שאתם מפנים אליו באובייקט CapacityBuffer. במדריך הזה אנחנו משתמשים באובייקט Deployment כדוגמה לעומס עבודה, אבל מאגרים זמניים למשאבי מחשוב תומכים בכל אחד מסוגי המשאבים הבאים:
- פריסה
- ReplicaSet
- StatefulSet
- ReplicationController
- משימה
- CustomResourceDefinitions (CRD) שמטמיעים את משאב המשנה
scale.
בקטע הזה מופיעות דוגמאות לאובייקטים האלה. אם כבר יש לכם עומס עבודה שאתם רוצים להגדיר עם מאגר זמני למשאבי מחשוב, אתם יכולים לדלג לקטע החלת מאגר זמני למשאבי מחשוב.
כדי ליצור עומס עבודה לדוגמה ב-Kubernetes, מבצעים את השלבים הבאים:
שומרים את המניפסט הבא בתור
namespace.yaml:apiVersion: v1 kind: Namespace metadata: name: capacity-buffer-example labels: name: capacity-buffer-exampleהמניפסט הזה יוצר מרחב שמות בשם
capacity-buffer-example.אופציונלי: כדי להשתמש במאגרים זמניים למשאבי מחשוב עם ComputeClass בהתאמה אישית, שומרים את המניפסט הבא בתור
custom-compute-class.yaml:apiVersion: cloud.google.com/v1 kind: ComputeClass metadata: name: ccc-example spec: # Buffers are also created according to these priorities priorities: - machineFamily: n4 - machineFamily: n4d - machineFamily: c4 - machineFamily: c4d nodePoolAutoCreation: enabled: trueהמניפסט הזה יוצר
ComputeClassבהתאמה אישית שמגדיר את סדרי העדיפויות של המחשוב לצמתים ש-GKE מקצה, ושולט בהם. מידע נוסף זמין במאמר ComputeClasses בהתאמה אישית.שומרים את המניפסט הבא בתור
buffer-pod-template.yaml:apiVersion: v1 kind: PodTemplate metadata: name: buffer-unit-template namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer template: spec: terminationGracePeriodSeconds: 0 containers: - name: buffer-container image: registry.k8s.io/pause:3.9 resources: requests: cpu: "1" memory: "1Gi" limits: cpu: "1" memory: "1Gi" # Optional: Using buffers with a custom ComputeClass / # controls the properties of the provisioned nodes. nodeSelector: cloud.google.com/compute-class: ccc-exampleהמניפסט הזה יוצר
PodTemplateשמגדיר את דרישות המשאבים ליחידה אחת של קיבולת מאגר (1מעבד ו-1Giזיכרון). ההגדרה הזו מציינת את הגודל של יחידות הקיבולת ש-GKE מקצה למאגר הנתונים הזמני. לדוגמה, עם PodTemplate כזה, אם האשכול יוגדל, GKE לא יחשיב צמתים עם פחות ממעבד אחד ו-1Gi של משאבים זמינים כחלק מהמאגר.שומרים את המניפסט הבא בתור
sample-workload-deployment.yaml:apiVersion: apps/v1 kind: Deployment metadata: name: critical-workload-ref namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer spec: replicas: 10 selector: matchLabels: app: critical-workload template: metadata: labels: app: critical-workload spec: containers: - name: busybox image: busybox command: ["sleep", "3600"] resources: requests: cpu: 100m # Optional: Using buffers with a custom ComputeClass / # controls the properties of the provisioned nodes. nodeSelector: cloud.google.com/compute-class: ccc-exampleהמניפסט הזה יוצר פריסה לדוגמה עם 10 רפליקות, שהן אובייקט העזר לדוגמה של מאגר מבוסס-אחוזים בקטע הבא.
מחילים את המניפסטים על האשכול:
kubectl apply -f namespace.yaml -f custom-compute-class.yaml -f buffer-pod-template.yaml -f sample-workload-deployment.yamlמוודאים ש-GKE יצר את האובייקטים:
kubectl get podtemplate -n capacity-buffer-example kubectl get deployment critical-workload-ref -n capacity-buffer-exampleהפלט אמור להיראות כך:
NAME AGE buffer-unit-template 1m NAME READY UP-TO-DATE AVAILABLE AGE critical-workload-ref 10/10 10 10 1m
החלת מאגר זמני למשאבי מחשוב
בקטע הזה מפורטות דוגמאות לסוגים השונים של מאגרים זמניים למשאבי מחשוב שאפשר להחיל על עומסי העבודה.
הגדרת מאגר קבוע של רפליקות
כשמגדירים CapacityBuffer עם רפליקות קבועות, מציינים את המספר המדויק של יחידות המאגר שרוצים על סמך PodTemplate.
כדי ליצור מאגר עם רפליקות קבועות:
שומרים את המניפסט הבא בתור
cb-fixed-replicas.yaml:apiVersion: autoscaling.x-k8s.io/v1beta1 kind: CapacityBuffer metadata: name: fixed-replica-buffer namespace: NAMESPACE spec: podTemplateRef: name: POD_TEMPLATE replicas: 3 provisioningStrategy: "STRATEGY"מחליפים את מה שכתוב בשדות הבאים:
-
NAMESPACE: השם של מרחב השמות, לדוגמהcapacity-buffer-example. -
POD_TEMPLATE: ה-PodTemplate שמגדיר את דרישות המשאבים, לדוגמהbuffer-unit-template. STRATEGY: אסטרטגיית ההקצאה,"buffer.x-k8s.io/active-capacity"(ברירת המחדל) או"buffer.gke.io/standby-capacity".
המניפסט הזה יוצר משאב CapacityBuffer שמפנה ל-PodTemplate כדי לבקש מספר ספציפי של יחידות מאגר.
-
מחילים את המניפסט:
kubectl apply -f cb-fixed-replicas.yamlמוודאים ש-GKE החיל את המאגר הזמני למשאבי מחשוב:
kubectl get capacitybuffer fixed-replica-buffer -n NAMESPACEבשדה
replicasבסטטוס אמור להופיע הערך3, שמשקף את מספר הרפליקות שהגדרתם במניפסט. בשדהSTATUSאמור להופיע הערךReadyForProvisioning.
הגדרת מאגר זמני למגבלות על משאבים
אתם יכולים להשתמש בשדה limits כדי להגדיר את כמות המשאבים המקסימלית שהמאגר יכול לצרוך, שמחושבת על סמך הגודל של PodTemplate.
כדי ליצור מאגר למגבלות המשאבים:
שומרים את המניפסט הבא בתור
cb-resource-limits.yaml:apiVersion: autoscaling.x-k8s.io/v1beta1 kind: CapacityBuffer metadata: name: resource-limit-buffer namespace: NAMESPACE spec: podTemplateRef: name: POD_TEMPLATE limits: cpu: "5" memory: "5Gi" provisioningStrategy: "STRATEGY"מחליפים את מה שכתוב בשדות הבאים:
-
NAMESPACE: השם של מרחב השמות, לדוגמהcapacity-buffer-example. -
POD_TEMPLATE: ה-PodTemplate שמגדיר את דרישות המשאבים, לדוגמהbuffer-unit-template. STRATEGY: אסטרטגיית ההקצאה,"buffer.x-k8s.io/active-capacity"(ברירת המחדל) או"buffer.gke.io/standby-capacity".
המניפסט הזה יוצר משאב CapacityBuffer עם מגבלה כוללת של 5 מעבדים וזיכרון בנפח 5GiB. אם אתם משתמשים בדוגמה של PodTemplate מהשלב הקודם, אתם מגדירים כל יחידה כ-CPU בנפח
1וזיכרון בנפח1Gi, מה שאמור להוביל ל-5 יחידות מאגר.-
מחילים את המניפסט:
kubectl apply -f cb-resource-limits.yamlמוודאים ש-GKE החיל את המאגר הזמני למשאבי מחשוב:
kubectl get capacitybuffer resource-limit-buffer -n NAMESPACEבודקים את הסטטוס של CapacityBuffer. בשדה
replicasאמור להופיע ערך שנגזר מהמגבלות שהגדרתם. אם אתם משתמשים בדוגמה של PodTemplate מהקטע הקודם, אתם אמורים לראות5יחידות מאגר, כי זה המספר המקסימלי של יחידות שמתאימות למגבלות שהוגדרו.
הגדרת מאגר נתונים זמני שמבוסס על אחוזים
הגדרת מאגר מבוסס-אחוזים משנה באופן דינמי את גודל המאגר על סמך אחוז מעומס עבודה קיים שניתן להתאמה לעומס. אפשר להשתמש במאגרים זמניים למשאבי מחשוב שמבוססים על אחוזים רק באובייקטים של Kubernetes שניתנים להתאמה, שמטמיעים את משאב המשנה scale, כמו Deployments, StatefulSets, ReplicaSets או Jobs. אי אפשר להגדיר מאגר מבוסס-אחוזים לתבניות Pod כי אין להן שדה replicas.
ברוב המקרים, כדאי להתחיל עם אסטרטגיות של רפליקות קבועות או מגבלות משאבים, ולא עם מאגרים שמבוססים על אחוזים. כדאי להביא בחשבון את הנקודות הבאות:
- מאגרים שמבוססים על אחוזים פחות מגיבים להגדלות פתאומיות אם עומס העבודה מוגדל למספרים נמוכים או לאפס, כי מרווח הבטיחות פוחת ביחס ל-Pods הפעילים.
- צומתי המתנה צוברים חיובים על מחשוב במהלך תקופת האתחול שלהם לפני ההשעיה. התאמה דינמית של מאגרי ה-standby בהתאם לתנודות בעומס העבודה מבזבזת משאבי מחשוב, ולכן כדאי להשתמש ברפליקות קבועות או במגבלות משאבים למאגרי ה-standby.
- מאגרים מבוססי-אחוזים שימושיים בעיקר למאגרים פעילים בפריסות גדולות, שבהן מספר הרפליקות אף פעם לא קטן.
כדי לשמור על שטח אחסון זמני מינימלי כשעומס העבודה שאליו מתייחסים מצטמצם, מגדירים את השדה replicas יחד עם השדה percentage. GKE משתמש בשדה שמוביל ליותר יחידות מאגר. כדי להגביל את גודל שטח האחסון הזמני, צריך להגדיר גם את השדה limits.
לדוגמה, נניח שיש מאגר עם percentage: 20 ו-replicas: 3 שמפנה לפריסה עם 10 רפליקות. 20% מ-10 רפליקות הם 2, וזה פחות מהערך 3 של replicas, אז GKE מקצה 3 יחידות מאגר. אם הפריסה תתרחב ל-20 רפליקות, המאגר יגדל ל-4 יחידות. למידע נוסף, קראו את מאמרי העזרה של CapacityBuffer.
כדי ליצור מאגר באחוזים, מבצעים את השלבים הבאים:
שומרים את המניפסט הבא בתור
cb-percentage-based.yaml:apiVersion: autoscaling.x-k8s.io/v1beta1 kind: CapacityBuffer metadata: name: percentage-buffer namespace: NAMESPACE spec: scalableRef: apiGroup: apps kind: Deployment name: SCALABLE_RESOURCE_NAME percentage: 20 provisioningStrategy: "STRATEGY"מחליפים את מה שכתוב בשדות הבאים:
-
NAMESPACE: השם של מרחב השמות. -
SCALABLE_RESOURCE_NAME: השם של המשאב שניתן להתאמה לעומס, לדוגמהcritical-workload-ref. STRATEGY: אסטרטגיית ההקצאה,"buffer.x-k8s.io/active-capacity"(ברירת המחדל) או"buffer.gke.io/standby-capacity".
המניפסט הזה יוצר משאב CapacityBuffer שמבקש שטח אחסון זמני ששווה ל-20% מהרפליקות של המשאב שאליו מתייחסים. אם אתם משתמשים בדוגמה לפריסה מהקטע הקודם, ערך הרפליקה מוגדר ל-
10.-
מחילים את המניפסט:
kubectl apply -f cb-percentage-based.yamlמוודאים ש-GKE החיל את המאגר הזמני למשאבי מחשוב:
kubectl get capacitybuffer percentage-buffer -n NAMESPACEבודקים את הסטטוס של CapacityBuffer. בשדה
replicasצריך להופיע ערך מחישוב האחוזים. אם אתם משתמשים בדוגמה לפריסה מהקטע הקודם, אמורות להופיע2יחידות מאגר, שהן 20% מ-10 הרפליקות שהוגדרו בפריסה.כדי לבדוק את ההתאמה הדינמית לעומס, מגדילים ידנית את הפריסה ל-20 רפליקות:
kubectl scale deployment critical-workload-ref -n NAMESPACE --replicas=20הבקר CapacityBuffer מגיב ומשנה באופן אוטומטי את קנה המידה של המאגר ל-4 רפליקות.
הקצאת מאגר זמני למשאבי מחשוב לעומס עבודה ספציפי
כברירת מחדל, כל Pod בהמתנה שתואם לאילוצי התזמון של צומת מאגר יכול לתבוע את קיבולת המאגר. אם כמה עומסי עבודה משתמשים באותו מאגר של צמתים או ComputeClass בהתאמה אישית, אתם יכולים להשתמש בהפרדת עומסי עבודה כדי להקצות מאגר זמני למשאבי מחשוב לעומס עבודה ספציפי. הגישה הזו דורשת יצירה אוטומטית של מאגר צמתים, או מאגר צמתים ייעודי למאגרים פעילים באשכולות רגילים.
כדאי להימנע מהקצאת מאגרים זמניים נפרדים למשאבי מחשוב לעומסי עבודה רבים. לכל מאגר ייעודי נדרש מאגר צמתים משלו, מה שמאריך את הזמן להקצאה ולמילוי מחדש של המאגרים. בקטע מדרגיות מפורטות המלצות למספר המאגרים.
כדי להקצות מאגר זמני למשאבי מחשוב לעומס עבודה ספציפי:
במניפסט של עומס העבודה, כמו
sample-workload-deployment.yamlמיצירת אובייקטים של Kubernetes שהם דרישות קדם, מוסיפים למפרט של ה-Pod סובלנות בהתאמה אישית ובורר צמתים:spec: tolerations: - key: KEY operator: Equal value: "VALUE" effect: NoSchedule nodeSelector: KEY: "VALUE" cloud.google.com/compute-class: ccc-exampleמחליפים את מה שכתוב בשדות הבאים:
-
KEY: מפתח מותאם אישית ל-taint ולתווית של הצומת, למשלgroup. למידע על קידומות מוגבלות של מפתחות, ראו המגבלות של הפרדת עומסי עבודה. -
VALUE: ערך בהתאמה אישית שמזהה את עומס העבודה, כמוcritical-workload.
באשכולות Autopilot, צריך להשאיר את ה-ComputeClass בהתאמה אישית או את בורר החומרה בשדה
nodeSelectorכדי שהמאגר הזמני ישתמש בחיוב מבוסס-צומת במקום במודל החיוב מבוסס-Pod שלא נתמך.-
מגדירים את CapacityBuffer כך שישתמש באותם אילוצי תזמון:
- אם ה-CapacityBuffer משתמש בשדה
scalableRef, צריך להפנות לעומס העבודה בשדהspec.scalableRef. המאגר מקבל באופן אוטומטי את השדותtolerationsו-nodeSelectorשל עומס העבודה. - אם ב-CapacityBuffer נעשה שימוש בשדה
podTemplateRef, צריך להוסיף את אותם שדותtolerationsו-nodeSelectorלמניפסט של PodTemplate, כמוbuffer-pod-template.yaml.
- אם ה-CapacityBuffer משתמש בשדה
מחילים את המניפסטים ויוצרים את CapacityBuffer. איך משתמשים במאגר זמני למשאבי מחשוב אם אתם טוענים מראש תמונות במאגרי המתנה, הוסיפו גם את הסבילות בהתאמה אישית ל-DaemonSet של הטעינה מראש, כדי שתוכלו לתזמן בצומתי המאגר הייעודיים. אם המאגר משתמש ב-ComputeClass בהתאמה אישית, ה-DaemonSet צריך גם סבילות ל-taint של ComputeClass:
tolerations: - key: "buffer.gke.io/standby-capacity-node-suspended" operator: "Exists" - key: KEY operator: Equal value: "VALUE" effect: NoSchedule - key: cloud.google.com/compute-class operator: Equal value: ccc-example effect: NoScheduleאחרי שהמידרוג האוטומטי של האשכול מקצה את צומתי המאגר, מוודאים שלצמתים יש את תווית הצומת הייעודית ואת ה-taint של הצומת:
kubectl get nodes -l KEY=VALUE \ -o custom-columns='NAME:.metadata.name,TAINTS:.spec.taints[*].key'כל צומת בפלט מציג את מפתח ה-taint של
KEY. אם המאגר משתמש ב-ComputeClass בהתאמה אישית, הצמתים מציגים גם את מפתח ה-taint שלcloud.google.com/compute-class. לצומתי מאגר זמני במצב המתנה יש גם פגמים ש-GKE מנהל, כמוbuffer.gke.io/standby-capacity-node-suspendedבצמתים מושהים. כשהיקף עומס העבודה גדל, מריצים את הפקודהkubectl get pods -n NAMESPACE -o wideומוודאים שבעמודהNODEמופיעים שמות הצמתים הייעודיים מהפלט הזה.
התאמה אישית של התנהגות המאגר הזמני במצב המתנה
אתם יכולים להשתמש בהערות כדי להתאים אישית את האופן שבו מאגרי הנתונים במצב המתנה מתחילים ומתרעננים.
מוסיפים את ההערות האלה לשדה metadata.annotations של המשאב CapacityBuffer:
-
buffer.gke.io/standby-capacity-init-time: משך הזמן שבו צומת נשאר פעיל אחרי היצירה, לפני ש-GKE משעה אותו. מציינים מחרוזת משך זמן כמו5mאו1h. ערך ברירת המחדל הוא5m.
buffer.gke.io/standby-capacity-refresh-frequency: התדירות שבה GKE מרענן צמתים מושהים. מציינים מחרוזת של משך זמן, כמו12hאו24h, עד למקסימום של120h(5 ימים). ערך ברירת המחדל הוא24h.
בדוגמה הבאה מוצג מניפסט עם השדות האופציונליים האלה, שמאפשרים להתאים אישית את ההתנהגות של מאגרי הנתונים הזמניים במצב המתנה:
apiVersion: autoscaling.x-k8s.io/v1beta1
kind: CapacityBuffer
metadata:
name: customized-standby-buffer
namespace: my-namespace
annotations:
buffer.gke.io/standby-capacity-init-time: "15m"
buffer.gke.io/standby-capacity-refresh-frequency: "12h"
spec:
podTemplateRef:
name: buffer-unit-template
replicas: 3
provisioningStrategy: "buffer.gke.io/standby-capacity"
טעינה מראש של תמונות במאגרי המתנה
כדי לקצר את זמני ההפעלה של עומסי העבודה כשצומת המתנה ממשיך לפעול, אתם יכולים לטעון מראש קובצי אימג' של קונטיינרים באמצעות DaemonSet. ה-DaemonSet פועל במהלך תקופת ההפעלה לפני שהצומת מושעה.
כדי לטעון מראש תמונות באמצעות DaemonSet:
שומרים את המניפסט הבא בתור
image-puller-daemonset.yaml:apiVersion: apps/v1 kind: DaemonSet metadata: name: image-prefetch-daemonset namespace: NAMESPACE spec: selector: matchLabels: name: image-prefetch template: metadata: labels: name: image-prefetch spec: tolerations: - key: "buffer.gke.io/standby-capacity-node-suspended" operator: "Exists" initContainers: - name: image-puller image: IMAGE_NAME command: ["sh", "-c", "true"] containers: - name: pause image: registry.k8s.io/pause:3.9מחליפים את מה שכתוב בשדות הבאים:
-
NAMESPACE: מרחב השמות של DaemonSet, לדוגמהcapacity-buffer-example. -
IMAGE_NAME: שם התמונה לטעינה מראש, לדוגמהyour-app-image:latest.
המניפסט הזה כולל את הסובלנות
buffer.gke.io/standby-capacity-node-suspendedכדי שה-DaemonSet יישאר מתוזמן בצומתי המתנה אחרי ש-GKE משעה אותם.-
מחילים את המניפסט של DaemonSet על האשכול:
kubectl apply -f image-puller-daemonset.yamlמוודאים שה-DaemonSet נוצר:
kubectl get daemonset image-prefetch-daemonset -n NAMESPACEמוודאים שהמאגר הזמני למשאבי מחשוב נוצר ומוכן להקצאה:
kubectl get capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACEבודקים את הסטטוס שלו. בשדה
STATUSאמור להופיע הערךReadyForProvisioning.
מעקב אחרי הסטטוס והביצועים של המאגר הזמני למשאבי מחשוב
אתם יכולים לעקוב אחרי הסטטוס והתקינות של המאגרים הזמניים למשאבי מחשוב באמצעות פקודות kubectl ומדדים של Cloud Monitoring.
אימות סטטוס המשאב CapacityBuffer
כדי לבדוק את התקינות של המאגרים הזמניים למשאבי מחשוב ולוודא שהם מוכנים לקבל עומסי עבודה:
כדי לקבל את הסטטוס של כל המאגרים הזמניים למשאבי מחשוב באשכול:
kubectl get capacitybuffer -Aבודקים את הסטטוס המפורט, התנאים ויומני האירועים של מאגר נתונים ספציפי:
kubectl describe capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
זיהוי צומתי מאגר המתנה מושהים
מכונות וירטואליות במאגר זמני מוקצות מראש, אבל נשארות במצב מושהה כדי להפחית את העלויות. אפשר לזהות את הצמתים המושעים האלה כי יש להם תנאי בהתאמה אישית. כדי לבדוק את המכונות של הצמתים שהושעו, מריצים את הפקודה הבאה:
kubectl get nodes -o custom-columns='NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status'
הסטטוס True מציין שהמכונה הווירטואלית במצב המתנה מושעית. הסטטוס False או <none> מציין צומת פעיל שפועל.
מעקב אחרי הביצועים באמצעות Cloud Monitoring
כדי לעקוב אחרי ההשפעה מקצה לקצה של המאגרים הזמניים למשאבי מחשוב על זמני ההרחבה, אתם יכולים להשתמש בלוחות הבקרה של זמן האחזור בהפעלה במסוף Google Cloud . בתרשימים Pod Startup Latency Distribution ו-Pod First Ready Latency אפשר לעקוב אחרי המדד kubernetes.io/pod/latencies/pod_first_ready, מיצירת ה-Pod ועד שהוא מוכן. אפשר גם לשלוח שאילתות לגבי אירועי Scheduled ב-Cloud Logging כדי למדוד את זמן האחזור של תזמון Pod. הוראות מופיעות במאמר מעקב אחרי מדדי זמן האחזור בהפעלה.
הסרת מאגרים זמניים למשאבי מחשוב
אם אתם לא צריכים יותר מאגר זמני למשאבי מחשוב בשביל עומסי העבודה, אתם יכולים למחוק את האובייקט CapacityBuffer. כך מסירים את הפלייסהולדרים של Pods ומאפשרים ל-Cluster Autoscaler לצמצם את הצמתים.
kubectl delete capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
מחליפים את CAPACITY_BUFFER_NAME בשם של ה-CapacityBuffer שרוצים למחוק.
פתרון בעיות
בקטע הבא מוסבר איך לפתור בעיות נפוצות שקשורות למאגרים זמניים למשאבי מחשוב.
המאגר הזמני למשאבי מחשוב לא מוכן בגלל מודל החיוב
אם יוצרים CapacityBuffer לעומס עבודה שמשתמש במודל החיוב שמבוסס על Pod (תשלום ל-Pod), המאגר הזמני למשאבי מחשוב לא יהיה מוכן להקצאה.
כדי לזהות את הבעיה, בודקים את הסטטוס של CapacityBuffer:
kubectl describe capacitybuffer BUFFER_NAME -n NAMESPACE
מחפשים תנאי מסוג ReadyForProvisioning עם סטטוס False.
כדי לפתור את הבעיה, ודאו שה-CapacityBuffer מפנה לעומס עבודה או ל-PodTemplate שתואמים לחיוב לפי צומת.
פודים של מאגר זמני לא מתוזמנים בצמתים שהוקצו על ידי ComputeClasses בהתאמה אישית
אם התלות בהגדרות של CapacityBuffer (לדוגמה, PodTemplate) בוחרת ComputeClass בהתאמה אישית, יכול להיות שתיתקלו בבעיה שבה פודים של מאגר זמני לא מתוזמנים בצמתים שהוקצו לאחרונה. הבעיה הזו גורמת למנגנון המידרוג האוטומטי של האשכול ליצור שוב ושוב מאגרי צמתים וצמתים מיותרים, בזמן שצמתים לא פעילים נמחקים.
הבעיה הזו מתרחשת אם ה-ComputeClass בהתאמה אישית מקצה צמתים עם טיינטים או דרישות ספציפיות של זמן ריצה, ולפודים של המאגר (או ל-PodTemplate שהם מסתמכים עליו) אין טולרציות או הגדרות תואמות.
כדי לפתור את הבעיה, צריך לעדכן את ההגדרה של CapacityBuffer ולציין את ה-tolerations, ה-node selectors או ה-runtime classes הנדרשים. לדוגמה, אם התלות בוחרת ComputeClass בהתאמה אישית שמוגדר עם GKE Sandbox, צריך לעדכן את התלות כדי לבצע אחת מהפעולות הבאות:
- צריך לציין את השדה
spec.runtimeClassName: gvisor. - מוסיפים סבילות מפורשת ל-taint של
sandbox.gke.io/runtime=gvisor:NoSchedule.
מידע נוסף מופיע במאמרי העזרה בנושא ComputeClass בהתאמה אישית.
צומתי מאגר הנתונים הזמני במצב המתנה לא ממשיכים לפעול
יכול להיות שצומתי מאגר הנתונים הזמני במצב המתנה שהושעו לא יופעלו מחדש בגלל אחת מהסיבות הבאות:
- כדי להמשיך צומת המתנה מושהה, צריך קיבולת זמינה של Compute Engine באזור של סוג המכונה של הצומת ודור ספציפי של פלטפורמת המעבד, כמו בסדרת המכונות E2 או N2. אם לאזור אין מספיק קיבולת מחשוב בשביל ההגדרה המדויקת הזו, הצומת לא ימשיך לפעול. למידע נוסף, ראו מגבלות ההשעיה וההמשך של Compute Engine.
- אם ב-ComputeClass בהתאמה אישית מופעלת העברה פעילה לצמתים בעדיפות גבוהה יותר (
activeMigration.optimizeRulePriority: true) ומכונות וירטואליות במודל Spot מוגדרות בעדיפות גבוהה יותר ממכונות וירטואליות על פי דרישה, GKE מעביר עם הזמן צמתים במצב המתנה על פי דרישה למכונות וירטואליות במודל Spot. מכונות וירטואליות במחיר נמוך כפופות יותר למגבלות קיבולת, ואי אפשר להמיר מכונות וירטואליות מושהות במחיר נמוך למכונות וירטואליות על פי דרישה כשמחדשים את הפעילות שלהן. לכן, המגבלות האלה יכולות למנוע את חידוש הפעילות של צומתי ההמתנה האלה. - המשך הפעילות של הצומת חורג ממכסות Compute Engine של הפרויקט. מידע נוסף זמין במאמר הקצאת המאגר הזמני למשאבי מחשוב נכשלה בגלל מגבלות המכסה.
כדי לזהות למה צומת במצב המתנה לא חזר לפעול, שולחים שאילתה ליומני הביקורת של Compute Engine ב-Logs Explorer כדי לחפש שגיאות מסוג ZONE_RESOURCE_POOL_EXHAUSTED או QUOTA_EXCEEDED בפעולות של compute.instances.resume.
כדי לפתור או לצמצם את הבעיה, נסו אחד או יותר מהפתרונות הבאים:
- להשתמש באשכולות אזוריים כדי שהמידרוג האוטומטי של האשכול יוכל להקצות או להמשיך צמתים בכמה אזורים.
- מגדירים כמה משפחות מכונות ברשימה
spec.prioritiesשל ה-ComputeClass בהתאמה אישית. אם אי אפשר להמשיך את הצמתים שהושעו, המידרוג האוטומטי של האשכול יכול לחזור ליצירת צמתים חדשים על סמך כלל עדיפות אחר. לצמתים החדשים האלה לוקח יותר זמן להיות מוכנים מאשר לצמתים במצב המתנה שהופעלו מחדש. ההגדרה הזו לא עוזרת לצמתים מושעים להמשיך, כי צומת מושעה יכול להמשיך רק עם סוג המכונה המקורי שלו. - משתמשים ב-ComputeClass ייעודי בהתאמה אישית עם מכונות וירטואליות על פי דרישה, או מגדירים את השדה
activeMigration.optimizeRulePriorityלערךfalseב-ComputeClass שבו משתמש מאגר ה-Standby. - כדאי לשלב את מאגר הנתונים הזמני במצב המתנה עם מאגר נתונים זמני קטן במצב פעיל, כדי לספוג עליות חדות מיידיות בתנועה.
המאגר הזמני למשאבי מחשוב לא מוקצה בגלל מגבלות המכסה
יכול להיות שהמאגר הזמני למשאבי מחשוב יקצה פחות רפליקות מהכמות שביקשתם, או שלא יצליח להגדיל את מספר הרפליקות אם הוא חורג מהמכסות של Kubernetes ResourceQuotas או של Compute Engine.
כדי לזהות איזו מכסה מגבילה את המאגר, בודקים אחת או יותר מהמכסות הבאות:
בודקים אם ResourceQuota של Kubernetes במרחב השמות מגביל את המאגר:
kubectl describe capacitybuffer \ CAPACITY_BUFFER_NAME \ -n NAMESPACEבפלט של
status.conditions, מחפשים תנאיLimitedByQuotasעם הסטטוסTrue. כל יחידות המאגר הפעילות והיחידות במצב המתנה, כולל יחידות שמגובות על ידי צומתי המתנה מושעים, נספרות במגבלות ResourceQuota של מרחב השמות כאילו הפודים של המאגר פועלים. אם מאגר נתונים זמני חורג מהמכסה של מרחב השמות, GKE מגביל את השדהstatus.replicasכך שיתאים למכסה הזמינה.בודקים אם מכסות הפרויקט ב-Compute Engine חוסמות את הקצאת הצמתים. ב-Logs Explorer, מחפשים אירועים מסוג
no.scale.up.nap.quota.exceededביומןcontainer.googleapis.com/cluster-autoscaler-visibility, או מחפשים שגיאות מסוגQUOTA_EXCEEDEDביומני הביקורת של Compute Engine.כשבודקים את המכסות של Compute Engine למאגרי המתנה, צריך לוודא את שתי המכסות הבאות בנוסף למכסות של vCPU וזיכרון:
- צומתי המתנה מושעים שומרים על כתובות ה-IP הפנימיות וכתובות ה-IP החיצוניות שלהם, מה שצורך את מכסת כתובות ה-IP שבשימוש.
- כשמשהים מכונת VM במצב המתנה, המערכת של Compute Engine כותבת את הזיכרון של הצומת בדיסק, וזה צורך מכסת דיסק של
Persistent disk standard (GB)באופן יחסי לגודל הזיכרון של הצומת.
כדי לפתור את הבעיה, אתם יכולים לבצע אחת מהפעולות הבאות:
- מגדילים את Kubernetes ResourceQuota במרחב השמות של המאגר הזמני.
- בקשה לשינוי המכסות ב-Compute Engine
- מפחיתים את הערך של
replicas,limitsאוpercentageבמניפסט של CapacityBuffer.
פודים של DaemonSet מפסיקים לקבל נתונים אחרי שצומת במצב המתנה ממשיך לפעול
אחרי שצומת מאגר מושעה במצב המתנה ממשיך לפעול, יכול להיות שפודים של DaemonSet בצומת הזה יפסיקו לקבל נתונים דרך חיבורים ארוכי טווח שנפתחו לפני שהצומת הושעה. ה-Pods לא מתעדים שגיאות ולא מתחברים מחדש.
הבעיה הזו מתרחשת כש-DaemonSet Pod פועל כלקוח לקבלה בלבד, למשל לתגובת HTTP בסטרימינג, לחיבור WebSocket, לאירועים שנשלחים מהשרת או לקריאת gRPC לסטרימינג מהשרת. בזמן שהצומת בהמתנה מושעה, פג הזמן הקצוב לתפוגה של השרת או של מכשיר רשת ביניים, והחיבור נסגר. כשהצומת ממשיך לפעול, מקבץ הרשת (network stack) של ה-Pod עדיין מחשיב את החיבור כפתוח. מכיוון שה-Pod לא שולח נתונים, הוא אף פעם לא מזהה שהחיבור נסגר וממתין לנתונים ללא הגבלת זמן.
כדי לפתור את הבעיה, צריך להגדיר את אפליקציית הלקוח ב-DaemonSet Pod לזיהוי חיבורים סגורים ולהתחבר מחדש, באחת מהדרכים הבאות:
- מגדירים את ה-TCP keepalive בצד הלקוח באפליקציה של ה-Pod (הפעלת keepalive רק בשרת לא שולחת התראה ל-Pod). מידע נוסף על הפרמטרים של TCP keepalive מופיע במאמר חיבורים במצב פעילות (idle).
- מפעילים את אפשרות השקע
SO_KEEPALIVEבספריית הלקוח או בסביבת זמן הריצה של השפה, כמוsocket.setKeepAlive(true, initialDelay)ב-Node.js אוnet.Dialer.KeepAliveב-Go. בחלק מסביבות זמן הריצה, האפשרות TCP keepalive מושבתת כברירת מחדל. - מגדירים זמן קצר של חוסר פעילות ב-keepalive (
TCP_KEEPIDLE), למשל כמה שניות, במקום להסתמך על ברירת המחדל של מערכת ההפעלה. - עדכנו את האפליקציה כך שתתפוס את שגיאת החיבור (כמו איפוס החיבור או זמן קצוב לתפוגה) כשבדיקת ה-keepalive נכשלת, ותפתח חיבור חדש.
- מפעילים את אפשרות השקע
- הגדירו אותות חיים (heartbeats) ברמת האפליקציה או קריאת פסקי זמן בלקוח, כמו מסגרות פינג ופונג של WebSocket או פינגים של gRPC keepalive, ועדכנו את האפליקציה כך שתתחבר מחדש כשמתרחש פסק זמן.
המאמרים הבאים
- איך מגדירים מאגרים זמניים למשאבי מחשוב ב-ComputeClasses בהתאמה אישית
- מידע נוסף על מאגרים זמניים למשאבי מחשוב
- למאמרי העזרה בנושא CapacityBuffer