פתרון בעיות ב-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 מגבילה את מפתחות אישורי ה-SSL ל-2,048 ביטים.

רזולוציה

צריך להקטין את הגודל של מפתח אישור ה-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.

  • כדי לבדוק את תקינות שירות לקצה העורפי שמתאים ל-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, הוא מסתיים באופן מיידי ומפסיק לטפל בבקשות. מאזן העומסים ממשיך לשלוח תעבורה נכנסת לקונטיינר שהופסק, מה שמוביל לשגיאות.

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

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

רזולוציה

הגדרת מאגרי תגים לטיפול ב-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

אם בקצה העורפי של מאזן העומסים יש רק מכונה אחת, צריך להגדיר את אסטרטגיית ההשקה כדי למנוע את השבתת המכונה היחידה לפני שהמכונה החדשה מתוכנתת באופן מלא. ב-pods של אפליקציות שמנוהלים על ידי עומס העבודה 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. כך מוודאים שתשתית איזון העומסים הבסיסית מתוכנתת במלואה. אחרת, כדאי להגביל את ה-Pods של ה-Backend לאזור אחד.

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

השקה תקועה

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

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

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

kubectl get pod POD_NAME -o wide

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

העמודה הזו לא קיימת בגרסה 1.12 ומטה של kubectl. יכול להיות ש-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 עדיין לא נפתרים. כדי להבין את הטעות בהגדרה, בודקים את אובייקטים EndpointSlice שמתאימים לשירות:

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

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

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

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 שהדומיין שלכם מפנה אליהן.

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

שיבוש בתקשורת בין אישורי SSL שמנוהלים על ידי 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 לא פועלת אם חסרים אישורים שמצורפים אליה.

אם יש שיבוש בתקשורת בין אישורי SSL שמנוהלים על ידי 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 משתנה ל-Active.
  4. מנתקים את האישור הישן מ-Ingress ומוחקים אותו.

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

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

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