פתרון בעיות בהפעלת עומסי עבודה ב-Cloud Service Mesh
במסמך הזה מוסבר על בעיות נפוצות ב-Cloud Service Mesh ואיך לפתור אותן. לקבלת עזרה נוספת, אפשר לעיין במאמר בנושא קבלת תמיכה.
שער נכשל בהפעלה עם פרוקסי ללא דיסטרולס כאשר נחשפת יציאה מורשית
כברירת מחדל, פרוקסי ללא הפצה מתחיל עם הרשאות שאינן הרשאות root, ובמקרים מסוימים זה עלול לגרום לכשלים בקישור ליציאות עם הרשאות. אם אתם רואים שגיאות דומות לאלה שמופיעות בהמשך במהלך הפעלת ה-proxy, צריך להחיל securityContext נוסף על פריסת שער.
Error adding/updating listener(s) 0.0.0.0_80: cannot bind '0.0.0.0:80': Permission denied
הדוגמה הבאה היא קובץ ה-YAML של פריסת שער ליציאה:
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-egressgateway
spec:
selector:
matchLabels:
app: istio-egressgateway
istio: egressgateway
template:
metadata:
annotations:
# This is required to tell Anthos Service Mesh to inject the gateway with the
# required configuration.
inject.istio.io/templates: gateway
labels:
app: istio-egressgateway
istio: egressgateway
spec:
containers:
- name: istio-proxy
image: auto # The image will automatically update each time the pod starts.
resources:
limits:
cpu: 2000m
memory: 1024Mi
requests:
cpu: 100m
memory: 128Mi
# Allow binding to all ports (such as 80 and 443)
securityContext:
sysctls:
- name: net.ipv4.ip_unprivileged_port_start
value: "0"
serviceAccountName: istio-egressgateway
החיבור נדחה כשמגיעים לנקודת קצה של Cloud Service Mesh
יכול להיות שתיתקלו מדי פעם בשגיאות של דחיית חיבור (ECONNREFUSED) בתקשורת מהאשכולות לנקודות הקצה, למשל Memorystore Redis, Cloud SQL או כל שירות חיצוני אחר שעומס העבודה של האפליקציה צריך לגשת אליו.
המצב הזה יכול לקרות אם עומס העבודה של האפליקציה מתחיל מהר יותר מהקונטיינר istio-proxy (Envoy) ומנסה להגיע לנקודת קצה חיצונית. בשלב הזה, הפקודה istio-init (initContainer) כבר הופעלה, ולכן יש כללי iptables שמפנים את כל התנועה היוצאת אל Envoy. מכיוון ש-istio-proxy עדיין לא מוכן, כללי ה-iptables יפנו את התנועה אל sidecar proxy שעדיין לא הופעל, ולכן האפליקציה מקבלת את השגיאה ECONNREFUSED.
השלבים הבאים מפרטים כיצד לבדוק אם זו השגיאה שאתה חווה:
בדוק את יומני ה-stackdriver באמצעות המסנן הבא כדי לזהות באילו פודים הייתה הבעיה.
בדוגמה הבאה מוצגת הודעת שגיאה אופיינית:
Error: failed to create connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect: connection refused [ioredis] Unhandled error event: Error: connect ECONNREFUSEDחפש אחר מופע של הבעיה. אם אתם משתמשים בגרסה הקודמת של Stackdriver, אז משתמשים ב-
resource.type="container".resource.type="k8s_container" textPayload:"$ERROR_MESSAGE$"מרחיבים את המופע האחרון כדי לקבל את שם הפוד, ורושמים את
pod_nameבקטעresource.labels.מאתרים את המופע הראשון של הבעיה בפוד:
resource.type="k8s_container" resource.labels.pod_name="$POD_NAME$"פלט לדוגמה:
E 2020-03-31T10:41:15.552128897Z post-feature-service post-feature-service-v1-67d56cdd-g7fvb failed to create connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect: connection refused post-feature-service post-feature-service-v1-67d56cdd-g7fvbרושמים את חותמת הזמן של השגיאה הראשונה בפוד הזה.
כדי לראות את אירועי ההפעלה של ה-Pod, משתמשים במסנן הבא.
resource.type="k8s_container" resource.labels.pod_name="$POD_NAME$"פלט לדוגמה:
I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Container image "docker.io/istio/proxyv2:1.3.3" already present on machine spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Created container spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Started container spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{APP-CONTAINER-NAME} Created container spec.containers{APP-CONTAINER-NAME} W 2020-03-31T10:41:17Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:26Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:28Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:31Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:58Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy}משתמשים בחותמות הזמן של השגיאות ושל אירועי ההפעלה של istio-proxy כדי לוודא שהשגיאות מתרחשות כש-
Envoyלא מוכן.אם השגיאות מתרחשות בזמן שהקונטיינר istio-proxy עדיין לא מוכן, זה נורמלי לקבל שגיאות של דחיית חיבור. בדוגמה הקודמת, הפוד ניסה להתחבר ל-Redis ברגע ש-
2020-03-31T10:41:15.552128897Zאבל עדיין נכשל בבדיקות המוכנות של2020-03-31T10:41:58Zistio-proxy.למרות שמכולת istio-proxy התחילה ראשונה, ייתכן שהיא לא הפכה מוכנה מספיק מהר לפני שהאפליקציה כבר ניסתה להתחבר לנקודת הקצה החיצונית.
אם זו הבעיה שנתקלתם בה, המשיכו לשלבים הבאים לפתרון בעיות.
הוסף הערות לתצורה ברמת הפוד. האפשרות הזו זמינה רק ברמת הפוד ולא ברמה הגלובלית.
annotations: proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'משנים את קוד האפליקציה כך שיבדוק אם
Envoyמוכן לפני שינסה לשלוח בקשות אחרות לשירותים חיצוניים. לדוגמה, כשמפעילים את האפליקציה, מתחיל לולאה ששולחת בקשות לנקודת הקצה של הבריאות של istio-proxy, והיא ממשיכה רק אחרי שמתקבל סטטוס 200. נקודת הקצה של הבדיקה istio-proxy health היא:http://localhost:15020/healthz/ready
מרוץ תהליכים במהלך הזרקת קובץ עזר בין Vault לבין Cloud Service Mesh
כשמשתמשים ב-vault לניהול סודות, לפעמים vault מוסיף sidecar לפני istio, וכתוצאה מכך הפודים נתקעים בסטטוס Init. במקרה כזה, הפודים שנוצרו נתקעים בסטטוס Init אחרי הפעלה מחדש של פריסה או פריסה של פוד חדש. לדוגמה:
E 2020-03-31T10:41:15.552128897Z
post-feature-service post-feature-service-v1-67d56cdd-g7fvb failed to create
connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect:
connection refused post-feature-service post-feature-service-v1-67d56cdd-g7fvb
הבעיה הזו נגרמת בגלל מצב מירוץ. גם Istio וגם vault מזריקים את
ה-sidecar, ו-Istio צריך להיות האחרון שעושה את זה. ה-proxy של istio לא פועל
במהלך אתחול הקונטיינרים. הקונטיינר istio init מגדיר כללי iptables כדי להפנות את כל התנועה לשרת ה-proxy. מכיוון שהיא עדיין לא פועלת, הכללים האלה מפנים לשום מקום וחוסמים את כל התנועה. לכן קובץ ה-init container צריך להיות האחרון, כדי שהפרוקסי יפעל מיד אחרי הגדרת כללי ה-iptables. לצערנו, הסדר לא דטרמיניסטי, ולכן אם Istio מוזרק קודם, הוא נשבר.
כדי לפתור את הבעיה הזו, צריך לאפשר את כתובת ה-IP של vault כדי שהתעבורה שמועברת לכתובת ה-IP של Vault לא תופנה מחדש ל-Envoy Proxy, שלא מוכן עדיין ולכן חוסם את התקשורת. כדי לעשות את זה, צריך להוסיף הערה חדשה בשם excludeOutboundIPRanges.
ב-Cloud Service Mesh מנוהל, אפשר לעשות זאת רק ברמת הפריסה או ה-Pod בקטע spec.template.metadata.annotations, לדוגמה:
apiVersion: apps/v1
kind: Deployment
...
...
...
spec:
template:
metadata:
annotations:
traffic.sidecar.istio.io/excludeOutboundIPRanges:
ב-Cloud Service Mesh בתוך האשכול, יש אפשרות להגדיר אותו כגלובלי באמצעות IstioOperator בקטע spec.values.global.proxy.excludeIPRanges, לדוגמה:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
proxy:
excludeIPRanges: ""
אחרי שמוסיפים את ההערה, מפעילים מחדש את עומסי העבודה.
זיהוי סוג תמונת ה-proxy שנעשה בה שימוש באשכול
כדי לזהות את סוג תמונת ה-proxy (default או distroless) שמשמשת בפוד ספציפי, אפשר לבדוק את מפרט הפוד.
מריצים את הפקודה הבאה כדי לבדוק את האימג' שבו נעשה שימוש בקונטיינר istio-proxy:
kubectl get pod POD_NAME -n NAMESPACE -o jsonpath='{.spec.containers[?(@.name=="istio-proxy")].image}'
- אם נתיב התמונה לא מכיל את התווים
-distrolessבתג או בסיומת, נעשה שימוש בתמונהdefault. - אם נתיב התמונה מכיל
-distrolessבתג או בסיומת, הוא משתמש ב-distrolessתְמוּנָה.
אימות כוונת ההגדרה
אפשר להגדיר את סוג התמונה בשתי דרכים (ההערה קודמת ל-MeshConfig):
הערה לגבי Pod: בודקים אם ל-Pod יש את ההערה
sidecar.istio.io/proxyImageType.kubectl get pod POD_NAME -n NAMESPACE -o jsonpath='{.metadata.annotations["sidecar.istio.io/proxyImageType"]}'MeshConfig: בודקים את ההגדרה
defaultConfig.image.imageTypeב-ConfigMapistio-RELEASE_CHANNELבמרחב השמותistio-system.
הערה: באשכולות עם מישור הבקרה המנוהל TRAFFIC_DIRECTOR:
- עבור אשכולות שהוקצו ישירות עם מישור בקרה מנוהל
TRAFFIC_DIRECTOR, יש תמיכה רק בתמונותdistroless. המערכת מתעלמת משינויים בסוגים אחרים של תמונות. - במקרים של אשכולות שהועברו ל
TRAFFIC_DIRECTORמישור הבקרה (כמו אשכולות שהועברו מ-CSM-ISTIOD), סוג התמונה הואdefaultכברירת מחדל, אבל אפשר להפעיל את האפשרותdistrolessבאמצעותMeshConfigאו הערת פוד. אין תמיכה בשינויים בסוגי תמונות אחרים (כמוdebug).