הגדרת כמה ממשקי רשת לקבוצות Pod

ממשקי רשת מרובים (multi-NIC) לפודים בתוכנת Google Distributed Cloud ל-VMware בלבד מאפשרים להפריד בין תעבורת הנתונים של מישור הבקרה לבין תעבורת הנתונים של מישור הנתונים. אפשר להשתמש ב-Multi-NIC לפודים באשכולות של משתמשים, אבל לא באשכולות של אדמינים. במאמר הזה מוסבר איך להפעיל את multi-NIC, לציין ממשקי רשת נוספים, להקצות אותם לפודים ולפתור בעיות בהגדרות האישיות.

מידע על multi-NIC לפודים

בידוד מישור הרשת חשוב למערכות שמשתמשות בווירטואליזציה של פונקציות רשת (NFV), כמו שירותי Networking מוגדרי-תוכנה ברשת WAN‏ (SD-WAN), מתווך מבוסס-ענן לאבטחת גישה (CASB) וחומות אש מהדור הבא (NG-FW). סוגים כאלה של NFV מסתמכים על גישה לממשקים מרובים כדי להפריד בין מישורי הבקרה והנתונים.

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

הגדרת כמה ממשקי רשת

באופן כללי, יש שלושה שלבים להגדרת כמה ממשקי רשת ל-Pods:

  1. מפעילים multi-NIC באשכול המשתמש באמצעות השדות multipleNetworkInterfaces ו-enableDataplaneV2 בקובץ התצורה של האשכול.

  2. מגדירים ממשקי רשת באמצעות הקטע additionalNodeInterfaces בקובץ התצורה של האשכול, ויוצרים משאב אחד או יותר בהתאמה אישית מסוג NetworkAttachmentDefinition.

  3. הקצאת ממשקי רשת ל-Pods באמצעות ההערה k8s.v1.cni.cncf.io/networks.

הפעלת multi-NIC

כדי להפעיל multi-NIC לפודים, מגדירים את השדות multipleNetworkInterfaces ו-enableDataplaneV2 בקובץ התצורה של אשכול המשתמשים לערך true.

apiVersion: v1
multipleNetworkInterfaces: true
enableDataplaneV2: true
  ...

הגדרת ממשקי רשת

בקובץ התצורה של האשכול, מציינים ממשקי רשת נוספים של צמתים בקטע additionalNodeInterfaces.

לדוגמה, הנה חלק מקובץ תצורה של אשכול משתמשים שמציג ממשק רשת נוסף של צומת:

apiVersion: v1
multipleNetworkInterfaces: true
enableDataplaneV2: true
network:
  serviceCIDR: "10.96.0.0/20"
  podCIDR: "192.168.0.0/16"
  vCenter:
    networkName: network-private310
  ...
  # New multiple network configs
  additionalNodeInterfaces:
  - networkName: "gke-network-1"
    ipBlockFilePath: "my-block-yaml"
    type: static

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

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: gke-network-1
  namespace: default
spec:
  config: '{
  "cniVersion":"0.3.0",
  "type": "ipvlan",
  "master": "ens224", # defines the node interface that this Pod interface would map to
  "mode": "l2",
  "ipam": {
    "type": "whereabouts",
    "range": "172.16.0.0/24"
   }
}'

שומרים את המניפסט כקובץ YAML, לדוגמה, my-nad.yaml, ויוצרים את ה-NetworkAttachmentDefinition:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG apply -f my-nad.yaml

מחליפים את USER_CLUSTER_KUBECONFIG בנתיב של קובץ ה-kubeconfig של אשכול המשתמש.

הקצאת ממשקי רשת ל-Pod

משתמשים בהערה k8s.v1.cni.cncf.io/networks כדי להקצות ממשק רשת אחד או יותר ל-Pod. כל ממשק רשת מצוין באמצעות מרחב שמות והשם של NetworkAttachmentDefinition, שמופרדים באמצעות לוכסן (/). כדי לציין כמה ממשקי רשת, צריך להשתמש ברשימה מופרדת בפסיקים.

בדוגמה הבאה, שני ממשקי רשת מוקצים ל-Pod של samplepod. ממשקי הרשת מצוינים באמצעות שמות של שני NetworkAttachmentDefinitions, gke-network-1 ו-gke-network-2, שנוצרו במרחב השמות default.

---
apiVersion: v1
kind: Pod
metadata:
  name: samplepod
  annotations:
    k8s.v1.cni.cncf.io/networks: default/gke-network-1,default/gke-network-2
spec:
  containers:
  ...

הגבלת ממשקי הרשת לקבוצה של צמתים

אם אתם לא רוצים ש-NetworkAttachmentDefinition יחול על אשכול שלם, אתם יכולים להגביל את הפונקציונליות שלו לקבוצה של צמתים.

אפשר לקבץ צומתי אשכולות באמצעות התווית הרגילה שהוקצתה לצומת או באמצעות תווית מותאמת אישית משלכם. לאחר מכן, אפשר לציין את תווית הצומת במניפסט של NetworkAttachmentDefinition באמצעות ההערה k8s.v1.cni.cncf.io/nodeSelector. ‫Google Distributed Cloud מאלץ את כל הפודים שמפנים למשאב המותאם אישית הזה להיפרס בצמתים שיש להם את התווית הזו.

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  annotations:
    k8s.v1.cni.cncf.io/nodeSelector: LABEL_KEY=LABEL_VALUE
  name: gke-network-1
spec:
...

בדוגמה הבאה מוצגת התווית my-label=multinicNP שצוינה ב-NetworkAttachmentDefinition, והיא מאלצת פריסה של כל ה-Pods שהוקצו לרשת gke-network-1 בצמתים שיש להם את התווית הזו.

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  annotations:
    k8s.v1.cni.cncf.io/nodeSelector: my-label=multinicNP
  name: gke-network-1
spec:
...

כדי להחיל תווית מותאמת אישית על צומת, משתמשים בפקודה kubectl label nodes:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG label nodes NODE_NAME LABEL_KEY=LABEL_VALUE 

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

  • ‫USER_CLUSTER_KUBECONFIG: הנתיב לקובץ kubeconfig של אשכול המשתמש.
  • ‫NODE_NAME: שם הצומת שאתם מתייגים.
  • ‫LABEL_KEY: המפתח שבו משתמשים בשביל התווית.
  • ‫LABEL_VALUE: ערך התווית.

בדוגמה הזו, הצומת my-node מקבל את התווית environment=production:

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG label nodes my-node environment=production

בעיות אבטחה

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

בתרשים הבא, Pods ממרחב השמות default לא יכולים לגשת לממשק הרשת במרחב השמות privileged.

שימוש במרחבי שמות כדי לבודד את התנועה ברשת.

יישומי פלאגין נתמכים של CNI

בקטע הזה מפורטים יישומי הפלאגין של CNI שנתמכים בתכונה multi-NIC ב-Google Distributed Cloud. צריך להשתמש רק בפלאגינים הבאים כשמציינים NetworkAttachmentDefinition.

יצירת ממשק:

  • ipvlan
  • macvlan
  • bridge

פלאגינים של Meta:

  • portmap
  • sbr
  • tuning

יישומי פלאגין של IPAM:

  • host-local
  • static
  • whereabouts

הגדרת המסלול

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

  • sbr
  • static
  • whereabouts

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

פלאגין SBR

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

בדוגמה הבאה, "gateway":"21.0.111.254" מוגדר ב-whereabouts, ו-sbr מוגדר כפלאגין משורשר אחרי ipvlan:

# ip route
default via 192.168.0.64 dev eth0  mtu 1500
192.168.0.64 dev eth0 scope link
# ip route list table 100
default via 21.0.111.254 dev net1
21.0.104.0/21 dev net1 proto kernel scope link src 21.0.111.1

פלאגינים סטטיים ופלאגינים של whereabouts

הפלאגין whereabouts הוא למעשה תוסף של הפלאגין static, ושניהם משתמשים באותה הגדרת ניתוב. לדוגמה להגדרה, ראו פלאגין לניהול כתובות IP סטטיות. אפשר להגדיר שער ומסלול כדי להוסיף אותם לטבלת הניתוב של ה-Pod. עם זאת, אי אפשר לשנות את שער ברירת המחדל של ה-Pod בדרך הזו.

בדוגמה הבאה אפשר לראות את התוספת של "routes": [{ "dst": "172.31.0.0/16" }] ב-NetworkAttachmentDefinition:

# ip route
default via 192.168.0.64 dev eth0  mtu 1500
172.31.0.0/16 via 21.0.111.254 dev net1
21.0.104.0/21 dev net1 proto kernel scope link src 21.0.111.1
192.168.0.64 dev eth0 scope link

תצורות לדוגמה

בקטע הזה מוצגות כמה מהגדרות הרשת הנפוצות שנתמכות בתכונה multi-NIC.

מחבר רשת אחד שמשמש כמה Pods:

מחבר רשת אחד שמשמש כמה פודים.

כמה מחברי רשת שמשמשים Pod אחד:

פוד אחד משתמש בכמה מחברי רשת.

כמה מחברי רשת שמפנים לאותו ממשק שמשמש Pod יחיד:

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

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

אותו מחבר רשת משמש כמה פעמים פוד אחד.

פתרון בעיות

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

בדיקת אירועי Pod

‫Multus מדווח על כשלים באמצעות אירועי Pod ב-Kubernetes. כדי להציג אירועים של Pod מסוים, משתמשים בפקודה הבאה של kubectl describe:

kubectl describe pod POD_NAME

בדיקת היומנים

בכל צומת, אפשר למצוא את יומני Whereabouts ו-Multus במיקומים הבאים:

  • /var/log/whereabouts.log
  • /var/log/multus.log

בדיקת הממשקים של ה-Pod

משתמשים בפקודה kubectl exec כדי לבדוק את הממשקים של ה-Pod. אחרי שמחילים את ה-NetworkAttachmentDefinitions, הממשקים של ה-Pod נראים כמו הפלט הבא:

user@node1:~$ kubectl exec samplepod-5c6df74f66-5jgxs -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: net1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether 00:50:56:82:3e:f0 brd ff:ff:ff:ff:ff:ff
    inet 21.0.103.112/21 scope global net1
       valid_lft forever preferred_lft forever
38: eth0@if39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 36:23:79:a9:26:b3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.2.191/32 scope global eth0
       valid_lft forever preferred_lft forever

קבלת סטטוס של Pod

משתמשים בפקודה kubectl get כדי לאחזר את סטטוס הרשת של Pod נתון:

kubectl get pods POD_NAME -oyaml

הנה פלט לדוגמה שמציג את הסטטוס של Pod עם כמה רשתות:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    k8s.v1.cni.cncf.io/network-status: |-
      [{
          "name": "",
          "interface": "eth0",
          "ips": [
              "192.168.1.88"
          ],
          "mac": "36:0e:29:e7:42:ad",
          "default": true,
          "dns": {}
      },{
          "name": "default/gke-network-1",
          "interface": "net1",
          "ips": [
              "21.0.111.1"
          ],
          "mac": "00:50:56:82:a7:ab",
          "dns": {}
      }]
    k8s.v1.cni.cncf.io/networks: gke-network-1