手当たり次第に書くんだ

飽きっぽいのは本能

Kubernetes Multus で Pod に追加 NIC を接続する – Calico eBPF 環境の bridge / macvlan / ipvlan L2 検証

前回の記事では、Multus CNI を既存 Kubernetes クラスタへ導入し、00-multus.conf が作成され、既存の Calico CNI が delegate として呼び出されることを確認しました。ただし、その時点では NetworkAttachmentDefinition を作成しておらず、Pod に追加 NIC は付与していませんでした。

今回は、Multus で Pod に primary CNI とは別の secondary network を接続し、KVM ホスト上の別 VM と L2 接続できるかを確認しました。試験した方式は bridge CNI、macvlan、ipvlan L2 です。

結論として、3 方式すべてで Pod と対向 VM の双方向通信に成功しました。一方で、最初に通信できなかった主因は Multus や macvlan / ipvlan ではなく、Calico eBPF が worker VM の secondary NIC に TCX program を attach していたことと、対向 VM 側の nftables がテスト subnet への出力を許可していなかったことでした。

検証の目的

目的は、管理用 Kubernetes クラスタで Multus を使い、Pod に primary CNI とは別の追加 NIC を付け、KVM ホスト上の別 VM と L2 接続できるか確認することです。

観点確認内容
MultusNetworkAttachmentDefinition に基づき Pod に net1 を追加できるか
bridge CNIworker VM 内の Linux bridge 経由で対向 VM と通信できるか
macvlanworker VM の secondary NIC を master として Pod を L2 接続できるか
ipvlan L2ipvlan L2 でも対向 VM と通信できるか
Calico eBPFprimary NIC と secondary NIC の BPF attach 対象を分けられるか

検証構成

公開記事ではホスト名を例示名に置き換えます。構成としては、KVM ホスト上にテスト用 Linux bridge を作り、worker VM と対向 VM の追加 NIC を同じ bridge へ接続しています。

KVM host
  br-multus-test
    |- mgmt worker VM
    |    `- enp5s0
    |         `- Multus Pod net1
    `- peer VM
         `- enp8s0: 192.0.2.1/24
要素例示名役割
KVM ホストkvm-host-01.example.localテスト用 bridge を持つ物理ホスト
worker VMk8s-worker-01.example.localMultus Pod を配置する Kubernetes node
対向 VMpeer-vm-01.example.localPod の secondary network から到達する相手
worker secondary NICenp5s0Multus の bridge / macvlan / ipvlan で使用
対向 VM secondary NICenp8s0192.0.2.1/24 を設定

KVM ホスト側の設定

KVM ホスト側では、テスト用 Linux bridge を作成し、worker VM と対向 VM に追加 NIC を hotplug します。以下は公開用にホスト名を置き換えた例です。

sudo ip link add br-multus-test type bridge
sudo ip link set br-multus-test up

sudo virsh attach-interface   --domain k8s-worker-01.example.local   --type bridge   --source br-multus-test   --model virtio   --mac 52:54:00:aa:32:10   --live

sudo virsh attach-interface   --domain peer-vm-01.example.local   --type bridge   --source br-multus-test   --model virtio   --mac 52:54:00:aa:32:01   --live

この bridge は、Kubernetes の Service や Calico の Pod network とは別の、Multus secondary network の疎通確認用です。

worker VM 側の NIC 設定

worker VM 側では、追加 NIC として enp5s0 を使用します。macvlan / ipvlan では、この interface を直接 master として使います。

sudo ip link set enp5s0 up promisc on

bridge CNI を試験する場合は、worker VM 内にも Linux bridge を作り、enp5s0 を bridge に収容しました。

sudo ip link add br-multus-test type bridge
sudo ip link set br-multus-test up
sudo ip link set enp5s0 master br-multus-test
sudo ip link set enp5s0 up

bridge CNI の試験後、macvlan / ipvlan を再試験する際には、enp5s0 を bridge から外して戻しています。

sudo ip link set enp5s0 nomaster
sudo ip link del br-multus-test
sudo ip link set enp5s0 up promisc on

対向 VM 側の設定

対向 VM 側では、追加 NIC enp8s0192.0.2.1/24 を設定します。

sudo ip addr flush dev enp8s0
sudo ip addr add 192.0.2.1/24 dev enp8s0
sudo ip link set enp8s0 up

途中で、対向 VM 側の nftables により 192.0.2.0/24 宛の出力が許可されていないことが分かりました。検証中は、一時的にテスト subnet への出力を許可しています。

sudo nft add element ip filter output_private_dst { 192.0.2.0/24 }

Calico eBPF の対象 interface を限定する

今回の検証で最も重要だった設定は、Calico eBPF の attach 対象を primary NIC に限定することです。最初に通信できなかった時点では、worker VM の追加 NIC enp5s0 に Calico eBPF の TCX program が attach されていました。

enp5s0 tcx/ingress cali_tc_preamble
enp5s0 tcx/egress  cali_tc_preamble

この状態では、Multus の secondary network として使いたい interface が Calico の BPF dataplane の対象にもなってしまいます。そこで、FelixConfiguration の bpfDataIfacePattern を設定し、Calico eBPF の対象を primary NIC である enp1s0 に限定しました。

kubectl --context k8s-mgmt.example.local   patch felixconfiguration default   --type merge   -p '{"spec":{"bpfDataIfacePattern":"^enp1s0$"}}'

設定後は、bpftool で BPF attach 状態を確認します。

sudo bpftool net | grep -E 'enp1s0|enp5s0'

期待する状態は、enp1s0 には cali_tc_preamble が表示され、enp5s0 は表示されないことです。

bridge CNI の NetworkAttachmentDefinition

bridge CNI では、worker VM 内の br-multus-test を使います。IPAM は static にし、Pod annotation 側で IP アドレスを指定します。

apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: kvm-bridge-test
  namespace: default
spec:
  config: |
    {
      "cniVersion": "0.3.1",
      "type": "bridge",
      "bridge": "br-multus-test",
      "capabilities": { "ips": true },
      "ipam": { "type": "static" }
    }
apiVersion: v1
kind: Pod
metadata:
  name: multus-kvm-bridge-pod
  namespace: default
  annotations:
    k8s.v1.cni.cncf.io/networks: |
      [{"name":"kvm-bridge-test","interface":"net1","ips":["192.0.2.10/24"]}]
spec:
  nodeName: k8s-worker-01.example.local
  restartPolicy: Never
  containers:
    - name: netshoot
      image: nicolaka/netshoot:latest
      command: ["sleep", "3600"]

macvlan の NetworkAttachmentDefinition

macvlan では、worker VM の enp5s0 を master として使い、mode は bridge にしました。

apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: kvm-macvlan-test
  namespace: default
spec:
  config: |
    {
      "cniVersion": "0.3.1",
      "type": "macvlan",
      "master": "enp5s0",
      "mode": "bridge",
      "capabilities": { "ips": true },
      "ipam": { "type": "static" }
    }
apiVersion: v1
kind: Pod
metadata:
  name: multus-kvm-macvlan-pod
  namespace: default
  annotations:
    k8s.v1.cni.cncf.io/networks: |
      [{"name":"kvm-macvlan-test","interface":"net1","ips":["192.0.2.10/24"]}]
spec:
  nodeName: k8s-worker-01.example.local
  restartPolicy: Never
  containers:
    - name: netshoot
      image: nicolaka/netshoot:latest
      command: ["sleep", "3600"]

ipvlan L2 の NetworkAttachmentDefinition

ipvlan では、同じく enp5s0 を master とし、mode は l2 にしました。Pod 側の IP は、bridge / macvlan と重複しないよう 192.0.2.11/24 にしています。

apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: kvm-ipvlan-test
  namespace: default
spec:
  config: |
    {
      "cniVersion": "0.3.1",
      "type": "ipvlan",
      "master": "enp5s0",
      "mode": "l2",
      "capabilities": { "ips": true },
      "ipam": { "type": "static" }
    }
apiVersion: v1
kind: Pod
metadata:
  name: multus-kvm-ipvlan-pod
  namespace: default
  annotations:
    k8s.v1.cni.cncf.io/networks: |
      [{"name":"kvm-ipvlan-test","interface":"net1","ips":["192.0.2.11/24"]}]
spec:
  nodeName: k8s-worker-01.example.local
  restartPolicy: Never
  containers:
    - name: netshoot
      image: nicolaka/netshoot:latest
      command: ["sleep", "3600"]

疎通確認

Pod から対向 VM へ ping し、逆方向として対向 VM から Pod の secondary network 側 IP へ ping します。以下は macvlan の例です。

kubectl --context k8s-mgmt.example.local   -n default exec multus-kvm-macvlan-pod --   ping -c 5 -W 2 192.0.2.1

ping -I enp8s0 -c 5 -W 2 192.0.2.10

ipvlan L2 の場合は、Pod IP を 192.0.2.11 として確認しています。

ping -I enp8s0 -c 5 -W 2 192.0.2.11
方式Pod から対向 VM対向 VM から Pod結果
bridge CNI192.0.2.10 から 192.0.2.1192.0.2.1 から 192.0.2.10OK
macvlan192.0.2.10 から 192.0.2.1192.0.2.1 から 192.0.2.10OK
ipvlan L2192.0.2.11 から 192.0.2.1192.0.2.1 から 192.0.2.11OK

実測では、すべて 0% packet loss でした。これにより、Multus secondary network として bridge CNI、macvlan、ipvlan L2 のいずれも、同じ KVM bridge 上の対向 VM と L2 接続できることを確認できました。

最初に通信できなかった理由

最初に通信できなかった理由は、Multus の NetworkAttachmentDefinition や macvlan / ipvlan の選択そのものではありませんでした。大きく二つの要因がありました。

要因内容対応
Calico eBPFworker VM の secondary NIC enp5s0 に TCX program が attach されていたbpfDataIfacePattern で primary NIC enp1s0 に限定
対向 VM の nftablesOUTPUT が default drop で、192.0.2.0/24 宛が許可されていなかった検証中はテスト subnet への出力を一時許可

この結果から、Calico eBPF 環境で Multus secondary network を使う場合、secondary NIC を Calico の BPF dataplane 対象から外す設計が必要だと分かりました。特に、primary NIC と secondary NIC が同じ worker VM に存在する構成では、Calico がどの interface を処理対象にするかを曖昧にしてはいけません。

まとめ

今回の検証では、Multus を使って Pod に primary CNI とは別の追加 NIC を付与し、KVM ホスト上の別 VM と L2 接続できることを確認しました。bridge CNI、macvlan、ipvlan L2 のいずれでも、Pod と対向 VM の双方向通信に成功しています。

一方で、通信できるかどうかは NetworkAttachmentDefinition の設定だけでは決まりません。worker VM の secondary NIC が KVM bridge へ正しく接続されていること、対向 VM の firewall が通信を許可していること、Calico eBPF が secondary NIC に干渉していないことを合わせて確認する必要があります。

今回の最重要設定は、FelixConfiguration の bpfDataIfacePattern: "^enp1s0$" です。Calico eBPF 環境で Multus secondary network を使うなら、Calico が primary NIC だけを BPF dataplane 対象にし、Multus 用の secondary NIC を処理対象から外す設計を最初から入れておくべきです。

参考書籍

参考
書籍
参考書籍

Kubernetes 完全ガイド 第 2 版

Kubernetes の Pod、CNI、Service、運用設計を体系的に確認したい場合の参考書籍です。価格や在庫はリンク先で確認してください。

Amazon で見る

このリンクは Amazon アソシエイトリンクです。

参考資料

関連する記事

Multus と CNI の関連記事
Kubernetes Multus で Pod に追加 NIC を接続する – Calico eBPF 環境の bridge / macvlan / ipvlan L2 検証

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る