Metonymical Deflection

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

vDPA の設定方法 vhost_vdpa + kubernetes編

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

本ブログでは、vhost_vdpaモジュールを使用したkubernetes(以下、k8s)のPod間通信について記載していきます。

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

vDPA の設定方法 vhost_vdpa + VM編 - Metonymical Deflection
vDPA の設定方法 virtio_vdpa + VM編 - Metonymical Deflection
vDPA の設定方法 vhost_vdpa + kubernetes + Accelerated Bridge CNI編 - 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.7-1.el8.elrepo.x86_64
Installed Environment Groups     : 
  @^graphical-server-environment
  @container-management
  @development
  @virtualization-client
  @virtualization-hypervisor
  @virtualization-tools 
Kubernetes                       : 1.21.1
Docker-CE                        : 20.10.6
flannel                          : latest
Multus                           : latest
sriov-cni                        : latest
sriov-network-device-plugin      : latest
1-2.全体の流れ
  1. 事前準備
  2. Kernelアップデート
  3. k8s Cluster & flannelの構築
  4. vDPA(SR-IOV)関連のビルドとデプロイ
  5. Podのデプロイ
  6. 動作確認
  7. 高度な設定

1~3までは比較的多くのドキュメントが存在しますので、重要な箇所以外は割愛します。
7はConfigMapやNetworkAttachmentDefinitionよる詳細な設定方法について記載しています。

1-3.全体構成

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

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

Red Hatgithubより引用
github.com

上記githubを読む限り、SR-IOVにおけるlegacyモードでの実装となっています。
このため、本ブログにおいてもlegacyモードによる設定方法を記載します。*3

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」としています。*4

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月11日現在、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をインストール*5
インストール済み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.7-1.el8.elrepo                           @elrepo-kernel
kernel-ml-core.x86_64                              5.12.7-1.el8.elrepo                           @elrepo-kernel
kernel-ml-devel.x86_64                             5.12.7-1.el8.elrepo                           @elrepo-kernel
kernel-ml-headers.x86_64                           5.12.7-1.el8.elrepo                           @elrepo-kernel
kernel-ml-modules.x86_64                           5.12.7-1.el8.elrepo                           @elrepo-kernel
kernel-ml-tools.x86_64                             5.12.7-1.el8.elrepo                           @elrepo-kernel
kernel-ml-tools-libs.x86_64                        5.12.7-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.2-OFED.5.2.2.2.0.1.rhel8u3                  @System
mlnx-ofa_kernel.x86_64                             5.2-OFED.5.2.2.2.0.1.rhel8u3                  @System
mlnx-ofa_kernel-devel.x86_64                       5.2-OFED.5.2.2.2.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.1
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.1
c83g152.md.jp   Ready                           44s    v1.21.1
4-9.vhost_vdpaモジュールの有効化 : Worker

5.vDPA(SR-IOV)関連のビルドとデプロイにて、sriov-cniのビルドやデプロイを実施します。
その際、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
modprobe vhost_vdpa
sleep 1
exit 0

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

5.vDPA(SR-IOV)関連のビルドとデプロイ

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

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

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

cd /usr/src/vdpa-deployment && \
make multus && \
make sriov-cni && \
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/sriov-cni 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/sriov-cni root@192.168.11.152 && \
> /usr/src/vdpa-deployment/scripts/load-image.sh nfvpe/sriov-cni 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-cni                      latest       521ab1f3a5a1   16 minutes ago   9.47MB
<none>                               <none>       88062f2c13d4   16 minutes ago   561MB
nfvpe/multus                         latest       aa8d9becca0f   17 minutes ago   331MB
<none>                               <none>       e75c422aef6e   17 minutes ago   1.34GB
nfvpe/sriov-device-plugin            latest       0dd5f325c600   18 minutes ago   42.7MB
<none>                               <none>       3deb8b5405fa   18 minutes ago   1.26GB
quay.io/coreos/flannel               v0.14.0      8522d622299c   2 weeks ago      67.9MB
k8s.gcr.io/kube-apiserver            v1.21.1      771ffcf9ca63   3 weeks ago      126MB
k8s.gcr.io/kube-proxy                v1.21.1      4359e752b596   3 weeks ago      131MB
k8s.gcr.io/kube-controller-manager   v1.21.1      e16544fd47b0   3 weeks ago      120MB
k8s.gcr.io/kube-scheduler            v1.21.1      a4183b88f6e6   3 weeks ago      50.6MB
golang                               alpine3.12   24d827672eae   3 weeks ago      301MB
golang                               alpine       722a834ff95b   3 weeks ago      301MB
fedora                               32           c451de0d2441   5 weeks ago      202MB
alpine                               3.12         13621d1b12d4   7 weeks ago      5.58MB
alpine                               3            6dbb9cc54074   7 weeks ago      5.61MB
k8s.gcr.io/pause                     3.4.1        0f8457a4c2ec   4 months ago     683kB
k8s.gcr.io/coredns/coredns           v1.8.0       296a6d5035e2   7 months ago     42.5MB
k8s.gcr.io/etcd                      3.4.13-0     0369cf4303ff   9 months ago     253MB
5-4.yamlファイルのデプロイ : CP

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

  1. /usr/src/vdpa-deployment/deployment/multus-daemonset.yaml
  2. /usr/src/vdpa-deployment/deployment/sriovcni-vdpa-daemonset.yaml
  3. /usr/src/vdpa-deployment/deployment/sriovdp-vdpa-daemonset.yaml
  4. /usr/src/vdpa-deployment/deployment/configMap-vdpa.yaml

1-3はmake deployコマンドでデプロイされます。
4はkubectlコマンドでデプロイします。

cd /usr/src/vdpa-deployment && \
make deploy && \
kubectl apply -f /usr/src/vdpa-deployment/deployment/configMap-vdpa.yaml

<出力例>

[root@c83g151 vdpa-deployment]# cd /usr/src/vdpa-deployment && \
> make deploy && \
> kubectl create -f /usr/src/vdpa-deployment/deployment/configMap-vdpa.yaml
serviceaccount/sriov-device-plugin created
daemonset.apps/kube-sriov-device-plugin-amd64 created
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
daemonset.apps/kube-sriov-cni-ds-amd64 created
configmap/sriovdp-config created
5-5.DaemonSet & ConfigMap & Podの確認 : CP

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

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

<出力例>

[root@c83g151 vdpa-deployment]# kubectl -n kube-system get ds
NAME                             DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                   AGE
kube-flannel-ds                  2         2         2       2            2                                     3h4m
kube-multus-ds-amd64             2         2         2       2            2           kubernetes.io/arch=amd64        6m52s
kube-proxy                       2         2         2       2            2           kubernetes.io/os=linux          3h4m
kube-sriov-cni-ds-amd64          2         2         2       2            2           beta.kubernetes.io/arch=amd64   6m52s
kube-sriov-device-plugin-amd64   2         2         2       2            2           beta.kubernetes.io/arch=amd64   6m52s


[root@c83g151 vdpa-deployment]# kubectl -n kube-system get cm
NAME                                 DATA   AGE
coredns                              1      3h4m
extension-apiserver-authentication   6      3h4m
kube-flannel-cfg                     2      3h4m
kube-proxy                           2      3h4m
kube-root-ca.crt                     1      3h4m
kubeadm-config                       2      3h4m
kubelet-config-1.21                  1      3h4m
multus-cni-config                    1      6m52s
sriovdp-config                       1      6m52s

[root@c83g151 vdpa-deployment]# kubectl -n kube-system get pod
NAME                                    READY   STATUS    RESTARTS   AGE
coredns-558bd4d5db-7kql2                1/1     Running   2          178m
coredns-558bd4d5db-nq8k7                1/1     Running   2          178m
etcd-c83g151.md.jp                      1/1     Running   2          178m
kube-apiserver-c83g151.md.jp            1/1     Running   2          178m
kube-controller-manager-c83g151.md.jp   1/1     Running   2          178m
kube-flannel-ds-89v57                   1/1     Running   2          174m
kube-flannel-ds-zwd7n                   1/1     Running   2          177m
kube-multus-ds-amd64-75rbf              1/1     Running   0          33s
kube-multus-ds-amd64-zk6w9              1/1     Running   0          33s
kube-proxy-fdv9r                        1/1     Running   2          174m
kube-proxy-l6t7h                        1/1     Running   2          178m
kube-scheduler-c83g151.md.jp            1/1     Running   2          178m
kube-sriov-cni-ds-amd64-2xfxw           1/1     Running   0          33s
kube-sriov-cni-ds-amd64-ndmmr           1/1     Running   0          33s
kube-sriov-device-plugin-amd64-4lt4p    1/1     Running   0          33s
kube-sriov-device-plugin-amd64-gbplp    1/1     Running   0          33s
5-6.ConfigMapの詳細確認 : CP

6.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-7.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 vdpa-deployment]# kubectl -n kube-system get pod -o wide |grep 152
kube-flannel-ds-89v57                   1/1     Running   2          4h8m    192.168.11.152   c83g152.md.jp              
kube-multus-ds-amd64-75rbf              1/1     Running   0          74m     192.168.11.152   c83g152.md.jp              
kube-proxy-fdv9r                        1/1     Running   2          4h8m    192.168.11.152   c83g152.md.jp              
kube-sriov-cni-ds-amd64-2xfxw           1/1     Running   0          74m     192.168.11.152   c83g152.md.jp              
kube-sriov-device-plugin-amd64-rg8hm    1/1     Running   0          73m     192.168.11.152   c83g152.md.jp              

[root@c83g151 vdpa-deployment]# kubectl -n kube-system delete pod kube-sriov-device-plugin-amd64-rg8hm
pod "kube-sriov-device-plugin-amd64-rg8hm" deleted

[root@c83g151 vdpa-deployment]# kubectl -n kube-system get pod -o wide |grep 152
kube-flannel-ds-89v57                   1/1     Running   2          4h9m    192.168.11.152   c83g152.md.jp              
kube-multus-ds-amd64-75rbf              1/1     Running   0          76m     192.168.11.152   c83g152.md.jp              
kube-proxy-fdv9r                        1/1     Running   2          4h9m    192.168.11.152   c83g152.md.jp              
kube-sriov-cni-ds-amd64-2xfxw           1/1     Running   0          76m     192.168.11.152   c83g152.md.jp              
kube-sriov-device-plugin-amd64-kwc5z    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-9.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.Podのデプロイ

/usr/src/vdpa-deployment/deployment/multus-daemonset.yaml で、CRDとして定義されているNetwork Attachment Definitionの設定を行います。
ここでは、vlan, spoofchk, ipamなどを設定していきます。
詳細は以下のサイトを参照してください。
sriov-cni/configuration-reference.md at rfe/vdpa · amorenoz/sriov-cni · GitHub

6-1.NetworkAttachmentDefinitionの設定 : CP

vdpa-mlx-vhost-net30は、Podのannotationsに指定します。

vi 96nA-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": "sriov",
  "cniVersion": "0.3.1",
  "name": "sriov-vdpa30",
  "vlan": 30,
  "trust": "on",
  "spoofchk": "off",
  "ipam": {
    "type": "host-local",
    "subnet": "192.168.30.0/24",
    "rangeStart": "192.168.30.64",
    "rangeEnd": "192.168.30.127"
  }
}'

kubectl apply -f 96nA-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   14m
6-2.Podのデプロイ : CP

ポイントは、annotationsとresourcesにNetwork Attachment Definitionで定義した値を指定している点です。

vi 16vdpa.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-net30",
        "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 16vdpa.yaml
kubectl get pod

出力例

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

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

kubectl describe pod vdpa-pod01

fig.1
f:id:metonymical:20210603000858j: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:   Thu, 03 Jun 2021 20:54:49 +0900
Labels:       
Annotations:  k8s.v1.cni.cncf.io/network-status:
                [{
                    "name": "",
                    "interface": "eth0",
                    "ips": [
                        "10.244.1.9"
                    ],
                    "mac": "26:9a:87:2a:70:70",
                    "default": true,
                    "dns": {}
                },{
                    "name": "default/vdpa-mlx-vhost-net30",
                    "interface": "net1",
                    "ips": [
                        "192.168.30.71"
                    ],
                    "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.9"
                    ],
                    "mac": "26:9a:87:2a:70:70",
                    "default": true,
                    "dns": {}
                },{
                    "name": "default/vdpa-mlx-vhost-net30",
                    "interface": "net1",
                    "ips": [
                        "192.168.30.71"
                    ],
                    "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.9
IPs:
  IP:  10.244.1.9
Containers:
  vdpa-single01:
    Container ID:  docker://cf57569807eb2de3d4901ff2ade55b845682d2c7a37ee88c7f6536498fd0b63e
    Image:         centos:latest
    Image ID:      docker-pullable://centos@sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
    Port:          
    Host Port:     
    Command:
      sleep
    Args:
      infinity
    State:          Running
      Started:      Thu, 03 Jun 2021 20:54:51 +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-9kqtb (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kube-api-access-9kqtb:
    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  26s   multus   Add eth0 [10.244.1.9/24]
  Normal  AddedInterface  25s   multus   Add net1 [192.168.30.71/24] from default/vdpa-mlx-vhost-net30
  Normal  Pulled          25s   kubelet  Container image "centos:latest" already present on machine
  Normal  Created         25s   kubelet  Created container vdpa-single01
  Normal  Started         25s   kubelet  Started container vdpa-single01
6-4.WorkerのMacアドレス確認 : Worker

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

ip link show ens2f0

出力例

[root@c83g152 ~]# ip link show ens2f0
8: ens2f0:  mtu 1500 qdisc mq 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, vlan 30, spoof checking off, link-state auto, trust on, query_rss off

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  26m   multus   Add eth0 [10.244.1.9/24]
  Normal  AddedInterface  26m   multus   Add net1 [192.168.30.71/24] from default/vdpa-mlx-vhost-net30
[root@c83g151 vdpa-deployment]# kubectl describe pod vdpa-pod02 |grep Add
  Normal  AddedInterface  26m   multus   Add eth0 [10.244.1.8/24]
  Normal  AddedInterface  26m   multus   Add net1 [192.168.30.70/24] from default/vdpa-mlx-vhost-net30
7-2.疎通確認
vdpa-pod01 192.168.30.71/24
vdpa-pod02 192.168.30.70/24

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

kubectl exec -it vdpa-pod01 -- ping 192.168.30.70

出力例

[root@c83g151 vdpa-deployment]# kubectl exec -it vdpa-pod01 -- ping 192.168.30.70
PING 192.168.30.70 (192.168.30.70) 56(84) bytes of data.
64 bytes from 192.168.30.70: icmp_seq=1 ttl=64 time=0.447 ms
64 bytes from 192.168.30.70: icmp_seq=2 ttl=64 time=0.166 ms
64 bytes from 192.168.30.70: icmp_seq=3 ttl=64 time=0.227 ms
64 bytes from 192.168.30.70: icmp_seq=4 ttl=64 time=0.217 ms
^C
--- 192.168.30.70 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 91ms
rtt min/avg/max/mdev = 0.166/0.264/0.447/0.108 ms

DACを経由して、Pod間で通信していることが確認できました。
設定方法としては以上となります。

次項では、より詳細な設定をするときの設定例を記載します。

8.高度な設定

ConfigMapとNetworkAttachmentDefinitionの設定により、fig.3のような構成も設定することができます。
fig.3
f:id:metonymical:20210603230304j:plain

yamlファイルを見れば、具体的に何をしているか理解できると思いますので、特に解説は記載しませんが、注目すべきポイントは赤文字で記載します。
事前にSR-IOVのVFを4つに増やしておいてください。

echo 2 > /sys/class/net/ens2f0/device/sriov_numvfs
echo 2 > /sys/class/net/ens2f1/device/sriov_numvfs
8-1.ConfigMapの設定 : CP
vi 83cm-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_vhost11",
                "selectors": {
                    "vendors": ["15b3"],
                    "devices": ["101e"],
                    "drivers": ["mlx5_core"],
                    "pciAddresses": ["0000:07:00.2"],
                    "vdpaType": "vhost"
                }
            },
            {
                "resourceName": "vdpa_mlx_vhost12",
                "selectors": {
                    "vendors": ["15b3"],
                    "devices": ["101e"],
                    "drivers": ["mlx5_core"],
                    "pciAddresses": ["0000:07:00.3"],
                    "vdpaType": "vhost"
                }
            },
            {
                "resourceName": "vdpa_mlx_vhost21",
                "selectors": {
                    "vendors": ["15b3"],
                    "devices": ["101e"],
                    "drivers": ["mlx5_core"],
                    "pciAddresses": ["0000:07:01.2"],
                    "vdpaType": "vhost"
                }
            },
            {
                "resourceName": "vdpa_mlx_vhost22",
                "selectors": {
                    "vendors": ["15b3"],
                    "devices": ["101e"],
                    "drivers": ["mlx5_core"],
                    "pciAddresses": ["0000:07:01.3"],
                    "vdpaType": "vhost"
                }
            },
            {
                "resourceName": "vdpa_mlx_virtio",
                "selectors": {
                    "vendors": ["15b3"],
                    "devices": ["101e"],
                    "drivers": ["mlx5_core"],
                    "vdpaType": "virtio"
                }
            }
        ]
    }

kubectl apply -f 83cm-vdpa.yaml
8-2.NetworkAttachmentDefinitionの設定 : CP
vi 93nA-vdpa11-22.yaml

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: vdpa-mlx-vhost-net11
  annotations:
    k8s.v1.cni.cncf.io/resourceName: intel.com/vdpa_mlx_vhost11
spec:
  config: '{
  "type": "sriov",
  "cniVersion": "0.3.1",
  "name": "sriov-vdpa",
  "vlan": 100,
  "trust": "on",
  "spoofchk": "off",
  "ipam": {
    "type": "host-local",
    "subnet": "192.168.100.0/24",
    "rangeStart": "192.168.100.64",
    "rangeEnd": "192.168.100.127"
  }
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: vdpa-mlx-vhost-net12
  annotations:
    k8s.v1.cni.cncf.io/resourceName: intel.com/vdpa_mlx_vhost12
spec:
  config: '{
  "type": "sriov",
  "cniVersion": "0.3.1",
  "name": "sriov-vdpa",
  "vlan": 200,
  "trust": "on",
  "spoofchk": "off",
  "ipam": {
    "type": "host-local",
    "subnet": "192.168.200.0/24",
    "rangeStart": "192.168.200.64",
    "rangeEnd": "192.168.200.127"
  }
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: vdpa-mlx-vhost-net21
  annotations:
    k8s.v1.cni.cncf.io/resourceName: intel.com/vdpa_mlx_vhost21
spec:
  config: '{
  "type": "sriov",
  "cniVersion": "0.3.1",
  "name": "sriov-vdpa",
  "vlan": 100,
  "trust": "on",
  "spoofchk": "off",
  "ipam": {
    "type": "host-local",
    "subnet": "192.168.100.0/24",
    "rangeStart": "192.168.100.128",
    "rangeEnd": "192.168.100.191"
  }
}'
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: vdpa-mlx-vhost-net22
  annotations:
    k8s.v1.cni.cncf.io/resourceName: intel.com/vdpa_mlx_vhost22
spec:
  config: '{
  "type": "sriov",
  "cniVersion": "0.3.1",
  "name": "sriov-vdpa",
  "vlan": 200,
  "trust": "on",
  "spoofchk": "off",
  "ipam": {
    "type": "host-local",
    "subnet": "192.168.200.0/24",
    "rangeStart": "192.168.200.128",
    "rangeEnd": "192.168.200.191"
  }
}'

kubectl apply -f 93nA-vdpa11-22.yaml
8-3.Podの設定 : CP
vi 13vdpa.yaml

apiVersion: v1
kind: Pod
metadata:
  name: vdpa-pod01
  annotations:
    k8s.v1.cni.cncf.io/networks: '[
      {
        "name": "vdpa-mlx-vhost-net11",
        "mac": "0C:FE:C0:FF:EE:11"
      },
      {
        "name": "vdpa-mlx-vhost-net12",
        "mac": "0C:FE:C0:FF:EE:12"
      }
      ]'
spec:
  nodeName: c83g152.md.jp
  containers:
  - name: vdpa-single01
    image: centos:latest
    imagePullPolicy: IfNotPresent
    securityContext:
      privileged: true
    resources:
      requests:
        intel.com/vdpa_mlx_vhost11: '1'
        intel.com/vdpa_mlx_vhost12: '1'
      limits:
        intel.com/vdpa_mlx_vhost11: '1'
        intel.com/vdpa_mlx_vhost12: '1'
    command: ["sleep"]
    args: ["infinity"]
---
apiVersion: v1
kind: Pod
metadata:
  name: vdpa-pod02
  annotations:
    k8s.v1.cni.cncf.io/networks: '[
      {
        "name": "vdpa-mlx-vhost-net21",
        "mac": "0C:FE:C0:FF:EE:21"
      },
      {
        "name": "vdpa-mlx-vhost-net22",
        "mac": "0C:FE:C0:FF:EE:22"
      }
      ]'
spec:
  nodeName: c83g152.md.jp
  containers:
  - name: vdpa-single02
    image: centos:latest
    imagePullPolicy: IfNotPresent
    securityContext:
      privileged: true
    resources:
      requests:
        intel.com/vdpa_mlx_vhost21: '1'
        intel.com/vdpa_mlx_vhost22: '1'
      limits:
        intel.com/vdpa_mlx_vhost21: '1'
        intel.com/vdpa_mlx_vhost22: '1'
    command: ["sleep"]
    args: ["infinity"]

kubectl apply -f 13vdpa.yaml
8-4.Podの詳細確認 : CP
[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:   Thu, 03 Jun 2021 22:23:33 +0900
Labels:       
Annotations:  k8s.v1.cni.cncf.io/network-status:
                [{
                    "name": "",
                    "interface": "eth0",
                    "ips": [
                        "10.244.1.12"
                    ],
                    "mac": "c6:01:75:97:75:91",
                    "default": true,
                    "dns": {}
                },{
                    "name": "default/vdpa-mlx-vhost-net11",
                    "interface": "net1",
                    "ips": [
                        "192.168.100.64"
                    ],
                    "mac": "0C: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"
                        }
                    }
                },{
                    "name": "default/vdpa-mlx-vhost-net12",
                    "interface": "net2",
                    "ips": [
                        "192.168.200.64"
                    ],
                    "mac": "0C:FE:C0:FF:EE:12",
                    "dns": {},
                    "device-info": {
                        "type": "vdpa",
                        "version": "1.0.0",
                        "vdpa": {
                            "parent-device": "vdpa1",
                            "driver": "vhost",
                            "path": "/dev/vhost-vdpa-1",
                            "pci-address": "0000:07:00.3"
                        }
                    }
                }]
              k8s.v1.cni.cncf.io/networks:
                [ { "name": "vdpa-mlx-vhost-net11", "mac": "0C:FE:C0:FF:EE:11" }, { "name": "vdpa-mlx-vhost-net12", "mac": "0C:FE:C0:FF:EE:12" } ]
              k8s.v1.cni.cncf.io/networks-status:
                [{
                    "name": "",
                    "interface": "eth0",
                    "ips": [
                        "10.244.1.12"
                    ],
                    "mac": "c6:01:75:97:75:91",
                    "default": true,
                    "dns": {}
                },{
                    "name": "default/vdpa-mlx-vhost-net11",
                    "interface": "net1",
                    "ips": [
                        "192.168.100.64"
                    ],
                    "mac": "0C: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"
                        }
                    }
                },{
                    "name": "default/vdpa-mlx-vhost-net12",
                    "interface": "net2",
                    "ips": [
                        "192.168.200.64"
                    ],
                    "mac": "0C:FE:C0:FF:EE:12",
                    "dns": {},
                    "device-info": {
                        "type": "vdpa",
                        "version": "1.0.0",
                        "vdpa": {
                            "parent-device": "vdpa1",
                            "driver": "vhost",
                            "path": "/dev/vhost-vdpa-1",
                            "pci-address": "0000:07:00.3"
                        }
                    }
                }]
Status:       Running
IP:           10.244.1.12
IPs:
  IP:  10.244.1.12
Containers:
  vdpa-single01:
    Container ID:  docker://df698de4764a4209703f9df3a641167cdf49222860d1e41f1c85de7ba1bb5146
    Image:         centos:latest
    Image ID:      docker-pullable://centos@sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
    Port:          
    Host Port:     
    Command:
      sleep
    Args:
      infinity
    State:          Running
      Started:      Thu, 03 Jun 2021 22:23:36 +0900
    Ready:          True
    Restart Count:  0
    Limits:
      intel.com/vdpa_mlx_vhost11:  1
      intel.com/vdpa_mlx_vhost12:  1
    Requests:
      intel.com/vdpa_mlx_vhost11:  1
      intel.com/vdpa_mlx_vhost12:  1
    Environment:                   
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-xst8f (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kube-api-access-xst8f:
    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  8m3s  multus   Add eth0 [10.244.1.12/24]
  Normal  AddedInterface  8m2s  multus   Add net1 [192.168.100.64/24] from default/vdpa-mlx-vhost-net11
  Normal  AddedInterface  8m2s  multus   Add net2 [192.168.200.64/24] from default/vdpa-mlx-vhost-net12
  Normal  Pulled          8m2s  kubelet  Container image "centos:latest" already present on machine
  Normal  Created         8m2s  kubelet  Created container vdpa-single01
  Normal  Started         8m1s  kubelet  Started container vdpa-single01

8-5.Workerの詳細確認 : Worker
[root@c83g152 ~]# ip link show ens2f0
8: ens2f0:  mtu 1500 qdisc mq 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 0c:fe:c0:ff:ee:11 brd ff:ff:ff:ff:ff:ff, vlan 100, spoof checking off, link-state auto, trust on, query_rss off
    vf 1     link/ether 0c:fe:c0:ff:ee:12 brd ff:ff:ff:ff:ff:ff, vlan 200, spoof checking off, link-state auto, trust on, query_rss off
[root@c83g152 ~]# ip link show ens2f1
9: ens2f1:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 94:40:c9:7e:1f:11 brd ff:ff:ff:ff:ff:ff
    vf 0     link/ether 0c:fe:c0:ff:ee:21 brd ff:ff:ff:ff:ff:ff, vlan 100, spoof checking off, link-state auto, trust on, query_rss off
    vf 1     link/ether 0c:fe:c0:ff:ee:22 brd ff:ff:ff:ff:ff:ff, vlan 200, spoof checking off, link-state auto, trust on, query_rss off

[root@c83g152 ~]# ls -Fal /sys/bus/vdpa/drivers/vhost_vdpa
total 0
drwxr-xr-x 2 root root    0 Jun  3 22:07 ./
drwxr-xr-x 3 root root    0 Jun  3 22:07 ../
--w------- 1 root root 4096 Jun  3 22:28 bind
lrwxrwxrwx 1 root root    0 Jun  3 22:28 module -> ../../../../module/vhost_vdpa/
--w------- 1 root root 4096 Jun  3 22:07 uevent
--w------- 1 root root 4096 Jun  3 22:28 unbind
lrwxrwxrwx 1 root root    0 Jun  3 22:28 vdpa0 -> ../../../../devices/pci0000:00/0000:00:03.0/0000:07:00.2/vdpa0/
lrwxrwxrwx 1 root root    0 Jun  3 22:28 vdpa1 -> ../../../../devices/pci0000:00/0000:00:03.0/0000:07:00.3/vdpa1/
lrwxrwxrwx 1 root root    0 Jun  3 22:28 vdpa2 -> ../../../../devices/pci0000:00/0000:00:03.0/0000:07:01.2/vdpa2/
lrwxrwxrwx 1 root root    0 Jun  3 22:28 vdpa3 -> ../../../../devices/pci0000:00/0000:00:03.0/0000:07:01.3/vdpa3/

[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             network        ConnectX Family mlx5Gen Virtual Function
pci@0000:07:00.3             network        ConnectX Family mlx5Gen Virtual Function
pci@0000:07:01.2             network        ConnectX Family mlx5Gen Virtual Function
pci@0000:07:01.3             network        ConnectX Family mlx5Gen Virtual Function

[root@c83g152 ~]# ls /dev
autofs           full          lp3     ptp4    shm       vcs2   vcsu5
block            fuse          mapper  ptp5    snapshot  vcs3   vcsu6
bsg              hpet          mcelog  ptp6    snd       vcs4   vfio
btrfs-control    hpilo         mem     ptp7    stderr    vcs5   vga_arbiter
bus              hugepages     mqueue  ptp8    stdin     vcs6   vhci
char             hwrng         net     ptp9    stdout    vcsa   vhost-net
cl               infiniband    null    pts     tty       vcsa1  vhost-vdpa-0
console          initctl       nvram   random  tty0      vcsa2  vhost-vdpa-1
core             input         port    raw     tty1      vcsa3  vhost-vdpa-2
cpu              ipmi0         ppp     rfkill  tty10     vcsa4  vhost-vdpa-3
cpu_dma_latency  kmsg          ptmx    rtc     tty11     vcsa5  vhost-vsock
disk             kvm           ptp0    rtc0    tty12     vcsa6  watchdog
dm-0             log           ptp1    sda     tty13     vcsu   watchdog0
dm-1             loop-control  ptp10   sda1    tty14     vcsu1  zero
dri              lp0           ptp11   sda2    tty15     vcsu2
fb0              lp1           ptp2    sg0     tty16     vcsu3
fd               lp2           ptp3    sg1     tty17     vcsu4


以上です。

9.最後に

以下のサイトを参考にさせて頂きました。
https://github.com/redhat-nfvpe/vdpa-deployment
https://docs.google.com/document/d/1DgZuksLVIVD5ZpNUNH7zPUr-8t6GKKQICDLqIwQv-FA/edit

今回はSR-IOVのLegacyモードを使用しましたが、次回はaccelerated-bridge-cniを使用して、swtichdevモードで検証してみたいと思います。
GitHub - k8snetworkplumbingwg/accelerated-bridge-cni

また、vDPAを使用した環境は、どれだけの組合せが存在するのかを考えましたが、少なくても2416通りくらいはありそうです。
2, 8は、過去記事で記載しました。9は、今回の記事となります。

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 DeflectionThis article
10 k8s pod kernel vhost switchdev vDPA の設定方法 vhost_vdpa + kubernetes + Accelerated Bridge CNI編 - Metonymical Deflection
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

これを全てやるのは効率が悪いので、ユースケースとして頻繁に利用されそうなものから、優先順位を付けて検証していきます。

なお、今回の内容は、以下の記事を理解できていれば、それほど難しくないと思いますので、やはり基礎の積み上げが大切だと実感しました。
vDPA の設定方法 vhost_vdpa + VM編 - Metonymical Deflection
CentOS8 KubernetesのSR-IOV設定方法 - Metonymical Deflection
今後、vDPAを利用している環境に遭遇したとき、どの組合せで構成されているのかを把握できることは大切ではないでしょうか?
クラウドネイティブ化するということは、抽象化が進むことを示唆しており、エンジニアとして、いつの間にか何もわからない状態になることだけは、避けなければいけないと考えています。

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

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

*3:swtichdevモードについては、Mellanoxが提供する”accelerated-bridge-cni”があり、今後検証していく予定です。GitHub - k8snetworkplumbingwg/accelerated-bridge-cni

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

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

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

*7:この他にdpdk-develやdpdk-appもビルドすることができます。しかし、外部NWと通信できなかったため、今回はPod上でDPDKを動作させずに、通常のCentOSのPodで通信させます。

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