本文說明如何使用 Multus CNI、IPVLAN CNI 外掛程式和 Whereabouts IPAM 外掛程式,在 Google Kubernetes Engine (GKE) 中設定具有多個網路介面的 Pod。
IPVLAN CNI 外掛程式會為額外的 Pod 介面提供第 2 層連線,而 Whereabouts IPAM 外掛程式則會動態指派 IP 位址給這些介面。
這項設定可啟用進階網路設定,例如分隔控制層和資料層流量,以強化網路隔離和區隔。
本文適用於負責設計及建構機構網路的雲端架構師和網路專家。如要進一步瞭解我們在內容中提及的常見角色和範例工作,請參閱「常見的 GKE 使用者角色和工作」。 Google Cloud
閱讀本文前,請務必先熟悉下列概念:
搭配使用 Multus 與 IPVLAN 的好處
使用這項解決方案為 Pod 設定多個網路介面,可享有幾項主要優勢。在第 2 層模式下設定 Multus 和 IPVLAN 的主要用途,是為了需要第 2 層鄰接的網路區隔:
- 流量隔離:隔離不同類型的流量,以提升安全性及效能。舉例來說,您可以將敏感的管理流量與應用程式資料流量分開。
- 控制層和資料層分離:將主要網路介面專用於控制層流量,同時透過次要 IPVLAN 介面導向高輸送量資料層流量。
- 第 2 層鄰接:滿足應用程式的需求,這些應用程式需要在相同次要網路上的 Pod 之間建立直接的第 2 層連線。
限制
使用 Multus 介面設定的 Pod 無法同時使用 GKE 的內建多網路功能。Pod 的網路設定必須使用 Multus 或叢集的內建多網路功能。
Multus 如何與 IPVLAN 和 Whereabouts 搭配運作
Multus 是 CNI 中繼外掛程式,可讓 Pod 連接至多個網路。Multus 會做為調度器,呼叫其他 CNI 外掛程式,根據 NetworkAttachmentDefinition 資源設定網路介面。您可以使用 NetworkAttachmentDefinition 定義每個額外網路,指定要用於該網路的 CNI 外掛程式 (例如 IPVLAN) 和 IPAM 外掛程式 (例如 Whereabouts)。
下圖說明 Multus 架構,其中包含 IPVLAN 和 Whereabouts 外掛程式。Whereabouts 外掛程式會與 Multus 和 IPVLAN 搭配運作,處理 Pod 其他網路介面的 IP 位址管理 (IPAM)。
本圖表顯示兩個節點,每個節點都有一個 Pod。每個 Pod 都有主要介面和額外介面。兩個主要介面會連至共用的網路介面卡,兩個額外介面則會連至不同的共用網路介面卡。
在 GKE 上使用 Multus、IPVLAN 和 Whereabouts 時,Pod 通常會有下列介面設定:
- 主要介面 (
eth0):GKE Dataplane V2 會管理這個介面,提供預設叢集連線。 - 其他介面 (
net1等):Multus 會管理這些介面。 針對您在 Pod 註解中指定的每個NetworkAttachmentDefinition,Multus 會以第 2 層模式叫用 IPVLAN CNI 外掛程式。這項設定可為次要虛擬私有雲網路提供第 2 層連線。 - IP 位址管理 (IPAM):您可以在
NetworkAttachmentDefinition中設定 Whereabouts IPAM 外掛程式。Whereabouts IPAM 外掛程式會從預先定義的範圍,動態指派 IP 位址給額外的 IPVLAN 介面。
使用多個網路排程 Pod
建立 Pod 並在註解中指定 NetworkAttachmentDefinition 時,GKE 排程器只會將 Pod 放在可滿足網路需求的節點上。排程器會找出節點集區中已設定必要次要網路介面的節點。這個節點識別程序可確保排程器將 Pod 排程至可連線至額外網路,並從指定範圍接收 IP 位址的節點。
以下各節將逐步引導您在 GKE 叢集上,使用 IPVLAN 和 Whereabouts 外掛程式設定 Multus。
事前準備
開始之前,請確認您已完成下列工作:
- 啟用 Google Kubernetes Engine API。 啟用 Google Kubernetes Engine API
- 如要使用 Google Cloud CLI 執行這項工作,請安裝並初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行
gcloud components update指令,取得最新版本。較舊的 gcloud CLI 版本可能不支援執行本文中的指令。
- 安裝
kubectl指令列工具。 - 設定執行 1.28 以上版本的 GKE 叢集,並啟用 Dataplane V2、IP 別名和多網路功能。如要瞭解如何設定,請參閱「為 Pod 設定多網路支援功能」。啟用多網路功能後,系統也會啟用多 IP 子網路和持續性 IP 高可用性政策功能,因此您不必手動設定節點間的連線。
- 使用 GKE 驗證的 Multus CNI 版本 (例如 v4.2.1),確保相容性。
設定虛擬私有雲
如要設定虛擬私有雲 (VPC),以便搭配 Multus 使用 (包括為節點網路建立子網路,以及為 Pod 網路建立次要範圍),請完成下列步驟:
建立新的虛擬私有雲或使用現有虛擬私有雲:
gcloud compute networks create VPC_NAME \ --subnet-mode=custom將
VPC_NAME替換為 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:虛擬私有雲的名稱。REGION:子網路的區域,例如us-central1。SECONDARY_RANGE_NAME:子網路中 Pod 的次要 IP 位址範圍名稱。SECONDARY_RANGE_CIDR:Pod 的次要 CIDR 範圍,例如172.16.1.0/24。Pod 上的其他介面會使用這個範圍。
這個指令會建立子網路,其中包含額外節點介面的主要 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 以上版本。
啟用多網路功能後,您就能建立具備多個網路介面的節點集區,這是 Multus CNI 的必要條件。
建立 GKE Standard 節點集區
建立連至其他虛擬私有雲網路的 GKE Standard 節點集區:
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:額外虛擬私有雲的名稱。SUBNET_NAME:子網路的名稱。SECONDARY_RANGE_NAME:子網路中 Pod 的次要 IP 位址範圍名稱。
這個指令會建立節點集區,其中的節點在 SUBNET_NAME 中有額外的網路介面,而這些節點上的 Pod 可以使用 SECONDARY_RANGE_NAME 中的 IP 位址。
如要進一步瞭解如何建立具備多網路功能的 GKE 叢集,請參閱「為 Pod 設定多網路支援」。
套用 Multus 部署作業
如要為 Pod 啟用多個網路介面,請安裝 Multus CNI 外掛程式。請將下列資訊清單 (包含必要的 DaemonSet 和自訂資源定義 (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 資訊清單
如要讓 Pod 連線至其他網路,請建立 NetworkAttachmentDefinition 資訊清單。這個資訊清單會定義 Pod 如何連線至網路,並指定 IPAM 外掛程式 (例如 Whereabouts) 指派的 IP 位址範圍。這個範圍必須是子網路的一部分,該子網路會連線至節點的額外網路介面。
將此資訊清單儲存為
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:節點的次要網路介面名稱,做為 IPVLAN 的master介面。在 GKE 中,次要網路介面通常以eth1開頭,並依序命名。如要確認介面名稱,請使用 SSH 連線至節點,然後執行ip addr指令。range:Pod 介面的 IP 位址範圍,與您為 Pod 建立的次要 IPv4 範圍相同 (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>。
以下範例顯示附加至 default 命名空間中名為 NAD_NAME 的 NetworkAttachmentDefinition 的 Pod 資訊清單:
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 指定的網路。
驗證 Pod 的額外 IP 位址
如要確認將 Pod 附加至其他網路後,Pod 是否收到額外 IP 位址,請檢查 Pod 中的網路介面:
如要檢查
samplepod並驗證額外 IP 位址,請使用下列指令:$kubectl describe pod PODNAME將
PODNAME替換為 Pod 名稱,例如samplepod。查看輸出內容。
eth0介面具有 Pod 的主要 IP 位址。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是eth0上的主要 IP 位址,而10.200.1.1是net1上的額外 IP 位址。
後續步驟
- 進一步瞭解 Multus CNI。
- 進一步瞭解 IPVLAN CNI。
- 進一步瞭解 Whereabouts IPAM。