בעיות בקישוריות של רשת אשכולות ב-Google Kubernetes Engine (GKE) עלולות לגרום לפסק זמן בחיבור, לחיבורים שנדחים, ל-Pods שלא ניתן להגיע אליהם, לשיבושים בשירות או לכשלים בתקשורת בין Pods.
אפשר להשתמש במסמך הזה כדי לפתור בעיות בקישוריות של אשכולות. לשם כך, צריך ללכוד מנות רשת (באמצעות toolbox ו-tcpdump) ולאבחן בעיות ברשת של Pod.
המידע הזה חשוב למנהלי פלטפורמות ולמפעילים, ולמפתחי אפליקציות שמאבחנים ומתקנים בעיות ברשת שמשפיעות על עומסי עבודה ב-GKE. מידע נוסף על התפקידים הנפוצים ועל משימות לדוגמה שאנחנו מתייחסים אליהם בתוכן של Cloud de Confiance by S3NSזמין במאמר תפקידי משתמשים נפוצים ומשימות ב-GKE.
בעיות בקישוריות שקשורות ללכידת חבילות נתונים ברשת ב-GKE
בקטע הזה מוסבר איך לפתור בעיות בקישוריות שקשורות ללכידת מנות נתונים ברשת, כולל תסמינים כמו פסק זמן לחיבור, שגיאות מסוג 'החיבור נדחה' או התנהגות לא צפויה של האפליקציה. בעיות הקישוריות האלה יכולות להתרחש ברמת הצומת או ברמת ה-Pod.
בעיות בקישוריות ברשת של האשכול נכללות בדרך כלל בקטגוריות הבאות:
- לא ניתן להגיע ל-Pods: יכול להיות שלא ניתן לגשת ל-Pod מתוך האשכול או מחוצה לו בגלל הגדרות שגויות של הרשת.
- שיבושים בשירות: יכול להיות שיהיו שיבושים או עיכובים בשירות.
- בעיות בתקשורת בין Pods: יכול להיות ש-Pods לא יוכלו לתקשר ביניהם בצורה יעילה.
יכולות להיות כמה סיבות לבעיות בקישוריות של אשכול GKE, כולל:
- הגדרות שגויות של הרשת: מדיניות רשת שגויה, כללי חומת אש שגויים או טבלאות ניתוב שגויות.
- באגים באפליקציה: שגיאות בקוד האפליקציה שמשפיעות על האינטראקציות עם הרשת.
- בעיות בתשתית: עומס ברשת, כשלים בחומרה או מגבלות במשאבים.
בקטע הבא מוסבר איך לפתור את הבעיה בצמתים או בתרמילים הבעייתיים.
מזהים את הצומת שבו פועל ה-Pod הבעייתי באמצעות הפקודה הבאה:
kubectl get pods POD_NAME -o=wide -n NAMESPACEמחליפים את מה שכתוב בשדות הבאים:
POD_NAMEבשם של ה-Pod.-
NAMESPACEעם מרחב השמות של Kubernetes.
מתחברים לצומת:
gcloud compute ssh NODE_NAME \ --zone=ZONEמחליפים את מה שכתוב בשדות הבאים:
-
NODE_NAME: שם הצומת. -
ZONE: שם האזור שבו פועל הצומת.
-
כדי לנפות באגים ב-Pod ספציפי, מזהים את הממשק
vethשמשויך ל-Pod:ip route | grep POD_IPמחליפים את
POD_IPבכתובת ה-IP של ה-Pod.מריצים את הפקודות של כלי הניהול.
פקודות toolbox
toolbox הוא כלי שמאפשר ליצור סביבה בקונטיינר בתוך צמתי GKE, לצורך ניפוי באגים ופתרון בעיות. בקטע הזה מוסבר איך להתקין את כלי השירות toolbox ואיך להשתמש בו כדי לפתור בעיות בצומת.
כשהכלי מחובר לצומת, מפעילים את הכלי
toolbox:toolboxהפעולה הזו תוריד את הקבצים שמסייעים לשימוש בכלי
toolbox.בהנחיית השורש
toolbox, מתקינים אתtcpdump:לצבי קבצים עם כתובות IP חיצוניות או Cloud NAT:
apt update -y && apt install -y tcpdumpבאשכולות פרטיים ללא Cloud NAT:
אם יש לכם אשכול פרטי ללא Cloud NAT, לא תוכלו להתקין את
tcpdumpבאמצעותapt. במקום זאת, מורידים את הקבציםlibpcapו-tcpdumpשל הגרסה מהמאגר הרשמי ומעתיקים את הקבצים למכונה הווירטואלית באמצעותgcloud compute scpאוgcloud storage cp. לאחר מכן, מתקינים את הספריות באופן ידני באמצעות השלבים הבאים:# Copy the downloaded packages to a staging area cp /media/root/home/USER_NAME/tcpdump-VERSION.tar.gz /usr/sbin/ cp /media/root/home/USER_NAME/libpcap-VERSION.tar.gz /usr/sbin/ cd /usr/sbin/ # Extract the archives tar -xvzf tcpdump-VERSION.tar.gz tar -xvzf libpcap-VERSION.tar.gz # Build and install libpcap (a dependency for tcpdump) cd libpcap-VERSION ./configure ; make ; make install # Build and install tcpdump cd ../tcpdump-VERSION ./configure ; make ; make install # Verify tcpdump installation tcpdump --versionמחליפים את מה שכתוב בשדות הבאים:
-
USER_NAME: שם המשתמש שלכם במערכת שבה נמצאים הקבצים. -
VERSION: מספר הגרסה הספציפי של החבילותtcpdumpו-libpcap.
-
מתחילים את תיעוד החבילות:
tcpdump -i eth0 -s 100 "port PORT" \ -w /media/root/mnt/stateful_partition/CAPTURE_FILE_NAMEמחליפים את מה שכתוב בשדות הבאים:
-
PORT: שם מספר היציאה. -
CAPTURE_FILE_NAME: השם של קובץ הלכידה.
-
מפסיקים את תיעוד החבילות ומפריעים ל-
tcpdump.כדי לצאת מארגז הכלים, מקלידים
exit.מציגים את קובץ לכידת המנות ובודקים את הגודל שלו:
ls -ltr /mnt/stateful_partition/CAPTURE_FILE_NAMEמעתיקים את לכידת החבילות מהצומת לספריית העבודה הנוכחית במחשב:
gcloud compute scp NODE_NAME:/mnt/stateful_partition/CAPTURE_FILE_NAME \ --zone=ZONEמחליפים את מה שכתוב בשדות הבאים:
-
NODE_NAME: שם הצומת. -
CAPTURE_FILE_NAME: השם של קובץ הלכידה. -
ZONE: שם האזור.
-
פקודות חלופיות
אפשר גם להשתמש בדרכים הבאות כדי לפתור בעיות בקישוריות של ה-Pods הבעייתיים:
עומס עבודה זמני לניפוי באגים שמצורף לקונטיינר של ה-Pod.
מריצים מעטפת ישירות ב-Pod היעד באמצעות
kubectl exec, ואז מתקינים ומפעילים את הפקודהtcpdump.
בעיות בקישוריות של רשת ה-Pod
כמו שצוין בדיון בנושא סקירה כללית של הרשת, חשוב להבין איך מחוברים ה-Pods ממרחבי השמות של הרשת שלהם למרחב השמות הבסיסי בצומת, כדי לפתור בעיות בצורה יעילה. בדיון הבא, אלא אם צוין אחרת, נניח שהאשכול משתמש ב-CNI המקורי של GKE ולא ב-CNI של Calico. כלומר, לא הוחלה מדיניות רשת.
ל-Pods בצמתים נבחרים אין זמינות
אם ל-Pods בצמתים נבחרים אין קישוריות לרשת, צריך לוודא שגשר Linux פועל:
ip address show cbr0
אם הגשר של Linux מושבת, מפעילים אותו:
sudo ip link set cbr0 up
מוודאים שהצומת לומד את כתובות ה-MAC של ה-Pod שמצורפות ל-cbr0:
arp -an
ל-Pods בצמתים נבחרים יש קישוריות מינימלית
אם ל-Pods בצמתים נבחרים יש קישוריות מינימלית, קודם צריך לוודא אם יש מנות שאבדו על ידי הפעלת tcpdump במאגר כלי העבודה:
sudo toolbox bash
אם עדיין לא עשיתם זאת, מתקינים את tcpdump בארגז הכלים:
apt install -y tcpdump
מריצים את הפקודה tcpdump מול cbr0:
tcpdump -ni cbr0 host HOSTNAME and port PORT_NUMBER and [TCP|UDP|ICMP]
אם נראה שמנות גדולות מושמטות במורד הזרם מהגשר (לדוגמה, לחיצת היד של TCP מסתיימת, אבל לא מתקבלים נתוני SSL), צריך לוודא שערך ה-MTU של כל ממשק Linux Pod מוגדר בצורה נכונה ל-MTU של רשת ה-VPC של האשכול.
ip address show cbr0
כשמשתמשים בשכבות-על (לדוגמה, Weave או Flannel), צריך להקטין עוד יותר את ה-MTU כדי להתאים את התקורה של האנקפסולציה בשכבת-העל.
MTU ב-GKE
ה-MTU שנבחר לממשק Pod תלוי בממשק רשת הקונטיינרים (CNI) שבו משתמשים צמתי האשכול ובהגדרת ה-MTU של ה-VPC הבסיסי. מידע נוסף זמין במאמר בנושא Pods.
ערך ה-MTU של ממשק ה-Pod הוא 1460 או שהוא עובר בירושה מהממשק הראשי של הצומת.
| CNI | MTU | GKE Standard |
|---|---|---|
| kubenet | 1460 | ברירת מחדל |
|
kubenet (GKE גרסה 1.26.1 ואילך) |
עבר בירושה | ברירת מחדל |
| Calico | 1460 |
הופעל באמצעות פרטים נוספים זמינים במאמר שליטה בתקשורת בין Pods ושירותים באמצעות מדיניות רשת. |
| netd | עבר בירושה | הופעל באמצעות אחת מהאפשרויות הבאות: |
| GKE Dataplane V2 | עבר בירושה |
הופעל באמצעות פרטים נוספים זמינים במאמר שימוש ב-GKE Dataplane V2. |
חיבורים שנכשלו לסירוגין
חיבורים אל ה-Pods וממנו מועברים על ידי iptables. התנועה נרשמת כערכים בטבלת conntrack, וכשיש הרבה עומסי עבודה לכל צומת, יכול להיות שייגמר המקום בטבלת conntrack ויופיע כשל. אפשר לרשום אותם ביומן במסוף הסדרתי של הצומת, למשל:
nf_conntrack: table full, dropping packet
אם אתם יכולים לקבוע שבעיות לסירוגין נובעות ממיצוי של conntrack, אתם יכולים להגדיל את גודל האשכול (ובכך להקטין את מספר עומסי העבודה והזרימות לכל צומת), או להגדיל את nf_conntrack_max:
new_ct_max=$(awk '$1 == "MemTotal:" { printf "%d\n", $2/32; exit; }' /proc/meminfo)
sysctl -w net.netfilter.nf_conntrack_max="${new_ct_max:?}" \
&& echo "net.netfilter.nf_conntrack_max=${new_ct_max:?}" >> /etc/sysctl.conf
אפשר גם להשתמש ב-NodeLocal DNSCache כדי לצמצם את מספר הרשומות של מעקב אחר חיבורים.
השגיאה bind: Address already in use (קישור: הכתובת כבר בשימוש) מופיעה לגבי מאגר תגים
אי אפשר להפעיל מאגר ב-Pod כי לפי יומני המאגר, היציאה שהאפליקציה מנסה להתחבר אליה כבר שמורה. הקונטיינר נמצא בלולאת קריסה. לדוגמה, ב-Cloud Logging:
resource.type="container"
textPayload:"bind: Address already in use"
resource.labels.container_name="redis"
2018-10-16 07:06:47.000 CEST 16 Oct 05:06:47.533 # Creating Server TCP listening socket *:60250: bind: Address already in use
2018-10-16 07:07:35.000 CEST 16 Oct 05:07:35.753 # Creating Server TCP listening socket *:60250: bind: Address already in use
כש-Docker קורס, לפעמים נשאר קונטיינר פעיל מאחור והוא לא עדכני. התהליך עדיין פועל במרחב השמות של הרשת שהוקצה ל-Pod, ומאזין ליציאה שלו. מכיוון ש-Docker ו-kubelet לא יודעים על הקונטיינר הישן, הם מנסים להפעיל קונטיינר חדש עם תהליך חדש, שלא יכול לבצע איגוד ליציאה כי הוא נוסף למרחב השמות של הרשת שכבר משויך ל-Pod.
כדי לאבחן את הבעיה:
צריך להזין את המזהה הייחודי האוניברסלי (UUID) של ה-Pod בשדה
.metadata.uuid:kubectl get pod -o custom-columns="name:.metadata.name,UUID:.metadata.uid" ubuntu-6948dd5657-4gsgg name UUID ubuntu-6948dd5657-4gsgg db9ed086-edba-11e8-bdd6-42010a800164מקבלים את הפלט של הפקודות הבאות מהצומת:
docker ps -a ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep [Pod UUID]בדיקת תהליכים שפועלים מ-Pod מסוים. מכיוון שהמזהה הייחודי האוניברסלי (UUID) של מרחבי השמות של cgroup מכיל את המזהה הייחודי האוניברסלי של ה-Pod, אפשר להשתמש בפקודה grep כדי לחפש את המזהה הייחודי האוניברסלי של ה-Pod בפלט של
ps. כדאי להשתמש ב-grep גם בשורה הקודמת, כדי לקבל את התהליכים עם מזהה מאגר התגים בארגומנט.docker-containerd-shimכדי לקבל פלט פשוט יותר, חותכים את שאר העמודה cgroup:# ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep -B 1 db9ed086-edba-11e8-bdd6-42010a800164 | sed s/'blkio:.*'/''/ 1283089 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim 276e173b0846e24b704d4 12: 1283107 1283089 Ss sys_pause 4026532393 pause /pause 12: 1283150 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim ab4c7762f5abf40951770 12: 1283169 1283150 Ss do_wait 4026532393 sh /bin/sh -c echo hello && sleep 6000000 12: 1283185 1283169 S hrtimer_nanosleep 4026532393 sleep sleep 6000000 12: 1283244 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim 44e76e50e5ef4156fd5d3 12: 1283263 1283244 Ss sigsuspend 4026532393 nginx nginx: master process nginx -g daemon off; 12: 1283282 1283263 S ep_poll 4026532393 nginx nginx: worker processברשימה הזו אפשר לראות את מזהי מאגרי התגים, שצריכים להיות גלויים גם ב-
docker ps.במקרה כזה:
docker-containerd-shim 276e173b0846e24b704d4להשהיהdocker-containerd-shim ab4c7762f5abf40951770for sh with sleep (sleep-ctr)-
docker-containerd-shim 44e76e50e5ef4156fd5d3ל-nginx (echoserver-ctr)
בודקים את הפלט של
docker ps:# docker ps --no-trunc | egrep '276e173b0846e24b704d4|ab4c7762f5abf40951770|44e76e50e5ef4156fd5d3' 44e76e50e5ef4156fd5d383744fa6a5f14460582d0b16855177cbed89a3cbd1f registry.k8s.io/echoserver@sha256:3e7b182372b398d97b747bbe6cb7595e5ffaaae9a62506c725656966d36643cc "nginx -g 'daemon off;'" 14 hours ago Up 14 hours k8s_echoserver-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0 ab4c7762f5abf40951770d3e247fa2559a2d1f8c8834e5412bdcec7df37f8475 ubuntu@sha256:acd85db6e4b18aafa7fcde5480872909bd8e6d5fbd4e5e790ecc09acc06a8b78 "/bin/sh -c 'echo hello && sleep 6000000'" 14 hours ago Up 14 hours k8s_sleep-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0 276e173b0846e24b704d41cf4fbb950bfa5d0f59c304827349f4cf5091be3327 registry.k8s.io/pause-amd64:3.1במקרים רגילים, כל מזהי מאגרי התגים מ-
psמופיעים ב-docker ps. אם יש קונטיינר שלא מופיע, זהו קונטיינר לא פעיל, וכנראה שתראו תהליך צאצא שלdocker-containerd-shim processבהאזנה בפורט TCP שמדווח כפורט שכבר נמצא בשימוש.כדי לוודא זאת, מריצים את הפקודה
netstatבמרחב השמות של הרשת של הקונטיינר. מקבלים את ה-pid של כל תהליך של קונטיינר (לאdocker-containerd-shim) עבור ה-Pod.בדוגמה הקודמת:
- 1283107 - pause
- 1283169 - sh
- 1283185 - sleep
- 1283263 - nginx master
- 1283282 - nginx worker
# nsenter -t 1283107 --net netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast gke-zonal-110-default-pool-fe00befa-n2hx ~ # nsenter -t 1283169 --net netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mastאפשר גם להריץ את הפקודה
netstatבאמצעותip netns, אבל צריך לקשר את מרחב השמות של הרשת של התהליך באופן ידני, כי Docker לא מבצע את הקישור:# ln -s /proc/1283169/ns/net /var/run/netns/1283169 gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns list 1283169 (id: 2) gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns exec 1283169 netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast gke-zonal-110-default-pool-fe00befa-n2hx ~ # rm /var/run/netns/1283169
השבתה זמנית של אותות אכיפה:
הפתרון לטווח הקצר הוא לזהות תהליכים לא פעילים באמצעות השיטה שמתוארת למעלה, ולסיים את התהליכים באמצעות הפקודה kill [PID].
כדי לפתור את הבעיה לטווח ארוך, צריך לזהות את הסיבה לקריסת Docker ולתקן אותה. סיבות אפשריות:
- תהליכי זומבי מצטברים, ולכן נגמרים מרחבי השמות של מזהי התהליכים
- באג ב-Docker
- עומס על המשאבים / שגיאת OOM
המאמרים הבאים
מידע כללי על אבחון בעיות DNS ב-Kubernetes זמין במאמר בנושא ניפוי באגים של רזולוציית DNS.
אם לא מצאתם פתרון לבעיה שלכם במסמכים, תוכלו להיעזר בקבלת תמיכה, כולל עצות בנושאים הבאים:
- פתיחת בקשת תמיכה באמצעות פנייה אל Cloud Customer Care.
- קבלת תמיכה מהקהילה על ידי פרסום שאלות ב-StackOverflow ושימוש בתג
google-kubernetes-engineכדי לחפש בעיות דומות. אפשר גם להצטרף לערוץ Slack#kubernetes-engineכדי לקבל תמיכה נוספת מהקהילה. - פתיחת דיווחים על בעיות או בקשות להוספת תכונות באמצעות הכלי הציבורי למעקב אחר בעיות.