פתרון בעיות ב-GKE Ingress

בעיות ב-Ingress ב-Google Kubernetes Engine ‏ (GKE) יכולות למנוע מתעבורה חיצונית או פנימית להגיע לשירותים שלכם.

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

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

הערה שגויה לגבי מחלקת ה-Ingress

תסמין

כשיוצרים Ingress, יכול להיות שתופיע השגיאה הבאה:

Missing one or more resources. If resource creation takes longer than expected, you might have an invalid configuration.

סיבות אפשריות

יכול להיות שהגדרתם את סוג ה-Ingress במניפסט בצורה שגויה כשיצרתם את ה-Ingress.

הפתרון

כדי לציין מחלקת Ingress, צריך להשתמש בהערה kubernetes.io/ingress.class. אי אפשר לציין GKE Ingress באמצעות spec.ingressClassName.

  • כדי לפרוס מאזן עומסים של אפליקציות (ALB) פנימי, משתמשים בהערה kubernetes.io/ingress.class: gce-internal.
  • כדי לפרוס מאזן עומסים חיצוני של אפליקציות (ALB), משתמשים בהערה kubernetes.io/ingress.class: gce.

הערה שגויה לגבי כתובת ה-IP הסטטית

תסמין

כשמגדירים Ingress חיצוני לשימוש בכתובת IP סטטית, יכול להיות שתוצג השגיאה הבאה:

Error syncing to GCP: error running load balancer syncing routine: loadbalancer <Name of load balancer> does not exist: the given static IP name <Static IP> doesn't translate to an existing static IP.

סיבות אפשריות

  • לא יצרתם כתובת IP חיצונית סטטית לפני שפרסתם את תעבורת הנתונים הנכנסת (ingress).
  • לא השתמשתם בהערה הנכונה לסוג מאזן העומסים.

הפתרון

אם אתם מגדירים תעבורת נתונים נכנסת (ingress) חיצונית:

אם מגדירים Ingress פנימי:

  • לפני שמפעילים את Ingress, צריך לשמור כתובת IP פנימית סטטית אזורית.
  • משתמשים בהערה kubernetes.io/ingress.regional-static-ip-name במשאב Ingress.

כתובת ה-IP הסטטית כבר בשימוש

תסמין

יכול להיות שתופיע השגיאה הבאה כשמציינים כתובת IP סטטית כדי להקצות את משאב ה-Ingress הפנימי או החיצוני:

Error syncing to GCP: error running load balancer syncing
routine: loadbalancer <LB name> does not exist:
googleapi: Error 409: IP_IN_USE_BY_ANOTHER_RESOURCE - IP ''<IP address>'' is already being used by another resource.

סיבות אפשריות

כתובת ה-IP הסטטית כבר נמצאת בשימוש של משאב אחר.

שגיאה כשמשביתים את HTTP ומשתמשים באישור שמנוהל על ידי Google

תסמין

אם אתם מגדירים אישור SSL בניהול Google ומשביתים את תעבורת ה-HTTP ב-Ingress, תופיע השגיאה הבאה:

Error syncing to GCP: error running load balancer syncing
routine: loadbalancer <Load Balancer name> does not exist:
googleapi: Error 404: The resource ''projects/<Project>/global/sslPolicies/<Policy name>' was not found, notFound

סיבות אפשריות

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

  • networking.gke.io/managed-certificates (לשיוך האישור שמנוהל על ידי Google ל-Ingress)
  • kubernetes.io/ingress.allow-http: false (להשבתת תעבורת HTTP)

הפתרון

משביתים את תעבורת ה-HTTP רק אחרי שמאזן העומסים החיצוני של אפליקציות מתוכנת באופן מלא. אפשר לעדכן את ה-Ingress ולהוסיף את ההערה kubernetes.io/ingress.allow-http: false למניפסט.

חסרה תת-רשת ל-proxy בלבד ל-Ingress פנימי

תסמין

כשפורסים Ingress למאזן עומסים של אפליקציות (ALB) פנימי, יכול להיות שתופיע השגיאה הבאה:

Error syncing to GCP: error running load balancer syncing routine:
loadbalancer <LB name> does not exist: googleapi: Error 400: Invalid value for field 'resource.target': 'https://www.googleapis.com/compute/v1/projects/<Project ID>/regions/<Region>/targetHttpsProxies/<Target proxy>'.
An active proxy-only subnetwork is required in the same region and VPC as
the forwarding rule.

סיבות אפשריות

לא יצרתם רשת משנה של proxy בלבד לפני שיצרתם את משאב ה-Ingress. נדרשת תת-רשת לשרת proxy בלבד למאזני עומסים פנימיים של אפליקציות.

הפתרון

צריך ליצור רשת משנה ל-proxy בלבד לפני שמפעילים את Ingress הפנימי.

המפתח של אישור ה-SSL גדול מדי

תסמין

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

Error syncing to GCP: error running load balancer syncing routine: loadbalancer gky76k70-load-test-trillian-api-ingress-fliismmb does not exist: Cert creation failures - k8s2-cr-gky76k70-znz6o1pfu3tfrguy-f9be3a4abbe573f7 Error:googleapi: Error 400: The SSL key is too large., sslCertificateKeyTooLarge

סיבות אפשריות

Google Cloud יש מגבלה של 2,048 ביט למפתחות של אישורי SSL.

הפתרון

צריך להקטין את הגודל של מפתח אישור ה-SSL ל-2,048 ביט או פחות.

שגיאה ביצירת Ingress ברמת Standard

תסמין

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

Error syncing to GCP: error running load balancer syncing routine: load balancer <LB Name> does not exist: googleapi: Error 400: STANDARD network tier (the project''s default network tier) is not supported: STANDARD network tier is not supported for global forwarding rule., badRequest

הפתרון

מגדירים את מסלול הרשת שמוגדר כברירת מחדל בפרויקט ל-Premium.

שגיאה צפויה 'לא נמצא' עבור k8s-ingress-svc-acct-permission-check-probe

בקר ה-Ingress מבצע בדיקות תקופתיות של הרשאות חשבון השירות על ידי אחזור משאב בדיקה מהפרויקט Google Cloud . הוא יופיע כ-GET של BackendService גלובלי (שלא קיים) עם השם k8s-ingress-svc-acct-permission-check-probe. מכיוון שהמשאב הזה לא אמור להתקיים בדרך כלל, בקשת GET תחזיר את השגיאה 'לא נמצא'. זה צפוי. בקר התנועה בודק שהקריאה ל-API לא נדחית בגלל בעיות הרשאה. אם תיצרו BackendService עם אותו שם, הפעולה GET תצליח במקום להחזיר את השגיאה 'לא נמצא'.

שגיאות בשימוש באיזון עומסים שמקורם בקונטיינר

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

  • במסמכי התיעוד בנושא איזון עומסים מוסבר איך מציגים את רשימת קבוצות נקודות הקצה ברשת.

  • אפשר למצוא את השם והאזורים של ה-NEG שתואם לשירות בביאור neg-status של השירות. קבלת מפרט השירות באמצעות:

    kubectl get svc SVC_NAME -o yaml
    

    ההערה metadata:annotations:cloud.google.com/neg-status מפרטת את השם של ה-NEG התואם של השירות ואת האזורים של ה-NEG.

  • כדי לבדוק את תקינות שירות ה-Backend שמתאים ל-NEG, מריצים את הפקודה הבאה:

    gcloud compute backend-services --project PROJECT_NAME \
        get-health BACKEND_SERVICE_NAME --global
    

    לשירות לקצה העורפי יש את אותו שם כמו ל-NEG שלו.

  • כדי להדפיס את יומני האירועים של שירות:

    kubectl describe svc SERVICE_NAME
    

    מחרוזת השם של השירות כוללת את השם ואת מרחב השמות של שירות GKE התואם.

אי אפשר ליצור אשכול עם כתובות IP של כינויים

תסמינים

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

ResponseError: code=400, message=IP aliases cannot be used with a legacy network.
סיבות אפשריות

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

רזולוציה

חשוב לוודא שלא יוצרים אשכול עם כתובות IP של כינויים ועם רשת מדור קודם שמופעלת בו-זמנית. מידע נוסף על שימוש בכתובות IP של כינוי זמין במאמר יצירת אשכול המותאם ל-VPC.

התנועה לא מגיעה לנקודות הקצה

תסמינים
שגיאות 502 או 503 או חיבורים שנדחו.
סיבות אפשריות

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

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

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

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

רזולוציה

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

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

lifecycle:
  preStop:
    exec:
      # if SIGTERM triggers a quick exit; keep serving traffic instead
      command: ["sleep","60"]

מידע נוסף על סיום של Pod

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

strategy:
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0

כדי לפתור בעיות שקשורות לתנועה שלא מגיעה לנקודות הקצה, צריך לוודא שכללי חומת האש מאפשרים תנועת TCP נכנסת לנקודות הקצה בטווחים 130.211.0.0/22 ו-35.191.0.0/16. מידע נוסף זמין במאמר בנושא הוספת בדיקות תקינות במסמכי התיעוד של Cloud Load Balancing.

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

gcloud compute backend-services list

אחזור סטטוס תקינות של קצה עורפי משירות הקצה העורפי:

gcloud compute backend-services get-health BACKEND_SERVICE_NAME

אם כל ה-backends לא תקינים, יכול להיות שיש הגדרה שגויה בחומת האש, ב-Ingress או בשירות.

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

אם חלק מהקצה העורפי לא מופיע ברשימת שירותי הקצה העורפי, יכול להיות שהסיבה לכך היא השהיה בתכנות. כדי לבדוק זאת, מריצים את הפקודה הבאה, שבה NEG_NAME הוא השם של שירות לקצה העורפי. (קבוצות NEG ושירותים לקצה העורפי חולקים את אותו שם):

gcloud compute network-endpoint-groups list-network-endpoints NEG_NAME

בודקים אם כל נקודות הקצה הצפויות נמצאות ב-NEG.

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

אם מגדירים מדיניות רשת לנקודת הקצה, צריך לוודא שמתאפשרת תעבורת נתונים נכנסת (ingress) מתת-רשת של שרת proxy בלבד.

ההשקה הושהתה

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

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

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

kubectl get pod POD_NAME -o wide

בודקים את העמודה READINESS GATES.

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

kubectl get pod POD_NAME -o yaml

שערי המוכנות והסטטוס שלהם מפורטים בפלט.

רזולוציה

מוודאים שקובץ אימג' של קונטיינר במפרט ה-Pod של ה-Deployment (פריסה) פועל בצורה תקינה ויכול להגיב לבדיקות תקינות. מוודאים שהבדיקות של תקינות השירות מוגדרות בצורה נכונה.

שגיאות במצב מוגבל

תסמינים

החל מגרסה 1.29.2-gke.1643000 של GKE, יכול להיות שתקבלו את האזהרות הבאות לגבי השירות שלכם בLogs Explorer כשמתבצע עדכון של קבוצות NEG:

Entering degraded mode for NEG <service-namespace>/<service-name>-<neg-name>... due to sync err: endpoint has missing nodeName field
סיבות אפשריות

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

דוגמאות לשגיאות נפוצות:

  • endpoint has missing pod/nodeName field
  • endpoint corresponds to an non-existing pod/node
  • endpoint information for attach/detach operation is incorrect
רזולוציה

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

kubectl get endpointslice -l kubernetes.io/service-name=<service-name>

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

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

NEG <service-namespace>/<service-name>-<neg-name>... is no longer in degraded mode

שגיאות בשימוש באישורי SSL בניהול Google

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

בדיקת אירועים ב-ManagedCertificate ובמשאבי Ingress

אם תעלו יותר אישורים מהמותר, אירוע עם סיבה TooManyCertificates יתווסף לManagedCertificate. אפשר לבדוק את האירועים באובייקט ManagedCertificate באמצעות הפקודה הבאה:

kubectl describe managedcertificate CERTIFICATE_NAME

מחליפים את CERTIFICATE_NAME בשם של ManagedCertificate.

אם מצרפים ManagedCertificate שלא קיים ל-Ingress, אירוע עם סיבה MissingCertificate נוסף ל-Ingress. כדי לבדוק את האירועים ב-Ingress, משתמשים בפקודה הבאה:

kubectl describe ingress INGRESS_NAME

מחליפים את INGRESS_NAME בשם של Ingress.

אישור מנוהל לא מוקצה כשהדומיין מתורגם לכתובות IP של כמה איזוני עומסים

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

במילים אחרות, אם הדומיין שלכם מוגדר עם כתובות IPv4 ו-IPv6 שמוגדרות עם אובייקטים שונים של Ingress, אתם צריכים ליצור אובייקט ManagedCertificate יחיד ולצרף אותו לשני האובייקטים של Ingress.

שיבוש בתקשורת בין אישורים שמנוהלים על ידי Google לבין Ingress

אישורים מנוהלים מתקשרים עם Ingress באמצעות ההערה ingress.gcp.kubernetes.io/pre-shared-cert. אתם יכולים לשבש את התקשורת הזו אם, לדוגמה:

  • מריצים תהליך אוטומטי שמנקה את ההערה ingress.gcp.kubernetes.io/pre-shared-cert
  • שמירת קובץ snapshot של Ingress, ואז מחיקה ושחזור של Ingress מקובץ ה-snapshot. בינתיים, יכול להיות שמשאב SslCertificate שמופיע בהערה ingress.gcp.kubernetes.io/pre-shared-cert נמחק. התכונה Ingress לא פועלת אם חסרים אישורים שמצורפים אליה.

אם יש שיבוש בתקשורת בין אישורי האבטחה שמנוהלים על ידי Google לבין Ingress, צריך למחוק את התוכן של ההערה ingress.gcp.kubernetes.io/pre-shared-cert ולהמתין עד שהמערכת תבצע סנכרון. כדי למנוע הישנות של הבעיה, צריך לוודא שההערה לא משתנה או נמחקת בטעות.

שגיאות אימות ביצירת אישור שמנוהל על ידי Google

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

spec.domains in body should have at most 100 items

ManagedCertificate בקובץ המניפסט שלכם מופיעים יותר מ-100 דומיינים בשדה spec.domains. אישורים שמנוהלים על ידי Google תומכים בעד 100 דומיינים בלבד.

spec.domains in body should match '^(([a-zA-Z0-9]+|[a-zA-Z0-9][-a-zA-Z0-9]*[a-zA-Z0-9])\.)+[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]\.?$'

ציינתם שם דומיין לא תקין או שם דומיין עם תו כללי בשדה spec.domains. האובייקט ManagedCertificate לא תומך בדומיינים עם תווים כלליים (לדוגמה, *.example.com).

spec.domains in body should be at most 63 chars long

ציינתם שם דומיין ארוך מדי. אישורים שמנוהלים על ידי Google תומכים בשמות דומיין באורך של 63 תווים לכל היותר.

עדכון ידני של אישור שמנוהל על ידי Google

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

  1. יוצרים ManagedCertificate לדומיין החדש.
  2. מוסיפים את השם של ManagedCertificate להערה networking.gke.io/managed-certificates ב-Ingress באמצעות רשימה מופרדת בפסיקים. אל תסירו את השם של האישור הישן.
  3. מחכים עד שהסטטוס של ManagedCertificate יהיה פעיל.
  4. מנתקים את האישור הישן מ-Ingress ומוחקים אותו.

כשיוצרים ManagedCertificate, Google Cloud נוצר אישור SSL בניהול Google. אי אפשר לעדכן את האישור הזה. אם מעדכנים את ManagedCertificate, Google Cloud אישור ה-SSL בניהול Google נמחק ונוצר מחדש.

כדי לספק Ingress מוצפן ומאובטח ב-HTTPS לאשכולות GKE, אפשר לעיין בדוגמה Secure Ingress.

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