TCE で Multus を試してみよう

TUNA-JP の関本(@tarowork64)と申します。
本日は「[TUNA-JP Advent Calendar 2021](https://qiita.com/advent-calendar/2021/tuna-jp)」の16日目のエントリとして、TCE で提供されている package の一つ、[Multus](https://github.com/k8snetworkplumbingwg/multus-cni) をご紹介します！

## Multus ってなに？
![Multus.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392874/82692b3b-3b0f-f627-00e8-d603582cad30.png)


Multus とは CNI プラグインの一つです。
通常、Kubernetes では、1つのネットワークインターフェイスしかもつことができません。Multus を使用することで、複数のインターフェイスを持つマルチホームな Pod を作成することが可能になります。Multus 自体は複数の CNI プラグインを呼び出すことができる メタ CNI プラグインという位置付けで機能します。

## 何につかうのだろうか

通信事業者のコアネットワークで利用される CNF で使われることが想定されます。例えば、 Pod でクラスター内部のサービスと制御通信をする場合は、オーバレイネットワークを経由して、（通信事業者としての）ユーザパケット処理は、sriov を併用して高パフォーマンスを実現する、などといったことが考えられます。

TCE で Multus がパッケージとして提供されているのは、あまりユースケースがわからない部分はありますが、商用版の Tanzu Kubernetes Grid との関連で利用できるようになっているのだと思います。


## とりあえず入れてみよう！

通常 Multus を導入する場合、[quick-start guide](https://github.com/k8snetworkplumbingwg/multus-cni/blob/master/docs/quickstart.md)に沿って進めます。
TCE では、Multus も package として提供され、管理可能となるため、インストールも `tanzu package install` コマンドでシンプルに行うことができます。

今回も Tanzu Community Edition の Standalone Cluster を利用しています。

早速インストールしてみます。
まずは`tanzu package available list`で Multus パッケージが利用可能であることと利用可能なバージョンを確認します。
![スクリーンショット 2021-12-16 0.25.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392874/d79d12a1-c952-d041-706f-aa4627268f86.png)


今回は 3.7.1 が利用できます。こちらを指定してインストールします。
![スクリーンショット 2021-12-16 0.25.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392874/f7f6b22c-a384-645e-a9b1-e92603d37a21.png)

インストールできました。


念のため、kubectl で確認してみます。
![スクリーンショット 2021-12-16 0.28.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392874/c9d6d34e-308e-552a-2165-1d37ef4e4383.png)


正常に Deamonset が作成されていることが確認できました。


## 動作確認
実際に Pod に複数の Nic が接続できるかを確認してみます。network-attachment-defs を定義して追加される CNI を何にするか指定します。今回は TCE のドキュメントと同じく [macvlan](https://www.cni.dev/plugins/current/main/macvlan/) を利用することとします。
以下のような マニュフェストファイルを適用します。(IP アドレスなどは環境に応じて変更してください)

```
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: macvlan-conf
spec:
  config: '{
      "cniVersion": "0.3.0",
      "type": "macvlan",
      "master": "eth0",
      "mode": "bridge",
      "ipam": {
        "type": "host-local",
        "subnet": "10.111.1.128/25",
        "rangeStart": "10.111.1.204",
        "rangeEnd": "10.111.1.210",
        "routes": [
          { "dst": "0.0.0.0/0" }
        ],
        "gateway": "10.111.1.253"
      }
    }'
```

この定義を実際に Pod に適用する場合、Pod のマニフェストに以下のような、annotation を書く必要があります。

```
annotations:
  k8s.v1.cni.cncf.io/networks: macvlan-conf
```

実際にサンプル Pod をデプロイしてみます。

```
apiVersion: v1
kind: Pod
metadata:
  name: samplepod
  annotations:
    k8s.v1.cni.cncf.io/networks: macvlan-conf
spec:
  containers:
  - name: samplepod
    command: ["/bin/ash", "-c", "trap : TERM INT; sleep infinity & wait"]
    image: alpine
```

Pod が作成されたので `ip a` で インターフェースと IP アドレス情報を確認してみます。

```
$ kubectl exec -it samplepod -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
3: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP 
    link/ether 86:01:f8:4e:82:df brd ff:ff:ff:ff:ff:ff
    inet 100.96.1.7/24 brd 100.96.1.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::8401:f8ff:fe4e:82df/64 scope link 
       valid_lft forever preferred_lft forever
4: net1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 26:c3:9d:22:70:f9 brd ff:ff:ff:ff:ff:ff
    inet 10.111.1.204/25 brd 10.111.1.255 scope global net1
       valid_lft forever preferred_lft forever
    inet6 fe80::24c3:9dff:fe22:70f9/64 scope link 
       valid_lft forever preferred_lft forever
```

net1 というインターフェースが追加されているのがわかります。
こちらが macvlan で設定されているインターフェースです。
無事複数のネットワークインターフェースをもつ Pod を作成することができました！


## まとめ
Multus による複数ネットワークインターフェースをもつ Pod を TCE 上に作成できました。
Multus もあまり馴染みがない方が多いと思いますが、実は結構簡単に試せます。