Kubernetes (K8s) の世界において、基本的に Pod は、NIC を 1つしか持てません。Multus CNI は、Pod に複数の NIC を割り当てられるようにするための CNI (Container Network Interface) Plugin です。
これは、Multus が、他の CNI Plugin を呼び出すための "meta-plugin" として動作することによって実現されています。下記の公式リポジトリにあるアーキテクチャ図とかが、イメージとして分かりやすいかと思います。
一般に、クラウドネイティブなアプリは、スケールアウトによって性能をスケールさせるため、Pod が 1つしか NIC を持てないからと言って、Pod 1つあたりのネットワーク性能が問題になるようなシーンは少ないかも知れません。
しかし、コンテナで実装されたネットワーク機能、CNF (Cloud Native Network Function) のユースケースにおいては、K8s の管理ネットワーク等とは別に、専用の高速ネットワークとして、2つ目、3つ目... の NIC が欲しくなったりするため、Multus の利用が有力視されるユースケースが存在します。
ただ、コンテナ自体がネットワーク機能を持つようなユースケースであるため、追加の NIC に割り当てられた IP アドレス等のリソース管理は、アプリが独自に行うことが想定されており、K8s の世界から追加のネットワークを管理する機能は、限定的であるのが現状です。
具体的には、例えば、「追加の NIC に割り当てられている IP アドレスを検出または管理 (IPAM) し、K8s の Service に対するエンドポイントとして、自動で更新し続けてくれる」というような機能は、現時点 (2023年4月) の Multus には実装されていません。1
また、ややこしいですが、この追加の NIC は、Multus 自身が用意してくれるのではなく、Mutlus はあくまで「元々 K8s Node に刺さっている NIC を使う」というイメージになります。
確かに、macvlan や ipvlan を使って、1つの NIC を複数の NIC であるかのように扱うことはできます。しかし、例えば、K8s Node が VM として動作している場合において、Multus に設定を入れたら、「自動で VM に仮想 NIC を追加してくれる」という訳ではありません。
Muluts の役目は、あくまで「他の CNI Plugin を呼び出すまで」であり、呼び出される CNI Plugin にも NIC 自体を用意する機能は実装されていません。
とはいえ、Mutlus の提供してくれる技術としては、とても興味深いです。
今回は、Tanzu Kubernetes Grid (TKG) 2.1 において、Tanzu CLI でインストールできる拡張パッケージとして、Multus が提供されているので、これで遊んでみたいと思います。
また、2つ目の NIC に対する IP アドレス管理 (IPAM) として Whereabouts という CNI Plugin も提供されているので、Mutlus と組合せて、遊んでみます。
前提
利用しているソフトウェアのバージョンは、下記の通りです。
- Tanzu Kubernetes Grid 2.1.1
- tanzu-standard パッケージ 2.1.1
また、TKG としては Standalone Management Cluster として構成し、実際に Multus で遊ぶ Workload Cluster を 1つデプロイしている状況を想定しています。
Workload Cluster のサイジングにおける注意
Node 台数は、Multus でどこまで遊ぶか次第で調整、で良いかと思います。しかし、Node の CPU や Mem といったリソースのサイジングとしては large
サイズ (4 CPUs, 16 GB memory, 40 GB disk) 以上が必要になります。
私が試した範囲では、どちらかと言うと CPU リソースが重要で、small
や medium
サイズ (2 CPUs) では、CPU リソース不足で Multus パッケージがインストールできませんでした。
手順
基本は、Tanzu Kubernetes Grid 2.1 の公式ドキュメントに記載に従って、実施していきます。
まず、kubectl
コマンドを使って、これから Multus をインストールしていく TKG クラスタに、Context が切り替わっていることを確認します。
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
management-admin@management management management-admin
* tkc01-admin@tkc01 tkc01 tkc01-admin
ここでは、management
という名前の Management Cluster からデプロイした、tkc01
という名前の Workload Cluster に、Multus をインストールしていきます。
tanzu-standard パッケージの追加
TKG の拡張機能が提供されている tanzu-standard
パッケージのリポジトリを登録します。
tanzu package repository add tanzu-standard --url projects.registry.vmware.com/tkg/packages/standard/repo:v2.1.1 --namespace tkg-system
バージョンについては、ご利用の TKG の ver に合わせて、選択してください。
登録済みのリポジトリを確認するコマンドで、↓正しく登録されているか確認します。
tanzu package repository list -A
NAMESPACE NAME SOURCE STATUS
tkg-system tanzu-standard (imgpkg) projects.registry.vmware.com/tkg/packages/standard/repo:v2.1.1 Reconcile succeeded
利用可能な Multus パッケージの確認
リポジトリを通じて、インストール可能な Multus パッケージの情報、主にバージョン情報について、確認していきます。
少し冗長ですが、順を追って紹介していくと、まず、登録済みのリポジトリを通じて、インストール可能なパッケージの一覧を確認します。
tanzu package available list
NAME DISPLAY-NAME
cert-manager.tanzu.vmware.com cert-manager
contour.tanzu.vmware.com contour
external-dns.tanzu.vmware.com external-dns
fluent-bit.tanzu.vmware.com fluent-bit
fluxcd-helm-controller.tanzu.vmware.com Flux Helm Controller
fluxcd-kustomize-controller.tanzu.vmware.com Flux Kustomize Controller
fluxcd-source-controller.tanzu.vmware.com Flux Source Controller
grafana.tanzu.vmware.com grafana
harbor.tanzu.vmware.com harbor
multus-cni.tanzu.vmware.com multus-cni
prometheus.tanzu.vmware.com prometheus
whereabouts.tanzu.vmware.com whereabouts
ここでは、Multus と Whereabouts のパッケージを確認していますが、その他にも複数の OSS パッケージが提供されているのが分かります。
次に、パッケージ名を指定して get
コマンドを実行すると、利用可能なバージョン情報を確認できます。
tanzu package available get multus-cni.tanzu.vmware.com
NAME: multus-cni.tanzu.vmware.com
DISPLAY-NAME: multus-cni
CATEGORIES: - networking
SHORT-DESCRIPTION: This package provides the ability for enabling attaching multiple network
interfaces to pods in Kubernetes
LONG-DESCRIPTION: This package provides the ability for enabling attaching multiple network
interfaces with different types of CNI to pods in Kubernetes, such as sriov and
macvlan
PROVIDER: VMware
MAINTAINERS: - name: Wang Jun
- name: Li Chenrui
- name: Zhou Ke
SUPPORT-DESCRIPTION: Support provided by VMware for deployment on Tanzu clusters. Best-effort support
for deployment on any conformant Kubernetes cluster. Contact support by opening
a support request via VMware Cloud Services or my.vmware.com.
VERSION RELEASED-AT
3.7.1+vmware.1-tkg.1 2021-06-05 03:00:00 +0900 JST
3.7.1+vmware.2-tkg.1 2021-06-05 03:00:00 +0900 JST
3.7.1+vmware.2-tkg.2 2021-06-05 03:00:00 +0900 JST
3.8.0+vmware.1-tkg.1 2023-03-08 23:51:55 +0900 JST
3.8.0+vmware.2-tkg.2 2023-03-08 23:51:55 +0900 JST
さらに、パッケージ名に加えて、バージョンまで指定することで、デフォルト値が記載された設定ファイルの雛形を取得することが出来ます。
tanzu package available get multus-cni.tanzu.vmware.com/3.8.0+vmware.2-tkg.2 --default-values-file-output multus-cni-data-values.yaml
Created default values file at multus-cni-data-values.yaml
NAME: multus-cni.tanzu.vmware.com
DISPLAY-NAME: multus-cni
CATEGORIES: - networking
SHORT-DESCRIPTION: This package provides the ability for enabling attaching multiple network
interfaces to pods in Kubernetes
LONG-DESCRIPTION: This package provides the ability for enabling attaching multiple network
interfaces with different types of CNI to pods in Kubernetes, such as sriov and
macvlan
PROVIDER: VMware
MAINTAINERS: - name: Wang Jun
- name: Li Chenrui
- name: Zhou Ke
SUPPORT-DESCRIPTION: Support provided by VMware for deployment on Tanzu clusters. Best-effort support
for deployment on any conformant Kubernetes cluster. Contact support by opening
a support request via VMware Cloud Services or my.vmware.com.
VERSION: 3.8.0+vmware.2-tkg.2
RELEASED-AT: 2023-03-08 23:51:55 +0900 JST
MIN-CAPACITY-REQUIREMENTS:
RELEASE-NOTES: multus-cni 3.8.0
https://github.com/k8snetworkplumbingwg/multus-cni/releases/tag/v3.8
LICENSES: VMware’s End User License Agreement (Underlying OSS license: Apache License 2.0)
参考までに、この設定ファイルの中身は、↓こんな感じでした。
# daemonset:
# resources:
# limits:
# cpu: 100m
# memory: 50Mi
# requests:
# cpu: 100m
# memory: 50Mi
# namespace: kube-system
ここでは特にデフォルト値から変更する必要が無かったので、以降の手順で利用していませんが、必要に応じて、設定ファイルを作成してください。
Multus パッケージのインストール
パッケージ本体のインストールの前に、パッケージをインストールする先の Namespace を作成します。
特に制限がある訳では無いですし、TKG 2.1 時点では、Multus のアンインストールがサポートされていないため、後片付けを意識して作成する必要もありません。
しかし、インストール先の Namespace は事前に作成しておく必要があるので、ここでは分かりやすさのために、multus-cni
という名前で作成しておきます。
kubectl create namespace multus-cni
その上で、実際に Multus パッケージをインストールしていきます。
tanzu package install multus-cni --package multus-cni.tanzu.vmware.com --version 3.8.0+vmware.2-tkg.2 --namespace multus-cni
補足
今回は、前述の設定ファイルを変更しておらず、デフォルト設定のままでインストールしているので、上記のオプションのみですが、何かしら設定を変更している場合には、--values-file
で、作成した設定ファイルを指定します。
tanzu package install multus-cni --package multus-cni.tanzu.vmware.com --version 3.8.0+vmware.2-tkg.2 --values-file multus-cni-data-values.yaml --namespace multus-cni
下記のコマンドで、正しくインストールできているか確認します。
tanzu package installed get multus-cni --namespace multus-cni
NAMESPACE: multus-cni
NAME: multus-cni
PACKAGE-NAME: multus-cni.tanzu.vmware.com
PACKAGE-VERSION: 3.8.0+vmware.2-tkg.2
STATUS: Reconcile succeeded
CONDITIONS: - type: ReconcileSucceeded
status: "True"
reason: ""
message: ""
ここまでで、Multus はインストールできているので、適当な Pod を作成し、2つ目の NIC を割り当てることが出来ますが、前述の通り、Whereabouts という IP アドレス管理 (IPAM) を提供してくれる CNI と組合せたいと思います。
Whereabouts によって、K8s Node を跨いで、クラスタ全体で適切に IP アドレスの割り当てが実行されます。
Whereabouts パッケージのインストール
パッケージの確認から記載していくと冗長なので、いきなりパッケージ情報の確認と、設定ファイルの雛形の取得から記載しています。
tanzu package available get whereabouts.tanzu.vmware.com/0.5.4+vmware.1-tkg.1 --default-values-file-output whereabouts-data-values.yaml
Created default values file at whereabouts-data-values.yaml
NAME: whereabouts.tanzu.vmware.com
DISPLAY-NAME: whereabouts
CATEGORIES: - networking
SHORT-DESCRIPTION: A CNI IPAM plugin that assigns IP addresses cluster-wide
LONG-DESCRIPTION: A CNI IPAM plugin that assigns IP addresses cluster-wide
PROVIDER: VMware
MAINTAINERS: - name: Jun Wang
- name: Chenrui Li
- name: Ke Zhou
SUPPORT-DESCRIPTION: Support provided by VMware for deployment on Tanzu clusters. Best-effort support
for deployment on any conformant Kubernetes cluster. Contact support by opening
a support request via VMware Cloud Services or my.vmware.com.
VERSION: 0.5.4+vmware.1-tkg.1
RELEASED-AT: 2023-03-08 23:51:55 +0900 JST
MIN-CAPACITY-REQUIREMENTS:
RELEASE-NOTES: whereabouts 0.5.4
https://github.com/k8snetworkplumbingwg/whereabouts/releases/tag/v0.5.4
LICENSES: VMware’s End User License Agreement (Underlying OSS license: Apache License 2.0)
ただ、こちらも今回はデフォルト設定から変更する必要が無かったので、以降の手順では利用していません。
# ip_reconciler:
# config:
# resources:
# requests:
# cpu: 100m
# memory: 50Mi
# schedule: '*/5 * * * *'
# namespace: kube-system
# whereabouts:
# config:
# resources:
# limits:
# cpu: 100m
# memory: 50Mi
# requests:
# cpu: 100m
# memory: 50Mi
よって、まずはインストール先の Namespace を作成し、
kubectl create namespace whereabouts
Whereabouts パッケージをインストールします。
tanzu package install whereabouts --package whereabouts.tanzu.vmware.com --version 0.5.4+vmware.1-tkg.1 --namespace whereabouts
こちらも、下記のコマンドで、正しくインストールできているか確認します。
tanzu package installed get whereabouts --namespace whereabouts
NAMESPACE: whereabouts
NAME: whereabouts
PACKAGE-NAME: whereabouts.tanzu.vmware.com
PACKAGE-VERSION: 0.5.4+vmware.1-tkg.1
STATUS: Reconcile succeeded
CONDITIONS: - type: ReconcileSucceeded
status: "True"
reason: ""
message: ""
Multus の設定
パッケージが正しくインストールされたので、ここからは Multus (および Whereabouts) に対して、「どんなネットワークに接続して欲しいか」を設定していきます。
そのためには、NetworkAttachmentDefinition
という CRD (Custom Resource Definition) を作成します。
今回作成したマニフェストは、↓こんな感じです。
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: macvlan-conf
spec:
config: '{
"cniVersion": "0.3.1",
"plugins": [
{
"type": "macvlan",
"capabilities": { "ips": true },
"master": "eth0",
"mode": "bridge",
"ipam": {
"type": "whereabouts",
"range": "192.168.120.0/24",
"range_start": "192.168.120.128",
"range_end": "192.168.120.191",
"gateway": "192.168.120.254"
}
} ]
}'
内容としては、Node VM の eth0
を親インタフェースとして、macvlan を使って追加の NIC を作成するように、設定してあります。
その際、Whereabouts を利用して、192.168.120.128-192.168.120.191
の範囲で IP アドレスを払い出せるようにしてあります。
このマニフェストを適用しておきます。
kubectl apply -f multus-cni-crd.yaml
動作確認
まず、2つの NIC を持つ Pod を作成するために、↓このようなマニフェストを作成します。
Annotation 部分で、先ほど作成した NetworkAttachmentDefinition
が指定しています。
apiVersion: v1
kind: Pod
metadata:
name: pod0
annotations:
k8s.v1.cni.cncf.io/networks: macvlan-conf
spec:
containers:
- name: pod0
command: ["/bin/ash", "-c", "trap : TERM INT; sleep infinity & wait"]
image: busybox
imagePullSecrets:
- name: docker-hub
このマニフェストを使って、Pod を作成します。
kubectl apply -f pod-with-multi-cni.yaml
Pod の実行を確認できたら、
$ kubectl get pods pod0
NAME READY STATUS RESTARTS AGE
pod0 1/1 Running 0 2m3s
Annotation の "k8s.v1.cni.cncf.io/network-status" 部分を見ると、net1
として、2本目の NIC に IP アドレスが割り当てられいることが確認できます。
$ kubectl describe pod pod0
# ...(略)...
Annotations: k8s.v1.cni.cncf.io/network-status:
[{
"name": "antrea",
"interface": "eth0",
"ips": [
"100.96.4.26"
],
"mac": "c2:ac:40:6d:57:0a",
"default": true,
"dns": {},
"routes": [
{
"dst": "0.0.0.0/0",
"gw": "100.96.4.1"
}
]
},{
"name": "default/macvlan-conf",
"interface": "net1",
"ips": [
"192.168.120.128"
],
"mac": "8e:4d:5d:39:30:fe",
"dns": {}
}]
k8s.v1.cni.cncf.io/networks: macvlan-conf
# ...(略)...
簡易な確認ですが、この pod0
から Gateway に対して、ping が通るかだけ、確認したいと思います。
まず、kubectl
コマンドを使ってpod0
に入り込みます。
kubectl exec -it pod0 -- sh
IP アドレスも先ほど確認した通りに割り当てられているようです。
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0@if31: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue
link/ether c2:ac:40:6d:57:0a brd ff:ff:ff:ff:ff:ff
inet 100.96.4.26/24 brd 100.96.4.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::c0ac:40ff:fe6d:570a/64 scope link
valid_lft forever preferred_lft forever
3: net1@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
link/ether 8e:4d:5d:39:30:fe brd ff:ff:ff:ff:ff:ff
inet 192.168.120.128/24 brd 192.168.120.255 scope global net1
valid_lft forever preferred_lft forever
inet6 fe80::8c4d:5dff:fe39:30fe/64 scope link
valid_lft forever preferred_lft forever
/ # ip r
default via 100.96.4.1 dev eth0
100.96.4.0/24 dev eth0 scope link src 100.96.4.26
192.168.120.0/24 dev net1 scope link src 192.168.120.128
実際に Gateway に対して、ping を実行してみると、疎通できていることが確認できます。
/ # ping -I net1 -c 3 192.168.120.254
PING 192.168.120.254 (192.168.120.254): 56 data bytes
64 bytes from 192.168.120.254: seq=0 ttl=64 time=0.504 ms
64 bytes from 192.168.120.254: seq=1 ttl=64 time=0.310 ms
64 bytes from 192.168.120.254: seq=2 ttl=64 time=0.242 ms
--- 192.168.120.254 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.242/0.352/0.504 ms
この先...
Multus + Whereabouts を使って、TKG 上で動作する Pod に、2つ目の NIC を割り当てられることが確認できました。
ただし、前述の通り、K8s の Service の世界から見える IP アドレスは、1つ目の NIC eth0
のものであるため、残念ながら、まだまだ使い勝手が良い訳ではありません。
しかし、Multus 自身あるいは、周辺の機能が整ってくれば、間違いなく面白い技術ではあるので、また更新があれば、ご紹介したいと思います。
-
multus-service として、Multus が追加した NIC についても、K8s の Service のような抽象化機能を実現しようとしているプロジェクトが存在しています。しかし、現時点 (2023年4月) においては、GitHub のページにもある通り、あくまで開発初期段階として扱う必要があるようです。 ↩