このドキュメントでは、Pod に複数のネットワーク インターフェース(マルチ NIC)を提供するように GKE on Bare Metal を構成する方法について説明します。Pod 用のマルチ NIC 機能は、コントロール プレーン トラフィックをデータプレーン トラフィックから分離して、プレーン間で分離するのに役立ちます。また、追加のネットワーク インターフェースによって、Pod のマルチキャスト機能を有効にできます。Pod のマルチ NIC はユーザー クラスタ、ハイブリッド クラスタ、スタンドアロン クラスタではサポートされています。管理者タイプのクラスタでは許可されません。
ネットワーク プレーンの分離は、広域ネットワーク(SD-WAN)のソフトウェア定義ネットワーキング、クラウド アクセス セキュリティ ブローカー(CASB)、次世代ファイアウォール(NG-FW)などのネットワーク機能仮想化(NFV)を使用するシステムにとって重要です。こうしたタイプの NFV は、コンテナとして実行しながら、管理インターフェースとデータプレーンを分離するために、複数のインターフェースを利用します。
複数ネットワーク インターフェースの構成では、ネットワーク インターフェースとノードプールの関連付けがサポートされ、パフォーマンスの向上が実現できます。クラスタには、複数のノードタイプを含めることができます。高パフォーマンスのマシンを 1 つのノードプールにグループ化するときは、ノードプールにインターフェースを追加してトラフィック フローを改善できます。
複数のネットワーク インターフェースを設定する
通常、次の 3 ステップで、Pod に複数のネットワーク インターフェースを設定します。
クラスタのカスタム リソースの
multipleNetworkInterfaces
フィールドを使用して、クラスタのマルチ NIC を有効にする。NetworkAttachmentDefinition
カスタム リソースを使用して、ネットワーク インターフェースを指定する。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
カスタム リソースを指定すると、GKE on Bare Metal は、クラスタ作成後、この名前を使用して NetworkAttachmentDefinition
カスタム リソースを制御します。GKE on Bare Metal では、クラスタの名前空間内のこのカスタム リソースを真のソースとして扱い、ターゲット クラスタの default
名前空間に調整します。
次の図では、GKE on Bare Metal で、NetworkAttachmentDefinition
カスタム リソースがクラスタ固有の名前空間から default
名前空間に反映される仕組みを示します。
省略可能ですが、クラスタ作成時にこの方法で NetworkAttachmentDefinition
カスタム リソースを指定することをおすすめします。ユーザー クラスタは、クラスタの作成時にカスタム リソースを指定すると最大の効果を発揮します。これは、管理クラスタから NetworkAttachmentDefinition
カスタム リソースを制御できるためです。
クラスタの作成時に NetworkAttachmentDefinition
カスタム リソースを指定しない場合は、NetworkAttachmentDefinition
カスタム リソースを既存のターゲット クラスタに直接追加できます。GKE on Bare Metal は、クラスタの Namespace に定義された NetworkAttachmentDefinition
カスタム リソースと整合されます。整合は削除時にも行われます。NetworkAttachmentDefinition
カスタム リソースがクラスタの Namespace から削除されると、GKE on Bare Metal はターゲット クラスタからカスタム リソースを削除します。
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-1
と gke-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
カスタム リソースが有効なノードプールを指定します。GKE on Bare Metal は、このカスタム リソースを参照するすべての Pod を、そうした特定のノードにデプロイします。次の例では、GKE on Bare Metal によって、gke-network-1
ネットワーク インターフェースに割り当てられたすべての Pod が multinicNP
NodePool に強制的にデプロイされます。GKE on Bare Metal は、それに応じて 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
: ラベルを付ける Node の名前。LABEL_KEY
: ラベルに使用するキー。LABEL_VALUE
: ラベル名
ノードにラベルが付けられたら、そのノードに baremetal.cluster.gke.io/label-taint-no-sync
アノテーションを適用して、GKE on Bare Metal によってラベルが整合されないようにします。ノードにラベルが付いているかどうかは、kubectl get nodes --show-labels
コマンドを使用して確認します。
セキュリティに関する懸念
NetworkAttachmentDefinition
カスタム リソースにより、ネットワークへの完全アクセス権が提供されるため、クラスタ管理者は、他のユーザーへの作成、更新、削除の権限に注意する必要があります。特定の NetworkAttachmentDefinition
カスタム リソースを分離する必要がある場合は、その名前空間の Pod のみがアクセスできる非デフォルトの名前空間に配置します。クラスタ構成ファイルで指定された NetworkAttachmentDefinition
カスタム リソースは、整合のため、常に default Namespace に配置されます。
次の図では、default
名前空間の Pod は、privileged
名前空間のネットワーク インターフェースにアクセスできません。
サポートされている CNI プラグイン
このセクションでは、GKE on Bare Metal のマルチ 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 は起動しません。このセクションでは、マルチ 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