בעיות באיזון העומסים ב-Google Kubernetes Engine (GKE) עלולות לגרום לשיבושים בשירות, כמו שגיאות HTTP 502, או למנוע גישה לאפליקציות.
במאמר הזה מוסבר איך לפתור שגיאות 502 מ-Ingress חיצוני, ואיך להשתמש ביומנים של איזון עומסים ובכלי אבחון, כמו check-gke-ingress, כדי לזהות בעיות.
המידע הזה חשוב לאדמינים ולמפעילים של פלטפורמות ולמפתחי אפליקציות שמגדירים ותחזקים שירותים עם איזון עומסים ב-GKE. מידע נוסף על התפקידים הנפוצים ועל דוגמאות למשימות שאנחנו מתייחסים אליהן בתוכן של Google Cloud זמין במאמר תפקידי משתמשים נפוצים ומשימות ב-GKE.
לא נמצא BackendConfig
השגיאה הזו מתרחשת כשמציינים BackendConfig ליציאת שירות בהערת השירות, אבל לא ניתן למצוא את משאב ה-BackendConfig בפועל.
כדי להעריך אירוע ב-Kubernetes, מריצים את הפקודה הבאה:
kubectl get event
פלט לדוגמה שמצביע על כך שלא נמצא BackendConfig:
KIND ... SOURCE
Ingress ... loadbalancer-controller
MESSAGE
Error during sync: error getting BackendConfig for port 80 on service "default/my-service":
no BackendConfig for service port exists
כדי לפתור את הבעיה, צריך לוודא שלא יצרתם את משאב BackendConfig במרחב השמות הלא נכון, או שכתבתם את ההפניה שלו בצורה שגויה בהערת השירות.
לא נמצאה מדיניות אבטחה של Ingress
אחרי שיוצרים את אובייקט ה-Ingress, אם מדיניות האבטחה לא משויכת כראוי לשירות LoadBalancer, צריך להעריך את אירוע Kubernetes כדי לראות אם יש טעות בהגדרה. אם ב-BackendConfig מוגדרת מדיניות אבטחה שלא קיימת, אירוע אזהרה מופק מעת לעת.
כדי להעריך אירוע ב-Kubernetes, מריצים את הפקודה הבאה:
kubectl get event
הפלט הבא לדוגמה מציין שמדיניות האבטחה לא נמצאה:
KIND ... SOURCE
Ingress ... loadbalancer-controller
MESSAGE
Error during sync: The given security policy "my-policy" does not exist.
כדי לפתור את הבעיה, צריך לציין את השם הנכון של מדיניות האבטחה ב-BackendConfig.
פתרון שגיאות מסדרה 500 באמצעות NEGs במהלך שינוי קנה מידה של עומסי עבודה ב-GKE
התסמין:
כשמשתמשים ב-NEGs שהוקצו ב-GKE לצורך איזון עומסים, יכול להיות שיוצגו שגיאות 502 או 503 בשירותים במהלך הקטנת העומס. 502 שגיאות מתרחשות כש-Pods מסתיימים לפני שחיבורים קיימים נסגרים, בעוד ששגיאות 503 מתרחשות כשנתיב התנועה מופנה אל Pods שנמחקו.
הבעיה הזו יכולה להשפיע על אשכולות אם אתם משתמשים במוצרים של GKE לניהול איזון עומסים שמשתמשים ב-NEGs, כולל Gateway, Ingress ו-NEGs עצמאיים. אם אתם משנים את גודל עומסי העבודה בתדירות גבוהה, הסיכון שהאשכול יושפע גבוה יותר.
אבחון:
הסרת Pod ב-Kubernetes בלי להסיר את נקודת הקצה שלו ולהסיר אותו קודם מ-NEG מובילה לשגיאות מסדרה 500. כדי להימנע מבעיות במהלך סיום הפעולה של ה-Pod, צריך לשים לב לסדר הפעולות. בתמונות הבאות מוצגים תרחישים שבהם BackendService Drain Timeout לא מוגדר ו-BackendService Drain Timeout מוגדר עם BackendConfig.
תרחיש 1: הערך של BackendService Drain Timeout לא מוגדר.
בתמונה הבאה מוצג תרחיש שבו הערך של BackendService Drain Timeout לא מוגדר.

תרחיש 2: הערך של BackendService Drain Timeout מוגדר.
בתמונה הבאה מוצג תרחיש שבו הערך BackendService Drain Timeout מוגדר.

הזמן המדויק שבו מתרחשות השגיאות מסוג 500 תלוי בגורמים הבאים:
זמן האחזור של ניתוק NEG API: זמן האחזור של ניתוק NEG API מייצג את הזמן הנוכחי שנדרש לסיום פעולת הניתוק ב- Google Cloud. הגורמים שמשפיעים על זה הם מגוונים ולא קשורים ל-Kubernetes, כולל סוג מאזן העומסים והאזור הספציפי.
חביון ניקוז: חביון ניקוז הוא הזמן שנדרש למאזן העומסים כדי להתחיל להפנות את התנועה מחלק מסוים במערכת. אחרי שמפעילים את הניקוז, מאזן העומסים מפסיק לשלוח בקשות חדשות לנקודת הקצה, אבל עדיין יש השהיה בהפעלת הניקוז (השהיית הניקוז), שיכולה לגרום לשגיאות זמניות מסוג 503 אם ה-Pod כבר לא קיים.
הגדרת בדיקת תקינות: סף בדיקת תקינות רגיש יותר מקצר את משך השגיאות מסוג 503, כי הוא יכול לאותת למאזן העומסים להפסיק לשלוח בקשות לנקודות קצה גם אם פעולת הניתוק לא הסתיימה.
תקופת חסד לסיום: תקופת החסד לסיום קובעת את משך הזמן המקסימלי שמוקצה ל-Pod כדי לצאת. עם זאת, אפשר לצאת מ-Pod לפני שתקופת החסד לסיום המינוי מסתיימת. אם חולף יותר זמן מהתקופה הזו עד שה-Pod מוכן, הוא נאלץ לצאת בסוף התקופה הזו. זו הגדרה ב-Pod שצריך להגדיר בהגדרת עומס העבודה.
פתרון אפשרי:
כדי למנוע את שגיאות 5XX, צריך להחיל את ההגדרות הבאות. ערכי הזמן הקצוב לתפוגה הם בגדר הצעה, ויכול להיות שתצטרכו להתאים אותם לאפליקציה הספציפית שלכם. בקטע הבא מפורט תהליך ההתאמה האישית.
בתמונה הבאה אפשר לראות איך משאירים את ה-Pod פעיל באמצעות וו preStop:

כדי להימנע משגיאות מסדרה 500, מבצעים את השלבים הבאים:
מגדירים את
BackendService Drain Timeoutשל השירות ל-1 דקה.משתמשי Ingress יכולים לעיין במאמר הגדרת פסק זמן ב-BackendConfig.
משתמשי Gateway יכולים לקרוא על הגדרת פסק הזמן ב-GCPBackendPolicy.
אם אתם מנהלים את BackendServices ישירות כשאתם משתמשים ב-Standalone NEGs, תוכלו לעיין במאמר בנושא הגדרת פסק זמן ישירות ב-Backend Service.
מאריכים את
terminationGracePeriodבפוד.מגדירים את
terminationGracePeriodSecondsב-Pod ל-3.5 דקות. בשילוב עם ההגדרות המומלצות, ההגדרה הזו מאפשרת ל-Pods חלון של 30 עד 45 שניות לכיבוי מסודר אחרי שנקודת הקצה של ה-Pod הוסרה מ-NEG. אם אתם צריכים יותר זמן לסגירה מסודרת, אתם יכולים להאריך את תקופת החסד או לפעול לפי ההוראות שמפורטות בקטע התאמה אישית של פסק זמן.במניפסט של ה-Pod הבא מוגדר זמן קצוב לתפוגה של 210 שניות (3.5 דקות) לזמן להשלמת תהליך (connection draining):
spec: terminationGracePeriodSeconds: 210 containers: - name: my-app ... ...החלת hook של
preStopעל כל מאגרי התגים.החלת וו
preStopשיבטיח שה-Pod יפעל למשך 120 שניות נוספות בזמן שנקודת הקצה של ה-Pod מתרוקנת במאזן העומסים ונקודת הקצה מוסרת מה-NEG.spec: containers: - name: my-app ... lifecycle: preStop: exec: command: ["/bin/sh", "-c", "sleep 120s"] ...
התאמה אישית של פסק זמן
כדי להבטיח את המשכיות של ה-Pod ולמנוע שגיאות מסדרה 500, ה-Pod צריך להיות פעיל עד להסרת נקודת הקצה מה-NEG. כדי למנוע במיוחד שגיאות 502 ו-503, כדאי להטמיע שילוב של פסק זמן ו-preStophook.
כדי להאריך את משך הפעולה של ה-Pod במהלך תהליך ההשבתה, מוסיפים preStop hook
ל-Pod. ה-hook preStop מופעל לפני שמתקבל אות ליציאה מ-Pod, כך שאפשר להשתמש ב-hook preStop כדי לשמור על הפעילות של ה-Pod עד שהנקודה המתאימה שלו מוסרת מ-NEG.
כדי להאריך את משך הזמן שבו ה-Pod נשאר פעיל במהלך תהליך הכיבוי, מוסיפים וו (hook) מסוג preStop להגדרת ה-Pod באופן הבא:
spec:
containers:
- name: my-app
...
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep <latency time>"]
אתם יכולים להגדיר פסק זמן והגדרות קשורות כדי לנהל את ההשבתה המבוקרת של ה-Pods במהלך צמצום של עומסי עבודה. אפשר לשנות את הגדרות הזמן הקצוב לתפוגה בהתאם לתרחישי שימוש ספציפיים. מומלץ להתחיל עם פרקי זמן ארוכים יותר להמתנה ואז לקצר אותם לפי הצורך. אפשר להתאים אישית את פסק הזמן על ידי הגדרת פרמטרים שקשורים לפסק זמן ו-hook של preStop באחת מהדרכים הבאות:
זמן קצוב לתפוגה של ניקוז שירות לקצה העורפי
כברירת מחדל, הפרמטר Backend Service Drain Timeout לא מוגדר ואין לו השפעה. אם מגדירים את הפרמטר Backend Service Drain Timeout ומפעילים אותו, מאזן העומסים מפסיק להפנות בקשות חדשות לנקודת הקצה וממתין עד שיגיע זמן קצוב לתפוגה לפני שהוא מסיים את החיבורים הקיימים.
אפשר להגדיר את הפרמטר Backend Service Drain Timeout באמצעות BackendConfig עם Ingress, GCPBackendPolicy עם Gateway או באופן ידני ב-BackendService עם NEGs עצמאיים. הזמן הקצוב לתפוגה צריך להיות ארוך פי 1.5 עד 2 מהזמן שנדרש לעיבוד הבקשה. כך, אם בקשה תתקבל ממש לפני תחילת הניקוז, היא תושלם לפני שהזמן הקצוב לתפוגה יסתיים. הגדרת הפרמטר Backend Service Drain Timeout לערך גדול מ-0 עוזרת לצמצם את מספר השגיאות 503, כי לא נשלחות בקשות חדשות לנקודות קצה שמתוזמנות להסרה. כדי שזמן קצוב לתפוגה זה יהיה אפקטיבי, עליך להשתמש בו עם ה-hook preStop כדי לוודא שה-Pod יישאר פעיל בזמן ההתרוקנות. בלי השילוב הזה, בקשות קיימות שלא הושלמו יקבלו שגיאת 502.
preStop זמן הצפייה ברגע המושך
ה-hook preStop צריך לעכב את השבתת ה-Pod מספיק זמן כדי שגם זמן האחזור של הניקוז וגם פסק הזמן של ניקוז שירות לקצה העורפי יושלמו. כך מובטח זמן להשלמת תהליך (connection draining) תקין והסרת נקודת הקצה מה-NEG לפני שה-Pod מושבת.
כדי לקבל תוצאות אופטימליות, צריך לוודא שpreStop זמן ההרצה של ה-hook גדול או שווה לסכום של Backend Service Drain Timeout ושל זמן האחזור של ההתרוקנות.
כדי לחשב את זמן ההפעלה האידיאלי של ה-hook, משתמשים בנוסחה הבאה:preStop
preStop hook execution time >= BACKEND_SERVICE_DRAIN_TIMEOUT + DRAIN_LATENCY
מחליפים את מה שכתוב בשדות הבאים:
-
BACKEND_SERVICE_DRAIN_TIMEOUT: השעה שהגדרתם לBackend Service Drain Timeout. -
DRAIN_LATENCY: זמן משוער של השהיית הניקוז. מומלץ להשתמש בדקה אחת כהערכה.
אם שגיאות 500 נמשכות, צריך להעריך את משך ההתרחשות הכולל ולהוסיף את הזמן הזה כפול 2 לזמן האחזור המשוער של הניקוז. כך מבטיחים של-Pod יהיה מספיק זמן להתרוקן בצורה תקינה לפני שהוא יוסר מהשירות. אם הערך הזה ארוך מדי לתרחיש השימוש הספציפי שלכם, אתם יכולים לשנות אותו.
לחלופין, אפשר להעריך את התזמון על ידי בדיקת חותמת הזמן של המחיקה מה-Pod וחותמת הזמן שבה נקודת הקצה הוסרה מה-NEG ביומני הביקורת של Cloud.
פרמטר של תקופת חסד לסיום
צריך להגדיר את הפרמטר terminationGracePeriod כך שיהיה מספיק זמן עד שה-hook preStop יסיים את הפעולה ועד שהפוד ישלים כיבוי תקין.
כברירת מחדל, אם לא מגדירים את הערך במפורש, הערך של terminationGracePeriod הוא 30 שניות.
אפשר לחשב את הערך האופטימלי של terminationGracePeriod באמצעות הנוסחה:
terminationGracePeriod >= preStop hook time + Pod shutdown time
כדי להגדיר את terminationGracePeriod בתצורה של ה-Pod באופן הבא:
spec:
terminationGracePeriodSeconds: <terminationGracePeriod>
containers:
- name: my-app
...
...
לא נמצא NEG כשיוצרים משאב Internal Ingress
יכול להיות שתקבלו את השגיאה הבאה כשאתם יוצרים Ingress פנימי ב-GKE:
Error syncing: error running backend syncing routine: googleapi: Error 404: The resource 'projects/PROJECT_ID/zones/ZONE/networkEndpointGroups/NEG' was not found, notFound
השגיאה הזו מתרחשת כי Ingress למאזני עומסים פנימיים של אפליקציות (ALB) דורש קבוצות של נקודות קצה ברשת (NEGs) כבק-אנד.
בסביבות של VPC משותף או באשכולות שמופעלת בהם מדיניות רשת, מוסיפים את ההערה cloud.google.com/neg: '{"ingress": true}' למניפסט של השירות.
504 Gateway Timeout: upstream request timeout
יכול להיות שתקבלו את השגיאה הבאה כשאתם ניגשים לשירות מ-Ingress פנימי ב-GKE:
HTTP/1.1 504 Gateway Timeout
content-length: 24
content-type: text/plain
upsteam request timeout
השגיאה הזו מתרחשת כי תנועה שנשלחת למאזני עומסים פנימיים של אפליקציות מועברת דרך שרתי proxy של Envoy בטווח של רשת משנה שמוגדרת כ-proxy בלבד.
כדי לאפשר תעבורה מטווח תת-הרשת של שרת proxy בלבד, יוצרים כלל חומת אש ב-targetPort של השירות.
שגיאה 400: ערך לא תקין בשדה 'resource.target'
יכול להיות שתקבלו את השגיאה הבאה כשאתם ניגשים לשירות מ-Ingress פנימי ב-GKE:
Error syncing:LB_NAME does not exist: googleapi: Error 400: Invalid value for field 'resource.target': 'https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION_NAME/targetHttpProxies/LB_NAME. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.
כדי לפתור את הבעיה, צריך ליצור רשת משנה לשרת proxy בלבד.
שגיאה במהלך הסנכרון: שגיאה בהפעלת שגרת הסנכרון של מאזן העומסים: מאזן העומסים לא קיים
יכול להיות שתקבלו אחת מהשגיאות הבאות כשמישור הבקרה של GKE משודרג או כשמשנים אובייקט Ingress:
"Error during sync: error running load balancer syncing routine: loadbalancer
INGRESS_NAME does not exist: invalid ingress frontend configuration, please
check your usage of the 'kubernetes.io/ingress.allow-http' annotation."
או:
Error during sync: error running load balancer syncing routine: loadbalancer LOAD_BALANCER_NAME does not exist:
googleapi: Error 400: Invalid value for field 'resource.IPAddress':'INGRESS_VIP'. Specified IP address is in-use and would result in a conflict., invalid
כדי לפתור את הבעיות האלה, אפשר לנסות את השלבים הבאים:
- מוסיפים את השדה
hostsבקטעtlsשל מניפסט ה-Ingress, ואז מוחקים את ה-Ingress. ממתינים חמש דקות עד ש-GKE ימחק את משאבי ה-Ingress שלא נעשה בהם שימוש. לאחר מכן, יוצרים מחדש את ה-Ingress. מידע נוסף זמין במאמר בנושא השדה hosts של אובייקט Ingress. - מבטלים את השינויים שביצעתם ב-Ingress. לאחר מכן, מוסיפים אישור באמצעות הערה או סוד של Kubernetes.
תעבורת נתונים נכנסת (ingress) חיצונית יוצרת שגיאות HTTP 502
ההנחיות הבאות יעזרו לכם לפתור שגיאות HTTP 502 במשאבי Ingress חיצוניים:
- מפעילים רישום ביומן לכל שירות לקצה העורפי שמשויך לכל שירות GKE שאליו יש הפניה ב-Ingress.
- כדאי להשתמש בפרטי הסטטוס כדי לזהות את הסיבות לתגובות HTTP 502. פרטי הסטטוס שמציינים שתגובת HTTP 502 הגיעה מהקצה העורפי מחייבים פתרון בעיות ב-Pods של השרת, ולא במאזן העומסים.
קבוצות של מכונות לא מנוהלות
יכול להיות שתיתקלו בשגיאות HTTP 502 במשאבי Ingress חיצוניים אם משאבי ה-Ingress החיצוניים משתמשים בקצה העורפי של קבוצת מופעים לא מנוהלת. הבעיה הזו מתרחשת אם כל התנאים הבאים מתקיימים:
- במאגר יש מספר גדול של צמתים בכל מאגרי הצמתים.
- ה-Pods של הצגת המודעות בשירות אחד או יותר שאליהם יש הפניה ב-Ingress ממוקמים רק בכמה צמתים.
- השירותים שאליהם מתייחס ה-Ingress משתמשים ב-
externalTrafficPolicy: Local.
כדי לבדוק אם שער ה-Ingress החיצוני שלכם משתמש בשרתי קצה של קבוצת מופעים לא מנוהלת:
נכנסים לדף Ingress במסוף Google Cloud .
לוחצים על השם של ה-Ingress החיצוני.
לוחצים על השם של מאזן העומסים. יוצג הדף פרטי איזון העומסים.
כדי לדעת אם ה-Ingress החיצוני שלכם משתמש ב-NEGs או בקבוצות של מכונות וירטואליות, צריך לעיין בטבלה שבקטע Backend services (שירותי קצה עורפי).
כדי לפתור את הבעיה, אפשר לנסות אחד מהפתרונות הבאים:
- שימוש באשכול המותאם ל-VPC.
- משתמשים ב-
externalTrafficPolicy: Clusterלכל שירות שמקושר ל-Ingress חיצוני. הפתרון הזה גורם לאובדן כתובת ה-IP המקורית של הלקוח במקורות של החבילה. - משתמשים בהערה
node.kubernetes.io/exclude-from-external-load-balancers=true. מוסיפים את ההערה לצמתים או למאגרי הצמתים שלא מריצים אף Pod של שרת לאף שירות שמפנה ל-Ingress חיצוני או לשירותLoadBalancerבאשכול.
שימוש ביומנים של מאזן העומסים לפתרון בעיות
אתם יכולים להשתמש ביומנים של מאזן עומסי רשת פנימי להעברת סיגנל ללא שינוי וביומנים של מאזן עומסי רשת חיצוני להעברת סיגנל ללא שינוי כדי לפתור בעיות במאזני עומסים ולבצע קורלציה בין התנועה ממאזני העומסים לבין משאבי GKE.
היומנים מצטברים לכל חיבור ומיוצאים כמעט בזמן אמת. יומנים נוצרים לכל צומת GKE שמעורב בנתיב הנתונים של שירות LoadBalancer, גם לתנועת נתונים נכנסת וגם לתנועת נתונים יוצאת. הרשומות ביומן כוללות שדות נוספים למשאבי GKE, כמו:
- שם האשכול
- מיקום האשכול
- שם השירות
- מרחב השמות של השירות
- שם ה-Pod
- מרחב השמות של ה-Pod
תמחור
אין חיובים נוספים על שימוש ביומנים. התמחור הסטנדרטי של Cloud Logging, BigQuery או Pub/Sub חל בהתאם לאופן ההטמעה של היומנים. הפעלת היומנים לא משפיעה על הביצועים של מאזן העומסים.
שימוש בכלי אבחון לפתרון בעיות
כלי האבחון check-gke-ingress בודק משאבי Ingress כדי לזהות טעויות נפוצות בהגדרות. אפשר להשתמש בכלי check-gke-ingress בדרכים הבאות:
- מריצים את כלי שורת הפקודה
gcpdiagבאשכול. תוצאות ה-Ingress מופיעות בקטע של כלל הבדיקהgke/ERR/2023_004. - אפשר להשתמש בכלי
check-gke-ingressלבד או כפלאגין של kubectl. לשם כך, פועלים לפי ההוראות במאמר check-gke-ingress.
המאמרים הבאים
אם לא מצאתם פתרון לבעיה שלכם במסמכים, תוכלו להיעזר בקבלת תמיכה, כולל עצות בנושאים הבאים:
- פתיחת בקשת תמיכה באמצעות פנייה אל Cloud Customer Care.
- קבלת תמיכה מהקהילה על ידי פרסום שאלות ב-StackOverflow ושימוש בתג
google-kubernetes-engineכדי לחפש בעיות דומות. אפשר גם להצטרף לערוץ Slack#kubernetes-engineכדי לקבל תמיכה נוספת מהקהילה. - פתיחת באגים או בקשות להוספת תכונות באמצעות הכלי הציבורי למעקב אחר בעיות.