為 Pod 設定多個網路介面

本文說明如何為 VMware 設定 Google Distributed Cloud (僅限軟體),為 Pod 提供多個網路介面 (多個 NIC)。Pod 的多 NIC 功能可協助區分控制層流量和資料層流量,在不同層之間建立區隔。額外網路介面也能為 Pod 啟用多點傳播功能。使用者叢集支援 Pod 的多重 NIC,但管理員叢集不支援。

本頁內容適用於負責安裝、設定及支援網路設備的網路專家。如要進一步瞭解我們在 Google Cloud 內容中提及的常見角色和範例工作,請參閱「常見的 GKE Enterprise 使用者角色和工作」。

對於使用網路功能虛擬化 (NFV) 的系統 (例如廣域網路 (SD-WAN) 中的軟體定義網路、雲端存取安全代理程式 (CASB) 和新一代防火牆 (NG-FW)) 而言,網路平面隔離非常重要。這類 NFV 必須存取多個介面,才能區隔控制層和資料層。

多個網路介面設定支援將網路介面與節點集區建立關聯,有助於提升效能。舉例來說,叢集可以包含多種節點類型。將高效能機器分組到一個節點集區後,您可以為節點集區建立額外的介面,改善流量。

設定多個網路介面

一般來說,為 Pod 設定多個網路介面需要三個步驟:

  1. 在叢集設定檔中使用 multipleNetworkInterfacesenableDataplaneV2 欄位,為使用者叢集啟用多重 NIC

  2. 使用叢集設定檔中的 additionalNodeInterfaces 區段指定網路介面,並建立一或多個 NetworkAttachmentDefinition 自訂資源。

  3. 使用 k8s.v1.cni.cncf.io/networks 註解將網路介面指派給 Pod

啟用多 NIC

如要為 Pod 啟用多重 NIC,請將使用者叢集設定檔中的 multipleNetworkInterfacesenableDataplaneV2 欄位設為 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 對應於 Pod 可用的網路。以下範例顯示 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

將網路介面指派給 Pod

使用 k8s.v1.cni.cncf.io/networks 註解,將一或多個網路介面指派給 Pod。每個網路介面都會以命名空間和 NetworkAttachmentDefinition 名稱指定,並以斜線 (/) 分隔。如要指定多個網路介面,請使用以半形逗號分隔的清單。

在下列範例中,系統會將兩個網路介面指派給 samplepod Pod。網路介面是由 default 命名空間中建立的兩個 NetworkAttachmentDefinitionsgke-network-1gke-network-2 名稱指定。

---
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 套用至整個叢集,可以將其功能限制在節點集。

您可以根據指派給節點的標準標籤或自訂標籤,將叢集節點分組。然後,您可以使用 k8s.v1.cni.cncf.io/nodeSelector 註解,在 NetworkAttachmentDefinition 資訊清單中指定節點標籤。Google Distributed Cloud 會強制將參照這個自訂資源的任何 Pod,部署在具有這個標籤的節點上。

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:
...

以下範例顯示 NetworkAttachmentDefinition 上標示的 my-label=multinicNP 標籤,並強制將指派給 gke-network-1 網路的所有 Pod 部署至具有這個標籤的節點。

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 

更改下列內容:

  • NODE_NAME:要加入標籤的節點名稱。
  • LABEL_KEY:標籤使用的鍵。
  • LABEL_VALUE:標籤值。

在本例中,節點 my-node 獲得 environment=production 標籤:

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

安全疑慮

NetworkAttachmentDefinition可提供網路的完整存取權,因此叢集管理員必須謹慎地將建立、更新或刪除存取權授予其他使用者。如要隔離特定 NetworkAttachmentDefinition,可以在建立時指定非預設的命名空間,只有該命名空間中的 Pod 才能存取。

在下圖中,default 命名空間的 Pod 無法存取 privileged 命名空間中的網路介面。

使用命名空間隔離網路流量。

支援的 CNI 外掛程式

本節列出 Google Distributed Cloud 多重 NIC 功能支援的 CNI 外掛程式。指定 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 位址。當應用程式選擇使用 NetworkAttachmentDefinition 的 IP 位址做為來源 IP 時,封包會落在 sbr 設定的額外路由表。sbr 路徑表會透過自己的預設閘道傳送流量,流量會經過 NetworkAttachmentDefinition 的介面。該表格中的預設閘道 IP 是由 whereaboutsstatic 外掛程式中的 gateway 欄位控管。sbr 外掛程式會以鏈結外掛程式的形式執行。如要進一步瞭解 sbr 外掛程式,包括使用資訊,請參閱「Source-based routing plugin」。

以下範例顯示在 whereabouts 中設定的 "gateway":"21.0.111.254",以及在 ipvlan 後設定為鏈結外掛程式的 sbr

# 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 外掛程式基本上是 static 外掛程式的擴充功能,兩者共用轉送設定。如需設定範例,請參閱靜態 IP 位址管理外掛程式。您可以定義閘道和路徑,並新增至 Pod 的轉送表。不過,您無法透過這種方式修改 Pod 的預設閘道。

以下範例顯示在 NetworkAttachmentDefinition 中新增 "routes": [{ "dst": "172.31.0.0/16" }] 的方式:

# 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

設定範例

本節說明多重 NIC 功能支援的常見網路設定。

多個 Pod 使用單一網路附件:

多個 Pod 使用單一網路附件。

單一 Pod 使用多個網路附件:

單一 Pod 使用多個網路附件。

多個網路附件指向單一 Pod 使用的相同介面:

多個網路附件指向單一 Pod 使用的相同介面。

單一 Pod 多次使用相同的網路附件:

單一 Pod 多次使用相同的網路附件。

疑難排解

如果額外網路介面設定錯誤,系統就不會啟動指派這些介面的 Pod。本節重點說明如何尋找資訊,以排解多重 NIC 功能的問題。

查看 Pod 事件

Multus 會透過 Kubernetes Pod 事件回報失敗情形。使用下列 kubectl describe 指令,查看特定 Pod 的事件:

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