במאמר הזה מוסבר איך להגדיר Pods ב-Google Kubernetes Engine (GKE) עם כמה ממשקי רשת באמצעות Multus CNI, התוסף IPVLAN CNI והתוסף Whereabouts IPAM.
תוסף ה-CNI IPVLAN מספק קישוריות ברמה 2 לממשקי Pod נוספים, ותוסף ה-IPAM Whereabouts מקצה להם כתובות IP באופן דינמי.
ההגדרה הזו מאפשרת לבצע הגדרות מתקדמות של רשתות, כמו הפרדה בין התנועה של רמת הבקרה לבין התנועה של רמת הנתונים, כדי לשפר את הבידוד והפילוח של הרשת.
המאמר הזה מיועד לארכיטקטים של ענן ולמומחי רשתות שתפקידם לתכנן את הרשת של הארגון. כדי לקבל מידע נוסף על תפקידים נפוצים ומשימות לדוגמה שאנחנו מתייחסים אליהם ב Google Cloud תוכן, אפשר לעיין במאמר תפקידים נפוצים של משתמשים ב-GKE ומשימות.
לפני שקוראים את המסמך הזה, חשוב לוודא שמכירים את המושגים הבאים:
- GKE networking.
- רשתות Kubernetes.
- Container Network Interface (CNI).
- IPVLAN.
- ניהול כתובות IP (IPAM).
יתרונות השימוש ב-Multus עם IPVLAN
הפתרון הזה מאפשר להגדיר את ה-Pods עם כמה ממשקי רשת, ויש לכך כמה יתרונות מרכזיים. תרחישי השימוש העיקריים להגדרת Multus עם IPVLAN במצב Layer 2 הם לפילוח רשת שדורש סמיכות של Layer 2:
- בידוד תנועה: בידוד של סוגים שונים של תנועה לשיפור האבטחה והביצועים. לדוגמה, אפשר להפריד בין תנועה רגישה של ניהול לבין תנועת נתונים של אפליקציות.
- הפרדה בין מישור הבקרה למישור הנתונים: הקצאת ממשק הרשת הראשי לתעבורה של מישור הבקרה, והפניית תעבורה של מישור הנתונים עם תפוקה גבוהה דרך ממשק IPVLAN משני.
- סמיכות בשכבה 2: עמידה בדרישות של אפליקציות שזקוקות לקישוריות ישירה בשכבה 2 בין Pods באותה רשת משנית.
מגבלות
ל-Multus עם IPVLAN ו-Whereabouts יש את המגבלות הבאות:
- אי אפשר להשתמש בו-זמנית ביכולות המובנות של GKE לרישות מרובה ב-Pods שהוגדרו עם ממשקי Multus. הגדרת הרשת של Pod צריכה להשתמש ב-Multus או בריבוי הרשתות המובנה של האשכול.
- כדי ש-Multus עם IPVLAN ו-Whereabouts יפעל בצורה תקינה, נדרש פתרון ARP בשכבה 2 בתוך ה-Pod.
- כברירת מחדל, רשתות משנה של VPC לא מאפשרות פתרון ARP בממשקים משניים של מכונות וירטואליות של Compute Engine. כדי לאפשר את פתרון ה-ARP הזה, אפשר להירשם לבדיקה הפרטית של התכונה
resolve-subnet-maskעל ידי פתיחת בקשת תמיכה.
איך Multus עובד עם IPVLAN ו-Whereabouts
Multus הוא מטא-תוסף CNI שמאפשר ל-Pods להתחבר לכמה רשתות. Multus פועל כרכיב לשליחת בקשות (dispatcher), שקורא לפלאגינים אחרים של CNI כדי להגדיר ממשקי רשת על סמך משאבי NetworkAttachmentDefinition. מגדירים כל רשת נוספת באמצעות NetworkAttachmentDefinition, שמציין באיזה פלאגין CNI (כמו IPVLAN) ובאיזה פלאגין IPAM (כמו Whereabouts) להשתמש עבור הרשת הזו.
בתרשים הבא מוצגת ארכיטקטורת Multus עם תוספי IPVLAN ו-Whereabouts.התוסף Whereabouts פועל עם Multus ו-IPVLAN כדי לטפל בניהול כתובות IP (IPAM) עבור ממשקי הרשת הנוספים של ה-Pods.
בתרשים הזה מוצגים שני צמתים, שלכל אחד מהם יש Pod אחד. לכל Pod יש ממשק ראשי וממשק נוסף. שני הממשקים הראשיים מתחברים לכרטיס רשת משותף, ושני הממשקים הנוספים מתחברים לכרטיס רשת משותף אחר.
כשמשתמשים ב-Multus עם IPVLAN ו-Whereabouts ב-GKE, בדרך כלל יש ל-Pods את הגדרות הממשק הבאות:
- ממשק ראשי (
eth0): ממשק זה מנוהל על ידי GKE Dataplane V2, ומספק קישוריות לאשכול כברירת מחדל. - ממשקים נוספים (
net1וכו'): Multus מנהל את הממשקים האלה. Multus מפעיל את התוסף IPVLAN CNI במצב Layer 2 לכלNetworkAttachmentDefinitionשאתם מציינים בהערות של Pod. ההגדרה הזו מספקת קישוריות בשכבה 2 לרשת VPC משנית. - ניהול כתובות IP (IPAM): אתם מגדירים את התוסף Whereabouts IPAM בתוך
NetworkAttachmentDefinition. התוסף Whereabouts IPAM מקצה באופן דינמי כתובות IP לממשקי IPVLAN נוספים מתוך טווח מוגדר מראש.
תזמון של פודים עם כמה רשתות
כשיוצרים Pod ומציינים NetworkAttachmentDefinition בהערות שלו, מתזמן GKE ממקם את ה-Pod רק בצומת שיכול לעמוד בדרישות הרשת. מתזמן העבודה מזהה צמתים במאגר צמתים שמוגדר בהם ממשק הרשת המשני הנדרש. תהליך זיהוי הצומת הזה עוזר לוודא שהמתזמן מתזמן את ה-Pod בצומת שיכול להתחבר לרשת הנוספת ולקבל כתובת IP מהטווח שצוין.
בקטעים הבאים מוסבר איך להגדיר את Multus עם פלאגינים של IPVLAN ו-Whereabouts באשכול GKE.
לפני שמתחילים
לפני שמתחילים, חשוב לוודא שביצעתם את הפעולות הבאות:
- מפעילים את ממשק Google Kubernetes Engine API. הפעלת Google Kubernetes Engine API
- כדי להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז להפעיל את gcloud CLI. אם התקנתם בעבר את ה-CLI של gcloud, מריצים את הפקודה
gcloud components updateכדי לקבל את הגרסה העדכנית. יכול להיות שגרסאות קודמות של ה-CLI של gcloud לא יתמכו בהרצת הפקודות שמופיעות במסמך הזה.
- מתקינים את כלי שורת הפקודה
kubectl. - מגדירים אשכול GKE בגרסה 1.28 ואילך עם Dataplane V2, IP Alias וריבוי רשתות מופעלים. איך מגדירים תמיכה בריבוי רשתות עבור Pods הפעלת ריבוי רשתות מפעילה גם את התכונות Multi-IP-Subnet ו-Persistent-IP HA Policy, שמבטלות את הצורך בהגדרה ידנית של קישוריות בין צמתים.
- כדי להבטיח תאימות, צריך להשתמש בגרסה של Multus CNI שאומתה על ידי GKE (למשל v4.2.1).
הגדרת VPC
כדי להגדיר את הענן הווירטואלי הפרטי (VPC) לשימוש עם Multus, כולל יצירת תת-רשת לרשת הצמתים וטווחים משניים לרשת הפודים, מבצעים את השלבים הבאים:
יוצרים VPC חדש או משתמשים ב-VPC קיים:
gcloud compute networks create VPC_NAME \ --subnet-mode=customמחליפים את
VPC_NAMEבשם של ה-VPC.יוצרים תת-רשת חדשה ב-VPC הזה:
gcloud compute networks subnets create SUBNET_NAME \ --range=PRIMARY_RANGE \ --network=VPC_NAME \ --region=REGION \ --secondary-range=SECONDARY_RANGE_NAME=SECONDARY_RANGE_CIDRמחליפים את מה שכתוב בשדות הבאים:
-
SUBNET_NAME: השם של תת-הרשת החדשה. -
PRIMARY_RANGE: טווח ה-CIDR הראשי של תת-הרשת, למשל10.0.1.0/24. הפקודה הזו משתמשת בטווח הזה לממשקי צמתים. -
VPC_NAME: השם של ה-VPC. -
REGION: האזור של רשת המשנה, למשלus-central1. -
SECONDARY_RANGE_NAME: השם של טווח כתובות ה-IP המשני של ה-Pods בתת-הרשת. -
SECONDARY_RANGE_CIDR: טווח ה-CIDR המשני של ה-Pods, למשל172.16.1.0/24. ממשקים נוספים ב-Pods משתמשים בטווח הזה.
הפקודה הזו יוצרת רשת משנה עם טווח CIDR ראשי לממשק צומת נוסף וטווח משני לממשקי Pod נוספים.
-
יצירת אשכול GKE Standard
יוצרים אשכול GKE Standard עם רשתות מרובות מופעלות:
gcloud container clusters create CLUSTER_NAME \
--cluster-version=CLUSTER_VERSION \
--enable-dataplane-v2 \
--enable-ip-alias \
--enable-multi-networking
מחליפים את מה שכתוב בשדות הבאים:
-
CLUSTER_NAME: השם של האשכול החדש. -
CLUSTER_VERSION: הגרסה של אשכול GKE. צריך להשתמש בגרסה 1.28 ואילך.
הפעלת multi-networking מאפשרת ליצור מאגרי צמתים עם כמה ממשקי רשת, שנדרשים ל-Multus CNI.
יצירת מאגר צמתים ב-GKE Standard
יוצרים מאגר צמתים של GKE Standard שמחובר לרשתות VPC נוספות:
gcloud container node-pools create NODEPOOL_NAME \
--cluster CLUSTER_NAME \
--zone "ZONE" \
--additional-node-network network=VPC_NAME,subnetwork=SUBNET_NAME \
--additional-pod-network subnetwork=SUBNET_NAME,pod-ipv4-range=SECONDARY_RANGE_NAME,max-pods-per-node=8
מחליפים את מה שכתוב בשדות הבאים:
-
NODEPOOL_NAME: השם של מאגר הצמתים החדש. -
CLUSTER_NAME: השם של האשכול. -
ZONE: האזור של מאגר הצמתים, למשלus-central1-c. -
VPC_NAME: השם של ה-VPC הנוסף. -
SUBNET_NAME: שם רשת המשנה. -
SECONDARY_RANGE_NAME: השם של טווח כתובות ה-IP המשני עבור ה-Pods בתת-הרשת.
הפקודה הזו יוצרת מאגר צמתים שבו לצמתים יש ממשק רשת נוסף ב-SUBNET_NAME, וקבוצות Pod בצמתים האלה יכולות להשתמש בכתובות IP מ-SECONDARY_RANGE_NAME.
מידע נוסף על יצירת אשכולות GKE עם יכולות של ריבוי רשתות זמין במאמר הגדרת תמיכה בריבוי רשתות עבור pods.
החלת הפריסה של Multus
כדי להפעיל כמה ממשקי רשת עבור ה-Pods, צריך להתקין את התוסף Multus CNI. שומרים את המניפסט הבא, שכולל את DaemonSet ואת Custom Resource Definition (CRD) הנדרשים, בשם multus-manifest.yaml:
apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: ippools.whereabouts.cni.cncf.io spec: group: whereabouts.cni.cncf.io names: kind: IPPool listKind: IPPoolList plural: ippools singular: ippool scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: description: IPPool is the Schema for the ippools API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: IPPoolSpec defines the desired state of IPPool properties: allocations: additionalProperties: description: IPAllocation represents metadata about the pod/container owner of a specific IP properties: id: type: string podref: type: string required: - id type: object description: Allocations is the set of allocated IPs for the given range. Its indices are a direct mapping to the IP with the same index/offset for the pools range. type: object range: description: Range is a RFC 4632/4291-style string that represents an IP address and prefix length in CIDR notation type: string required: - allocations - range type: object type: object served: true storage: true status: acceptedNames: kind: "" plural: "" conditions: [] storedVersions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.4.1 name: overlappingrangeipreservations.whereabouts.cni.cncf.io spec: group: whereabouts.cni.cncf.io names: kind: OverlappingRangeIPReservation listKind: OverlappingRangeIPReservationList plural: overlappingrangeipreservations singular: overlappingrangeipreservation scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: description: OverlappingRangeIPReservation is the Schema for the OverlappingRangeIPReservations API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: OverlappingRangeIPReservationSpec defines the desired state of OverlappingRangeIPReservation properties: containerid: type: string podref: type: string required: - containerid type: object required: - spec type: object served: true storage: true status: acceptedNames: kind: "" plural: "" conditions: [] storedVersions: [] --- kind: ConfigMap apiVersion: v1 metadata: name: multus-cni-config namespace: kube-system labels: app: gke-multinet data: cni-conf.json: | { "name": "multus-cni-network", "type": "multus", "confDir": "/etc/cni/net.d", "namespaceIsolation": true, "logLevel": "verbose", "logFile": "/var/log/multus.log", "kubeconfig": "/var/lib/kubelet/kubeconfig", "clusterNetwork": "gke-pod-network" } --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: network-attachment-definitions.k8s.cni.cncf.io spec: group: k8s.cni.cncf.io scope: Namespaced names: plural: network-attachment-definitions singular: network-attachment-definition kind: NetworkAttachmentDefinition shortNames: - net-attach-def versions: - name: v1 served: true storage: true schema: openAPIV3Schema: description: 'NetworkAttachmentDefinition is a CRD schema specified by the Network Plumbing Working Group to express the intent for attaching pods to one or more logical or physical networks. More information available at: https://github.com/k8snetworkplumbingwg/multi-net-spec' type: object properties: apiVersion: description: 'APIVersion defines the versioned schema of this represen tation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: 'NetworkAttachmentDefinition spec defines the desired state of a network attachment' type: object properties: config: description: 'NetworkAttachmentDefinition config is a JSON-formatted CNI configuration' type: string --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: multus-role rules: - apiGroups: ["k8s.cni.cncf.io"] resources: - '*' verbs: - '*' --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: whereabouts rules: - apiGroups: - whereabouts.cni.cncf.io resources: - ippools - overlappingrangeipreservations verbs: - get - list - watch - create - update - patch - delete - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - apiGroups: - coordination.k8s.io resources: - leases resourceNames: - whereabouts verbs: - '*' - apiGroups: [""] resources: - pods verbs: - list - get --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: multus-role-binding subjects: - kind: Group name: system:nodes roleRef: kind: ClusterRole name: multus-role apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: whereabouts-role-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: whereabouts subjects: - kind: ServiceAccount name: whereabouts-sa namespace: kube-system --- apiVersion: v1 kind: ServiceAccount metadata: name: whereabouts-sa namespace: kube-system --- apiVersion: apps/v1 kind: DaemonSet metadata: name: gke-multinet namespace: kube-system labels: app: gke-multinet spec: selector: matchLabels: app: gke-multinet template: metadata: labels: app: gke-multinet spec: priorityClassName: system-node-critical hostNetwork: true tolerations: - operator: Exists serviceAccountName: whereabouts-sa containers: - name: whereabouts-gc command: [/ip-control-loop] args: - "--log-level=debug" - "--enable-pod-watch=false" - "--cron-schedule=* * * * *" image: gcr.io/gke-release/whereabouts:v0.7.0-gke.3@sha256:2bb8450a99d86c73b262f5ccd8c433d3e3abf17d36ee5c3bf1056a1fe479e8c2 env: - name: NODENAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - name: WHEREABOUTS_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" initContainers: - name: install-multus-config image: gcr.io/gke-release/multus-cni:v4.2.1-gke.6@sha256:25b48b8dbbf6c78a10452836f52dee456514783565b70633a168a39e6d322310 args: - "--cni-conf-dir=/host/etc/cni/net.d" - "--multus-conf-file=/tmp/multus-conf/00-multus.conf" - "--multus-log-level=verbose" - "--multus-kubeconfig-file-host=/var/lib/kubelet/kubeconfig" - "--skip-multus-binary-copy=true" - "--skip-config-watch=true" resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" securityContext: privileged: true volumeMounts: - name: cni mountPath: /host/etc/cni/net.d - name: multus-cfg mountPath: /tmp/multus-conf - name: install-whereabouts command: ["/bin/sh"] args: - -c - > SLEEP=false /install-cni.sh image: gcr.io/gke-release/whereabouts:v0.7.0-gke.3@sha256:2bb8450a99d86c73b262f5ccd8c433d3e3abf17d36ee5c3bf1056a1fe479e8c2 env: - name: NODENAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - name: WHEREABOUTS_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" securityContext: privileged: true volumeMounts: - name: cni mountPath: /host/etc/cni/net.d - name: cnibin mountPath: /host/opt/cni/bin - name: install-binary image: gcr.io/gke-release/multus-cni:v4.2.1-gke.6@sha256:25b48b8dbbf6c78a10452836f52dee456514783565b70633a168a39e6d322310 command: ["/gkecmd"] args: - "-operation=copy" - "-cni-bin-dir=/host/opt/cni/bin" resources: requests: cpu: "10m" memory: "100Mi" limits: cpu: "10m" memory: "100Mi" securityContext: privileged: true volumeMounts: - name: cnibin mountPath: /host/opt/cni/bin volumes: - hostPath: path: /var/lib/kubelet/kubeconfig type: File name: kubelet-credentials - name: cni hostPath: path: /etc/cni/net.d type: DirectoryOrCreate - name: cnibin hostPath: path: /home/kubernetes/bin type: DirectoryOrCreate - name: multus-cfg configMap: name: multus-cni-config items: - key: cni-conf.json path: 00-multus.conf updateStrategy: rollingUpdate: maxUnavailable: 2 type: RollingUpdate
לאחר מכן, מחילים את המניפסט על האשכול:
kubectl apply -f multus-manifest.yaml
יצירת קובץ מניפסט של NetworkAttachmentDefinition
כדי לאפשר ל-Pods להתחבר לרשתות נוספות, צריך ליצור
NetworkAttachmentDefinition manifest. המניפסט הזה מגדיר איך פודים מתחברים לרשת ומציין את טווח כתובות ה-IP שמוקצה על ידי פלאגין IPAM, כמו Whereabouts. הטווח הזה צריך להיות חלק מרשת המשנה שמקשרת את ממשקי הרשת הנוספים של הצמתים.
שומרים את קובץ המניפסט בשם
nad.yaml. קובץ המניפסט הזה משתמש בתוספים IPVLAN ו-Whereabouts.apiVersion: "k8s.cni.cncf.io/v1" kind: NetworkAttachmentDefinition metadata: name: NAD_NAME spec: config: '{ "cniVersion": "0.3.1", "plugins": [ { "type": "ipvlan", "master": "eth1", "mode": "l2", "ipam": { "type": "whereabouts", "range": SECONDARY_RANGE_NAME } } ] }'המניפסט כולל את השדות הבאים:
-
NAD_NAME: השם שלNetworkAttachmentDefinition. -
master: השם של ממשק הרשת המשני של הצומת, שמשמש כממשקmasterעבור IPVLAN. ב-GKE, ממשקי רשת משניים מתחילים בדרך כלל ב-eth1והשמות שלהם הם רציפים. כדי לוודא מהו שם הממשק, מתחברים לצומת באמצעות SSH ומריצים את הפקודהip addr. -
range: טווח כתובות ה-IP לממשקי Pod, שזהה לטווח המשני של כתובות IPv4 שיצרתם עבור ה-Pods (SECONDARY_RANGE_NAME). לדוגמה,172.16.1.0/24.
-
מחילים את המניפסט על האשכול:
kubectl apply -f nad.yaml
צירוף של מכשירי Pod לרשתות נוספות
כדי לצרף Pod לרשת נוספת, מוסיפים את ההערה k8s.v1.cni.cncf.io/networks
למניפסט של ה-Pod. אם יש כמה ערוצים, צריך לספק רשימה של שמות הערוצים NetworkAttachmentDefinition בפורמט הבא, כשהשמות מופרדים באמצעות פסיקים:
<namespace>/<nad-name>.
בדוגמה הבאה מוצג מניפסט של Pod שמצורף ל-NetworkAttachmentDefinition בשם NAD_NAME במרחב השמות default:
apiVersion: v1
kind: Pod
metadata:
name: samplepod
annotations:
k8s.v1.cni.cncf.io/networks: default/NAD_NAME
spec:
containers:
- name: sample-container
image: nginx
מחליפים את NAD_NAME בשם של NetworkAttachmentDefinition שיצרתם.
כשמחילים את המניפסט הזה, Kubernetes יוצר את ה-Pod עם ממשק רשת נוסף (net1) שמחובר לרשת שצוינה ב-NetworkAttachmentDefinition.
אימות כתובת ה-IP הנוספת של ה-Pod
כדי לוודא ש-Pod מקבל כתובת IP נוספת אחרי שמצרפים את ה-Pod לרשת נוספת, בודקים את ממשקי הרשת ב-Pod:
כדי לבדוק את
samplepodולאמת את כתובת ה-IP הנוספת, משתמשים בפקודה הבאה:$kubectl describe pod PODNAMEמחליפים את
PODNAMEבשם ה-Pod, למשלsamplepod.בודקים את הפלט. בממשק
eth0מופיעה כתובת ה-IP הראשית של ה-Pod. התוסף Whereabouts מקצה את כתובת ה-IP הנוספת לממשק אחר, כמוnet1.הפלט אמור להיראות כך:
k8s.v1.cni.cncf.io/network-status: [{ "name": "gke-pod-network", "interface": "eth0", "ips": [ "10.104.3.4" ], "mac": "ea:e2:f6:ce:18:b5", "default": true, "dns": {}, "gateway": [ "\u003cnil\u003e" ] },{ "name": "default/my-nad", "interface": "net1", "ips": [ "10.200.1.1" ], "mac": "42:01:64:c8:c8:07", "dns": {} }] k8s.v1.cni.cncf.io/networks: default/my-nadבדוגמה הזו,
10.104.5.19היא כתובת ה-IP הראשית ב-eth0, ו-10.200.1.1היא כתובת ה-IP הנוספת ב-net1.