Metonymical Deflection

ゆるく日々のコト・たまにITインフラ

vDPA の設定方法 vhost_vdpa + kubernetes + Accelerated Bridge CNI編

Accelerated Bridge CNIを使用したKubernetes環境におけるvDPA(virtio data path acceleration)の設定方法について記載しました。*1
vDPAの詳細はThe official Red Hat blogを参照してください。

前回の記事と異なる点は、Accelerated Bridge CNIを使用していることです。
SR-IOV CNI(前回の記事)の場合、SR-IOV Legacyモードを使用しましたが、
Accelerated Bridge CNIの場合、SR-IOV Switchdevモードを使用します。
これに伴い、Linux Bridgeを使用することが可能になります。

Accelerated Bridge CNIの詳細は以下のURLを参照してください。
GitHub - k8snetworkplumbingwg/accelerated-bridge-cni

以下は関連記事の一覧となります。

vDPA の設定方法 vhost_vdpa + VM編 - Metonymical Deflection
vDPA の設定方法 virtio_vdpa + VM編 - Metonymical Deflection
vDPA の設定方法 vhost_vdpa + kubernetes編 - Metonymical Deflection
vDPA の設定方法 番外編 - Metonymical Deflection
Scalable Function の設定方法 vdpa + VM編 - Metonymical Deflection

1.構成

1-1.環境
1.ControlPlane
VMWare              : VMware(R) Workstation 15 Pro 15.5.1 build-15018445 

2.Worker
IA server                        : ProLiant DL360p Gen8 or DL360 Gen9
System ROM                       : P71 01/22/2018
NIC                              : Mellanox ConnectX-6 Dx (MCX623106AS-CDAT)
Mellanox OFED                    : v5.3-1.0.0.1

3.ControlPlane&Worker common
OS                               : CentOS8.3(2011)
Kernel(ControlPlane)             : 4.18.0-240.el8.x86_64 
Kernel(Worker)                   : 5.12.12-1.el8.elrepo.x86_64
Installed Environment Groups     : 
  @^graphical-server-environment
  @container-management
  @development
  @virtualization-client
  @virtualization-hypervisor
  @virtualization-tools 
Kubernetes                       : 1.21.2
Docker-CE                        : 20.10.7
flannel                          : latest
Multus                           : latest
sriov-network-device-plugin      : latest
accelerated-bridge-cni           : latest
1-2.全体の流れ
  1. 事前準備
  2. Kernelアップデート
  3. k8s Cluster & flannelの構築
  4. vDPA & Accelerated Bridge CNI関連のビルドとデプロイ
  5. Linux Bridge設定 & Podのデプロイ
  6. 動作確認

1-3までは比較的多くのドキュメントが存在しますので、重要な箇所以外は割愛します。
4-6が前回記事と異なるポイントになります。

1-3.全体構成

DAC(Direct Attached Cable)を使用してループ接続します。 *2
fig.1
f:id:metonymical:20210621235434j:plain
fig.1は簡易的に記載しており、内部アーキテクチャは省略しています。このため、実際は以下の構成をイメージして頂ければと思います。

fig.2
f:id:metonymical:20210621220154j:plain

Red Hatgithubより引用
github.com

2.事前準備

特に記載しませんが、SELinux無効化、FW無効化、NTP時刻同期設定は事前に行っています。

2-1.swapとHostsファイル設定 : CP(ControlPlane)&Worker
swap無効化
vi /etc/fstab

#/dev/mapper/cl-swap     swap                    swap    defaults        0 0

hostsファイル設定
vi /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 c80g105.md.jp c80g105
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.11.151 c83g151 c83g151.md.jp
192.168.11.152 c83g152 c83g152.md.jp
2-2.HugePageとIOMMUの有効化 : Worker
sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ default_hugepagesz=1G hugepagesz=1G hugepages=16\"/g" /etc/default/grub
sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ intel_iommu=on iommu=pt pci=realloc\"/g" /etc/default/grub
grub2-mkconfig -o /etc/grub2.cfg

次にHugePageのマウント設定を実施しておきます。次回OS起動時に自動マウントされます。

vi /etc/fstab

nodev  /dev/hugepages hugetlbfs pagesize=1GB    0 0
2-3.SR-IOV VFの設定 : Worker

SR-IOV VFの設定を実施します。VF数を増やしても問題ありませんが、ここでは説明をシンプルにするため、VF数「1」としています。*3

vi /etc/rc.local

echo 1 > /sys/class/net/ens2f0/device/sriov_numvfs
echo 1 > /sys/class/net/ens2f1/device/sriov_numvfs
sleep 1
ip link set ens2f0 vf 0 mac 00:11:22:33:44:00
ip link set ens2f1 vf 0 mac 00:11:22:33:44:10
sleep 1
exit 0

chmod +x /etc/rc.d/rc.local
2-4.Mellanoxドライバ(OFED)のインストール : Worker

isoファイルはMellanoxのサイトからDLしてください。Mellanox Download Site
DLしたisoファイルは、/root/tmp/に保存してください。
以下のコマンドにて、Mellanoxドライバをインストールします。

dnf -y install tcl tk unbound && \
mount -t iso9660 -o loop /root/tmp/MLNX_OFED_LINUX-5.3-1.0.0.1-rhel8.3-x86_64.iso /mnt && \
/mnt/mlnxofedinstall --upstream-libs --dpdk --ovs-dpdk --with-mft --with-mstflint

インストールが完了したら、再起動してください。

reboot

再起動が完了したら、HugePageを確認します。

cat /proc/meminfo | grep Huge
grep hugetlbfs /proc/mounts

[root@c83g152 ~]# cat /proc/meminfo | grep Huge
AnonHugePages:    452608 kB
ShmemHugePages:        0 kB
FileHugePages:         0 kB
HugePages_Total:      16
HugePages_Free:       16
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:    1048576 kB
Hugetlb:        16777216 kB

[root@c83g152 ~]# grep hugetlbfs /proc/mounts
nodev /dev/hugepages hugetlbfs rw,relatime,pagesize=1024M 0 0

3.Kernelアップデート : Worker

2021年6月21日現在、vDPA関連モジュールは高い頻度で更新されていますので、最新のKernelをインストールします。

3-2.Kernelのインストール
dnf list installed | grep kernel
dnf -y --enablerepo=elrepo-kernel install kernel-ml kernel-ml-devel
dnf list installed | grep kernel
reboot

現在インストール済みのKernelを確認
kernel-ml, kernel-ml-develをインストール*4
インストール済みKernelの確認
再起動

3-3.Kernel headersなどのインストール
uname -r
dnf -y swap --enablerepo=elrepo-kernel kernel-headers -- kernel-ml-headers && \
dnf -y remove kernel-tools kernel-tools-libs && \
dnf -y --enablerepo=elrepo-kernel install kernel-ml-tools kernel-ml-tools-libs
dnf list installed | grep kernel

現在起動中のKernel Version確認
kernel-headersのインストール
既存のkernel-tools kernel-tools-libsの削除
kernel-tools kernel-tools-libsのインストール
インストール済みKernelの確認

以下の出力になっていればOKです。

[root@c83g152 ~]# dnf list installed | grep kernel
kernel.x86_64                                      4.18.0-240.el8                                @anaconda
kernel-core.x86_64                                 4.18.0-240.el8                                @anaconda
kernel-devel.x86_64                                4.18.0-240.el8                                @anaconda
kernel-ml.x86_64                                   5.12.12-1.el8.elrepo                          @elrepo-kernel
kernel-ml-core.x86_64                              5.12.12-1.el8.elrepo                          @elrepo-kernel
kernel-ml-devel.x86_64                             5.12.12-1.el8.elrepo                          @elrepo-kernel
kernel-ml-headers.x86_64                           5.12.12-1.el8.elrepo                          @elrepo-kernel
kernel-ml-modules.x86_64                           5.12.12-1.el8.elrepo                          @elrepo-kernel
kernel-ml-tools.x86_64                             5.12.12-1.el8.elrepo                          @elrepo-kernel
kernel-ml-tools-libs.x86_64                        5.12.12-1.el8.elrepo                          @elrepo-kernel
kernel-modules.x86_64                              4.18.0-240.el8                                @anaconda
kmod-kernel-mft-mlnx.x86_64                        4.16.1-1.rhel8u3                              @System
kmod-mlnx-ofa_kernel.x86_64                        5.3-OFED.5.3.1.0.0.1.rhel8u3                  @System
mlnx-ofa_kernel.x86_64                             5.3-OFED.5.3.1.0.0.1.rhel8u3                  @System
mlnx-ofa_kernel-devel.x86_64                       5.3-OFED.5.3.1.0.0.1.rhel8u3                  @System

4.k8s Cluster & flannelの構築

4-1.Dockerのインストール : CP&Worker
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo && \
dnf -y install --allowerasing  docker-ce docker-ce-cli containerd.io && \
systemctl start docker && systemctl enable docker
4-3.k8sのインストール : CP&Worker
CP
dnf -y install kubeadm kubectl

Worker
dnf -y install kubeadm

CP&Worker
systemctl start kubelet.service && \
systemctl enable kubelet.service
4-4.Dockerの設定 : CP&Worker
cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}
EOF

mkdir -p /etc/systemd/system/docker.service.d

systemctl daemon-reload && \
systemctl restart docker
4-5.k8sClusterの構築 : CP
kubeadm init --apiserver-advertise-address=192.168.11.151 --pod-network-cidr=10.244.0.0/16

<出力例>
最後に以下の出力が表示されますので、赤文字部分をコピーしておいてください。
WorkerがCPへJoinする際に使用します。

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.11.151:6443 --token 0gfh5j.vgu76alcycb2tc2e \
    --discovery-token-ca-cert-hash sha256:edcb1a3856838586a6ea7c99200daafa4fbb639e822838f4df81ce09d2faaac3 
4-6.k8s Cluster構築後の設定 : CP
コンフィグファイルのコピー
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

コマンド補完設定
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc
4-7.flannelのインストール : CP
cd /usr/src && \
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml && \
kubectl apply -f kube-flannel.yml

kubectl get nodes

<出力例>
以下のようにReadyとなるまで待ってください。

[root@c83g151 ~]# kubectl get nodes
NAME            STATUS     ROLES                  AGE   VERSION
c83g151.md.jp   Ready      control-plane,master   44s   v1.21.2
4-8.WorkerのJoin : Worker
kubeadm join 192.168.11.151:6443 --token 0gfh5j.vgu76alcycb2tc2e \
    --discovery-token-ca-cert-hash sha256:edcb1a3856838586a6ea7c99200daafa4fbb639e822838f4df81ce09d2faaac3

<出力例>
以下のようにWorkerもReadyとなるまで待ってください。

[root@c83g151 ~]# kubectl get nodes
NAME            STATUS   ROLES                  AGE    VERSION
c83g151.md.jp   Ready    control-plane,master   5m2s   v1.21.2
c83g152.md.jp   Ready                           44s    v1.21.2
4-9.SR-IOV switchdev modeへ変更 : Worker
4-9-1.現在の動作モードを確認
lshw -businfo -c network
devlink dev eswitch show pci/0000:07:00.0
devlink dev eswitch show pci/0000:07:00.1

PCIバイスのbsf(bus, slot, function)番号を確認
07:00.0(ens2f0)のステータス確認
07:00.1(ens2f1)のステータス確認

以下のように出力されます。

[root@c83g152 ~]# lshw -businfo -c network
Bus info          Device      Class          Description
========================================================
pci@0000:04:00.0  ens1f0      network        82599ES 10-Gigabit SFI/SFP+ Network Connection
pci@0000:04:00.1  ens1f1      network        82599ES 10-Gigabit SFI/SFP+ Network Connection
pci@0000:03:00.0  eno1        network        NetXtreme BCM5719 Gigabit Ethernet PCIe
pci@0000:03:00.1  eno2        network        NetXtreme BCM5719 Gigabit Ethernet PCIe
pci@0000:03:00.2  eno3        network        NetXtreme BCM5719 Gigabit Ethernet PCIe
pci@0000:03:00.3  eno4        network        NetXtreme BCM5719 Gigabit Ethernet PCIe
pci@0000:07:00.0  ens2f0      network        MT2892 Family [ConnectX-6 Dx]
pci@0000:07:00.1  ens2f1      network        MT2892 Family [ConnectX-6 Dx]
pci@0000:07:00.2  ens2f0v0    network        ConnectX Family mlx5Gen Virtual Function
pci@0000:07:01.2  ens2f1v0    network        ConnectX Family mlx5Gen Virtual Function

[root@c83g152 ~]# devlink dev eswitch show pci/0000:07:00.0
pci/0000:07:00.0: mode legacy inline-mode none encap disable

[root@c83g152 ~]# devlink dev eswitch show pci/0000:07:00.1
pci/0000:07:00.1: mode legacy inline-mode none encap disable
4-9-2.動作モードの変更

bsf番号が微妙に異なっている点に注意してください。*5

echo 0000:07:00.2 > /sys/bus/pci/drivers/mlx5_core/unbind && \
echo 0000:07:01.2 > /sys/bus/pci/drivers/mlx5_core/unbind && \
devlink dev eswitch set pci/0000:07:00.0 mode switchdev && \
devlink dev eswitch set pci/0000:07:00.1 mode switchdev && \
echo 0000:07:00.2 > /sys/bus/pci/drivers/mlx5_core/bind && \
echo 0000:07:01.2 > /sys/bus/pci/drivers/mlx5_core/bind

VFのmlx5_coreドライバをアンバインドします。

07:00.2 ens2f0v0
07:01.2 ens2f1v0

PFの動作モードをswitchdevに変更します。

07:00.0 ens2f0
07:00.1 ens2f1

VFのmlx5_coreドライバを再バインドします。

07:00.2 ens2f0v0
07:01.2 ens2f1v0
4-9-3.変更後の動作モードを確認
devlink dev eswitch show pci/0000:07:00.0
devlink dev eswitch show pci/0000:07:00.1

switchdev モードに変更されました。

[root@c83g152 ~]# devlink dev eswitch show pci/0000:07:00.0
pci/0000:07:00.0: mode switchdev inline-mode none encap enable

[root@c83g152 ~]# devlink dev eswitch show pci/0000:07:00.1
pci/0000:07:00.1: mode switchdev inline-mode none encap enable

VF Representerが追加されています。

[root@c83g152 ~]# lshw -businfo -c network                                                                                   Bus info          Device      Class          Description
========================================================
pci@0000:04:00.0  ens1f0      network        82599ES 10-Gigabit SFI/SFP+ Network Connection
pci@0000:04:00.1  ens1f1      network        82599ES 10-Gigabit SFI/SFP+ Network Connection
pci@0000:03:00.0  eno1        network        NetXtreme BCM5719 Gigabit Ethernet PCIe
pci@0000:03:00.1  eno2        network        NetXtreme BCM5719 Gigabit Ethernet PCIe
pci@0000:03:00.2  eno3        network        NetXtreme BCM5719 Gigabit Ethernet PCIe
pci@0000:03:00.3  eno4        network        NetXtreme BCM5719 Gigabit Ethernet PCIe
pci@0000:07:00.0  ens2f0      network        MT2892 Family [ConnectX-6 Dx]
pci@0000:07:00.1  ens2f1      network        MT2892 Family [ConnectX-6 Dx]
pci@0000:07:00.2  ens2f0v0    network        ConnectX Family mlx5Gen Virtual Function
pci@0000:07:01.2  ens2f1v0    network        ConnectX Family mlx5Gen Virtual Function
pci@0000:07:00.0  ens2f0_0    network        Ethernet interface
pci@0000:07:00.1  ens2f1_0    network        Ethernet interface

さらに、NICのHW offload機能が有効化されていることも確認します。

ethtool -k ens2f0 |grep tc
ethtool -k ens2f1 |grep tc

[root@c83g152 ~]# ethtool -k ens2f0 |grep tc
tcp-segmentation-offload: on
        tx-tcp-segmentation: on
        tx-tcp-ecn-segmentation: off [fixed]
        tx-tcp-mangleid-segmentation: off
        tx-tcp6-segmentation: on
hw-tc-offload: on

[root@c83g152 ~]# ethtool -k ens2f1 |grep tc
tcp-segmentation-offload: on
        tx-tcp-segmentation: on
        tx-tcp-ecn-segmentation: off [fixed]
        tx-tcp-mangleid-segmentation: off
        tx-tcp6-segmentation: on
hw-tc-offload: on
4-10.vhost_vdpaモジュールの有効化 : Worker

5.vDPA & Accelerated Bridge CNI関連のビルドとデプロイにて、sriov-device-pluginのビルドやデプロイを実施します。
その際、vhost_vdpaモジュールが有効化されていないと、Workerリソースとして認識されないため、事前に有効化しておきます。

modprobe vhost_vdpa
lsmod |grep vd
ls -Fal /dev
ls -Fal /sys/bus/vdpa/drivers/vhost_vdpa

[root@c83g152 ~]# lsmod |grep vd
vhost_vdpa             24576  0
vhost                  57344  1 vhost_vdpa
mlx5_vdpa              45056  0
vhost_iotlb            16384  3 vhost_vdpa,vhost,mlx5_vdpa
vdpa                   16384  2 vhost_vdpa,mlx5_vdpa
irqbypass              16384  2 vhost_vdpa,kvm
mlx5_core            1216512  2 mlx5_vdpa,mlx5_ib

[root@c83g152 ~]# ls -Fal /dev
total 0
drwxr-xr-x  22 root root          3660 Apr  8 00:02 ./
dr-xr-xr-x. 17 root root           244 Apr  7 20:30 ../
crw-r--r--   1 root root       10, 235 Apr  7 23:28 autofs
drwxr-xr-x   2 root root           160 Apr  7 23:28 block/
drwxr-xr-x   2 root root           100 Apr  7 23:28 bsg/
============ s n i p ============
drwxr-xr-x   2 root root            60 Apr  7 23:28 vfio/
crw-------   1 root root       10, 127 Apr  7 23:28 vga_arbiter
crw-------   1 root root       10, 137 Apr  7 23:28 vhci
crw-------   1 root root       10, 238 Apr  7 23:28 vhost-net
crw-------   1 root root      240,   0 Apr  8 00:06 vhost-vdpa-0
crw-------   1 root root      240,   1 Apr  8 00:06 vhost-vdpa-1
crw-------   1 root root       10, 241 Apr  7 23:28 vhost-vsock

[root@c83g152 ~]# ls -Fal /sys/bus/vdpa/drivers/vhost_vdpa
total 0
drwxr-xr-x 2 root root    0 Apr  8 00:06 ./
drwxr-xr-x 3 root root    0 Apr  7 23:49 ../
--w------- 1 root root 4096 Apr  8 00:07 bind
lrwxrwxrwx 1 root root    0 Apr  8 00:07 module -> ../../../../module/vhost_vdpa/
--w------- 1 root root 4096 Apr  8 00:06 uevent
--w------- 1 root root 4096 Apr  8 00:07 unbind
lrwxrwxrwx 1 root root    0 Apr  8 00:07 vdpa0 -> ../../../../devices/pci0000:00/0000:00:03.0/0000:07:00.2/vdpa0/
lrwxrwxrwx 1 root root    0 Apr  8 00:07 vdpa1 -> ../../../../devices/pci0000:00/0000:00:03.0/0000:07:01.2/vdpa1/

上記の出力結果より、以下のことが確認できます。

  • /dev/vhost-vdpa-0と/dev/vhost-vdpa-1がvhost_vdpaデバイスとして認識されている
  • 0000:07:00.2/vdpa0と0000:07:01.2/vdpa1がvhost_vdpaドライバで制御されている

また、OS起動時に有効化されるように設定しておきます。*6
青文字箇所を追記。

vi /etc/rc.local

echo 1 > /sys/class/net/ens2f0/device/sriov_numvfs
echo 1 > /sys/class/net/ens2f1/device/sriov_numvfs
sleep 1
ip link set ens2f0 vf 0 mac 00:11:22:33:44:00
ip link set ens2f1 vf 0 mac 00:11:22:33:44:10
sleep 1
echo 0000:07:00.2 > /sys/bus/pci/drivers/mlx5_core/unbind && \
echo 0000:07:01.2 > /sys/bus/pci/drivers/mlx5_core/unbind && \
devlink dev eswitch set pci/0000:07:00.0 mode switchdev && \
devlink dev eswitch set pci/0000:07:00.1 mode switchdev && \
echo 0000:07:00.2 > /sys/bus/pci/drivers/mlx5_core/bind && \
echo 0000:07:01.2 > /sys/bus/pci/drivers/mlx5_core/bind
sleep 1
modprobe vhost_vdpa
sleep 1
exit 0

ここまでの準備が整ったらCP&Workerをもう一度再起動してください。

5.vDPA & Accelerated Bridge CNI関連のビルドとデプロイ

5-1.Golangのインストール : CP
dnf -y install epel-release golang
5-2.Docker imageのビルド : CP

ここでは、以下2つのimageをビルドします。*7

  • multus
  • sriov-dp
cd /usr/src && \
git clone https://github.com/redhat-nfvpe/vdpa-deployment.git

cd /usr/src/vdpa-deployment && \
make multus && \
make sriov-dp
5-3.Docker imageのコピー : CP

ビルドしたDocker imageをWorkerにコピーします。

/usr/src/vdpa-deployment/scripts/load-image.sh nfvpe/sriov-device-plugin root@192.168.11.152 && \
/usr/src/vdpa-deployment/scripts/load-image.sh nfvpe/multus root@192.168.11.152

<出力例>

[root@c83g151 vdpa-deployment]# /usr/src/vdpa-deployment/scripts/load-image.sh nfvpe/sriov-device-plugin root@192.168.11.152 && \
> /usr/src/vdpa-deployment/scripts/load-image.sh nfvpe/multus root@192.168.11.152
+ IMAGE=nfvpe/sriov-device-plugin
+ NODE=root@192.168.11.152
++ mktemp -d
+ temp=/tmp/tmp.Lh8BaezUtC
+ dest=/tmp/tmp.Lh8BaezUtC/image.tar
+ save nfvpe/sriov-device-plugin /tmp/tmp.Lh8BaezUtC/image.tar
+ local image=nfvpe/sriov-device-plugin
+ local dest=/tmp/tmp.Lh8BaezUtC/image.tar
+ echo 'Saving nfvpe/sriov-device-plugin into /tmp/tmp.Lh8BaezUtC/image.tar'
Saving nfvpe/sriov-device-plugin into /tmp/tmp.Lh8BaezUtC/image.tar
+ docker save -o /tmp/tmp.Lh8BaezUtC/image.tar nfvpe/sriov-device-plugin
============ s n i p ============
+ echo 'Loading /tmp/tmp.Z6emF9eiAs/image.tar into root@192.168.11.152'
Loading /tmp/tmp.Z6emF9eiAs/image.tar into root@192.168.11.152
+ ssh root@192.168.11.152 'docker load'
Loaded image: nfvpe/multus:latest
+ rm -r /tmp/tmp.Z6emF9eiAs

Docker Imageの確認 : CP&Worker

[root@c83g151 vdpa-deployment]# docker images
REPOSITORY                           TAG          IMAGE ID       CREATED        SIZE
nfvpe/sriov-device-plugin            latest       4bbc4ec2506d   29 hours ago   42.7MB
<none>                               <none>       9d6fcc3268de   29 hours ago   1.26GB
nfvpe/multus                         latest       5b78ae4af974   29 hours ago   331MB
<none>                               <none>       d4742876ce8d   29 hours ago   1.35GB
k8s.gcr.io/kube-apiserver            v1.21.2      106ff58d4308   6 days ago     126MB
k8s.gcr.io/kube-controller-manager   v1.21.2      ae24db9aa2cc   6 days ago     120MB
k8s.gcr.io/kube-scheduler            v1.21.2      f917b8c8f55b   6 days ago     50.6MB
k8s.gcr.io/kube-proxy                v1.21.2      a6ebd1c1ad98   6 days ago     131MB
golang                               alpine3.12   baed0e68a17f   11 days ago    301MB
mellanox/accelerated-bridge-cni      v0.1.0       9adde4aff112   2 weeks ago    11MB
quay.io/coreos/flannel               v0.14.0      8522d622299c   5 weeks ago    67.9MB
alpine                               3.12         13621d1b12d4   2 months ago   5.58MB
k8s.gcr.io/pause                     3.4.1        0f8457a4c2ec   5 months ago   683kB
centos                               centos7      8652b9f0cb4c   7 months ago   204MB
k8s.gcr.io/coredns/coredns           v1.8.0       296a6d5035e2   8 months ago   42.5MB
k8s.gcr.io/etcd                      3.4.13-0     0369cf4303ff   9 months ago   253MB
5-4.Accelerated Bridge CNIのビルド : CP
cd /usr/src && \
git clone https://github.com/k8snetworkplumbingwg/accelerated-bridge-cni.git && \
cd accelerated-bridge-cni/ && \
make

<出力例>

[root@c83g151 vdpa-deployment]# cd /usr/src && \
> git clone https://github.com/k8snetworkplumbingwg/accelerated-bridge-cni.git && \
> cd accelerated-bridge-cni/ && \
> make
Cloning into 'accelerated-bridge-cni'...
remote: Enumerating objects: 3426, done.
============ s n i p ============
github.com/k8snetworkplumbingwg/accelerated-bridge-cni/cmd/accelerated-bridge
Building accelerated-bridge...
Done!
## Build executable file
building goveralls...
running coverage tests...
?       github.com/k8snetworkplumbingwg/accelerated-bridge-cni/cmd/accelerated-bridge   [no test files]
ok      github.com/k8snetworkplumbingwg/accelerated-bridge-cni/pkg/cache        0.006s  coverage: 72.2% of statements
ok      github.com/k8snetworkplumbingwg/accelerated-bridge-cni/pkg/config       0.006s  coverage: 90.9% of statements
ok      github.com/k8snetworkplumbingwg/accelerated-bridge-cni/pkg/manager      0.010s  coverage: 53.7% of statements
?       github.com/k8snetworkplumbingwg/accelerated-bridge-cni/pkg/manager/mocks        [no test files]
?       github.com/k8snetworkplumbingwg/accelerated-bridge-cni/pkg/plugin       [no test files]
?       github.com/k8snetworkplumbingwg/accelerated-bridge-cni/pkg/types        [no test files]
ok      github.com/k8snetworkplumbingwg/accelerated-bridge-cni/pkg/utils        0.006s  coverage: 64.3% of statements
5-5.yamlファイルのデプロイ : CP

以下4つのファイルをデプロイします。

  1. /usr/src/vdpa-deployment/deployment/multus-daemonset.yaml
  2. /usr/src/vdpa-deployment/deployment/sriovdp-vdpa-daemonset.yaml
  3. /usr/src/vdpa-deployment/deployment/configMap-vdpa.yaml
  4. /usr/src/accelerated-bridge-cni/images/k8s-v1.16/accelerated-bridge-cni-daemonset.yaml
kubectl apply -f /usr/src/vdpa-deployment/deployment/multus-daemonset.yaml && \
kubectl apply -f /usr/src/vdpa-deployment/deployment/sriovdp-vdpa-daemonset.yaml && \
kubectl apply -f /usr/src/vdpa-deployment/deployment/configMap-vdpa.yaml && \
kubectl apply -f /usr/src/accelerated-bridge-cni/images/k8s-v1.16/accelerated-bridge-cni-daemonset.yaml

<出力例>

[root@c83g151 accelerated-bridge-cni]# kubectl apply -f /usr/src/vdpa-deployment/deployment/multus-daemonset.yaml && \
> kubectl apply -f /usr/src/vdpa-deployment/deployment/sriovdp-vdpa-daemonset.yaml && \
> kubectl apply -f /usr/src/vdpa-deployment/deployment/configMap-vdpa.yaml && \
> kubectl apply -f /usr/src/accelerated-bridge-cni/images/k8s-v1.16/accelerated-bridge-cni-daemonset.yaml
customresourcedefinition.apiextensions.k8s.io/network-attachment-definitions.k8s.cni.cncf.io created
clusterrole.rbac.authorization.k8s.io/multus created
clusterrolebinding.rbac.authorization.k8s.io/multus created
serviceaccount/multus created
configmap/multus-cni-config created
daemonset.apps/kube-multus-ds-amd64 created
serviceaccount/sriov-device-plugin created
daemonset.apps/kube-sriov-device-plugin-amd64 created
configmap/sriovdp-config created
daemonset.apps/kube-accelerated-bridge-cni-ds-amd64 created
5-6.DaemonSet & ConfigMap & Podの確認 : CP

5-5.でデプロイしたDaemonSetとConfigMapを確認します。

kubectl -n kube-system get ds
kubectl -n kube-system get cm
kubectl -n kube-system get pod

<出力例>

[root@c83g151 accelerated-bridge-cni]# kubectl -n kube-system get ds
NAME                                   DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                   AGE
kube-accelerated-bridge-cni-ds-amd64   2         2         2       2            2           beta.kubernetes.io/arch=amd64   12s
kube-flannel-ds                        2         2         2       2            2                                     11m
kube-multus-ds-amd64                   2         2         2       2            2           kubernetes.io/arch=amd64        13s
kube-proxy                             2         2         2       2            2           kubernetes.io/os=linux          13m
kube-sriov-device-plugin-amd64         2         2         2       2            2           beta.kubernetes.io/arch=amd64   13s
[root@c83g151 accelerated-bridge-cni]# kubectl -n kube-system get cm
NAME                                 DATA   AGE
coredns                              1      13m
extension-apiserver-authentication   6      13m
kube-flannel-cfg                     2      11m
kube-proxy                           2      13m
kube-root-ca.crt                     1      13m
kubeadm-config                       2      13m
kubelet-config-1.21                  1      13m
multus-cni-config                    1      13s
sriovdp-config                       1      12s
[root@c83g151 accelerated-bridge-cni]# kubectl -n kube-system get pod
NAME                                         READY   STATUS    RESTARTS   AGE
coredns-558bd4d5db-76v4h                     1/1     Running   0          13m
coredns-558bd4d5db-qrn74                     1/1     Running   0          13m
etcd-c83g151.md.jp                           1/1     Running   0          13m
kube-accelerated-bridge-cni-ds-amd64-2dvtm   1/1     Running   0          14s
kube-accelerated-bridge-cni-ds-amd64-mxs92   1/1     Running   0          14s
kube-apiserver-c83g151.md.jp                 1/1     Running   0          13m
kube-controller-manager-c83g151.md.jp        1/1     Running   0          13m
kube-flannel-ds-2n457                        1/1     Running   0          11m
kube-flannel-ds-h9c9r                        1/1     Running   0          11m
kube-multus-ds-amd64-x5cdn                   1/1     Running   0          15s
kube-multus-ds-amd64-zt5pj                   1/1     Running   0          15s
kube-proxy-2585z                             1/1     Running   0          13m
kube-proxy-znl8n                             1/1     Running   0          11m
kube-scheduler-c83g151.md.jp                 1/1     Running   0          13m
kube-sriov-device-plugin-amd64-6cccp         1/1     Running   0          15s
kube-sriov-device-plugin-amd64-k8ktz         1/1     Running   0          15s
5-7.ConfigMapの詳細確認 : CP

6.Linux Bridge設定 & Podのデプロイにおいて、"resourceName": "vdpa_mlx_vhost"が、Network Attachment DefinitionやPodの設定に関連してくるため、事前に確認しておきます。

cat /usr/src/vdpa-deployment/deployment/configMap-vdpa.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: sriovdp-config
  namespace: kube-system
data:
  config.json: |
    {
        "resourceList": [{
                "resourceName": "vdpa_ifcvf_vhost",
                "selectors": {
                    "vendors": ["1af4"],
                    "devices": ["1041"],
                    "drivers": ["ifcvf"],
                    "vdpaType": "vhost"
                }
            },
            {
                "resourceName": "vdpa_mlx_vhost",
                "selectors": {
                    "vendors": ["15b3"],
                    "devices": ["101e"],
                    "drivers": ["mlx5_core"],
                    "vdpaType": "vhost"
                }
            },
            {
                "resourceName": "vdpa_mlx_virtio",
                "selectors": {
                    "vendors": ["15b3"],
                    "devices": ["101e"],
                    "drivers": ["mlx5_core"],
                    "vdpaType": "virtio"
                }
            }
        ]
    }

<補足>

resourceName 任意の名前となります。6-1.NetworkAttachmentDefinitionの設定で、この名前を明示的に指定します。
vendors PCI Device IDのベンダ識別子となります。15b3はMellanox製品であることを示しています。*8
devices PCI Device IDのデバイス識別子となります。101eはConnectX-6 DxのVFであることを示しています。
drivers mlx5_coreドライバを指定します。
vdpaType vhostを指定しています。このオプションが通常のSR-IOV Device plug-inからvDPA用として拡張されているポイントになります。

PCI Device IDは以下のコマンドで確認できます。

[root@c83g152 ~]# lspci -nn |grep Mellanox
07:00.0 Ethernet controller [0200]: Mellanox Technologies MT2892 Family [ConnectX-6 Dx] [15b3:101d]
07:00.1 Ethernet controller [0200]: Mellanox Technologies MT2892 Family [ConnectX-6 Dx] [15b3:101d]
07:00.2 Ethernet controller [0200]: Mellanox Technologies ConnectX Family mlx5Gen Virtual Function [15b3:101e]
07:01.2 Ethernet controller [0200]: Mellanox Technologies ConnectX Family mlx5Gen Virtual Function [15b3:101e]
5-8.Workerリソースの確認 : CP

vdpa_mlx_vhostがWorkerリソースとして認識されていることを確認します。

kubectl get node c83g152.md.jp -o json | jq '.status.allocatable'

出力例

[root@c83g151 vdpa-deployment]# kubectl get node c83g152.md.jp -o json | jq '.status.allocatable'
{
  "cpu": "16",
  "ephemeral-storage": "127203802926",
  "hugepages-1Gi": "16Gi",
  "hugepages-2Mi": "0",
  "intel.com/vdpa_mlx_vhost": "2",
  "memory": "148123456Ki",
  "pods": "110"
}

"2"は、認識されたVFの数となります。

<補足>
この値が"0"、またはこの行(intel.com/vdpa_mlx_vhost)が表示されないときは、sriov-device-pluginのPodを一度削除します。
sriov-device-pluginは、DaemonSetとしてデプロイされているため、Podを削除しても自動的に再作成されます。
これにより、sriov-device-pluginがvdpa_mlx_vhostの再登録を試行します。

[root@c83g151 ~]# kubectl -n kube-system get pod -o wide |grep 152
kube-accelerated-bridge-cni-ds-amd64-2dvtm   1/1     Running   2          28h   192.168.11.152   c83g152.md.jp              
kube-flannel-ds-h9c9r                        1/1     Running   2          29h   192.168.11.152   c83g152.md.jp              
kube-multus-ds-amd64-x5cdn                   1/1     Running   2          28h   192.168.11.152   c83g152.md.jp              
kube-proxy-znl8n                             1/1     Running   2          29h   192.168.11.152   c83g152.md.jp              
kube-sriov-device-plugin-amd64-6cccp         1/1     Running   2          28h   192.168.11.152   c83g152.md.jp              

[root@c83g151 ~]# kubectl -n kube-system delete pod kube-sriov-device-plugin-amd64-6cccp
pod "kube-sriov-device-plugin-amd64-6cccp" deleted

[root@c83g151 ~]# kubectl -n kube-system get pod -o wide |grep 152
kube-accelerated-bridge-cni-ds-amd64-2dvtm   1/1     Running   2          28h   192.168.11.152   c83g152.md.jp              
kube-flannel-ds-h9c9r                        1/1     Running   2          29h   192.168.11.152   c83g152.md.jp              
kube-multus-ds-amd64-x5cdn                   1/1     Running   2          28h   192.168.11.152   c83g152.md.jp              
kube-proxy-znl8n                             1/1     Running   2          29h   192.168.11.152   c83g152.md.jp              
kube-sriov-device-plugin-amd64-c7j84         1/1     Running   0          3s    192.168.11.152   c83g152.md.jp              

再度、Workerのリソースを確認します。

kubectl get node c83g152.md.jp -o json | jq '.status.allocatable'

それでも認識されないときは、4-10.vhost_vdpaモジュールの有効化 : Worker を参照してください。
ポイントは、以下2点です。

  1. /dev/vhost-vdpa-0と/dev/vhost-vdpa-1がvhost_vdpaデバイスとして認識されていること
  2. 0000:07:00.2/vdpa0と0000:07:01.2/vdpa1がvhost_vdpaドライバで制御されていること

上記2つの条件を満たさない限り、vdpa_mlx_vhostがWorkerリソースとして認識されることはありません。

6.Linux Bridge設定 & Podのデプロイ

6-1.NetworkAttachmentDefinitionの設定 : CP
vi 961nA-vdpa30.yaml

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: vdpa-mlx-vhost-net30
  annotations:
    k8s.v1.cni.cncf.io/resourceName: intel.com/vdpa_mlx_vhost
spec:
  config: '{
  "type": "accelerated-bridge",
  "cniVersion": "0.3.1",
  "name": "sriov-vdpa30",
  "bridge": "br30ens2f0",
  "trust": "on",
  "spoofchk": "off",
  "ipam": {
    "type": "host-local",
    "subnet": "192.168.30.0/24",
    "rangeStart": "192.168.30.64",
    "rangeEnd": "192.168.30.127"
  }
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: vdpa-mlx-vhost-net31
  annotations:
    k8s.v1.cni.cncf.io/resourceName: intel.com/vdpa_mlx_vhost
spec:
  config: '{
  "type": "accelerated-bridge",
  "cniVersion": "0.3.1",
  "name": "sriov-vdpa31",
  "bridge": "br31ens2f1",
  "trust": "on",
  "spoofchk": "off",
  "ipam": {
    "type": "host-local",
    "subnet": "192.168.30.0/24",
    "rangeStart": "192.168.30.128",
    "rangeEnd": "192.168.30.191"
  }
}'

kubectl apply -f 961nA-vdpa30.yaml
kubectl get network-attachment-definitions.k8s.cni.cncf.io

出力例

[root@c83g151 vdpa-deployment]# kubectl get network-attachment-definitions.k8s.cni.cncf.io
NAME                   AGE
vdpa-mlx-vhost-net30   4h24m
vdpa-mlx-vhost-net31   4h24m

<補足>

name Podのannotationsでvdpa-mlx-vhost-net30/31を設定します。
k8s.v1.cni.cncf.io/resourceName 5-7で確認した名前を設定しています。加えて、Podのannotationsでも設定します。
type 必須の設定です。Accelerated Bridge CNIを使用するため、明示的に"accelerated-bridge"と設定する必要があります。*9
bridge 今回の構成では必須の設定です。Linux Bridgeの名前を設定することにより、PodがどのBridgeに接続するかが決定されます。*10
rangeStart & rangeEnd 今回の構成では、アドレスレンジが重複しないように、vdpa-mlx-vhost-net30とvdpa-mlx-vhost-net31で別けています。

詳細は以下のURLを参照してください。
accelerated-bridge-cni/configuration-reference.md at master · k8snetworkplumbingwg/accelerated-bridge-cni · GitHub
Accelerated Bridge CNIの場合、vlanとtrunkの設定方法がSR-IOV CNIと異なっている点に注意が必要です。
これはLinux Bridgeを使用するため、VLANタグ付けはLinux Bridge側に任せているのではないかと想定しています。

6-2.Linux Bridgeの設定 : Worker

fig.1の(1)-(7)の順番で設定します。
fig.1
f:id:metonymical:20210621235434j:plain

(1) 4-10で既に設定済みです。modprobe vhost_vdpaコマンドを実行します。
(2)(3) 1つ目のBridgeを作成します。PF ens2f0をアップリンクとして設定します。
(4)(5) 2つ目のBridgeを作成します。PF ens2f1をアップリンクとして設定します。
(6) Pod作成時に自動的に設定されます。Accelerated Bridge CNIがVF rep ens2f0_0とens2f1_0をダウンリンクとして設定します。
(7) 次項6-3でPodを作成します。
Worker
(1)
modprobe vhost_vdpa

(2)
nmcli connection add type bridge autoconnect yes con-name br30ens2f0 ifname br30ens2f0
nmcli connection modify br30ens2f0 bridge.stp no
nmcli connection modify br30ens2f0 ipv4.method disabled ipv6.method ignore
nmcli connection up br30ens2f0
(3)
nmcli connection add type bridge-slave ifname ens2f0 master br30ens2f0

(4)
nmcli connection add type bridge autoconnect yes con-name br31ens2f1 ifname br31ens2f1
nmcli connection modify br31ens2f1 bridge.stp no
nmcli connection modify br31ens2f1 ipv4.method disabled ipv6.method ignore
nmcli connection up br31ens2f1
(5)
nmcli connection add type bridge-slave ifname ens2f1 master br31ens2f1

CP
(6)(7)次項6-3に記載
kubectl apply -f 161vdpa.yaml
6-2-1.Linux Bridgeの作成 : Worker
nmcli connection add type bridge autoconnect yes con-name br30ens2f0 ifname br30ens2f0
nmcli connection modify br30ens2f0 bridge.stp no
nmcli connection modify br30ens2f0 ipv4.method disabled ipv6.method ignore
nmcli connection up br30ens2f0
nmcli connection add type bridge-slave ifname ens2f0 master br30ens2f0

nmcli connection add type bridge autoconnect yes con-name br31ens2f1 ifname br31ens2f1
nmcli connection modify br31ens2f1 bridge.stp no
nmcli connection modify br31ens2f1 ipv4.method disabled ipv6.method ignore
nmcli connection up br31ens2f1
nmcli connection add type bridge-slave ifname ens2f1 master br31ens2f1
6-2-2.Linux Bridgeの確認 : Worker
nmcli con show

[root@c83g152 ~]# nmcli con show
NAME                 UUID                                  TYPE      DEVICE
System eno1          a60ea695-651d-46f8-9d93-5ac92f504956  ethernet  eno1
br11eno2             6862ba45-5873-4930-ac46-e3c7cfa3074a  bridge    br11eno2
br30ens2f0           5838f8cd-9f3e-441c-8f72-989e54f8780d  bridge    br30ens2f0
br31ens2f1           0737de11-7b3b-48a7-a742-ced4375ab3b7  bridge    br31ens2f1
docker0              12600c36-dadb-49c9-a082-02b0a51e0424  bridge    docker0
virbr0               a3aec808-57a6-4f35-94f0-0081c8571eab  bridge    virbr0
bridge-slave-eno2    acd7a4d7-585c-4d88-9456-49ac852475ba  ethernet  eno2
bridge-slave-ens2f0  d24f6a37-97cf-471a-abff-e53582effc05  ethernet  ens2f0
bridge-slave-ens2f1  aa37266c-312b-43fa-9e7b-244a7269c90d  ethernet  ens2f1
eno3                 700cd313-7aae-4eb0-9591-a3813e40ef2f  ethernet  --
eno4                 1e768d3b-37ff-47be-ad6a-907710def01f  ethernet  --
ens1f0               49155983-26e5-4070-834a-49b8a52fbd02  ethernet  --
ens1f1               cb97a04a-3130-47b9-af13-2293fca218ee  ethernet  --
6-3.Podのデプロイ : CP

ポイントは、annotationsとresourcesにNetwork Attachment Definitionで定義した値を指定している点です。
また、Accelerated Bridge CNI特有の設定はありません。

vi 161vdpa.yaml

apiVersion: v1
kind: Pod
metadata:
  name: vdpa-pod01
  annotations:
    k8s.v1.cni.cncf.io/networks: '[
      {
        "name": "vdpa-mlx-vhost-net30",
        "mac": "ca:fe:c0:ff:ee:11"
      }
      ]'
spec:
  nodeName: c83g152.md.jp
  containers:
  - name: vdpa-single01
    image: centos:latest
    imagePullPolicy: IfNotPresent
    securityContext:
      privileged: true
    resources:
      requests:
        intel.com/vdpa_mlx_vhost: '1'
      limits:
        intel.com/vdpa_mlx_vhost: '1'
    command: ["sleep"]
    args: ["infinity"]
---
apiVersion: v1
kind: Pod
metadata:
  name: vdpa-pod02
  annotations:
    k8s.v1.cni.cncf.io/networks: '[
      {
        "name": "vdpa-mlx-vhost-net31",
        "mac": "ca:fe:c0:ff:ee:12"
      }
      ]'
spec:
  nodeName: c83g152.md.jp
  containers:
  - name: vdpa-single02
    image: centos:latest
    imagePullPolicy: IfNotPresent
    securityContext:
      privileged: true
    resources:
      requests:
        intel.com/vdpa_mlx_vhost: '1'
      limits:
        intel.com/vdpa_mlx_vhost: '1'
    command: ["sleep"]
    args: ["infinity"]


kubectl apply -f 161vdpa.yaml
kubectl get pod

出力例

[root@c83g151 vdpa-deployment]# kubectl get pod
NAME         READY   STATUS    RESTARTS   AGE
vdpa-pod01   1/1     Running   0          7s
vdpa-pod02   1/1     Running   0          7s
6-4.Podの詳細確認 : CP

ここでは、kubectl describeコマンドにより、Podステータスの詳細を確認していきます。

kubectl describe pod vdpa-pod01

fig.1
f:id:metonymical:20210621235434j:plain
device-infoの各パラメータ(/dev/vhost-vdpa-0, 07:00.2)とfig.1が一致していることを確認してください。
出力例

[root@c83g151 vdpa-deployment]# kubectl describe pod vdpa-pod01
Name:         vdpa-pod01
Namespace:    default
Priority:     0
Node:         c83g152.md.jp/192.168.11.152
Start Time:   Wed, 23 Jun 2021 00:03:55 +0900
Labels:       
Annotations:  k8s.v1.cni.cncf.io/network-status:
                [{
                    "name": "",
                    "interface": "eth0",
                    "ips": [
                        "10.244.1.7"
                    ],
                    "mac": "56:5b:99:80:a4:6f",
                    "default": true,
                    "dns": {}
                },{
                    "name": "default/vdpa-mlx-vhost-net30",
                    "interface": "net1",
                    "ips": [
                        "192.168.30.66"
                    ],
                    "mac": "CA:FE:C0:FF:EE:11",
                    "dns": {},
                    "device-info": {
                        "type": "vdpa",
                        "version": "1.0.0",
                        "vdpa": {
                            "parent-device": "vdpa0",
                            "driver": "vhost",
                            "path": "/dev/vhost-vdpa-0",
                            "pci-address": "0000:07:00.2"
                        }
                    }
                }]
              k8s.v1.cni.cncf.io/networks: [ { "name": "vdpa-mlx-vhost-net30", "mac": "CA:FE:C0:FF:EE:11" } ]
              k8s.v1.cni.cncf.io/networks-status:
                [{
                    "name": "",
                    "interface": "eth0",
                    "ips": [
                        "10.244.1.7"
                    ],
                    "mac": "56:5b:99:80:a4:6f",
                    "default": true,
                    "dns": {}
                },{
                    "name": "default/vdpa-mlx-vhost-net30",
                    "interface": "net1",
                    "ips": [
                        "192.168.30.66"
                    ],
                    "mac": "CA:FE:C0:FF:EE:11",
                    "dns": {},
                    "device-info": {
                        "type": "vdpa",
                        "version": "1.0.0",
                        "vdpa": {
                            "parent-device": "vdpa0",
                            "driver": "vhost",
                            "path": "/dev/vhost-vdpa-0",
                            "pci-address": "0000:07:00.2"
                        }
                    }
                }]
Status:       Running
IP:           10.244.1.7
IPs:
  IP:  10.244.1.7
Containers:
  vdpa-single01:
    Container ID:  docker://67e8a82543cd8e4db556e8bd502f42659260e2d50192a5a0f13860d1cefc09ef
    Image:         centos:latest
    Image ID:      docker-pullable://centos@sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
    Port:          
    Host Port:     
    Command:
      sleep
    Args:
      infinity
    State:          Running
      Started:      Wed, 23 Jun 2021 00:03:57 +0900
    Ready:          True
    Restart Count:  0
    Limits:
      intel.com/vdpa_mlx_vhost:  1
    Requests:
      intel.com/vdpa_mlx_vhost:  1
    Environment:                 
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-gq69j (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kube-api-access-gq69j:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason          Age   From     Message
  ----    ------          ----  ----     -------
  Normal  AddedInterface  39s   multus   Add eth0 [10.244.1.7/24]
  Normal  AddedInterface  39s   multus   Add net1 [192.168.30.66/24] from default/vdpa-mlx-vhost-net30
  Normal  Pulled          39s   kubelet  Container image "centos:latest" already present on machine
  Normal  Created         39s   kubelet  Created container vdpa-single01
  Normal  Started         39s   kubelet  Started container vdpa-single01

Podデプロイ時、Workerの/var/log/messagesには以下のメッセージが出力されます。

[root@c83g152 ~]# tail -f /var/log/messages

Jun 21 19:38:41 c83g152 kubelet[2033]: I0621 19:38:41.415300    2033 topology_manager.go:187] "Topology Admit Handler"
Jun 21 19:38:41 c83g152 kubelet[2033]: I0621 19:38:41.419085    2033 topology_manager.go:187] "Topology Admit Handler"
Jun 21 19:38:41 c83g152 systemd[1]: Created slice libcontainer container kubepods-besteffort-pod7cba503f_5336_425e_b32c_45869b6f9020.slice.
Jun 21 19:38:41 c83g152 systemd[1]: Created slice libcontainer container kubepods-besteffort-poddd78b5ac_06f3_48f1_bbc9_2443fa88c653.slice.
============ s n i p ============
Jun 21 19:38:42 c83g152 kernel: br30ens2f0: port 2(ens2f0_0) entered blocking state
Jun 21 19:38:42 c83g152 kernel: br30ens2f0: port 2(ens2f0_0) entered disabled state
Jun 21 19:38:42 c83g152 kernel: device ens2f0_0 entered promiscuous mode
Jun 21 19:38:42 c83g152 kernel: br30ens2f0: port 2(ens2f0_0) entered blocking state
Jun 21 19:38:42 c83g152 kernel: br30ens2f0: port 2(ens2f0_0) entered forwarding state
Jun 21 19:38:42 c83g152 NetworkManager[1192]:   [1624271922.7254] device (ens2f0_0): Activation: starting connection 'ens2f0_0' (84f4ad71-e7dc-44ba-8755-2e3d6279b037)
Jun 21 19:38:42 c83g152 NetworkManager[1192]:   [1624271922.7258] device (ens2f0_0): state change: disconnected -> prepare (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:42 c83g152 NetworkManager[1192]:   [1624271922.7273] device (ens2f0_0): state change: prepare -> config (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:42 c83g152 NetworkManager[1192]:   [1624271922.7298] device (ens2f0_0): state change: config -> ip-config (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:42 c83g152 NetworkManager[1192]:   [1624271922.7303] device (br30ens2f0): bridge port ens2f0_0 was attached
Jun 21 19:38:42 c83g152 NetworkManager[1192]:   [1624271922.7304] device (ens2f0_0): Activation: connection 'ens2f0_0' enslaved, continuing activation
Jun 21 19:38:42 c83g152 NetworkManager[1192]:   [1624271922.7308] device (ens2f0_0): state change: ip-config -> ip-check (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:42 c83g152 NetworkManager[1192]:   [1624271922.7398] device (ens2f0_0): state change: ip-check -> secondaries (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:42 c83g152 NetworkManager[1192]:   [1624271922.7404] device (ens2f0_0): state change: secondaries -> activated (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:42 c83g152 NetworkManager[1192]:   [1624271922.7431] device (ens2f0_0): Activation: successful, device activated.
Jun 21 19:38:42 c83g152 systemd[1]: iscsi.service: Unit cannot be reloaded because it is inactive.
Jun 21 19:38:42 c83g152 kernel: mlx5_core 0000:07:00.2 temp_17: renamed from ens2f0v0
Jun 21 19:38:42 c83g152 NetworkManager[1192]:   [1624271922.7876] device (ens2f0v0): interface index 17 renamed iface from 'ens2f0v0' to 'temp_17'
Jun 21 19:38:42 c83g152 kernel: br31ens2f1: port 2(ens2f1_0) entered blocking state
Jun 21 19:38:42 c83g152 kernel: br31ens2f1: port 2(ens2f1_0) entered disabled state
Jun 21 19:38:42 c83g152 kernel: device ens2f1_0 entered promiscuous mode
Jun 21 19:38:42 c83g152 kernel: br31ens2f1: port 2(ens2f1_0) entered blocking state
Jun 21 19:38:42 c83g152 kernel: br31ens2f1: port 2(ens2f1_0) entered forwarding state
Jun 21 19:38:42 c83g152 kernel: mlx5_core 0000:07:00.2 net1: renamed from temp_17
Jun 21 19:38:42 c83g152 kernel: mlx5_core 0000:07:00.2 net1: Link up
Jun 21 19:38:42 c83g152 kernel: mlx5_core 0000:07:01.2 temp_18: renamed from ens2f1v0
Jun 21 19:38:43 c83g152 kubelet[2033]: I0621 19:38:42.708881    6118 event.go:278] Event(v1.ObjectReference{Kind:"Pod", Namespace:"default", Name:"vdpa-pod01", UID:"7cba503f-5336-425e-b32c-45869b6f9020", APIVersion:"v1", ResourceVersion:"3642", FieldPath:""}): type: 'Normal' reason: 'AddedInterface' Add eth0 [10.244.1.4/24]
Jun 21 19:38:43 c83g152 kubelet[2033]: 2021-06-21T19:38:42+09:00 INF Attaching rep ens2f0_0 to the bridge br30ens2f0
Jun 21 19:38:43 c83g152 kubelet[2033]: I0621 19:38:43.003540    6118 event.go:278] Event(v1.ObjectReference{Kind:"Pod", Namespace:"default", Name:"vdpa-pod01", UID:"7cba503f-5336-425e-b32c-45869b6f9020", APIVersion:"v1", ResourceVersion:"3642", FieldPath:""}): type: 'Normal' reason: 'AddedInterface' Add net1 [192.168.30.65/24] from default/vdpa-mlx-vhost-net30
Jun 21 19:38:43 c83g152 kernel: mlx5_core 0000:07:01.2 net1: renamed from temp_18
Jun 21 19:38:43 c83g152 kernel: mlx5_core 0000:07:01.2 net1: Link up
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1334] device (temp_17): state change: disconnected -> unmanaged (reason 'removed', sys-iface-state: 'removed')
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1418] device (ens2f1v0): state change: disconnected -> unmanaged (reason 'removed', sys-iface-state: 'removed')
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1466] device (ens2f1_0): Activation: starting connection 'ens2f1_0' (b0db37c4-3214-497b-80e2-c532ea2e54c2)
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1469] device (ens2f1_0): state change: disconnected -> prepare (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1480] device (ens2f1_0): state change: prepare -> config (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1488] device (ens2f1_0): state change: config -> ip-config (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1492] device (br31ens2f1): bridge port ens2f1_0 was attached
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1492] device (ens2f1_0): Activation: connection 'ens2f1_0' enslaved, continuing activation
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1497] device (ens2f1_0): state change: ip-config -> ip-check (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:43 c83g152 kubelet[2033]: I0621 19:38:42.708792    6117 event.go:278] Event(v1.ObjectReference{Kind:"Pod", Namespace:"default", Name:"vdpa-pod02", UID:"dd78b5ac-06f3-48f1-bbc9-2443fa88c653", APIVersion:"v1", ResourceVersion:"3643", FieldPath:""}): type: 'Normal' reason: 'AddedInterface' Add eth0 [10.244.1.5/24]
Jun 21 19:38:43 c83g152 kubelet[2033]: 2021-06-21T19:38:42+09:00 INF Attaching rep ens2f1_0 to the bridge br31ens2f1
Jun 21 19:38:43 c83g152 kubelet[2033]: I0621 19:38:43.150099    6117 event.go:278] Event(v1.ObjectReference{Kind:"Pod", Namespace:"default", Name:"vdpa-pod02", UID:"dd78b5ac-06f3-48f1-bbc9-2443fa88c653", APIVersion:"v1", ResourceVersion:"3643", FieldPath:""}): type: 'Normal' reason: 'AddedInterface' Add net1 [192.168.30.129/24] from default/vdpa-mlx-vhost-net31
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1710] device (ens2f1_0): state change: ip-check -> secondaries (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1716] device (ens2f1_0): state change: secondaries -> activated (reason 'none', sys-iface-state: 'external')
Jun 21 19:38:43 c83g152 NetworkManager[1192]:   [1624271923.1739] device (ens2f1_0): Activation: successful, device activated.
Jun 21 19:38:43 c83g152 systemd[2041]: var-lib-docker-overlay2-524994f068d6d26da4d1a605184e6de152bf73c5a986154266fe173dd7160fd8\x2dinit-merged.mount: Succeeded.
Jun 21 19:38:43 c83g152 systemd[1]: var-lib-docker-overlay2-524994f068d6d26da4d1a605184e6de152bf73c5a986154266fe173dd7160fd8\x2dinit-merged.mount: Succeeded.
Jun 21 19:38:43 c83g152 systemd[2041]: var-lib-docker-overlay2-397914421b4b0f2e6a93c8262d6bd7c747dbdfaff65f7f674be5513b35d2ca6c\x2dinit-merged.mount: Succeeded.
Jun 21 19:38:43 c83g152 systemd[1]: var-lib-docker-overlay2-397914421b4b0f2e6a93c8262d6bd7c747dbdfaff65f7f674be5513b35d2ca6c\x2dinit-merged.mount: Succeeded.
Jun 21 19:38:43 c83g152 systemd[1]: iscsi.service: Unit cannot be reloaded because it is inactive.
Jun 21 19:38:43 c83g152 dockerd[2034]: time="2021-06-21T19:38:43.223212683+09:00" level=warning msg="custom mrw permissions for device /dev/vhost-vdpa-1 are ignored in privileged mode" container=b31ebb7e20322aed53aa95e5d30ff86d3d153edd2eb1ccfeceed24db0cc3a339
Jun 21 19:38:43 c83g152 dockerd[2034]: time="2021-06-21T19:38:43.223313924+09:00" level=warning msg="custom mrw permissions for device /dev/vhost-vdpa-0 are ignored in privileged mode" container=52d8b02b57b1f979bcff398fcaf5b276ad056b73fe93aff10bb104c35a4b31d6
Jun 21 19:38:43 c83g152 dockerd[2034]: time="2021-06-21T19:38:43.223395596+09:00" level=warning msg="path in container /dev/vhost-vdpa-0 already exists in privileged mode" container=52d8b02b57b1f979bcff398fcaf5b276ad056b73fe93aff10bb104c35a4b31d6
Jun 21 19:38:43 c83g152 dockerd[2034]: time="2021-06-21T19:38:43.223319641+09:00" level=warning msg="path in container /dev/vhost-vdpa-1 already exists in privileged mode" container=b31ebb7e20322aed53aa95e5d30ff86d3d153edd2eb1ccfeceed24db0cc3a339
============ s n i p ============
Jun 21 19:38:53 c83g152 systemd[1]: NetworkManager-dispatcher.service: Succeeded.
6-5.WorkerのMacアドレス確認 : Worker

Podのannotationsで指定したMACアドレスがWorkerのVFに反映されていることを確認してください。

ip link show ens2f0

出力例

[root@c83g152 ~]# ip link show ens2f0
15: ens2f0:  mtu 1500 qdisc mq master br30ens2f0 state UP mode DEFAULT group default qlen 1000
    link/ether 94:40:c9:7e:1f:10 brd ff:ff:ff:ff:ff:ff
    vf 0     link/ether ca:fe:c0:ff:ee:11 brd ff:ff:ff:ff:ff:ff, spoof checking off, link-state disable, trust off, query_rss off
6-6.WorkerのLinux Bridgeの確認 : Worker

WorkerのVF rep(ens2f0_0, ens2f1_0)が自動的に設定されていることを確認してください。

nmcli con show

出力例

[root@c83g152 ~]# nmcli con show
NAME                 UUID                                  TYPE      DEVICE
System eno1          a60ea695-651d-46f8-9d93-5ac92f504956  ethernet  eno1
cni0                 eacb774c-9306-4c9d-8eb3-2382d9b4c5da  bridge    cni0
br11eno2             6862ba45-5873-4930-ac46-e3c7cfa3074a  bridge    br11eno2
br30ens2f0           5838f8cd-9f3e-441c-8f72-989e54f8780d  bridge    br30ens2f0
br31ens2f1           0737de11-7b3b-48a7-a742-ced4375ab3b7  bridge    br31ens2f1
docker0              12600c36-dadb-49c9-a082-02b0a51e0424  bridge    docker0
virbr0               a3aec808-57a6-4f35-94f0-0081c8571eab  bridge    virbr0
bridge-slave-eno2    acd7a4d7-585c-4d88-9456-49ac852475ba  ethernet  eno2
bridge-slave-ens2f0  d24f6a37-97cf-471a-abff-e53582effc05  ethernet  ens2f0
bridge-slave-ens2f1  aa37266c-312b-43fa-9e7b-244a7269c90d  ethernet  ens2f1
ens2f0_0             112da873-9159-412b-a576-b70eb1dcb97b  ethernet  ens2f0_0
ens2f1_0             714af871-890d-4e24-8ad6-bcea1ea7c208  ethernet  ens2f1_0
eno3                 700cd313-7aae-4eb0-9591-a3813e40ef2f  ethernet  --
eno4                 1e768d3b-37ff-47be-ad6a-907710def01f  ethernet  --
ens1f0               49155983-26e5-4070-834a-49b8a52fbd02  ethernet  --
ens1f1               cb97a04a-3130-47b9-af13-2293fca218ee  ethernet  --

7.動作確認 : CP

7-1.PodのIPアドレス確認

PodのIPアドレスは動的アサインされるため、事前に確認しておきます。

kubectl describe pod vdpa-pod01 |grep Add
kubectl describe pod vdpa-pod02 |grep Add

出力例

[root@c83g151 vdpa-deployment]# kubectl describe pod vdpa-pod01 |grep Add
  Normal  AddedInterface  7m22s  multus   Add eth0 [10.244.1.7/24]
  Normal  AddedInterface  7m22s  multus   Add net1 [192.168.30.66/24] from default/vdpa-mlx-vhost-net30
[root@c83g151 vdpa-deployment]# kubectl describe pod vdpa-pod02 |grep Add
  Normal  AddedInterface  7m23s  multus   Add eth0 [10.244.1.6/24]
  Normal  AddedInterface  7m23s  multus   Add net1 [192.168.30.130/24] from default/vdpa-mlx-vhost-net31
7-2.疎通確認
vdpa-pod01 192.168.30.66/24
vdpa-pod02 192.168.30.130/24

上記のIPアドレスだったので、vdpa-pod01から192.168.30.130へPingを実行します。

kubectl exec -it vdpa-pod01 -- ping 192.168.30.130

出力例

[root@c83g151 vdpa-deployment]# kubectl exec -it vdpa-pod01 -- ping 192.168.30.130
PING 192.168.30.130 (192.168.30.130) 56(84) bytes of data.
64 bytes from 192.168.30.130: icmp_seq=1 ttl=64 time=0.510 ms
64 bytes from 192.168.30.130: icmp_seq=2 ttl=64 time=0.590 ms
64 bytes from 192.168.30.130: icmp_seq=3 ttl=64 time=0.551 ms
64 bytes from 192.168.30.130: icmp_seq=4 ttl=64 time=0.510 ms
^C
--- 192.168.30.130 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 63ms
rtt min/avg/max/mdev = 0.510/0.540/0.590/0.037 ms

DACを経由して、Pod間で通信していることが確認できました。

また、Workerのbridge monitor fdbにてPodのMACアドレスを学習していることが確認できます。
Pingを飛ばす前にWokerで以下のコマンドを実行しておきます。

bridge monitor fdb

赤文字がPing実行時に学習したMACアドレスとなります。
それ以外はPod起動時に学習したMACアドレスとなります。

[root@c83g152 ~]# bridge monitor fdb
7a:d9:02:4d:7c:8f dev cni0 vlan 1 master cni0 permanent
82:9f:e7:63:77:47 dev vethdbd6a26b master cni0 permanent
82:9f:e7:63:77:47 dev vethdbd6a26b vlan 1 master cni0 permanent
Deleted 7a:d9:02:4d:7c:8f dev cni0 vlan 1 master cni0 permanent
42:83:37:60:8a:8d dev veth78a2b6ab master cni0 permanent
42:83:37:60:8a:8d dev veth78a2b6ab vlan 1 master cni0 permanent
fe:42:e8:04:50:51 dev veth78a2b6ab master cni0
b2:4b:f8:68:fe:b0 dev vethdbd6a26b master cni0
7a:d9:02:4d:7c:8f dev cni0 master cni0 permanent
7a:d9:02:4d:7c:8f dev cni0 vlan 1 master cni0 permanent
ea:03:d9:6b:62:a3 dev ens2f0_0 master br30ens2f0 permanent
ea:03:d9:6b:62:a3 dev ens2f0_0 vlan 1 master br30ens2f0 permanent
e6:2e:2e:d8:04:3d dev ens2f1_0 master br31ens2f1 permanent
e6:2e:2e:d8:04:3d dev ens2f1_0 vlan 1 master br31ens2f1 permanent
ca:fe:c0:ff:ee:11 dev ens2f0_0 master br30ens2f0
ca:fe:c0:ff:ee:11 dev ens2f1 master br31ens2f1
ca:fe:c0:ff:ee:12 dev ens2f1_0 master br31ens2f1
ca:fe:c0:ff:ee:12 dev ens2f0 master br30ens2f0


以上です。

8.最後に

以下のサイトを参考にさせて頂きました。
GitHub - k8snetworkplumbingwg/accelerated-bridge-cni

今回の記事はNo10に該当します。

No vm(qemu)/k8s k8s Pod/VMI vDPA Framework vDPA Type SR-IOV mode Related Articles
1 vm - kernel vhost lagacy Not started
2 vm - kernel vhost switchdev vDPA の設定方法 vhost_vdpa + VM編 - Metonymical Deflection
3 vm - kernel virtio lagacy Not started
4 vm - kernel virtio switchdev Not started
5 vm - dpdk vhost lagacy Not started
6 vm - dpdk vhost switchdev Not started
7 vm - dpdk virtio lagacy Not started
8 vm - dpdk virtio switchdev vDPA の設定方法 virtio_vdpa + VM編 - Metonymical Deflection
9 k8s pod kernel vhost lagacy vDPA の設定方法 vhost_vdpa + kubernetes編 - Metonymical Deflection
10 k8s pod kernel vhost switchdev This article
11 k8s pod kernel virtio lagacy Not started
12 k8s pod kernel virtio switchdev Not started
13 k8s pod dpdk client lagacy Not started
14 k8s pod dpdk client switchdev Not started
15 k8s pod dpdk server lagacy Not started
16 k8s pod dpdk server switchdev Not started

次回はkubevirtを使用したvmi(Virtual Machine Instance)の設定について試してみたいと思います。
現時点で、kubevirtはvfio-pciのみのサポートとなるため一旦保留にします。

*1:各種ドキュメントを確認した結果、vDPAの"v"は、virtual, vhost, virtioの3種類ありますが、意味は全て同じようです。本ブログでは、 Introduction to vDPA kernel framework に従い、virtioの表記で統一しました。

*2:対向機器に100Gbpsスイッチや100GNIC搭載サーバが用意できない場合を考慮し、ループ接続としています。但し、Podで生成したパケットが物理的に外部へ送信されることが重要と考えているため、fig.1の構成としています。

*3:VMの場合、MACアドレス設定は必須でしたが、k8s Podの場合、yamlMACアドレスを記述するため、必須設定ではありません。

*4:coreやmodulesも同時にインストールされます

*5:蛇足ですが、bsf番号の前の「0000」は、Domain番号と呼ばれています。私が知る限りでは「0000」以外の値を見たことが無いため、あまり気にしなくてよいと思います。

*6:ソースからKernelをビルドする際、make menuconfigなどでvhost_vdpaを有効化しておけば、この設定は不要です。

*7:前回の記事では、sriov-cniも同時にビルドしました。今回は使用しないためビルドしませんが、sriov-cniをビルドしても問題ありません。6-1.NetworkAttachmentDefinitionの設定にて、明示的にaccelerated-bridgeを指定するため、sriov-cniとaccelerated-bridge-cniが混在しても問題ありません。

*8:こちらで確認できます。PCI Devices

*9:前回の記事では、"sriov"と設定しています。

*10:何も指定しない場合、Defaultでcni0のBridgeが設定されます。