שימוש ב-GKE Dataplane V2

בדף הזה מוסבר איך להפעיל את GKE Dataplane V2 באשכולות Google Kubernetes Engine ‏ (GKE) ואיך לפתור בעיות שקשורות אליו.

בגרסאות 1.22.7-gke.1500 ואילך ובגרסאות 1.23.4-gke.1500 ואילך, האפשרות GKE Dataplane V2 מופעלת באשכולות Autopilot חדשים. אם אתם נתקלים בבעיות בשימוש ב-GKE Dataplane V2, דלגו אל פתרון בעיות.

יצירת אשכול GKE עם GKE Dataplane V2

אפשר להפעיל את GKE Dataplane V2 כשיוצרים אשכולות חדשים עם GKE בגרסה 1.20.6-gke.700 ואילך באמצעות ה-CLI של gcloud או GKE API. אפשר גם להפעיל את GKE Dataplane V2 בתצוגה מקדימה כשיוצרים אשכולות חדשים עם GKE בגרסה 1.17.9 ואילך.

המסוף

כדי ליצור אשכול חדש עם GKE Dataplane V2, מבצעים את המשימות הבאות:

  1. נכנסים לדף Create a Kubernetes cluster במסוף Google Cloud .

    מעבר אל יצירת אשכול Kubernetes

  2. בקטע 'רשת', מסמנים את התיבה הפעלת Dataplane V2. האפשרות Enable Kubernetes Network Policy מושבתת כשבוחרים באפשרות Enable Dataplane V2, כי האכיפה של מדיניות הרשת מוטמעת ב-GKE Dataplane V2.

  3. לוחצים על יצירה.

gcloud

כדי ליצור אשכול חדש עם GKE Dataplane V2, משתמשים בפקודה הבאה:

gcloud container clusters create CLUSTER_NAME \
    --enable-dataplane-v2 \
    --enable-ip-alias \
    --release-channel CHANNEL_NAME \
    --location COMPUTE_LOCATION

מחליפים את מה שכתוב בשדות הבאים:

  • CLUSTER_NAME: השם של האשכול החדש.
  • CHANNEL_NAME: ערוץ הפצה שכולל את GKE בגרסה 1.20.6-gke.700 ואילך. אם אתם מעדיפים לא להשתמש בערוץ הפצה, אתם יכולים להשתמש גם בדגל --cluster-version במקום בדגל --release-channel, ולציין גרסה 1.20.6-gke.700 ומעלה.
  • COMPUTE_LOCATION: המיקום של Compute Engine של האשכול החדש.

API

כדי ליצור אשכול חדש עם GKE Dataplane V2, צריך לציין את השדה datapathProvider באובייקט networkConfig בבקשת create ליצירת האשכול.

בקטע ה-JSON הבא מוצגת ההגדרה שנדרשת כדי להפעיל את GKE Dataplane V2:

"cluster":{
   "initialClusterVersion":"VERSION",
   "ipAllocationPolicy":{
      "useIpAliases":true
   },
   "networkConfig":{
      "datapathProvider":"ADVANCED_DATAPATH"
   },
   "releaseChannel":{
      "channel":"CHANNEL_NAME"
   }
}

מחליפים את מה שכתוב בשדות הבאים:

  • VERSION: גרסת האשכול, שצריכה להיות GKE 1.20.6-gke.700 ואילך.
  • CHANNEL_NAME: ערוץ הפצה שכולל את GKE גרסה 1.20.6-gke.700 ואילך.

פתרון בעיות ב-GKE Dataplane V2

בקטע הזה מוסבר איך לחקור ולפתור בעיות ב-GKE Dataplane V2.

  1. מוודאים ש-GKE Dataplane V2 מופעל:

    kubectl -n kube-system get pods -l k8s-app=cilium -o wide
    

    אם GKE Dataplane V2 פועל, הפלט כולל Pods עם הקידומת anetd-. ‫anetd הוא בקר הרשת של GKE Dataplane V2.

  2. אם הבעיה היא בשירותים או באכיפת מדיניות הרשת, כדאי לבדוק את anetd יומני ה-Pod. משתמשים בבוררי היומנים הבאים ב-Cloud Logging:

    resource.type="k8s_container"
    labels."k8s-pod/k8s-app"="cilium"
    resource.labels.cluster_name="CLUSTER_NAME"
    
  3. אם יצירת ה-Pod נכשלת, כדאי לבדוק את יומני ה-kubelet כדי לקבל רמזים. משתמשים בבוררי היומנים הבאים ב-Cloud Logging:

    resource.type="k8s_node"
    log_name=~".*/logs/kubelet"
    resource.labels.cluster_name="CLUSTER_NAME"
    

    מחליפים את CLUSTER_NAME בשם של האשכול, או מסירים אותו לגמרי כדי לראות את היומנים של כל האשכולות.

  4. אם ה-Pods של anetd לא פועלים, צריך לבדוק את ה-ConfigMap של cilium-config כדי לראות אם בוצעו בו שינויים. מומלץ להימנע משינוי שדות קיימים ב-ConfigMap הזה, כי שינויים כאלה עלולים לערער את היציבות של האשכול ולשבש את anetd. ה-ConfigMap מתוקן בחזרה למצב ברירת המחדל רק אם נוספים לו שדות חדשים. שינויים בשדות קיימים לא יתוקנו, ואנחנו ממליצים לא לשנות או להתאים אישית את ConfigMap.

בעיות מוכרות

כשמשתמשים ב-GKE Dataplane V2, יכול להיות שנתקלים בבעיות הידועות הבאות.

תם הזמן הקצוב לתפוגה של החיבורים ל-Pods שלא מוכנים

אם ה-Pod לא מוכן, יכול להיות שהחיבורים לשירות המשויך יסתיימו בטיימ-אאוט. זו ההתנהגות הצפויה של GKE Dataplane V2, והיא שונה מ-kube-proxy, שיכול להחזיר שגיאה מהירה יותר connection refused.

בעיות בקישוריות לסירוגין שקשורות להתנגשויות בטווח NodePort באשכולות GKE Dataplane V2

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

  • ip-masq-agent בהתאמה אישית: אם אתם משתמשים ב-ip-masq-agent בהתאמה אישית (גרסה 2.10 ואילך), שבה לאשכול יש שירותים של NodePort או איזון עומסים, יכול להיות שתיתקלו בבעיות קישוריות לסירוגין בגלל שהם מתנגשים עם טווח NodePort. מגרסה 2.10 ואילך, הארגומנט --random-fully מיושם ב-ip-masq-agent באופן פנימי כברירת מחדל. כדי לפתור את הבעיה, צריך להגדיר באופן מפורש את --random-fully=false (רלוונטי החל מגרסה 2.11) בקטע arguments בהגדרות של ip-masq-agent. פרטים על ההגדרה מופיעים במאמר הגדרת סוכן להסוואת כתובות IP באשכולות רגילים.

  • חפיפה בטווח היציאות האפימריות: אם יש חפיפה בין טווח היציאות האפימריות שמוגדר על ידי net.ipv4.ip_local_port_range בצמתי GKE לבין הטווח NodePort (30000-32767), יכול להיות שזה גם יגרום לבעיות בקישוריות. כדי למנוע את הבעיה הזו, צריך לוודא ששני הטווחים האלה לא חופפים.

בודקים את ההגדרות של ip-masq-agent ואת טווח היציאות האפימריות כדי לוודא שאין התנגשות עם הטווח של NodePort. אם נתקלתם בבעיות קישוריות לסירוגין, כדאי לבדוק את הסיבות האפשריות האלה ולשנות את ההגדרה בהתאם.

בעיות בקישוריות ל-hostPort באשכולות GKE Dataplane V2

גרסאות GKE שהושפעו: 1.29 ואילך

בקטרי GKE שמשתמשים ב-GKE Dataplane V2, יכול להיות שתיתקלו בכשלים בקישוריות כשהתנועה מכוונת לכתובת IP:יציאה של צומת, כאשר היציאה היא hostPort שהוגדרה ב-Pod. הבעיות האלה מתעוררות בשני תרחישים עיקריים:

  • צמתים עם hostPort מאחורי מאזן עומסי רשת להעברת סיגנל ללא שינוי:

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

    פתרון עקיף: כשחושפים hostPort של Pod בצומת עם מאזן עומסי רשת מסוג passthrough, מציינים את כתובת ה-IP הפנימית או כתובת ה-IP החיצונית של מאזן עומסי הרשת בשדה hostIP של ה-Pod.

    ports:
    - containerPort: 62000
      hostPort: 62000
      protocol: TCP
      hostIP: 35.232.62.64
    - containerPort: 60000
      hostPort: 60000
      protocol: TCP
      hostIP: 35.232.62.64
      # Assuming 35.232.62.64 is the external IP address of a passthrough Network Load Balancer.
    
  • hostPort יש התנגשות עם טווח NodePort שמור:

    אם ה-hostPort של ה-Pod מתנגש עם טווח ה-NodePort השמור (30000-32767), יכול להיות ש-Cilium לא יצליח להעביר תנועה ל-Pod. ההתנהגות הזו נצפתה בגרסאות של אשכולות החל מגרסה 1.29, כי Cilium מנהל עכשיו את היכולות של hostPort, ומחליף את השיטה הקודמת של Portmap. זו התנהגות צפויה ב-Cilium, והיא מוזכרת בתיעוד הציבורי שלהם.

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

המלצה: מומלץ לעבור לשירותי NodePort במקום ל-hostPort כדי לשפר את המהימנות. NodePort השירותים מספקים יכולות דומות.

טווח יציאות של מדיניות רשת לא נכנס לתוקף

אם מציינים שדה endPort במדיניות רשת באשכול שמופעל בו GKE Dataplane V2, השדה לא ייכנס לתוקף.

Kubernetes Network Policy API מאפשר לציין טווח של יציאות שבהן נאכף Network Policy. ה-API הזה נתמך באשכולות עם Calico Network Policy, אבל לא באשכולות עם GKE Dataplane V2.

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

מידע נוסף זמין במאמר בנושא KEP-2079: Network Policy to support Port Ranges.

גרסאות קבועות

כדי לפתור את הבעיה, צריך לשדרג את האשכול לגרסה 1.32 ואילך של GKE.

מדיניות הרשת מפילה חיבור בגלל חיפוש שגוי של מעקב אחר חיבורים

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

ההשפעה של הבעיה הזו תלויה במספר ה-Pods שהוגדרו לשירות. לדוגמה, אם לשירות יש פוד אחד של קצה עורפי, החיבור תמיד ייכשל. אם לשירות יש 2 תרמילי Backend, החיבור נכשל ב-50% מהמקרים.

גרסאות קבועות

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

  • ‫1.28.3-gke.1090000 ואילך.

פתרונות עקיפים

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

אובדן מנות בזרימות של חיבורי hairpin

כש-Pod יוצר חיבור TCP לעצמו באמצעות Service, כך שה-Pod הוא גם המקור וגם היעד של החיבור, מעקב החיבורים של GKE Dataplane V2 eBPF עוקב אחרי מצבי החיבור באופן שגוי, מה שמוביל לדליפה של רשומות conntrack.

כשמתרחשת דליפה של טופל חיבור (פרוטוקול, כתובת IP של המקור/היעד ויציאה של המקור/היעד), חיבורים חדשים שמשתמשים באותו טופל חיבור עלולים לגרום להשמטה של מנות חוזרות.

גרסאות קבועות

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

  • ‫1.28.3-gke.1090000 ואילך
  • ‫1.27.11-gke.1097000 ואילך

פתרונות עקיפים

אפשר לנסות את הפתרונות הבאים:

  • הפעלת שימוש חוזר ב-TCP (keep-alives) לאפליקציות שפועלות ב-Pods שאולי מתקשרות עם עצמן באמצעות שירות. כך נמנעת הנפקת דגל ה-TCP FIN ודליפה של רשומת מעקב החיבור.

  • כשמשתמשים בחיבורים לטווח קצר, חושפים את ה-Pod באמצעות מאזן עומסים של שרת proxy, כמו Gateway, כדי לחשוף את השירות. כתוצאה מכך, היעד של בקשת החיבור מוגדר לכתובת ה-IP של מאזן העומסים, ומונע מ-GKE Dataplane V2 לבצע SNAT לכתובת ה-IP של ה-loopback.

שדרוג של מישור הבקרה של GKE גורם לקיפאון של anetd Pod

כשמשדרגים אשכול GKE שמופעל בו GKE Dataplane V2 (נתיב נתונים מתקדם) מגרסה 1.27 לגרסה 1.28, יכול להיות שתיתקלו במצב של חסימה הדדית (deadlock). יכול להיות שיהיו שיבושים בעומסי העבודה בגלל חוסר היכולת לסיים פודים ישנים או לתזמן רכיבים נדרשים כמו anetd.

מטרה

תהליך השדרוג של האשכול מגדיל את דרישות המשאבים של רכיבי GKE Dataplane V2. העלייה הזו עלולה לגרום למאבק על משאבים, שישבש את התקשורת בין התוסף Cilium Container Network Interface ‏ (CNI) לבין Cilium daemon.

תסמינים

יכול להיות שתראו את התסמינים הבאים:

  • anetd תרמילים נתקעים במצב Pending.
  • תאי Pod של עומסי עבודה נתקעים במצב Terminating.
  • שגיאות שמצביעות על כשלים בתקשורת של Cilium, כמו failed to connect to Cilium daemon.
  • שגיאות במהלך ניקוי משאבי הרשת בארגזי חול של Pod, לדוגמה:

    1rpc error: code = Unknown desc = failed to destroy network for sandbox "[sandbox_id]": plugin type="cilium-cni" failed (delete): unable to connect to Cilium daemon... connection refused
    

דרך לעקיפת הבעיה

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

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

    kubectl get nodes $NODE_NAME -o json | jq '.status.allocatable | {cpu, memory}'
    
  2. כדי להגדיל באופן זמני את המעבד והזיכרון שניתן להקצות, מריצים את הפקודה הבאה:

    kubectl patch node $NODE_NAME -p '{"status":{"allocatable":{"cpu":CPU_VALUE, "memory":MEMORY_VALUE}}}'
    

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

kubectl delete pod POD_NAME -n NAMESPACE --grace-period=0 --force

מחליפים את מה שכתוב בשדות הבאים:

  • POD_NAME: שם ה-Pod.
  • NAMESPACE: מרחב השמות של ה-Pod.

אחרי שמגדילים את המשאבים שניתן להקצות בצומת, וכשהשדרוג מגרסה 1.27 של GKE לגרסה 1.28 מסתיים, ה-Pod‏ anetd פועל בגרסה החדשה יותר.

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