Pod の複数のネットワーク インターフェースを構成する

このドキュメントでは、Pod にマルチ ネットワーク インターフェース(マルチ NIC)を提供するように VMware 用 Google Distributed Cloud(ソフトウェアのみ)を構成する方法について説明します。Pod 用のマルチ NIC 機能は、コントロール プレーン トラフィックをデータプレーン トラフィックから分離して、プレーン間で分離するのに役立ちます。また、追加のネットワーク インターフェースによって、Pod のマルチキャスト機能を有効にできます。Pod のマルチ NIC は、ユーザー クラスタではサポートされていますが、管理クラスタでは許可されません。

ネットワーク プレーンの分離は、広域ネットワーク(SD-WAN)のソフトウェア定義ネットワーキング、クラウド アクセス セキュリティ ブローカー(CASB)、次世代ファイアウォール(NG-FW)などのネットワーク機能仮想化(NFV)を使用するシステムにとって重要です。これらのタイプの NFV は、コントロール プレーンとデータプレーンを分離するために、複数のインターフェースを利用します。

マルチ ネットワーク インターフェースの構成では、ネットワーク インターフェースとノードプールの関連付けがサポートされ、パフォーマンスの向上を実現できます。たとえば、1 つのクラスタには、混在するノードタイプを含めることができます。高パフォーマンスのマシンを 1 つのノードプールにグループ化するときは、ノードプールにインターフェースを作成してトラフィック フローを改善できます。

マルチ ネットワーク インターフェースを設定する

Pod にマルチ ネットワーク インターフェースを設定する場合、通常、次の 3 ステップで行います。

  1. クラスタ構成ファイルで multipleNetworkInterfaces フィールドと enableDataplaneV2 フィールドを使用して、ユーザー クラスタのマルチ NIC を有効にする

  2. クラスタ構成ファイルの additionalNodeInterfaces セクションでネットワーク インターフェースを指定し、1 つ以上の NetworkAttachmentDefinition カスタム リソースを作成する。

  3. k8s.v1.cni.cncf.io/networks アノテーションを使用して、Pod にネットワーク インターフェースを割り当てる

マルチ NIC を有効にする

Pod のマルチ 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

前述の構成でクラスタを作成したら、追加のネットワーク インターフェースを指定するユーザー クラスタに、1 つ以上の 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 アノテーションを使用して、1 つ以上のネットワーク インターフェースを Pod に割り当てます。各ネットワーク インターフェースは、NetworkAttachmentDefinition とスラッシュ(/)で区切られた Namespace で指定します。マルチ ネットワーク インターフェースを指定する場合は、カンマ区切りのリストを使用します。

次の例では、2 つのネットワーク インターフェースが samplepod Pod に割り当てられます。ネットワーク インターフェースは、default Namespace に作成された 2 つの 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:
...

次の例では、NetworkAttachmentDefinitionmy-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-nodeenvironment=production ラベルを適用しています。

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

セキュリティに関する懸念

NetworkAttachmentDefinition により、ネットワークへの完全アクセス権が提供されるため、クラスタ管理者は、他のユーザーへの作成、更新、削除の権限に注意する必要があります。特定の NetworkAttachmentDefinition を分離する必要がある場合は、作成時にデフォルト以外の Namespace を指定し、その Namespace の Pod のみがアクセスできるようにします。

次の図では、default Namespace の Pod は、privileged Namespace のネットワーク インターフェースにアクセスできません。

ネットワーク トラフィックを分離するために Namespace を使用。

サポートされている CNI プラグイン

このセクションでは、Google Distributed Cloud のマルチ NIC 機能でサポートされている CNI プラグインの一覧を示します。NetworkAttachmentDefinition を指定する場合は、次のプラグインのみを使用します。

インターフェースの作成:

  • ipvlan
  • macvlan
  • bridge

メタプラグイン:

  • portmap
  • sbr
  • tuning

IPAM プラグイン:

  • host-local
  • static
  • whereabouts

ルートの構成

NetworkAttachmentDefinitions が 1 つ以上割り当てられている Pod には、複数のネットワーク インターフェースがあります。デフォルトでは、この状況の Pod のルーティング テーブルは、割り当てられた NetworkAttachmentDefinitions からローカルで使用できる追加のインターフェースのみで拡張されます。デフォルト ゲートウェイにバインドされたパケットは、Pod のデフォルト インターフェース eth0 を使用するように引き続き構成されます。この動作は、次の CNI プラグインを使用することにより変更できます。

  • sbr
  • static
  • whereabouts

たとえば、ほとんどのトラフィックがデフォルト ゲートウェイを経由するようにする場合、これは、トラフィックがデフォルトのネットワーク インターフェースを経由することを意味します。ただし、特定のトラフィックがデフォルト以外のインターフェースを通過するように設定します。両方のインターフェース タイプで同じエンドポイントを使用できるため、宛先 IP(通常のルーティング)に基づいてトラフィックの曖昧さを取り除くことが難しい場合もあります。このような場合は、ソースベースのルーティング(SBR)が役立ちます。

SBR プラグイン

sbr プラグインを使用すると、アプリケーションでルーティングの決定を制御できるようになります。アプリケーションは、確立する接続の送信元 IP アドレスとして使用するものを制御します。アプリケーションが送信元 IP として NetworkAttachmentDefinition の IP アドレスを使用すると、パケットは追加のルーティング テーブル sbr に設定されます。sbr ルーティング テーブルは、独自のデフォルト ゲートウェイ経由でトラフィックを送信します。このデフォルト ゲートウェイは NetworkAttachmentDefinition のインターフェースを通じて送信されます。テーブル内のデフォルト ゲートウェイ IP は、whereabouts または static プラグイン内の gateway フィールドで制御されます。sbr プラグインはチェーン プラグインとして実行されます。使用状況など、sbr プラグインの詳細については、ソースベースのルーティング プラグインをご覧ください。

次の例は、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

static プラグインと whereabouts プラグイン

whereabouts プラグインは基本的に static プラグインの拡張であり、これら 2 つはルーティング構成を共有します。構成例については、静的 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 イベントを使用して障害が報告されます。特定の Pod のイベントを表示するには、次の kubectl describe コマンドを使用します。

kubectl describe pod POD_NAME

ログを確認する

次の場所で、各ノードの Whereabouts ログと Multus ログを見つけることができます。

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

Pod インターフェースを確認する

Pod インターフェースを確認するには kubectl exec コマンドを使用します。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 のステータスを取得する

特定の Pod のネットワーク ステータスを取得するには kubectl get を使用します。

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