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

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

このページは、ネットワーク機器の設置、構成、サポートを行うネットワーク スペシャリストを対象としています。Google Cloud のコンテンツで参照する一般的なロールとタスク例の詳細については、一般的な GKE Enterprise ユーザーロールとタスクをご覧ください。

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

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

複数のネットワーク インターフェースを設定する

通常、次の 3 ステップで、Pod に複数のネットワーク インターフェースを設定します。

  1. クラスタのカスタム リソースの multipleNetworkInterfaces フィールドを使用して、クラスタのマルチ NIC を有効にする

  2. NetworkAttachmentDefinition カスタム リソースを使用して、ネットワーク インターフェースを指定する

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

ネットワーキング要件に最適な方法で、マルチ NIC 機能を構成して使用する際に有用な追加情報を提供します。

マルチ NIC を有効にする

Pod でマルチ NIC を有効にするには、クラスタのカスタム リソースの clusterNetwork セクションに multipleNetworkInterfaces フィールドを追加して true に設定します。

  ...
  clusterNetwork:
    multipleNetworkInterfaces: true
    pods:
      cidrBlocks:
      - 192.168.0.0/16
    services:
      cidrBlocks:
      - 10.96.0.0/20
  ...

ネットワーク インターフェースを指定する

NetworkAttachmentDefinition カスタム リソースを使用して、追加のネットワーク インターフェースを指定します。NetworkAttachmentDefinition カスタム リソースは、Pod で使用できるネットワークに対応しています。次の例に示すように、クラスタ構成内でカスタム リソースを指定できます。または、NetworkAttachmentDefinition カスタム リソースを直接作成することもできます。

---
apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
  name: my-cluster
  namespace: cluster-my-cluster
spec:
    type: user
    clusterNetwork:
      multipleNetworkInterfaces: true
...
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: gke-network-1
  namespace: cluster-my-cluster
spec:
  config: '{
  "cniVersion":"0.3.0",
  "type": "ipvlan",
  "master": "enp2342",  # defines the node interface that this pod interface would
                         map to.
  "mode": "l2",
  "ipam": {
    "type": "whereabouts",
    "range": "172.120.0.0/24"
  }
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: gke-network-2
  namespace: cluster-my-cluster
spec:
  config: '{
  "cniVersion":"0.3.0",
  "type": "macvlan",
  "mode": "bridge",
  "master": "vlan102",
  "ipam": {
    "type": "static",
    "addresses": [
      {
        "address": "10.10.0.1/24",
        "gateway": "10.10.0.254"
      }
    ],
    "routes": [
      { "dst": "192.168.0.0/16", "gw": "10.10.5.1" }
    ]
  }
}'

クラスタの構成ファイルで NetworkAttachmentDefinition カスタム リソースを指定すると、Google Distributed Cloud は、クラスタ作成後、この名前を使用して NetworkAttachmentDefinition カスタム リソースを制御します。Google Distributed Cloud では、クラスタの Namespace 内のこのカスタム リソースを信頼できる情報源として扱い、ターゲット クラスタの default Namespace に調整します。

次の図は、Google Distributed Cloud が NetworkAttachmentDefinition カスタム リソースをクラスタ固有の Namespace から default Namespace に調整する方法を示しています。

NetworkAttachmentDefinition の整合

省略可能ですが、クラスタ作成時にこの方法で NetworkAttachmentDefinition カスタム リソースを指定することをおすすめします。ユーザー クラスタは、クラスタの作成時にカスタム リソースを指定すると最大の効果を発揮します。これは、管理クラスタから NetworkAttachmentDefinition カスタム リソースを制御できるためです。

クラスタの作成時に NetworkAttachmentDefinition カスタム リソースを指定しない場合は、NetworkAttachmentDefinition カスタム リソースを既存のターゲット クラスタに直接追加できます。Google Distributed Cloud は、クラスタの Namespace に定義された NetworkAttachmentDefinition カスタム リソースと調整します。調整は削除時にも行われます。NetworkAttachmentDefinition カスタム リソースがクラスタの Namespace から削除されると、Google Distributed Cloud はターゲット クラスタからカスタム リソースを削除します。

Pod にネットワーク インターフェースを割り当てる

k8s.v1.cni.cncf.io/networks アノテーションを使用して、1 つ以上のネットワーク インターフェースを Pod に割り当てます。各ネットワーク インターフェースは、Namespace と NetworkAttachmentDefinition カスタム リソースの名前をスラッシュ(/)で区切って指定します。

---
apiVersion: v1
kind: Pod
metadata:
  name: samplepod
  annotations:
    k8s.v1.cni.cncf.io/networks: NAMESPACE/NAD_NAME
spec:
  containers:
  ...

次のように置き換えます。

  • NAMESPACE: Namespace。デフォルトの Namespace(標準)には default を使用します。例外については、セキュリティに関する懸念をご覧ください。
  • NAD_NAME: NetworkAttachmentDefinition カスタム リソースの名前。

複数のネットワーク インターフェースを指定するには、カンマ区切りのリストを使用します。

次の例では、2 つのネットワーク インターフェースが samplepod Pod に割り当てられます。ネットワーク インターフェースは、ターゲット クラスタのデフォルトの名前空間にある 2 つの NetworkAttachmentDefinition カスタム リソースの名前(gke-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:
  ...

ネットワーク インターフェースを NodePool に制限する

k8s.v1.cni.cncf.io/nodeSelector アノテーションを使用して、NetworkAttachmentDefinition カスタム リソースが有効なノードプールを指定します。Google Distributed Cloud は、このカスタム リソースを参照するすべての Pod を、そうした特定のノードに強制的にデプロイします。次の例では、Google Distributed Cloud によって、gke-network-1 ネットワーク インターフェースが割り当てられたすべての Pod が multinicNP NodePool に強制的にデプロイされます。Google Distributed Cloud は、NodePool に baremetal.cluster.gke.io/node-pool ラベルを付加します。

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  annotations:
    k8s.v1.cni.cncf.io/nodeSelector: baremetal.cluster.gke.io/node-pool=multinicNP
  name: gke-network-1
spec:
...

使用するのは標準ラベルに限定されません。カスタムラベルをクラスタノードに適用することで、クラスタノードから独自のカスタムプールを作成できます。カスタムラベルは、kubectl label nodes コマンドを使用して適用します。

kubectl label nodes NODE_NAME LABEL_KEY=LABEL_VALUE

次のように置き換えます。

  • NODE_NAME: ラベルを付けるノードの名前。
  • LABEL_KEY: ラベルに使用するキー。
  • LABEL_VALUE: ラベル名

ノードにラベルが付けられたら、そのノードに baremetal.cluster.gke.io/label-taint-no-sync アノテーションを適用して、Google Distributed Cloud によってラベルが調整されないようにします。ノードにラベルが付いているかどうかは、kubectl get nodes --show-labels コマンドを使用して確認します。

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

NetworkAttachmentDefinition カスタム リソースにより、ネットワークへの完全アクセス権が提供されるため、クラスタ管理者は、他のユーザーへの作成、更新、削除の権限に注意する必要があります。特定の NetworkAttachmentDefinition カスタム リソースを分離する必要がある場合は、その Namespace の Pod のみがアクセスできる非デフォルトの名前空間に配置します。クラスタ構成ファイルで指定された NetworkAttachmentDefinition カスタム リソースは、調整のため、常にデフォルトの Namespace に配置されます。

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

Namespace を使用してネットワーク トラフィックを分離する

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

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

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

  • ipvlan
  • macvlan
  • bridge
  • sriov

メタプラグイン:

  • portmap
  • sbr
  • tuning

IPAM プラグイン:

  • host-local
  • static
  • whereabouts

ルートの構成

1 つ以上の NetworkAttachmentDefinition カスタム リソースが割り当てられている Pod は、複数のネットワーク インターフェースを備えています。デフォルトでは、この状況のルーティング テーブルは、割り当てられた NetworkAttachmentDefinition カスタム リソースからローカルで使用可能な追加のインターフェースのみを使用して拡張されます。デフォルト ゲートウェイは、引き続き 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 イベントを使用して障害が報告されます。次の kubectl describeコマンドを使用して、特定の Pod のイベントを表示します。

kubectl describe pod POD_NAME

ログを確認する

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

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

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

Pod インターフェースを確認するには kubectl exec コマンドを使用します。NetworkAttachmentDefinition カスタム リソースが正常に適用されると、Pod インターフェースの出力は次のようになります。

$ 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