Multusでipvlanで複数NICを持つPodを作成する

はじめに

Multusでipvlanで複数NICを持つPodを作成する方法が詰まったことが多かったので、備忘録を込めて記載する

環境

  • Windows11(ホストOS)
  • Ubuntu22.04.3(ゲストOS、Virtualbox上に構築)
  • k3s
  • calico

構築と確認

k3sのインストール

docs.tigera.io を参考に実施する。

cni pluginのインストール

https://github.com/containernetworking/plugins から必要なcni pluginをインストールする。 Goをインストールしてcniのpluginをコンパイルし、cniをインストールする。

$ cd ~
$ curl -OL https://go.dev/dl/go1.21.6.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.21.6.linux-amd64.tar.gz
$ cat >> ~/.bashrc << "EOF"
export GOPATH=/usr/local/go
export PATH=$PATH:$GOPATH/bin
EOF
$ source ~/.barhrc

$ git clone https://github.com/containernetworking/plugins
$ cd plugins/
$ ./build_linux.sh

$ cd bin
$ sudo install -m 755 -D bridge            /opt/cni/bin
$ sudo install -m 755 -D host-device       /opt/cni/bin
$ sudo install -m 755 -D ipvlan            /opt/cni/bin
$ sudo install -m 755 -D loopback          /opt/cni/bin
$ sudo install -m 755 -D macvlan           /opt/cni/bin
$ sudo install -m 755 -D vlan              /opt/cni/bin
$ sudo install -m 755 -D dhcp              /opt/cni/bin
$ sudo install -m 755 -D host-local        /opt/cni/bin
$ sudo install -m 755 -D static            /opt/cni/bin

multusのclone

$ git clone https://github.com/k8snetworkplumbingwg/multus-cni
$ cd multus-cni

multusのインストール

今回はv3.9.3を使用する。

$ git checkout v3.9.3
$ cat ./deployments/multus-daemonset-thick-plugin.yml | kubectl apply -f -

interfae 確認

$ 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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:95:fa:9c brd ff:ff:ff:ff:ff:ff
    inet 100.64.1.18/22 metric 100 brd 100.64.3.255 scope global dynamic enp0s3
       valid_lft 602466sec preferred_lft 602466sec
    inet6 240b:11:400:e700:a00:27ff:fe95:fa9c/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 2591851sec preferred_lft 604651sec
    inet6 fe80::a00:27ff:fe95:fa9c/64 scope link
       valid_lft forever preferred_lft forever

複数interfaceを持つpodを作成

calicoとmultusで作成されるNICを異なるNICに紐づくようにしたいが、今回は省略するため、同じNIC(enp0s3)を使用することとする。 NetworkAttachmentDefinitionで、MasterのInterfaceを指定しないため、自動的にenp0s3が指定されるはずである。

iplanの場合

$ cat > pod-ipvlan.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
  name: test-pod-ipvlan
  annotations:
    k8s.v1.cni.cncf.io/networks: ipvlan-conf
spec:
  containers:
  - name: test-pod-ipvlan
    command: ["/bin/sh", "-c", "trap : TERM INT; sleep infinity & wait"]
    image: alpine
EOF

$ cat > net-attach-def-ipvlan.yaml << EOF
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
   name: ipvlan-conf
spec:
   config: '{
      "cniVersion": "0.3.1",
      "type": "ipvlan",
      "ipam": {
         "type": "host-local",
         "subnet": "198.17.0.0/24"
      }
 }'
EOF

# pod作成
$ kubectl apply -f net-attach-def-ipvlan.yaml
$ kubectl apply -f pod-ipvlan.yaml
$ kubectl get pods
NAME              READY   STATUS              RESTARTS   AGE
test-pod-ipvlan   1/1     Running             0          8m14s

# interface確認
$ kubectl exec -it test-pod-ipvlan -- 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
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
3: eth0@if56: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1480 qdisc noqueue state UP qlen 1000
    link/ether d6:42:48:c8:c6:a7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.243.240/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::d442:48ff:fec8:c6a7/64 scope link
       valid_lft forever preferred_lft forever
4: net1@tunl0: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UNKNOWN
    link/ether 08:00:27:95:fa:9c brd ff:ff:ff:ff:ff:ff
    inet 198.17.0.205/24 brd 198.17.0.255 scope global net1
       valid_lft forever preferred_lft forever
    inet6 fe80::800:2700:195:fa9c/64 scope link
       valid_lft forever preferred_lft forever

github.com にあるpluginsという記載のあるJSONファイルだと上手に動作しなかったので、古いタイプのフォーマットで記載する。

bridgeの場合

bridgeを使った場合も記載する。

$ cat net-attach-def-bridge.yaml
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: bridge-conf
spec:
  config: >
    {
        "cniVersion": "0.3.0",
        "type": "bridge",
        "bridge": "test-br",
        "ipam": {
            "type": "host-local",
            "subnet": "192.168.1.0/24",
            "rangeStart": "192.168.1.100",
            "rangeEnd": "192.168.1.200"
        }
    }

$ cat pod-bridge.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod-bridge
  annotations:
    k8s.v1.cni.cncf.io/networks: bridge-conf
spec:
  containers:
  - name: test-pod-bridge
    command: ["/bin/sh", "-c", "trap : TERM INT; sleep infinity & wait"]
    image: alpine

# pod作成
$ kubectl apply -f net-attach-def-bridge.yaml
$ kubectl apply -f cat pod-bridge.yaml
$ kubectl get pods
NAME              READY   STATUS              RESTARTS   AGE
test-pod-bridge   1/1     Running             0          28m

# interface確認
$ kubectl exec -it test-pod-bridge -- 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
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
3: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1480 qdisc noqueue state UP qlen 1000
    link/ether 06:35:61:72:8d:6d brd ff:ff:ff:ff:ff:ff
    inet 192.168.243.199/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::435:61ff:fe72:8d6d/64 scope link
       valid_lft forever preferred_lft forever
4: net1@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 3a:28:10:f4:47:17 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.100/24 brd 192.168.1.255 scope global net1
       valid_lft forever preferred_lft forever
    inet6 fe80::3828:10ff:fef4:4717/64 scope link
       valid_lft forever preferred_lft forever

参考

anywhere.eks.amazonaws.com