פתרון בעיות בצמתים עם הסטטוס NotReady ב-GKE

סטטוס NotReady ב-Google Kubernetes Engine‏ (GKE) מציין ש-kubelet של הצומת לא מדווח לרמת הבקרה בצורה תקינה. מכיוון ש-Kubernetes לא יתזמן קבוצות Pod חדשות בצומת NotReady, הבעיה הזו עלולה לצמצם את קיבולת האפליקציה ולגרום להשבתה.

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

המידע הזה מיועד לאדמינים ולמפעילים של פלטפורמות שאחראים על יציבות האשכולות, ולמפתחי אפליקציות שרוצים להבין את התנהגות האפליקציות שקשורה לתשתית. מידע נוסף על התפקידים הנפוצים ומשימות לדוגמה שאנחנו מתייחסים אליהם ב Cloud de Confiance by S3NS תוכן זמין במאמר תפקידי משתמשים נפוצים ומשימות ב-GKE.

לפני שמתחילים

  • כדי לקבל את ההרשאות שדרושות לביצוע המשימות שמתוארות במאמר הזה, צריך לבקש מהאדמין להקצות לכם את תפקידי ה-IAM הבאים בפרויקט Cloud de Confiance by S3NS :

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

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

  • מגדירים את כלי שורת הפקודה kubectl כדי לתקשר עם אשכול GKE:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location LOCATION \
        --project PROJECT_ID
    

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

    • CLUSTER_NAME: השם של האשכול.
    • LOCATION: האזור או התחום של Compute Engine (לדוגמה, us-central1 או us-central1-a) של האשכול.
    • PROJECT_ID: מזהה הפרויקט ב- Cloud de Confiance by S3NS .

בדיקת הסטטוס והתנאים של הצומת

כדי לוודא שהסטטוס של הצומת הוא NotReady ולעזור לכם לאבחן את שורש הבעיה, תוכלו לבצע את השלבים הבאים כדי לבדוק את התנאים, האירועים, היומנים ומדדי המשאבים של הצומת:

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

    kubectl get nodes -o wide
    

    הפלט אמור להיראות כך:

    NAME                                STATUS     ROLES    AGE   VERSION               INTERNAL-IP  EXTERNAL-IP  OS-IMAGE                             KERNEL-VERSION   CONTAINER-RUNTIME
    gke-cluster-pool-1-node-abc1        Ready      <none>   94d   v1.32.3-gke.1785003   10.128.0.1   1.2.3.4      Container-Optimized OS from Google   6.6.72+          containerd://1.7.24
    gke-cluster-pool-1-node-def2        Ready      <none>   94d   v1.32.3-gke.1785003   10.128.0.2   5.6.7.8      Container-Optimized OS from Google   6.6.72+          containerd://1.7.24
    gke-cluster-pool-1-node-ghi3        NotReady   <none>   94d   v1.32.3-gke.1785003   10.128.0.3   9.10.11.12   Container-Optimized OS from Google   6.6.72+          containerd://1.7.24
    

    בפלט, מחפשים צמתים עם הערך NotReady בעמודה STATUS ורושמים את השמות שלהם.

  2. כדי לראות מידע נוסף על צמתים ספציפיים עם הסטטוס NotReady, כולל התנאים שלהם ואירועי Kubernetes האחרונים:

    kubectl describe node NODE_NAME
    

    מחליפים את NODE_NAME בשם של צומת עם סטטוס NotReady.

    בפלט, מתמקדים בקטע Conditions כדי להבין את תקינות הצומת ובקטע Events כדי לראות את היסטוריית הבעיות האחרונות. לדוגמה:

    Name:                   gke-cluster-pool-1-node-ghi3
    ...
    Conditions:
    Type                          Status    LastHeartbeatTime                 LastTransitionTime                Reason                   Message
    ----                          ------    -----------------                 ------------------                ------                   -------
    NetworkUnavailable            False     Wed, 01 Oct 2025 10:29:19 +0100   Wed, 01 Oct 2025 10:29:19 +0100   RouteCreated             RouteController created a route
    MemoryPressure                Unknown   Wed, 01 Oct 2025 10:31:06 +0100   Wed, 01 Oct 2025 10:31:51 +0100   NodeStatusUnknown        Kubelet stopped posting node status.
    DiskPressure                  Unknown   Wed, 01 Oct 2025 10:31:06 +0100   Wed, 01 Oct 2025 10:31:51 +0100   NodeStatusUnknown        Kubelet stopped posting node status.
    PIDPressure                   False     Wed, 01 Oct 2025 10:31:06 +0100   Wed, 01 Oct 2025 10:29:00 +0100   KubeletHasSufficientPID  kubelet has sufficient PID available
    Ready                         Unknown   Wed, 01 Oct 2025 10:31:06 +0100   Wed, 01 Oct 2025 10:31:51 +0100   NodeStatusUnknown        Kubelet stopped posting node status.
    Events:
    Type     Reason                   Age                  From                                   Message
    ----     ------                   ----                 ----                                   -------
    Normal   Starting                 32m                  kubelet, gke-cluster-pool-1-node-ghi3  Starting kubelet.
    Warning  PLEGIsNotHealthy         5m1s (x15 over 29m)  kubelet, gke-cluster-pool-1-node-ghi3  PLEG is not healthy: pleg was last seen active 5m1.123456789s ago; threshold is 3m0s
    Normal   NodeHasSufficientMemory  5m1s (x16 over 31m)  kubelet, gke-cluster-pool-1-node-ghi3  Node gke-cluster-pool-1-node-ghi3 status is now: NodeHasSufficientMemory
    

    בקטע Conditions, הסטטוס True של תנאי לא כלול או Unknown של התנאי Ready מציין שיש בעיה. חשוב לשים לב לשדות Reason ו-Message בתנאים האלה, כי הם מסבירים את הסיבה לבעיה.

    הסבר על כל סוג של תנאי:

    • KernelDeadlock: True אם ליבת מערכת ההפעלה של הצומת זיהתה מצב של קיפאון, שזו שגיאה חמורה שיכולה לגרום להקפאת הצומת.
    • FrequentUnregisterNetDevice: True אם הצומת מבטל לעיתים קרובות את הרישום של מכשירי הרשת שלו, מה שיכול להעיד על בעיות בדרייבר או בחומרה.
    • NetworkUnavailable: True אם הרשת של הצומת לא מוגדרת בצורה נכונה.
    • OutOfDisk: True אם המקום הפנוי בדיסק מוצה לחלוטין. המצב הזה חמור יותר מ-DiskPressure.
    • MemoryPressure: True אם הזיכרון של הצומת נמוך.
    • DiskPressure: True אם נפח האחסון בדיסק של הצומת נמוך.
    • PIDPressure: True אם הצומת חווה מיצוי של מזהה התהליך (PID).
    • Ready: מציין אם הצומת תקין ומוכן לקבל Pods.
      • True אם הצומת תקין.
      • False אם הצומת לא תקין ולא מקבל Pods.
      • Unknown אם בקר הצומת לא קיבל נתונים מהצומת במשך תקופת חסד (ברירת המחדל היא 50 שניות) וסטטוס הצומת לא ידוע.

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

  3. כדי להבין למה הצומת קיבל את הסטטוס NotReady, צריך לעיין ביומנים של הצומת ושל הרכיבים שלו.

    1. בודקים את היומנים של kubelet כדי לראות את הסטטוס של NotReady.

      kubelet הוא הסוכן הראשי שמדווח על הסטטוס של הצומת למישור הבקרה, ולכן סביר להניח שההודעה המילולית NotReady תופיע ביומנים שלו. היומנים האלה הם המקור המוסמך לאבחון בעיות באירועים של מחזור החיים של Pod, בתנאי לחץ על משאבים (כמו MemoryPressure או DiskPressure) ובקישוריות של הצומת למישור הבקרה של Kubernetes.

    2. נכנסים לדף Logs Explorer במסוף Cloud de Confiance :

      כניסה לדף Logs Explorer

    3. בחלונית השאילתה, מזינים את השאילתה הבאה:

      resource.type="k8s_node"
      resource.labels.node_name="NODE_NAME"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      log_id("kubelet")
      textPayload=~"(?i)NotReady"
      

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

      • NODE_NAME: שם הצומת שבודקים.
      • CLUSTER_NAME: השם של האשכול.
      • LOCATION: האזור או התחום של Compute Engine (לדוגמה, us-central1 או us-central1-a) של האשכול.
    4. לוחצים על Run query (הפעלת שאילתה) ובודקים את התוצאות.

    5. אם היומנים של kubelet לא חושפים את שורש הבעיה, צריך לבדוק את היומנים של container-runtime ושל node-problem-detector. יכול להיות שהרכיבים האלה לא יתעדו את הסטטוס NotReady באופן ישיר, אבל לרוב הם יתעדו את הבעיה הבסיסית (כמו כשל בזמן ריצה או תגובה לשגיאת ליבה קריטית) שגרמה לבעיה.

    6. בחלונית השאילתות של Logs Explorer, מזינים את השאילתה הבאה:

      resource.type="k8s_node"
      resource.labels.node_name="NODE_NAME"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      log_id("COMPONENT_NAME")
      

      מחליפים את COMPONENT_NAME באחד מהערכים הבאים:

      • container-runtime: זמן הריצה (containerd), שאחראי למחזור החיים המלא של הקונטיינר, כולל משיכת תמונות וניהול של הרצת הקונטיינר. חשוב לבדוק את היומנים של container-runtime כדי לפתור בעיות שקשורות ליצירת מופע של קונטיינר, לשגיאות בשירות זמן הריצה או לבעיות שנגרמות בגלל ההגדרה של זמן הריצה.
      • node-problem-detector: כלי שבאופן יזום עוקב אחרי מגוון בעיות ברמת הצומת ומדווח עליהן למישור הבקרה. היומנים שלו חיוניים לזיהוי בעיות מערכתיות בסיסיות שעלולות לגרום לחוסר יציבות של הצומת – כמו חסימות ליבה, פגיעה במערכת הקבצים או כשלים בחומרה – שאולי לא יתועדו על ידי רכיבים אחרים של Kubernetes.
    7. לוחצים על Run query (הפעלת שאילתה) ובודקים את התוצאות.

  4. משתמשים ב-Metrics Explorer כדי לחפש ניצול יתר של משאבים בסביבות הזמן שבהן הצומת הפך ל-NotReady:

    1. במסוף Cloud de Confiance , נכנסים לדף Metrics Explorer:

      לדף Metrics Explorer

    2. ב-Metrics Explorer, בודקים אם יש ניצול יתר של משאבים במופע הבסיסי של Compute Engine של הצומת. מתמקדים במדדים שקשורים למעבד (CPU), לזיכרון ולמדדי קלט/פלט (I/O) בדיסק. לדוגמה:

      • מדדים של צומתי GKE: מתחילים עם מדדים שמופיעה לפניהם הקידומת kubernetes.io/node/, כמו kubernetes.io/node/cpu/allocatable_utilization או kubernetes.io/node/memory/allocatable_utilization. המדדים האלה מראים כמה מהמשאבים הזמינים של הצומת נמצאים בשימוש על ידי ה-Pods. הכמות הזמינה לא כוללת את המשאבים ש-Kubernetes שומרת להוצאות תקורה של המערכת.
      • מדדים של מערכת ההפעלה של האורח: כדי לראות תצוגה מתוך מערכת ההפעלה של הצומת, משתמשים במדדים עם הקידומת compute.googleapis.com/guest/, כמו compute.googleapis.com/guest/cpu/usage או compute.googleapis.com/guest/memory/bytes_used.
      • מדדי Hypervisor: כדי לראות את הביצועים של המכונה הווירטואלית ברמת ה-Hypervisor, משתמשים במדדים שמתחילים בקידומת compute.googleapis.com/instance/, כמו compute.googleapis.com/instance/cpu/utilization או במדדי קלט/פלט של דיסק כמו compute.googleapis.com/instance/disk/read_bytes_count.

      כדי לראות את המדדים של מערכת ההפעלה של האורח וההיפר-ויז'ור, צריך לסנן לפי שם המכונה הבסיסית של Compute Engine, ולא לפי שם הצומת של Kubernetes. כדי למצוא את שם המופע של צומת, מריצים את הפקודה kubectl describe node NODE_NAME ומחפשים את השדה ProviderID בפלט. שם המופע הוא החלק האחרון של הערך הזה. לדוגמה:

      ...
      Spec:
      ProviderID: gce://my-gcp-project-123/us-central1-a/gke-my-cluster-default-pool-1234abcd-5678
      ...
      

      בדוגמה הזו, שם המכונה הוא gke-my-cluster-default-pool-1234abcd-5678.

זיהוי הסיבה לפי הסימפטום

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

קטגוריה סימפטום או הודעת יומן סיבה אפשרית שלבים לפתרון בעיות
תנאים של צמתים NetworkUnavailable: True בעיה בקישוריות בין הצומת לבין מישור הבקרה או כשל בתוסף Container Network Interface‏ (CNI). פתרון בעיות בקישוריות לרשת
MemoryPressure: True אין מספיק זיכרון בצומת. פתרון בעיות של מחסור במשאבי צומת
DiskPressure: True אין מספיק מקום בכונן של הצומת. פתרון בעיות של מחסור במשאבי צומת
PIDPressure: True לצומת אין מספיק מזהי תהליכים זמינים. פתרון בעיות של מחסור במשאבי צומת
אירועים והודעות ביומן PLEG is not healthy יש עומס יתר על Kubelet בגלל עומס גבוה על המעבד (CPU) או על קלט/פלט (I/O), או בגלל יותר מדי פודים. פתרון בעיות שקשורות ל-PLEG
Out of memory: Kill process
sys oom event
הזיכרון של הצומת מוצה לחלוטין. פתרון בעיות שקשורות לאירועי OOM ברמת המערכת
leases.coordination.k8s.io...is forbidden מרחב השמות kube-node-lease נתקע בתהליך הסיום. פתרון בעיות שקשורות למרחב השמות kube-node-lease
Container runtime not ready
runtime is down
שגיאות שמתייחסות ל-/run/containerd/containerd.sock או ל-docker.sock
שירות Containerd או Docker נכשל או שההגדרה שלו שגויה. פתרון בעיות בזמן הריצה של קונטיינרים
‫Pods תקועים ב-Terminating
יומני Kubelet מציגים DeadlineExceeded עבור kill container
יומני containerd מציגים הודעות חוזרות של Kill container
תהליכים שנתקעו במצב שינה של הדיסק שלא ניתן להפריע לו (מצב D), בדרך כלל קשור לקלט/פלט. פתרון בעיות בתהליכים שנתקעו במצב D
תסמינים ברמת האשכול כמה צמתים נכשלים אחרי הפעלת DaemonSet. ‫DaemonSet מפריע לפעולות של הצומת. פתרון בעיות שנגרמות על ידי DaemonSets של צד שלישי
compute.instances.preempted ביומני הביקורת. המערכת ביצעה preempt למכונה וירטואלית (VM) זמנית במודל Spot, וזו התנהגות צפויה. אישור הקדימות של הצומת
kube-system Pods תקועים ב-Pending. ה-webhook של בקרת הכניסה חוסם רכיבים קריטיים. פתרון בעיות שנגרמות על ידי רכיבי webhook של אישור
exceeded quota: gcp-critical-pods מכסה שהוגדר בצורה שגויה חוסם את ה-Pods של המערכת. פתרון בעיות שנובעות ממכסות משאבים

בדיקה של אירועי NotReady צפויים

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

אישור פעולות במחזור החיים של הצומת

תסמינים:

במהלך אירועים מסוימים במחזור החיים, בצומת מוצג באופן זמני הסטטוס NotReady.

הסיבה:

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

  • שדרוגים של מאגר הצמתים: במהלך שדרוג, כל צומת מרוקן ומוחלף. לצומת החדש והמשודרג יש סטטוס של NotReady עד שהוא מסיים את האתחול ומצטרף לאשכול.
  • תיקון אוטומטי של צומת: כש-GKE מחליף צומת לא תקין, הצומת החלופי נשאר במצב NotReady בזמן ההקצאה.
  • הגדלת הקיבולת של המידרוג האוטומטי באשכול: כשמוסיפים צמתים חדשים, הם מתחילים בסטטוס NotReady והופכים לסטטוס Ready רק אחרי שהם מוקצים באופן מלא ומצטרפים לאשכול.
  • שינויים ידניים בתבנית של הגדרות מכונה: מערכת GKE יוצרת מחדש את הצמתים כשמחילים שינויים בתבנית. לצומת החדש יש סטטוס NotReady במהלך שלב ההפעלה.

הפתרון:

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

אישור של הפסקת הפעלה של צומת

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

תסמינים:

אם מופיעים התסמינים הבאים, סביר להניח שהסטטוס NotReady של הצומת נובע משיבוש צפוי של VM במודל Spot:

  • צומת נכנס באופן לא צפוי למצב NotReady לפני שהוא נמחק ונוצר מחדש על ידי התכונה לשינוי גודל האוטומטי של האשכול.
  • ביומני הביקורת של Cloud מוצג אירוע compute.instances.preempted עבור מכונת ה-VM הבסיסית.

הסיבה:

הצומת פעל ב-VM במודל Spot או ב-VM זמני, ו-Compute Engine ביטל את ההקצאה של משאבי המחשוב האלה למשימה אחרת. יכול להיות שתהיה הפרעה לשימוש במכונות וירטואליות מסוג Spot בכל שלב, אבל בדרך כלל תקבלו התראה על סיום השימוש 30 שניות מראש.

הפתרון:

כדאי להשתמש במכונות Spot VM או במכונות Preemptible VM רק לעומסי עבודה באצווה, לעומסי עבודה בלי שמירת מצב או לעומסי עבודה עמידים בכשלים, שמיועדים לטפל בסיום תהליכים תכוף בצורה חלקה. לעומסי עבודה של ייצור או לעומסי עבודה עם מצב (stateful) שלא יכולים לסבול הפרעות פתאומיות, כדאי להקצות את מאגרי הצמתים באמצעות מכונות וירטואליות רגילות לפי דרישה.

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

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

פתרון בעיות שקשורות ללחץ על משאבי הצמתים

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

תסמינים:

אם אתם רואים את התנאים והיומנים הבאים של הצומת, סביר להניח שהסיבה לסטטוס NotReady של הצומת היא ניצול יתר של המשאבים:

  • בפלט של הפקודה kubectl describe node, מוצג הסטטוס True לתנאים כמו OutOfDisk,‏ MemoryPressure,‏ DiskPressure או PIDPressure.
  • יומני kubelet עשויים להכיל אירועים של חוסר זיכרון (OOM), שמציינים שהופעל OOM Killer של המערכת.

הסיבה:

עומסי העבודה בצומת דורשים ביחד יותר משאבים ממה שהצומת יכול לספק.

הפתרון:

במקרים של אשכולות רגילים, אפשר לנסות את הפתרונות הבאים:

במערכות Autopilot, אין לכם שליטה ישירה על סוגי המכונות של הצמתים או על גדלי דיסקי האתחול. קיבולת הצומת מנוהלת באופן אוטומטי על סמך בקשות ה-Pod. מוודאים שבקשות המשאבים של עומס העבודה נמצאות במסגרת המגבלות של Autopilot ומשקפות בצורה מדויקת את הצרכים של האפליקציה. בעיות מתמשכות במשאבים עשויות להצביע על הצורך באופטימיזציה של בקשות Pod או, במקרים נדירים, על בעיה בפלטפורמה שדורשת עזרה מ-Cloud Customer Care.

פתרון אירועי OOM ברמת המערכת

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

תסמינים:

אם מופיעים התסמינים הבאים, סביר להניח שאירוע OOM ברמת המערכת הוא הסיבה לחוסר היציבות של הצומת:

  • ההודעה Out of memory: Kill process מופיעה ביומני המסוף הסדרתיים של הצומת.
  • יומני kubelet מכילים אירועים של oom_watcher, שמציינים ש-kubelet זיהה אירוע OOM ברמת המערכת.
  • סיום לא צפוי של תהליכים שונים, כולל תהליכי daemon של מערכת או פודים של עומסי עבודה, שלא בהכרח צורכים את הכי הרבה זיכרון.

הסיבה:

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

הפתרון:

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

פתרון בעיות שקשורות ל-PLEG

מחולל אירועים במחזור חיים של ה-Pod‏ (PLEG) הוא רכיב בתוך kubelet. הוא בודק מעת לעת את המצב של כל מאגרי התגים בצומת ומדווח על כל שינוי בחזרה ל-kubelet.

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

תסמינים:

אם מופיעים הסימפטומים הבאים, יכול להיות ש-PLEG לא פועל בצורה תקינה:

  • היומנים של kubelet עבור הצומת מכילים הודעה שדומה ל-PLEG is not healthy.
  • הסטטוס של הצומת משתנה לעיתים קרובות בין Ready ל-NotReady.

הסיבה:

בעיות ב-PLEG נגרמות בדרך כלל מבעיות בביצועים שמונעות מ-kubelet לקבל עדכונים בזמן מריצת הקונטיינר. הסיבות הנפוצות לכך הן:

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

הפתרון:

במקרים של אשכולות Standard, כדאי להפחית את העומס על משאבי הצומת:

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

אם אתם לא משתמשים ב-ComputeClasses, אתם צריכים להתאים את הפריסות של עומסי העבודה (למשל, מספר העותקים והבקשות או המגבלות של המשאבים) ולוודא שהן עומדות במגבלות של Autopilot. אם הבעיות ב-PLEG נמשכות אחרי האופטימיזציה של עומסי העבודה, אפשר לפנות ל-Cloud Customer Care.

פתרון בעיות בתהליכים שנתקעו במצב D

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

תסמינים:

  • תאי Pod, במיוחד אלה שמשתמשים באחסון ברשת כמו NFS, נתקעים במצב Terminating למשך זמן רב.
  • ב-Kubelet logs מופיעות שגיאות DeadlineExceeded כשמנסים לעצור קונטיינר.
  • יכול להיות שיוצגו ביומני המסוף הסדרתי של הצומת הודעות ליבה לגבי hung tasks או משימות שנחסמו למשך יותר מ-120 שניות.

הסיבה:

תהליכים עוברים למצב D כשהם ממתינים להשלמת פעולת קלט/פלט (I/O) ולא ניתן להפריע להם. הסיבות הנפוצות לכך הן:

  • מערכות קבצים מרחוק איטיות או לא מגיבות, למשל שיתוף NFS שהוגדר בצורה שגויה או שעבר עומס יתר.
  • ירידה חמורה בביצועי הדיסק או שגיאות קלט/פלט בחומרה בדיסקים המקומיים של הצומת.

הפתרון:

כדי לפתור בעיות בתהליכים במצב D, צריך לזהות את מקור הקלט/פלט ואז לנקות את המצב על ידי בחירה באחת מהאפשרויות הבאות:

אשכולות רגילים

  1. מאתרים את התהליך התקוע ומנסים להבין למה הוא מחכה:

    1. מתחברים לצומת המושפע באמצעות SSH:

      gcloud compute ssh NODE_NAME \
          --zone ZONE \
          --project PROJECT_ID
      

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

      • NODE_NAME: השם של הצומת שאליו רוצים להתחבר.
      • ZONE: אזור Compute Engine של הצומת.
      • PROJECT_ID: מזהה הפרויקט.
    2. מחפשים תהליכים במצב D:

      ps -eo state,pid,comm,wchan | grep '^D'
      

      הפלט אמור להיראות כך:

      D  12345  my-app      nfs_wait
      D  54321  data-writer io_schedule
      

      לפלט לא תהיה כותרת. העמודות, לפי הסדר, מייצגות:

      • מדינה
      • מזהה תהליך (PID)
      • פקודה
      • ערוץ המתנה (wchan)
    3. בודקים את העמודה wchan כדי לזהות את מקור הקלט/פלט:

      • אם העמודה wchan כוללת מונחים כמו nfs או rpc, התהליך ממתין לשיתוף NFS.
      • אם העמודה wchan כוללת מונחים כמו io_schedule,‏ jbd2 או ext4, התהליך ממתין לדיסק האתחול המקומי של הצומת.
    4. כדי לקבל פרטים נוספים על פונקציות הליבה שהתהליך ממתין להן, בודקים את סטאק הביצוע של הליבה של התהליך:

      cat /proc/PID/stack
      

      מחליפים את PID במזהה התהליך שמצאתם בשלב הקודם.

  2. מפעילים מחדש את הצומת. הפעלה מחדש היא לרוב הדרך היעילה ביותר לנקות תהליך שנתקע במצב D.

    1. מרוקנים את הצומת.
    2. מוחקים את המכונה הווירטואלית הבסיסית. בדרך כלל, מערכת GKE יוצרת מכונה וירטואלית חדשה כדי להחליף אותה.
  3. אחרי שמטפלים בבעיה המיידית, צריך לבדוק את מערכת האחסון הבסיסית כדי למנוע הישנות של הבעיה.

    • לבעיות ב-NFS (אחסון ברשת): משתמשים בכלי המעקב של ספק האחסון כדי לבדוק אם יש חביון גבוה, שגיאות בצד השרת או בעיות ברשת בין צומת GKE לבין שרת NFS.

    • לבעיות בדיסק מקומי: בודקים אם יש הגבלת קצב העברת נתונים (I/O) ב-Cloud Monitoring על ידי צפייה במדדים compute.googleapis.com/instance/disk/throttled_read_ops_count ו-compute.googleapis.com/instance/disk/throttled_write_ops_count של מכונת Compute Engine.

אשכולות במצב Autopilot

  1. מנסים לזהות את מקור החסימה:

    גישת SSH ישירה לצמתים והרצת פקודות כמו ps או cat /proc לא זמינות באשכולות של Autopilot. צריך להסתמך על יומנים ומדדים.

    1. בדיקת יומני הצמתים: ב-Cloud Logging, מנתחים את היומנים מהצומת המושפע. לסנן לפי שם הצומת ופרק הזמן של הבעיה. מחפשים הודעות ליבה שמציינות שגיאות קלט/פלט, פסק זמן של אחסון (לדוגמה, לדיסק או ל-NFS) או הודעות ממנהלי התקנים של CSI.
    2. בודקים את יומני העומס: בודקים את היומנים של ה-Pods שפועלים בצומת המושפע. יומני האפליקציות עשויים לחשוף שגיאות שקשורות לפעולות על קבצים, לקריאות למסד נתונים או לגישה לאחסון ברשת.
    3. שימוש ב-Cloud Monitoring: למרות שאי אפשר לקבל פרטים ברמת התהליך, אפשר לבדוק אם יש בעיות קלט/פלט ברמת הצומת.
  2. מפעילים החלפה של צומת כדי לנקות את הסטטוס.

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

    ‫GKE מזהה באופן אוטומטי צמתים לא תקינים ומתחיל לתקן אותם, בדרך כלל על ידי החלפת המכונה הווירטואלית הבסיסית.

    אם הצומת נשאר תקוע אחרי הניקוי ולא מוחלף אוטומטית, צריך לפנות ל-Cloud Customer Care.

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

    • לבעיות בדיסק מקומי: בודקים אם יש הגבלת קצב העברת נתונים (throttling) ב-Cloud Monitoring על ידי הצגת המדדים compute.googleapis.com/instance/disk/throttled_read_ops_count ו-compute.googleapis.com/instance/disk/throttled_write_ops_count. אפשר לסנן את המדדים האלה לפי קבוצת המופעים הבסיסית של מאגר הצמתים, אבל Google מנהלת את המופעים הבודדים.
    • לבעיות ב-NFS (אחסון ברשת): משתמשים בכלי המעקב של ספק האחסון כדי לבדוק אם יש חביון גבוה, שגיאות בצד השרת או בעיות ברשת בין צומת GKE לבין שרת NFS. בודקים את היומנים של כל ה-Pods של מנהלי התקנים של CSI ב-Cloud Logging.

פתרון בעיות בכשלים של רכיבי ליבה

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

פתרון בעיות בזמן הריצה של מאגרים

בעיות בזמן הריצה של הקונטיינר, כמו containerd, יכולות למנוע מ-kubelet להפעיל Pods בצומת.

תסמינים:

אם ההודעות הבאות מופיעות ביומני kubelet, סביר להניח שבעיה בזמן הריצה של הקונטיינר היא הסיבה לסטטוס NotReady של הצומת:

  • Container runtime not ready
  • Container runtime docker failed!
  • docker daemon exited
  • שגיאות בהתחברות לשקע של זמן הריצה (לדוגמה, unix:///var/run/docker.sock או unix:///run/containerd/containerd.sock).

הסיבה:

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

הפתרון:

כדי לפתור בעיות בזמן הריצה של קונטיינרים:

  1. ניתוח יומני זמן ריצה של קונטיינרים:

    1. נכנסים לדף Logs Explorer במסוף Cloud de Confiance .

      כניסה לדף Logs Explorer

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

      resource.type="k8s_node"
      resource.labels.node_name="NODE_NAME"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      log_id("container-runtime")
      severity>=WARNING
      

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

      • NODE_NAME: שם הצומת שבודקים.
      • CLUSTER_NAME: השם של האשכול.
      • LOCATION: האזור או התחום של Compute Engine (לדוגמה, us-central1 או us-central1-a) של האשכול.
    3. לוחצים על הפעלת שאילתה ובודקים את הפלט כדי לראות הודעות שגיאה ספציפיות שמציינות למה זמן הריצה נכשל. הודעה כמו failed to load TOML ביומני containerd ב-Cloud Logging מציינת בדרך כלל קובץ עם מבנה פגום.

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

      resource.type="k8s_node"
      resource.labels.node_name="NODE_NAME"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      log_id("container-runtime")
      ("starting containerd" OR "Containerd cri plugin version" OR "serving..."
      OR "loading plugin" OR "containerd successfully booted")
      

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

  2. בודקים את ההגדרה של containerd כדי לראות אם יש שינויים: הגדרות שגויות עלולות לגרום לזמן הריצה של הקונטיינר להיכשל. אפשר לבצע שינויים בהגדרות באמצעות קובץ הגדרות של מערכת הצמתים או באמצעות שינויים ישירים שמבוצעים על ידי עומסי עבודה עם הרשאות מורחבות.

    1. בודקים אם מאגר הצמתים משתמש בקובץ תצורה של מערכת הצמתים:

      gcloud container node-pools describe NODE_POOL_NAME \
          --cluster CLUSTER_NAME \
          --location LOCATION \
          --format="yaml(config.containerdConfig)"
      

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

      • NODE_POOL_NAME: השם של מאגר הצמתים.
      • CLUSTER_NAME: השם של האשכול.
      • LOCATION: האזור או התחום של Compute Engine שבו נמצא האשכול.

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

    2. אם ההתאמות האישיות שמנוהלות על ידי GKE לא פעילות, או אם אתם חושדים בשינויים אחרים, חפשו עומסי עבודה שאולי משנים את מערכת הקבצים של הצומת ישירות. מחפשים DaemonSets עם הרשאות גבוהות (securityContext.privileged: true) או נפחים של hostPath שמבצעים mount של ספריות רגישות כמו /etc.

      כדי לבדוק את ההגדרות שלהם, מציגים את כל ה-DaemonSets בפורמט YAML:

      kubectl get daemonsets --all-namespaces -o yaml
      

      בודקים את הפלט ואת היומנים של כל DaemonSet חשוד.

    3. במקרים של אשכולות רגילים, בודקים את קובץ ההגדרות ישירות. אי אפשר לגשת ל-SSH ולבדוק קבצים באופן ידני באשכולות של Autopilot, כי Google מנהלת את הגדרות זמן הריצה. אם נתקלים בבעיות שחוזרות על עצמן בזמן הריצה, צריך לדווח עליהן לצוות Cloud Customer Care של Google.

      אם משתמשים באשכול רגיל, בודקים את הקובץ:

      1. מתחברים לצומת באמצעות SSH:

        gcloud compute ssh NODE_NAME \
            --zone ZONE \
            --project PROJECT_ID
        

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

        • NODE_NAME: השם של הצומת שאליו רוצים להתחבר.
        • ZONE: אזור Compute Engine של הצומת.
        • PROJECT_ID: מזהה הפרויקט.
      2. הצגת התוכן של קובץ ההגדרות של containerd:

        sudo cat /etc/containerd/config.toml
        
      3. כדי לבדוק אם בוצעו שינויים לאחרונה, מציגים את פרטי הקובץ:

        ls -l /etc/containerd/config.toml
        
    4. משווים את התוכן של הקובץ הזה לפלט של containerdConfig מהפקודה gcloud node-pools describe שהרצתם בשלב הקודם. כל הגדרה ב-/etc/containerd/config.toml שלא מופיעה בפלט של gcloud היא שינוי לא מנוהל.

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

  3. פתרון בעיות נפוצות בזמן ריצה: שלבים נוספים לפתרון בעיות מפורטים במאמר פתרון בעיות בזמן הריצה של מארח הקונטיינר.

פתרון בעיות במרחב השמות kube-node-lease

המשאבים במרחב השמות kube-node-lease אחראים לתחזוקת תקינות הצומת. אין למחוק את מרחב השמות הזה. ניסיונות למחוק את מרחב השמות הזה גורמים לכך שמרחב השמות נתקע במצב Terminating. כשמרחב השמות kube-node-lease נתקע בסטטוס Terminating, רכיבי ה-kubelet לא יכולים לחדש את חוזי החכירה של בדיקות תקינות. הבעיה הזו גורמת לרמת הבקרה להתייחס לצמתים כאל צמתים לא תקינים, מה שמוביל לבעיה באשכול שבה הצמתים עוברים לסירוגין בין הסטטוסים Ready ו-NotReady.

תסמינים:

אם אתם רואים את הסימנים הבאים, סביר להניח שהסיבה לחוסר היציבות של האשכול היא בעיה במרחב השמות kube-node-lease:

  • ביומני kubelet בכל צומת מוצגות שגיאות קבועות שדומות לשגיאות הבאות:

    leases.coordination.k8s.io NODE_NAME is forbidden: unable to create new content in namespace kube-node-lease because it is being terminated
    
  • הסטטוסים של הצמתים באשכול מתחלפים שוב ושוב בין Ready ל-NotReady.

הסיבה:

מרחב השמות kube-node-lease, שמנהל את האותות של צומת, תקוע באופן חריג בסטטוס Terminating. השגיאה הזו מונעת משרת ה-API של Kubernetes לאפשר יצירה או שינוי של אובייקט במרחב השמות. כתוצאה מכך, רכיבי ה-kubelet לא יכולים לחדש את אובייקטי ה-Lease שלהם, שהם חיוניים לסימון הפעילות שלהם למישור הבקרה. בלי עדכוני הסטטוס האלה, מישור הבקרה לא יכול לוודא שהצמתים תקינים, ולכן הסטטוסים של הצמתים מתחלפים בין Ready ל-NotReady.

הסיבות הבסיסיות לכך שמרחב השמות kube-node-lease עצמו עלול להיתקע בסטטוס Terminating כוללות את הסיבות הבאות:

  • משאבים עם finalizers: למרות שזה פחות נפוץ במרחב השמות של המערכת kube-node-lease (שמכיל בעיקר אובייקטים מסוג Lease), יכול להיות שלמשאב בתוכו יהיה finalizer. ‫Finalizers ב-Kubernetes הם מפתחות שמסמנים לבקר לבצע משימות ניקוי לפני שאפשר למחוק משאב. אם בקר האחראי להסרת ה-finalizer לא פועל בצורה תקינה, המשאב לא נמחק ותהליך המחיקה של מרחב השמות נעצר.
  • שירותי API מצטברים לא תקינים או לא מגיבים: יכול להיות שהסיום של מרחב השמות ייחסם אם אובייקט APIService, שמשמש לרישום של שרת API מצטבר, מקושר למרחב השמות והופך ללא תקין. יכול להיות שרמת הבקרה תמתין עד שהשרת המצטבר של ה-API יכובה או ינוקה בצורה תקינה, אבל זה לא יקרה אם השירות לא מגיב.
  • בעיות במישור הבקרה או בבקר: במקרים נדירים, באגים או בעיות במישור הבקרה של Kubernetes, במיוחד בבקר של מרחב השמות, עלולים למנוע את מנגנון איסוף הזבל ומחיקת מרחב השמות.

הפתרון:

פועלים לפי ההנחיות במאמר בנושא פתרון בעיות של מרחבי שמות שנתקעו במצב Terminating.

פתרון בעיות בקישוריות לרשת

בעיות ברשת יכולות למנוע מצומת לתקשר עם מישור הבקרה או למנוע מרכיבים קריטיים כמו תוסף CNI לפעול, מה שמוביל למצב NotReady.

תסמינים:

אם אתם מזהים את התסמינים הבאים, יכול להיות שבעיות ברשת הן הסיבה לסטטוס NotReady של הצמתים:

  • התנאי NetworkNotReady הוא True.
  • ב-Kubelet logs בצומת מוצגות שגיאות דומות לשגיאות הבאות:
    • connection timeout to the control plane IP address
    • network plugin not ready
    • CNI plugin not initialized
    • הודעות connection refused או timeout כשמנסים להגיע לכתובת ה-IP של מישור הבקרה.
  • ‫Pods, במיוחד במרחב השמות kube-system, נתקעים ב-ContainerCreating עם אירועים כמו NetworkPluginNotReady.

הסיבה:

תסמינים שקשורים לרשת בדרך כלל מעידים על כשל באחד מהתחומים הבאים:

  • בעיות בקישוריות: הצומת לא מצליח ליצור חיבור רשת יציב למישור הבקרה של Kubernetes.
  • כשל בתוסף CNI: תוסף CNI, שאחראי להגדרת הרשת של ה-Pod, לא פועל בצורה תקינה או שהאתחול שלו נכשל.
  • בעיות ב-webhook: הגדרות שגויות של webhooks של הרשאות יכולות להפריע למשאבים שקשורים לתוסף CNI, ולמנוע את ההגדרה התקינה של הרשת.

הפתרון:

כדי לפתור בעיות ברשת:

  1. טיפול בסטטוס NetworkNotReady זמני: בצמתים שנוצרו לאחרונה, נורמלי לראות אירוע NetworkNotReady קצר. הסטטוס הזה אמור להיפתר תוך דקה או שתיים בזמן שהתוסף CNI ורכיבים אחרים עוברים אתחול. אם הסטטוס לא משתנה, ממשיכים לשלבים הבאים.

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

    1. בדיקת הכללים של חומת האש: מוודאים שהכללים של חומת האש ב-VPC מאפשרים את תעבורת הנתונים הנדרשת בין צמתי ה-GKE לבין מישור הבקרה. מידע על הכללים ש-GKE דורש לתקשורת בין הצומת לבין מישור הבקרה זמין במאמר בנושא כללים של חומת אש שנוצרים באופן אוטומטי.
    2. בדיקת הקישוריות: משתמשים בבדיקת הקישוריות במרכז Network Intelligence כדי לוודא את נתיב הרשת בין כתובת ה-IP הפנימית של הצומת לבין כתובת ה-IP של נקודת הקצה של מישור הבקרה ביציאה 443. תוצאה של Not Reachable יכולה לעזור לכם לזהות את כלל חומת האש או את בעיית הניתוב שחוסמים את התקשורת.
  3. בודקים את הסטטוס והיומנים של פלאגין CNI: אם הרשת של הצומת לא מוכנה, יכול להיות שהבעיה היא בפלאגין CNI.

    1. בדיקת הסטטוס של ה-Pod של CNI: מזהים את הפלאגין של CNI שנמצא בשימוש (לדוגמה, netd או calico-node) ובודקים את הסטטוס של ה-Pods שלו במרחב השמות kube-system. אפשר לסנן כדי להציג את הצומת הספציפי באמצעות הפקודה הבאה:

      kubectl get pods \
          -n kube-system \
          -o wide \
          --field-selector spec.nodeName=NODE_NAME \
          | grep -E "netd|calico|anetd"
      
    2. בדיקת היומנים של CNI Pod: אם ה-Pods לא פועלים בצורה תקינה, צריך לבדוק את היומנים שלהם ב-Cloud Logging כדי לראות הודעות שגיאה מפורטות. כדי להשתמש ב-netd Pods בצומת ספציפי, אפשר להשתמש בשאילתה שדומה לשאילתה הבאה:

      resource.type="k8s_container"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      resource.labels.namespace_name="kube-system"
      labels."k8s-pod/app"="netd"
      resource.labels.node_name="NODE_NAME"
      severity>=WARNING
      
    3. טיפול בשגיאות ספציפיות של CNI שקשורות לכתובת:

      • אם ביומנים מופיע Failed to allocate IP address, יכול להיות שטווח כתובות ה-IP של ה-Pod מוצה. מאמתים את ניצול כתובות ה-IP של ה-Pod ובודקים את טווחי ה-CIDR של האשכול.
      • אם ביומנים מופיע NetworkPluginNotReady או cni plugin not initialized, צריך לוודא שלצומת יש מספיק משאבי מעבד וזיכרון. אפשר גם לנסות להפעיל מחדש את ה-Pod של CNI על ידי מחיקה שלו, מה שמאפשר ל-DaemonSet ליצור אותו מחדש.
      • אם אתם משתמשים ב-GKE Dataplane V2 והיומנים מציגים את השגיאה Cilium API client timeout exceeded, צריך להפעיל מחדש את ה-Pod‏ anetd בצומת.
    4. בודקים אם יש הפרעות של webhook של הרשאה: ‏ webhooks לא תקינים יכולים למנוע הפעלה של CNI Pods, ולגרום לכך שהצומת יהיה בסטטוס NetworkNotReady.

    5. בדיקת יומני שרת ה-API: בודקים את יומני שרת ה-API ב-Cloud Logging כדי לראות אם יש שגיאות שקשורות לקריאות של webhook. כדי לזהות אם webhook חוסם יצירה של משאב CNI, מחפשים הודעות כמו failed calling webhook.

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

פתרון בעיות בהגדרות שגויות של אשכולות

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

פתרון בעיות שנגרמות על ידי ווּבּהוּקים של הרשאות

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

תסמינים:

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

  • ‫Pods, במיוחד במרחב השמות kube-system (כמו CNI או Pods של אחסון), תקועים במצב Pending או Terminating.
  • צמתים חדשים לא מצליחים להצטרף לאשכול, ולעתים קרובות מתרחש פסק זמן עם סטטוס NotReady.

הסיבה:

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

הפתרון:

בודקים את הגדרות ה-webhook כדי לוודא שהן עמידות ומוגדרות בצורה נכונה. כדי למנוע הפסקות בשירות, מגדירים את השדה failurePolicy לערך Ignore עבור ווּבּהוּקים לא קריטיים. כדי למנוע מצבים של קיפאון במישור הבקרה, חשוב לוודא שהשירות שמגבה את ה-webhook הקריטי זמין מאוד, ולהחריג את מרחב השמות kube-system מפיקוח ה-webhook באמצעות namespaceSelector. למידע נוסף, ראו איך מוודאים את היציבות של מישור הבקרה כשמשתמשים ב-webhook.

פתרון בעיות שנגרמות בגלל מכסות משאבים

חישוב שגוי של מכסת משאבים במרחב השמות kube-system יכול למנוע מ-GKE ליצור פודים קריטיים של המערכת. הבעיה הזו יכולה למנוע מצמתים חדשים להצטרף לאשכול בהצלחה, כי רכיבים כמו רשת (CNI) ו-DNS חסומים.

תסמינים:

  • ‫Pods קריטיים במרחב השמות kube-system (לדוגמה, netd,‏ konnectivity-agent או kube-dns) תקועים בסטטוס Pending.
  • הודעות שגיאה ביומני האשכול או בפלט kubectl describe pod מציגות כשלים כמו exceeded quota: gcp-critical-pods.

הסיבה:

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

הפתרון:

  1. הסיבה הסבירה ביותר היא בעיה ב-webhook, ולכן כדאי לפעול לפי ההנחיות שבקטע פתרון בעיות שנגרמות על ידי webhooks של הרשאות כדי לזהות ולתקן webhooks שעלולים לחסום רכיבי מערכת. ברוב המקרים, תיקון ה-webhook פותר את בעיית המכסה באופן אוטומטי.
  2. בודקים אם השימוש שתועד במכסת המשאבים לא מסונכרן עם המספר בפועל של הפודים הפועלים. בשלב הזה בודקים אם הערך של המונה באובייקט ResourceQuota שגוי:

    1. בודקים את נפח השימוש המדווח במכסה:

      kubectl get resourcequota gcp-critical-pods -n kube-system -o yaml
      
    2. בודקים את המספר בפועל של ה-Pods:

      kubectl get pods -n kube-system --no-headers | wc -l
      
  3. אם נראה שמספר הפעמים שהשתמשתם ב-ResourceQuota לא נכון (לדוגמה, אם הוא גבוה בהרבה ממספר ה-Pods בפועל), צריך למחוק את האובייקט gcp-critical-pods. מישור הבקרה של GKE מתוכנן ליצור מחדש את האובייקט הזה באופן אוטומטי עם ספירת השימוש הנכונה והמתואמת:

    kubectl delete resourcequota gcp-critical-pods -n kube-system
    
  4. עוקבים אחרי מרחב השמות kube-system למשך כמה דקות כדי לוודא שהאובייקט נוצר מחדש ושהתזמון של ה-Pods בהמתנה מתחיל.

פתרון בעיות שנגרמות על ידי DaemonSets של צד שלישי

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

תסמינים:

אם אתם מבחינים בתסמינים הבאים, יכול להיות שהסיבה לכשלים בצמתים היא DaemonSet של צד שלישי שנפרס או שונה לאחרונה:

  • מספר צמתים, שיכול להיות שהם נמצאים באשכול, נכנסים למצב NotReady זמן קצר אחרי הפריסה או העדכון של DaemonSet.
  • ביומני Kubelet של הצמתים המושפעים מופיעות שגיאות כמו השגיאות הבאות:
    • container runtime is down
    • Failed to create pod sandbox
    • שגיאות בהתחברות לשקע של זמן הריצה של הקונטיינר (לדוגמה, /run/containerd/containerd.sock).
  • תאי Pod, כולל תאי Pod של המערכת או תאי Pod של DaemonSet, תקועים במצבים PodInitializing או ContainerCreating.
  • יומני מאגרי תגים של אפליקציות מציגים שגיאות חריגות, כמו exec format error.
  • הכלי Node Problem Detector עשוי לדווח על תנאים שקשורים לתקינות זמן הריצה או ללחץ על המשאבים.

הסיבה:

יכול להיות ש-DaemonSet של צד שלישי משפיע על יציבות הצומת מהסיבות הבאות:

  • צריכה מוגזמת של מעבד, זיכרון או קלט/פלט בדיסק, שמשפיעה על הביצועים של רכיבי צומת קריטיים.
  • הפרעה לפעולה של זמן הריצה של הקונטיינר.
  • גורם לקונפליקטים עם הגדרת הרשת של הצומת או עם התוסף Container Network Interface ‏ (CNI).
  • שינוי הגדרות המערכת או מדיניות האבטחה באופן לא מכוון.

הפתרון:

כדי לבדוק אם DaemonSet הוא הגורם לבעיה, מבודדים אותו ובודקים אותו:

  1. זיהוי DaemonSets: מציגים רשימה של כל ה-DaemonSets שפועלים באשכול:

    kubectl get daemonsets --all-namespaces
    

    חשוב לשים לב במיוחד ל-DaemonSets שלא נכללים בהתקנת ברירת המחדל של GKE.

    לרוב אפשר לזהות את ה-DaemonSets האלה על ידי בדיקה של:

    • Namespace (מרחב שמות): רכיבי GKE שמוגדרים כברירת מחדל פועלים בדרך כלל במרחב השמות kube-system. סביר להניח ש-DaemonSets במרחבי שמות אחרים הם של צד שלישי או מותאמים אישית.
    • שמות: ל-DaemonSets שמוגדרים כברירת מחדל יש בדרך כלל שמות כמו gke-metrics-agent, netd או calico-node. לסוכנים של צד שלישי יש בדרך כלל שמות שמשקפים את המוצר.
  2. השוואה בין זמן הפריסה: בודקים אם המראה של NotReady הצמתים חופף לפריסה או לעדכון של DaemonSet ספציפי של צד שלישי.

  3. בדיקה בצומת יחיד:

    1. בוחרים צומת מושפע.
    2. מגדרים ומרוקנים את הצומת.
    3. כדי למנוע זמנית את התזמון של DaemonSet בצומת הזה:
      • החלת תווית צומת זמנית והגדרת זיקה או אנטי-זיקה של צומת במניפסט של DaemonSet.
      • מוחקים את ה-Pod של DaemonSet בצומת הספציפי הזה.
    4. מפעילים מחדש את המכונה הווירטואלית של הצומת.
    5. בודקים אם הצומת הופך ל-Ready ונשאר יציב בזמן ש-DaemonSet לא פועל בו. אם הבעיות מופיעות מחדש אחרי שמחזירים את DaemonSet, סביר להניח שהוא גורם לבעיות.
  4. עיון במסמכי התיעוד של הספק: אם אתם חושדים שסוכן צד שלישי הוא הגורם לבעיה, כדאי לעיין במסמכי התיעוד של הספק כדי לראות אם יש בעיות תאימות ידועות או שיטות מומלצות להפעלת הסוכן ב-GKE. אם אתם צריכים תמיכה נוספת, אתם יכולים לפנות לספק התוכנה.

מוודאים שהצומת שוחזר

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

  1. בודקים את הסטטוס של הצומת:

    kubectl get nodes -o wide
    

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

  2. בודקים את הקטע Conditions של הצומת:

    kubectl describe node NODE_NAME
    

    בקטע Conditions, מאמתים את הערכים הבאים:

    • התנאי Ready הוא בסטטוס True.
    • התנאים השליליים שהסטטוס שלהם היה True (לדוגמה, MemoryPressure או NetworkUnavailable) מקבלים עכשיו את הסטטוס False. בשדות Reason ו-Message של התנאים האלה צריך לציין שהבעיה נפתרה.
  3. תזמון של Pod לבדיקה. אם הצומת לא הצליח להריץ עומסי עבודה בעבר, צריך לבדוק אם מתוזמכים בו פודים חדשים ואם פודים קיימים פועלים ללא בעיות:

    kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=NODE_NAME
    

    הסטטוס של ה-Pods בצומת צריך להיות Running או Completed. לא אמורים לראות ש-Pods נתקעו בסטטוס Pending או בסטטוסי שגיאה אחרים.

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