מאגרי קיבולת משפרים את מהירות התגובה והאמינות של עומסי עבודה קריטיים. הם עושים זאת באמצעות ניהול פרואקטיבי של קיבולת עודפת של אשכולות ומצבים מושהים של קיבולת שהוקצתה מראש והוגדרה מראש, באמצעות CapacityBuffer CustomResourceDefinition (CRD) של Kubernetes. שימוש במאגרי קיבולת מאפשר לכם להגדיר במפורש כמות מסוימת של קיבולת צומת לא בשימוש באשכול. הקיבולת השמורה הזו עוזרת לקצר את זמן התזמון של ה-Pod.
כשעומס עבודה בעדיפות גבוהה צריך להתרחב במהירות, עומס העבודה החדש יכול להשתמש בקיבולת הפנויה באופן מיידי בלי לחכות להקצאת צמתים. הגישה הזו מצמצמת את זמן האחזור ומונעת תחרות על משאבים במהלך עליות פתאומיות בביקוש.
בדף הזה מוסברות שיטות להגדרת מאגרי קיבולת: מאגר קבוע של רפליקות, מאגר של מגבלות משאבים ומאגר שמבוסס על אחוזים.
לפני שמתחילים
לפני שמתחילים, חשוב לוודא שביצעתם את הפעולות הבאות:
- מפעילים את ממשק Google Kubernetes Engine API. הפעלת Google Kubernetes Engine API
- כדי להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז להפעיל את gcloud CLI. אם התקנתם בעבר את ה-CLI של gcloud, מריצים את הפקודה
gcloud components updateכדי לקבל את הגרסה העדכנית. יכול להיות שגרסאות קודמות של ה-CLI של gcloud לא יתמכו בהרצת הפקודות שמופיעות במסמך הזה.
- צריך ליצור אשכול GKE בגרסה 1.35.2-gke.1842000 עבור מאגרי נתונים פעילים, או בגרסה 1.36.0-gke.2253000 ואילך עבור מאגרי נתונים במצב המתנה, או לקבל גישה לאשכול כזה.
- מפעילים הקצאת משאבים אוטומטית של צמתים באשכולות רגילים. בקטגוריות של Autopilot, ניהול ההקצאות האוטומטי של הצמתים כבר מופעל. הקצאת משאבים אוטומטית לצמתים היא אופציונלית אבל מומלצת למאגרי זיכרון פעילים, ונדרשת למאגרי זיכרון במצב המתנה.
יצירת אובייקטים של Kubernetes שנדרשים מראש
כדי להגדיר CapacityBuffer, צריך מרחב שמות שמכיל את כל האובייקטים הנדרשים (ה-CapacityBuffer עצמו ומשאבים נוספים כמו PodTemplate או עומס עבודה). ה-PodTemplate וה-CapacityBuffer צריכים להיות באותו מרחב שמות. אתם יכולים ליצור מרחב שמות או להשתמש במרחב שמות קיים, כולל מרחב השמות default.
בהתאם לסוג ה-CapacityBuffer שאתם מגדירים, תצטרכו גם אחת מהאפשרויות הבאות:
- PodTemplate: מגדיר את דרישות המשאבים ליחידה אחת של קיבולת מאגר. ההגדרה שצוינה באובייקט CapacityBuffer מפנה לתבנית ה-Pod.
עומס עבודה: עומס עבודה קיים שמופיע בהפניה באובייקט CapacityBuffer. במדריך הזה נעשה שימוש באובייקט Deployment כדוגמה לעומס עבודה, אבל מאגרי קיבולת תומכים בכל אחד מסוגי המשאבים הבאים:
- פריסה
- ReplicaSet
- StatefulSet
- ReplicationController
- משימה
CustomResourceDefinitions (CRDs) שמטמיעים את משאב המשנה
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 namespace: capacity-buffer-example spec: # Buffers are also created according to these priorities priorities: - machineFamily: n4 - machineFamily: n4d - machineFamily: c4 - machineFamily: c4d nodePoolAutoCreation: enabled: trueקובץ המניפסט הזה יוצר
ComputeClassמותאם אישית שמגדיר את סדרי העדיפויות של המחשוב עבור הצמתים שמוקצים על ידי GKE. מידע נוסף זמין במאמר בנושא custom 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שמגדיר את דרישות המשאבים של יחידה אחת של קיבולת מאגר (1CPU ו-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 יחידות עיבוד מרכזיות (CPU) ו-5 GiB זיכרון. אם משתמשים בדוגמה של PodTemplate מהשלב הקודם, מגדירים כל יחידה כ-
1CPU ו-1GiMemory, וכך אמורות להתקבל 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. אי אפשר להגדיר מאגר מבוסס-אחוזים לתבניות של פודים כי אין להן שדה replicas.
בדרך כלל מומלץ להתחיל עם שכפול קבוע או עם אסטרטגיות של הגבלת משאבים, ולא עם מאגרי זיכרון מבוססי-אחוזים. מאגרי זיכרון מבוססי-אחוזים פחות רגישים להגדלות פתאומיות אם עומס העבודה גדל למספרים נמוכים או לאפס, כי מרווח הביטחון גדל באופן יחסי ל-Pods פעילים. הן שימושיות בעיקר לפריסות גדולות שבהן מספר העותקים אף פעם לא יורד לרמה נמוכה מאוד.
כדי ליצור מאגר מבוסס-אחוזים, מבצעים את השלבים הבאים:
שומרים את קובץ המניפסט הבא בשם
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 רפליקות.
התאמה אישית של התנהגות מאגר ההמתנה
אפשר להשתמש בהערות כדי להתאים אישית את האופן שבו מאגרי ההמתנה מתחילים ומתרעננים.
מוסיפים את ההערות האלה לשדה metadata.annotations של משאב CapacityBuffer:
-
buffer.gke.io/standby-capacity-init-time: משך הזמן שבו צומת נשאר פעיל אחרי שהוא נוצר, לפני שהוא מושעה. הפורמט הוא מחרוזת של משך זמן (לדוגמה,5mאו1h). ערך ברירת המחדל הוא5m. -
buffer.gke.io/standby-capacity-refresh-frequency: באיזו תדירות מתבצע רענון של צמתים מושעים. ערך ברירת המחדל הוא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-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.
-
מחילים את מניפסט ה-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
כדי לעקוב אחרי הביצועים של מאגרי הקיבולת, כדאי לעקוב אחרי המשאבים הבאים ב-Cloud Monitoring:
- זמן האחזור של התגובה (
cluster_autoscaler/reaction_time_milliseconds): המדד הזה עוקב אחרי משך הזמן שנדרש ל-Cluster Autoscaler כדי לקבל החלטה לגבי שינוי גודל, על סמך הביקוש בהמתנה של CapacityBuffer. - יומנים של Cluster Autoscaler: מחפשים רשומות ביומן כמו
"Capacity pod processor injecting ..."כדי לראות אירועים פעילים של החלפת Pod מאגר.
הסרת מאגרי קיבולת
אם אתם לא צריכים יותר מאגר קיבולת לעומסי העבודה, אתם יכולים למחוק את האובייקט CapacityBuffer. הפעולה הזו מסירה את ה-Pods של ה-placeholder ומאפשרת ל-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 שתואמים לחיוב מבוסס-צומת.
שגיאות הרשאה במשאבים מותאמים אישית שניתנים להרחבה
אם מגדירים את CapacityBuffer לעבודה עם אובייקטים מותאמים אישית שניתנים להרחבה (באמצעות השדה scalableRef), יכול להיות שהכלי לאוטוסקיילינג של האשכול לא יצליח לשנות את גודל המאגר אם אין לו את ההרשאות הנדרשות.
כדי לפתור את הבעיה, צריך להעניק ידנית את ההרשאות הנדרשות על ידי יצירת ClusterRole ו-ClusterRoleBinding, כמו בדוגמה הבאה:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: custom-scale-getter
rules:
- apiGroups: ["api.example.com"]
resources: ["customreplicatedresources/scale"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ca-custom-scale-getter
subjects:
- kind: User
name: "system:cluster-autoscaler"
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: custom-scale-getter
מידע נוסף על הגדרת RBAC זמין במאמרי העזרה של Kubernetes בנושא RBAC.
המאמרים הבאים
- מידע נוסף על קיבולת עודפת
- אפשר לעיין בתיעוד של CapacityBuffer CRD.