סיכום: תרחיש לדוגמה של פתרון בעיות

חשוב להבין את כלי פתרון הבעיות הספציפיים ל-Google Kubernetes Engine ‏ (GKE), אבל כדי להעמיק את הידע, כדאי לראות איך משתמשים בהם יחד כדי לפתור בעיה מהעולם האמיתי.

דוגמה מודרכת שמשלבת שימוש במסוף Google Cloud , בכלי שורת הפקודה kubectl, ב-Cloud Logging וב-Cloud Monitoring כדי לזהות את שורש הבעיה של שגיאת OutOfMemory (OOMKilled).

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

התרחיש

אתם מהנדסי התמיכה של אפליקציית אינטרנט בשם product-catalog שפועלת ב-GKE.

החקירה מתחילה כשמקבלים התראה אוטומטית מ-Cloud Monitoring:

Alert: High memory utilization for container 'product-catalog' in 'prod' cluster.

ההתראה הזו מציינת שיש בעיה, ושהבעיה קשורה לעומס העבודה product-catalog.

אישור הבעיה במסוף Google Cloud

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

  1. במסוף Google Cloud , עוברים לדף Workloads ומסננים את עומס העבודה product-catalog.
  2. בודקים את עמודת הסטטוס Pods. במקום הערך התקין 3/3, מוצג הערך עם סטטוס לא תקין: 2/3. הערך הזה מציין שאחד מ-Pods של האפליקציה לא נמצא בסטטוס Ready.
  3. כדי לבדוק את העניין לעומק, לוחצים על שם עומס העבודה product-catalog כדי לעבור לדף הפרטים שלו.
  4. בדף הפרטים, צופים בקטע Managed Pods (תאי Pod מנוהלים). אתם מזהים מיד בעיה: בעמודה Restarts של ה-Pod מופיע 14, מספר גבוה באופן חריג.

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

איך מוצאים את הסיבה באמצעות פקודות kubectl

עכשיו, אחרי שגיליתם שהאפליקציה מופעלת מחדש שוב ושוב, אתם צריכים לגלות למה. הפקודה kubectl describe היא כלי טוב למטרה הזו.

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

    kubectl get pods -n prod
    

    הפלט שיתקבל:

    NAME                             READY  STATUS            RESTARTS  AGE
    product-catalog-d84857dcf-g7v2x  0/1    CrashLoopBackOff  14        25m
    product-catalog-d84857dcf-lq8m4  1/1    Running           0         2h30m
    product-catalog-d84857dcf-wz9p1  1/1    Running           0         2h30m
    
  2. כדי לקבל את היסטוריית האירועים המפורטת, מתארים את ה-Pod הלא יציב:

    kubectl describe pod product-catalog-d84857dcf-g7v2x -n prod
    
  3. בודקים את הפלט ומחפשים רמזים בקטעים Last State ו-Events:

    Containers:
      product-catalog-api:
        ...
        State:          Waiting
          Reason:       CrashLoopBackOff
        Last State:     Terminated
          Reason:       OOMKilled
          Exit Code:    137
          Started:      Mon, 23 Jun 2025 10:50:15 -0700
          Finished:     Mon, 23 Jun 2025 10:54:58 -0700
        Ready:          False
        Restart Count:  14
    ...
    Events:
      Type     Reason     Age                           From                Message
      ----     ------     ----                          ----                -------
      Normal   Scheduled  25m                           default-scheduler   Successfully assigned prod/product-catalog-d84857dcf-g7v2x to gke-cs-cluster-default-pool-8b8a777f-224a
      Normal   Pulled     8m (x14 over 25m)             kubelet             Container image "us-central1-docker.pkg.dev/my-project/product-catalog/api:v1.2" already present on machine
      Normal   Created    8m (x14 over 25m)             kubelet             Created container product-catalog-api
      Normal   Started    8m (x14 over 25m)             kubelet             Started container product-catalog-api
      Warning  BackOff    3m (x68 over 22m)             kubelet             Back-off restarting failed container
    

    הפלט מספק שני רמזים חשובים:

    • קודם כל, בקטע Last State רואים שמאגר התגים הסתיים עם Reason: OOMKilled, מה שאומר שנגמר לו הזיכרון. הסיבה הזו מאומתת על ידי Exit Code: 137, שהוא קוד היציאה הסטנדרטי של Linux לתהליך שהופסק בגלל צריכת זיכרון מוגזמת.
    • שנית, בקטע Events מוצג אירוע Warning: BackOff עם ההודעה Back-off restarting failed container. ההודעה הזו מאשרת שהמאגר נמצא בלולאת כשל, וזו הסיבה הישירה לסטטוס CrashLoopBackOff שראיתם קודם.

הצגה חזותית של ההתנהגות באמצעות מדדים

הפקודה kubectl describe הראתה לכם מה קרה, אבל Cloud Monitoring יכול להראות לכם את ההתנהגות של הסביבה שלכם לאורך זמן.

  1. במסוף Google Cloud , עוברים אל Metrics Explorer.
  2. בוחרים את המדד container/memory/used_bytes.
  3. מסננים את הפלט לפי האשכול, מרחב השמות ושם ה-Pod הספציפיים.

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

איתור שורש הבעיה ביומנים

עכשיו אתם יודעים שזיכרון המכולה עומד להיגמר, אבל עדיין לא ברור לכם למה בדיוק. כדי לגלות את שורש הבעיה, משתמשים ב-Logs Explorer.

  1. במסוף Google Cloud , עוברים אל Logs Explorer.
  2. כותבים שאילתה כדי לסנן את היומנים של הקונטיינר הספציפי רק מהזמן שלפני הקריסה האחרונה (שמופיעה בפלט של הפקודה kubectl describe):

    resource.type="k8s_container"
    resource.labels.cluster_name="example-cluster"
    resource.labels.namespace_name="prod"
    resource.labels.pod_name="product-catalog-d84857dcf-g7v2x"
    timestamp >= "2025-06-23T17:50:00Z"
    timestamp < "2025-06-23T17:55:00Z"
    
  3. ברישומים, אפשר לראות דפוס חוזר של הודעות ממש לפני כל קריסה:

    {
      "message": "Processing large image file product-image-large.jpg",
      "severity": "INFO"
    },
    {
      "message": "WARN: Memory cache size now at 248MB, nearing limit.",
      "severity": "WARNING"
    }
    

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

הממצאים

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

  • ההתראה על מעקב הודיעה לכם שהייתה בעיה.
  • במסוף Google Cloud הוצג שהבעיה השפיעה על משתמשים (הפעלה מחדש).
  • פקודות kubectl הצביעו על הסיבה המדויקת להפעלה מחדש (OOMKilled).
  • ב-Metrics Explorer אפשר לראות את דפוס דליפת הזיכרון לאורך זמן.
  • ב-Logs Explorer נחשפה ההתנהגות הספציפית שגורמת לבעיה בזיכרון.

עכשיו אפשר להטמיע פתרון. אפשר לבצע אופטימיזציה של קוד האפליקציה כדי לטפל בקבצים גדולים בצורה יעילה יותר, או להגדיל את מגבלת הזיכרון של הקונטיינר (במיוחד את הערך spec.containers.resources.limits.memory) במניפסט ה-YAML של עומס העבודה.

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