פתרון בעיות של תחרות על משאבים

כדי לפתור בעיות של קונטיינרים איטיים, לא תקינים או כאלה שהופסקו ב-Google Distributed Cloud, אתם יכולים לאבחן תחרות על משאבים. הסיבות הנפוצות כוללות ויסות של המעבד (CPU), פודים מסוג OOMKilled, זמן אחזור של שרת ה-API ו-etcd, וצווארי בקבוק של המעבד או האחסון ב-vSphere. זיהוי הסיבה עוזר להתאים את המשאבים לעומסי העבודה, לצמתים ולמכונות הווירטואליות כדי לשמור על יציבות האשכולות.

סקירה כללית

לפעמים יכולה להיות תחרות על משאבים ב-Google Distributed Cloud, וכתוצאה מכך הקונטיינרים עלולים לפעול לאט יותר, לא לפעול כמו שצריך או להיסגר. זה יכול לקרות בגלל צריכה גבוהה של מעבד (CPU) או זיכרון על ידי הקונטיינרים.

איך פועל ניהול המעבד (CPU) וניהול הזיכרון

  • מעבד (CPU):

    • Pod מתוזמן לצומת על סמך בקשות ה-CPU שצוינו על ידי הקונטיינרים ב-Pod.
    • קונטיינר ב-Pod לא יכול להשתמש ביותר מעבדים (CPU) מהמגבלה שצוינה על ידי הקונטיינר
    • השימוש במעבד (CPU) של הקונטיינר מוגבל במגבלת המעבד (CPU).
    • אם השימוש במעבד (CPU) מוגבל ברמת הצומת, המערכת מקצה למאגרים באופן אוטומטי את מחזורי המעבד (CPU) באופן יחסי לבקשות.

    איך מתזמנים Pods עם בקשות למשאבים

  • זיכרון:

    • Pod מתוזמן לצומת על סמך בקשות הזיכרון שצוינו על ידי הקונטיינרים ב-Pod.
    • קונטיינר לא יכול להשתמש ביותר זיכרון מהמגבלה שצוינה בקונטיינר.
    • אם לא צוינה מגבלת זיכרון, יכול להיות שקונטיינר יצרוך את כל הזיכרון הזמין בצומת. אחר כך המערכת עשויה להפעיל את OOM-Killer (מחסל הזיכרון החסר) ולפנות את ה-Pods בעדיפות נמוכה.

למידע נוסף, קראו את המאמרים הבאים:

בעיות

הקונטיינר נהיה איטי

בעיות של תחרות על משאבי המעבד (CPU) עלולות לגרום למכולות לפעול לאט. הנה כמה מהסיבות האפשריות:

ניצול גבוה של המעבד (CPU) בקונטיינר:

קונטיינר יכול להיות איטי אם הוא לא מקבל מחזורי מעבד (CPU) באופן פרופורציונלי לבקשות המעבד, או אם בקשות המעבד הוגדרו לערך נמוך יותר ממה שהקונטיינר צריך. לכן, בדקו את היחס בין מגבלת המעבד (CPU) לבין ניצול המעבד (CPU) של הקונטיינר.

במסוף Google Cloud > ‏Monitoring > ‏Metrics explorer, מריצים את השאילתה הבאה ב-PromQL editor:

  avg_over_time({
    "__name__"="kubernetes.io/anthos/container/cpu/limit_utilization",
    "monitored_resource"="k8s_container",
    "cluster_name"="CLUSTER_NAME",
    "container_name"="CONTAINER_NAME",
    "pod_name"="POD_NAME",
    "namespace_name"="NAMESPACE_NAME"
  }[${__interval}])

לאחר מכן, מבצעים את אחת מהפעולות הבאות:

ניצול גבוה של המעבד (CPU) בצומת

אם היחס בין מגבלת המעבד (CPU) לניצול שלו לא גבוה באף אחד מהקונטיינרים של ה-Pod, יכול להיות שלצומת אין מספיק מחזורי מעבד (CPU) להקצות לקבוצת הקונטיינרים שפועלים בצומת. כדי לבדוק את היחס בין השימוש בפועל ב-CPU לבין ה-CPUs שניתן להקצות בצומת:

  1. מאתרים את הצומת של ה-Pod שפועל לאט:

    kubectl get pod –kubeconfig CLUSTER_KUBECONFIG --namespace NAMESPACE POD --output wide
    
  2. במסוףGoogle Cloud > Monitoring ‏> Metrics explorer, מריצים את השאילתה הבאה ב-PromQL editor:

    avg_over_time({
      "__name__"="kubernetes.io/anthos/node/cpu/allocatable_utilization",
      "monitored_resource"="k8s_node",
      "cluster_name"="CLUSTER_NAME",
      "node_name"="NODE_NAME"
    }[${__interval}])
    

    אם היחס הזה גבוה (‎>=0.8), המשמעות היא שלצומת אין מספיק מחזורי מעבד (CPU) והוא מנוצל יתר על המידה. כדי לבדוק את השימוש ב-CPU בכל שאר ה-Pods בצומת הזה, ולבדוק אם יש קונטיינר אחר שמשתמש ביותר יחידות CPU, צריך לפעול לפי השלבים הבאים.

    1. מציגים את כל ה-Pods בצומת:
    kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=NODE_NAME
    
    1. בודקים את ניצול המעבד (CPU) בכל קונטיינר:
    avg_over_time({
      "__name__"="kubernetes.io/anthos/container/cpu/limit_utilization",
      "monitored_resource"="k8s_container",
      "cluster_name"="CLUSTER_NAME",
      "container_name"="CONTAINER_NAME",
      "pod_name"="POD_NAME",
      "namespace_name"="NAMESPACE_NAME"
    }[${__interval}])
    

    אם יש קונטיינר אחר שמשתמש ב-CPU גבוה בצומת, מגדילים את בקשות ה-CPU והמגבלות בקונטיינר שפועל לאט. הפעולה הזו תיצור מחדש את ה-Pod בצומת אחר כדי לקבל את מחזורי המעבד הנדרשים.

אם מדובר ב-Pod של המערכת שפועל לאט, פנו לתמיכה של Google.

הקצאת יתר של מעבד (CPU) ברמת vSphere

אם צריכת המעבד (CPU) לא גבוהה בצומת או ב-Pod, והקונטיינר עדיין איטי, יכול להיות שהמכונה הווירטואלית נמצאת במצב של oversubscription ברמת ה-vSphere. לכן, הצומת לא יכול לקבל את מחזורי המעבד (CPU) הצפויים מהווירטואליזציה הבסיסית.

כדי לבדוק אם המכונה הווירטואלית נמצאת במצב של oversubscription, פועלים לפי השלבים האלה. אם זוהה רישום יתר, נסו את הפעולות הבאות:

  • להעביר חלק מהמכונות הווירטואליות למארחים אחרים.
  • בודקים את מספר המעבדים הווירטואליים לכל מכונה וירטואלית במארח, ומקטינים אותו.
  • להקצות יותר משאבים למכונות הווירטואליות של האשכול.
  • מגדילים את בקשות ה-CPU ואת המגבלות על הקונטיינר. הפעולה הזו תיצור מחדש את ה-Pod בצומת אחר כדי לקבל את מחזורי המעבד הנדרשים.

Pod gets OOMkilled (Out of Memory-Killed)

יכול להיות שה-Pods יקבלו OOMKilled בגלל דליפות זיכרון או הגדרה לא נכונה של בקשות זיכרון ומגבלות על הקונטיינרים. הנה כמה מהסיבות האפשריות:

שימוש גבוה בזיכרון בקונטיינר

‫Pod יכול לקבל OOMkilled אם קונטיינר כלשהו ב-Pod צורך יותר מהזיכרון הכולל שהוקצה. לכן, בדקו את היחס בין בקשות הזיכרון למגבלות הזיכרון בקונטיינר.

במסוףGoogle Cloud > Monitoring ‏> Metrics explorer, מריצים את השאילתה הבאה ב-PromQL editor:

avg_over_time({
  "__name__"="kubernetes.io/anthos/container/memory/limit_utilization",
  "monitored_resource"="k8s_container",
  "memory_type"="non-evictable",
  "cluster_name"="CLUSTER_NAME",
  "container_name"="CONTAINER_NAME",
  "pod_name"="POD_NAME",
  "namespace_name"="NAMESPACE_NAME"
}[${__interval}])

לאחר מכן, מבצעים את אחת מהפעולות הבאות:

שימוש גבוה בזיכרון בצומת

אם השימוש בזיכרון של כל ה-Pods שפועלים בצומת חורג מהזיכרון הזמין, יכול להיות שה-Pod יקבל את הסטטוס OOMkilled. לכן, צריך לבדוק אם המצב MemoryPressure בצומת הוא True.

  1. מריצים את הפקודה הבאה ובודקים את הקטע Conditions:

    kubectl describe nodes --kubeconfig CLUSTER_KUBECONFIG NODE-NAME
    
  2. אם התנאי MemoryPressure הוא True, בודקים את ניצול הזיכרון בצומת:

    avg_over_time({
      "__name__"="kubernetes.io/anthos/node/memory/allocatable_utilization",
      "monitored_resource"="k8s_node",
      "memory_type"="non-evictable",
      "cluster_name"="CLUSTER_NAME",
      "node_name"="NODE_NAME",
    }[${__interval}])
    

    אם היחס הזה גבוה (‎>= 0.8), המשמעות היא שלצומת אין מספיק זיכרון להקצות ל-Pod, אולי בגלל תהליכים מסוימים או Pods אחרים שצורכים הרבה זיכרון.

  3. במסוףGoogle Cloud > Monitoring ‏> Metrics explorer, מריצים את השאילתה הבאה בעורך PromQL כדי לבדוק את השימוש בזיכרון של הקונטיינרים בצומת:

    avg_over_time({
      "__name__"="kubernetes.io/anthos/container_memory_usage_bytes",
      "monitored_resource"="k8s_node",
      "cluster_name"="CLUSTER_NAME",
      "node_name"="NODE_NAME",
    }[${__interval}])
    

    אם יש קונטיינר שמשתמש בזיכרון רב, בודקים את הפעולה של הקונטיינר או מגדילים את בקשת הזיכרון של הקונטיינר, לפי הצורך.

אם מדובר ב-Pod של המערכת שצורך הרבה זיכרון, פנו לתמיכה של Google.

בנוסף, אתם יכולים להפעיל את התכונה התאמה אוטומטית לעומס (automatic scaling) ב-Google Distributed Cloud כדי להגדיל או לצמצם את מאגרי הצמתים באופן אוטומטי בהתאם לדרישות של עומסי העבודה.

איך מפעילים את ההתאמה האוטומטית לעומס

בעיות ב-etcd

לפעמים יכולים להיות כשלים בקונטיינרים של אשכולות Anthos ב-VMware בגלל בעיות בשרת etcd, ואתם עשויים לראות את הדברים הבאים:

  • יומני שרת API חוזרים בפורמט:

    etcdserver: request timed out וגם etcdserver: leader changed

  • יומני etcd חוזרים בפורמט:

    W | wal: sync duration of 2.466870869s, expected less than 1s וגם W | etcdserver: read-only range request * took too long

הנה כמה מהסיבות האפשריות:

ויסות נתונים (throttle) של מעבד (CPU)

יכול להיות ששרת ה-etcd איטי בגלל ויסות הנתונים של המעבד (CPU) ב-Pod של שרת ה-etcd או בצומת שבו פועל שרת ה-etcd. כדי לבדוק אם יש בעיות של תחרות על משאבי המעבד, פועלים לפי השלבים בקטע המאגר נהיה איטי.

אם אתם מזהים תחרות על משאבי המעבד (CPU) ב-Pod של שרת ectd או בצומת, הוסיפו מעבדים לצומת של מישור הבקרה באשכול המשתמש. משתמשים ב-gkectl update כדי לערוך את השדה cpus בקובץ התצורה של אשכול המשתמש.

Etcd Pod OOMkilled

יכול להיות שה-Pod של etcd יופסק בגלל מחסור בזיכרון (OOMkilled) בגלל בעיות של תחרות על משאבים. כדי לבדוק אם יש בעיות של תחרות על זיכרון ב-Pod של שרת ה-etcd או בצומת שבו פועל שרת ה-etcd, פועלים לפי השלבים בקטע Pod gets OOMkilled (Out of Memory-Killed)‎.

אם אתם מזהים OOMkills ב-Pod של etcd, הגדילו את הזיכרון שזמין לצומת של מישור הבקרה באשכול המשתמש. משתמשים ב-gkectl update כדי לערוך את השדה memoryMB בקובץ התצורה של אשכול המשתמש.

איטיות בדיסק

אם אין בעיות בצריכת המעבד (CPU) או הזיכרון ב-Pod של שרת ה-etcd או בצומת, יכול להיות שה-etcd איטי כי מאגר הנתונים הבסיסי איטי או מוגבל.

כדאי לבדוק אם קיימות הבעיות הבאות:

  • כדי לבדוק אם לשרת etcd לוקח יותר מדי זמן לקרוא מהדיסק הבסיסי או לכתוב אליו:

    1. אחזור של יומני etcd:

      kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n ETCD_POD_NAMESPACE ETCD_POD
      
    2. כדי לזהות אם ל-etcd לוקח יותר מדי זמן לקרוא מהדיסק, מחפשים את הרשומות של התבנית הבאה:

      W | etcdserver: read-only range request "key:\"/registry/configmaps/default/clusterapi-vsphere-controller-manager-leader-election\" " with result "range_response_count:1 size:685" took too long (6.893127339s) to execute

    3. כדי לזהות אם הכתיבה של etcd לדיסק נמשכת יותר מדי זמן, חפשו את הרשומות של התבנית הבאה:

      W | wal: sync duration of 2.466870869s, expected less than 1s

    אם אחת מתבניות היומן שלמעלה או שתיהן מופיעות לעיתים קרובות ביומני ה-etcd, זה מצביע על איטיות בדיסק. לאחר מכן בודקים את הביצועים של מאגר הנתונים והדיסקים.

  • כדי לבדוק את המדדים של etcd:

    1. אחזור זמני האחזור של סנכרון etcd wal:

      במסוףGoogle Cloud > Monitoring ‏> Metrics explorer, מריצים את השאילתה הבאה ב-PromQL editor:

      histogram_quantile(0.99,
        sum by ("le") (
          increase({
            "__name__"="kubernetes.io/anthos/etcd_disk_wal_fsync_duration_seconds_bucket",
            "monitored_resource"="k8s_container",
            "cluster_name"="CLUSTER_NAME",
            "pod_name"="POD_NAME",
            "namespace_name"="NAMESPACE_NAME"
          }[${__interval}])
        )
      )
      
    2. מאחזרים את זמני האחזור של הכתיבה ב-etcd:

      במסוףGoogle Cloud > Monitoring ‏> Metrics explorer, מריצים את השאילתה הבאה ב-PromQL editor:

      histogram_quantile(0.99,
        sum by ("le") (
          increase({
            "__name__"="kubernetes.io/anthos/etcd_disk_backend_commit_duration_seconds",
            "monitored_resource"="k8s_container",
            "cluster_name"="CLUSTER_NAME",
            "pod_name"="POD_NAME",
            "namespace_name"="NAMESPACE_NAME"
          }[${__interval}])
        )
      )
      

    אם הערך של p99 ב-etcd_disk_wal_fsync_duration_seconds הוא באופן עקבי מעל 10ms, או אם הערך של p99 ב-etcd_disk_backend_commit_duration_seconds הוא באופן עקבי מעל 25ms, זה מצביע על איטיות בדיסק. לאחר מכן בודקים את הביצועים של מאגר הנתונים והדיסקים.

זמני האחזור של קריאה/כתיבה בדיסק של המכונה הווירטואלית

כדי לבדוק את זמני האחזור של הקריאה/כתיבה בדיסק הווירטואלי של ה-VM:

  1. מזהים את הצומת של ה-Pod האיטי של etcd:

    kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG get pods -n ETCD_POD_NAMESPACE ETCD_POD -owide
    
  2. נכנסים ל-vSphere ובוחרים את המכונה הווירטואלית שזוהתה בשלב הקודם: ב-vSphere, עוברים אל Monitor ‏> Performance ‏> Advanced, ובוחרים באפשרות Virtual Disk בקטע View כדי לזהות את זמני האחזור של הקריאה והכתיבה של הדיסקים הווירטואליים.

    אם זמן האחזור של הקריאה/כתיבה בדיסק הווירטואלי גבוה:

    • בודקים מכונות וירטואליות אחרות שפועלות במאגר הנתונים כדי לבדוק אם יש שימוש גבוה בפעולות קלט/פלט לשנייה (IOPS). אם באחת מהמכונות הווירטואליות יש קפיצות חדות ב-IOPS, צריך לבדוק את התפקוד של המכונה הווירטואלית הזו.
    • כדאי להתייעץ עם צוות המעבדה או התשתית כדי לוודא שרוחב הפס לקריאה ולכתיבה לא מוגבל בשום שלב.
    • כדאי להתייעץ עם צוות המעבדה או התשתית כדי לזהות בעיות בביצועי הדיסק ובביצועי האחסון, אם יש כאלה.

מידע נוסף זמין במאמר שיטות מומלצות להרחבת המשאבים.

בעיות בשרת ה-API

אם יש עיכוב בתקשורת בין הקונטיינרים ב-Google Distributed Cloud לבין שרת ה-API, או אם הפקודות של Kubectl נכשלות או שלוקח להן יותר מדי זמן להגיב, יכול להיות שיש בעיות בשרת ה-API.

הנה כמה מהסיבות האפשריות:

נפח גבוה של בקשות API

אם התדירות והנפח של הבקשות לשרת ה-API גבוהים מדי, יכול להיות שהתגובה שלו תהיה איטית. יכול להיות שזמן התגובה האיטי יימשך גם אחרי ששרת ה-API יתחיל לווסת את הבקשות. לכן, צריך לבדוק את קצב בקשות ה-API בשרת ה-API.

במסוףGoogle Cloud > Monitoring ‏> Metrics explorer, מריצים את השאילתה הבאה ב-PromQL editor:

sum by (verb) (
  rate({
    "__name__"="kubernetes.io/anthos/apiserver_request_total",
    "monitored_resource"="k8s_container",
    "cluster_name"="CLUSTER_NAME",
    "pod_name"="APISERVER_POD_NAME",
    "namespace_name"="NAMESPACE_NAME"
   }[${__interval}])
)

אם יש עלייה לא צפויה בבקשות ה-API, אפשר להשתמש ברישום ביומן הביקורת של Cloud כדי לזהות את ה-Pod ששולח שאילתות לשרת ה-API בתדירות גבוהה מדי.

  • אם מדובר ב-Pod של המערכת, פנו אל התמיכה של Google.
  • אם מדובר ב-Pod של משתמש, צריך לבדוק לעומק אם בקשות ה-API צפויות.

ויסות נתונים (throttle) של מעבד (CPU)

קצב בקשות גבוה בשרת ה-API יכול להוביל לוויסות של המעבד (CPU). במקרה כזה, יכול להיות ששרת ה-API יפעל לאט בגלל תחרות על משאבי המעבד (CPU) ב-Pod של שרת ה-API או בצומת.

כדי לבדוק אם יש בעיות של תחרות על משאבי המעבד (CPU) ב-Pod או בצומת, אפשר לעיין בקטע ה-Container נהיה איטי.

‫שרת API Pod OOMkilled

יכול להיות שה-Pod של שרת ה-API יופסק בגלל מחסור בזיכרון (OOMkilled) בגלל בעיות של תחרות על משאבים. כדי לבדוק אם יש בעיות של תחרות על משאבי זיכרון ב-Pod או בצומת, פועלים לפי השלבים שמפורטים בקטע Pod gets OOMkilled (Out of Memory-Killed)‎.

תגובות איטיות של etcd

שרת ה-API מסתמך על תקשורת עם אשכול ה-etcd כדי להציג בקשות קריאה/כתיבה ללקוחות. אם ה-etcd איטי או לא מגיב, גם שרת ה-API הופך לאיטי.

אחזור היומנים של שרת ה-API כדי לבדוק אם שרת ה-API איטי בגלל בעיות ב-etcd:

kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n APISERVER_NAMESPACE APISERVER_POD_NAME

אם אתם רואים יומנים חוזרים כמו etcdserver: request timedout או etcdserver: leader changed, פועלים לפי השלבים שמפורטים בקטע בעיות ב-Etcd כדי לפתור בעיות שקשורות לדיסק.

אם האשכול לא מייצא מדדים

השיטות שהוצגו קודם לכן במסמך הזה מסתמכות על ייצוא מדדים מהאשכול לפרויקט ב- Google Cloud .

אם האשכול לא מייצא מדדים, אתם יכולים להשתמש בשורת הפקודה כדי לבדוק את התחרות על המשאבים. הנה כמה פקודות שאפשר להריץ בתחנת העבודה של האדמין כדי להציג מדדים.

כדי לראות את המדדים של צומת:

kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \
    /apis/metrics.k8s.io/v1beta1/nodes/NODE_NAME | jq

מחליפים את מה שכתוב בשדות הבאים:

  • ‫CLUSTER_KUBECONFIG: הנתיב לקובץ kubeconfig של האשכול
  • ‫NODE_NAME: שם הצומת

הצגת מדדים של Pod:

kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \
    /apis/metrics.k8s.io/v1beta1/namespaces/NAMESPACE/pods/POD_NAME | jq

מחליפים את מה שכתוב בשדות הבאים:

  • ‫NAMESPACE: מרחב השמות של ה-Pod
  • ‫POD_NAME: שם ה-Pod

הצגת מדדים לכל הצמתים:

kubectl --kubeconfig CLUSTER_KUBECONFIG top node

הצגת מדדים לכל ה-Pods במרחב שמות:

kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --namespace NAMESPACE

הצגת מדדים של קונטיינרים בכל ה-Pods במרחב שמות:

kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --containers --namespace NAMESPACE

למידע נוסף, קראו את המאמרים kubectl top pod ו-kubectl top node.

אפשר גם להריץ את הפקודה top מתוך קונטיינר שפועל בצומת.

יש שתי דרכים להריץ פקודה בתוך קונטיינר:

  • בתחנת העבודה של האדמין, מריצים את הפקודה kubectl exec כדי לקבל מעטפת בקונטיינר. מריצים את הפקודה במעטפת.

  • יוצרים חיבור SSH לצומת. לאחר מכן משתמשים ב-docker exec כדי לקבל מעטפת (shell) בקונטיינר. מריצים את הפקודה במעטפת.

המאמרים הבאים

אם אתם צריכים עזרה נוספת, תוכלו לפנות אל Cloud Customer Care.

במאמר קבלת תמיכה תוכלו לקרוא מידע נוסף על מקורות המידע לתמיכה, כולל: