注:
- 此教程需要访问 Oracle Cloud。要注册免费账户,请参阅开始使用 Oracle Cloud Infrastructure Free Tier 。
- 它使用 Oracle Cloud Infrastructure 身份证明、租户和区间示例值。完成实验室时,请将这些值替换为特定于云环境的那些值。
使用多用户 CNI 为 OKE 上的云池配置 SR-IOV 接口
简介
SR-IOV 是一种规范,允许单个 PCIe 设备显示为多个单独的物理 PCIe 设备。SR-IOV 通过引入物理功能 (physical function,PF) 和虚拟功能 (virtual function,VF) 的理念来发挥作用。PF 由主机使用,通常表示单个 NIC 端口。VF 是 PF 的轻量级版本。在适当的支持下,SR-IOV 为物理硬件(如 SmartNIC)提供了一种将自身作为多个不同的(网络接口)设备呈现的方式。通过容器,我们可以将这些接口 (VF) 之一从主机移到容器或 Pod 的网络名称空间中,以便容器现在可以直接访问接口。这种优势在于,我们不会使用 virt-io
获取任何开销,也不会获得本机设备性能。
注:本教程中介绍的插件和流程仅适用于裸金属实例。对于基于虚拟机的实例,需要一组不同的插件和配置。
目标
本教程介绍了如何为在 OKE 群集上运行的 pod 设置基于 SR-IOV 虚拟功能的辅助网络接口。它利用 SRIOV-CNI 插件将 SR-IOV 虚拟功能管理为可以在节点上分配的资源,使用多用户元 CNI 将其他网络接口添加到 pod。
工作原理
该方法具有多个层和组件。Kubernetes 设备插件管理一组虚拟功能并将其发布为节点上的可分配资源。当 pod 请求此类资源时,可以将 pod 分配给资源可用的节点,而 SR-IOV CNI 可以将虚拟功能激活到 pod 的网络名称空间中。CNI 元插件(如 Multus)处理 Pod 的多个网络附件,以便 Pod 可以通过 SR-IOV 和叠加网络进行通信。
我们首先在支持 SR-IOV 的 smartNICs 上设置了一些 VF,然后将自己呈现为单个 NIC。然后,我们将这些 VF 配置为 Oracle Cloud Infrastructure (OCI) 可识别的 MAC 地址。这些 VF 是在多用户外部创建的,可以是手动创建的(如本教程中所述),也可以是在创建节点时调用的脚本。此时,我们有一个 VF 池,每个 VF 由主机标识为单独的 NIC 和 OCI MAC 地址。Kubernetes 网络检测工作组维护了一个专用网络设备插件,该插件将搜索 VF 并发布为可分配的节点资源。SR-IOV CNI(也来自 Kubernetes 网络检测工作组)与设备插件一起工作,并根据云池生命周期管理这些虚拟功能的分配。
现在,我们有一个或多个节点具有 VF 池,这些 VF 由 SR-IOV 设备插件识别和管理,作为可分配的节点资源。这些可由 pod 请求。SR-IOV CNI 在创建云池时将 VF 激活(移动)到云池的网络名称空间,并在删除云池时释放 VF(将其移回根名称空间)。这使 VF 可分配给其他云池。像 Multus 这样的元插件可以为 CNI 提供 VF 信息并管理 Pod 上的多个网络附件。
任务 1:设置主机
我们从裸金属主机开始,可在其中为 PCIe 接口设置 VF。对于裸金属主机,我们执行以下步骤。
-
创建 VF:通过 SSH 连接到裸金属节点。查找物理设备并向其添加虚拟功能。
注:仅自动化需要用于获取设备名称的脚本。
此处的示例在设备上创建两个 VF。
# Gets the physical device. Alterntively, just run `ip addr show` and look at the primary iface to set $PHYSDEV URL=http://169.254.169.254/opc/v1/vnics/ baseAddress=`curl -s ${URL} | jq -r '.[0] | .privateIp'` PHYSDEV=`ip -o -4 addr show | grep ${baseAddress} | awk -F: '{gsub(/^[ \t]|[ \t]$/,"",$2);split($2,out,/[ \t]+/);print out[1]}'` # Add two VFs echo "2" > /sys/class/net/${PHYSDEV}/device/sriov_numvfs # Verify the VFs ip link show ${PHYSDEV}
-
将 OCI MAC 地址分配给 VF。
这些 VF 现在将具有自动生成的 MAC 地址(或 000)。我们需要为来自这些通信的 OCI MAC 地址设置为允许在 OCI 网络上使用。在主机上创建与创建的 VF 数相同的 VNIC 附件数。记下每个 VNIC 附件的 MAC 地址。现在,我们将 OCI 识别的每个 MAC 地址分配给我们创建的 VFS。
# For each MAC address from the VNIC attachments ip link set ${PHYSDEV} vf <n= 0..numVFs> mac <MAC Address from VNIC attachment> spoofchk off # verify all VFs have Mac addresses from OCI ip link show ${PHYSDEV}
这将完成主机设置(最好是自动执行),因为需要在需要向云池提供 SR-IOV 网络资源的每台主机上执行该设置。
任务 2:安装 SR-IOV CNI
此 CNI 可以作为守护进程集安装在 1.16+ 群集上。没有 SR-IOV 设备的节点由设备插件本身以正常方式进行处理。
git clone https://github.com/k8snetworkplumbingwg/sriov-cni.git && cd sriov-cni
kubectl apply -f images/k8s-v1.16/sriov-cni-daemonset.yaml && cd..
任务 3:安装 SR-IOV 网络设备插件
注:设备插件不会实时创建 VF,必须单独创建它们。
设备插件在节点上搜索并通告支持 SR-IOV 的网络设备。要实现此目的,设备插件需要一种配置,使它能够创建设备插件端点。配置标识所使用的设备和驱动程序。
-
为 SR-IOV 资源池创建 ConfigMap。要设置 ConfigMap,我们需要知道设备使用的供应商 ID、设备 ID 和驱动程序。
-
要查找供应商 ID 和设备 ID,请执行以下操作:
lspci -nn|grep Virtual 31:02.0 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme-E Ethernet Virtual Function [14e4:16dc] 31:02.1 Ethernet controller [0200]: Broadcom Inc. and subsidiaries NetXtreme-E Ethernet Virtual Function [14e4:16dc]
-
在上例中,我们有两个 VF,最后的信息位为我们提供了供应商 ID (
14e4
) 和设备 ID (16dc
)。我们可以使用lspci
使用的 hwdata 进行交叉检查。cat /usr/share/hwdata/pci.ids|grep 16dc
-
要查找使用的驱动程序,请执行以下操作:
# filtering based on the PCIe slots. find /sys | grep drivers.*31:02.0|awk -F/ '{print $6}' bnxt_en
-
-
设置 ConfigMap。ConfigMap 应命名为
sriovdp-config
,并且应具有键config.json
cat << EOF > sriovdp-config.yaml apiVersion: v1 kind: ConfigMap metadata: name: sriovdp-config namespace: kube-system data: config.json: | { "resourceList": [{ "resourceName": "mlnx_sriov_rdma", "resourcePrefix": "mellanox.com", "selectors": { "vendors": ["15b3"], "devices": ["101e"], "drivers": ["mlx5_core"], "isRdma": false } }, { "resourceName": "netxtreme_sriov_rdma", "resourcePrefix": "broadcom.com", "selectors": { "vendors": ["14e4"], "devices": ["16dc"], "drivers": ["bnxt_en"], "isRdma": false } } ] } EOF kubectl create -f sriovdp-config.yaml
-
设置设备插件。创建配置映射后,可以将设备插件安装为守护进程集。
git clone https://github.com/k8snetworkplumbingwg/sriov-network-device-plugin.git && cd sriov-network-device-plugin kubectl create -f deployments/k8s-v1.16/sriovdp-daemonset.yaml && cd ..
-
部署守护进程后,您可以查看容器日志以进行故障排除。成功部署后,节点应列出虚拟功能作为可分配资源。
kubectl get node <node_name> -o json | jq '.status.allocatable' { "broadcom.com/netxtreme_sriov_rdma": "2", "cpu": "128", "ephemeral-storage": "37070025462", "hugepages-1Gi": "0", "hugepages-2Mi": "0", "memory": "527632840Ki", "pods": "110" }
任务 4:安装元插件 CNI(多用户)
Multus 是一个元插件,它可以向下游 CNI 提供 VF 信息,例如 SR-IOV CNI 插件,用于在启用具有多个网络接口的“多宿主”云池或云池时处理网络资源检测。
-
安装多用户:
git clone https://github.com/k8snetworkplumbingwg/multus-cni.git && cd multus-cni kubectl apply -f images/multus-daemonset.yml && cd ..
注:
-
标记为
stable
的守护进程集使用的默认映像需要 kubelet 为v1.20.x
。如果在较旧的群集上进行安装,请编辑清单中的 deamonset 并使用多用户映像标记v3.7.1
。 -
此清单为
kind:NetworkAttachmentDefinition
创建新的 CRD 并通过守护进程集在所有节点上提供多用户二进制文件。
-
-
要将其他接口附加到 pod,我们需要配置要连接的接口。这封装在
NetworkAttachmentDefinition
类型的定制资源中。此配置本质上是打包为定制资源的 CNI 配置。我们来设置一个示例 NetworkAttachmentDefinition
cat << EOF > sriov-net1.yaml apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition metadata: name: sriov-net1 annotations: k8s.v1.cni.cncf.io/resourceName: broadcom.com/netxtreme_sriov_rdma spec: config: '{ "type": "sriov", "cniVersion": "0.3.1", "name": "sriov-network", "ipam": { "type": "host-local", "subnet": "10.20.30.0/25", "routes": [{ "dst": "0.0.0.0/0" }], "gateway": "10.20.10.1" } }' EOF kubectl apply -f sriov-net1.yaml
任务 5:使用多个接口部署和测试云池
-
Pod 现在可以使用注释和资源请求请求请求其他接口。资源请求将帮助调度程序根据节点上的 VF 可用性分配 pod,注释允许元插件 (Multus) 知道要使用的
NetworkAttachmentDefinition
(CNI 配置)。下面是一个带测试 pod 的示例:
## Create the first pod cat << EOF | kubectl create -f - apiVersion: v1 kind: Pod metadata: name: testpod1 annotations: k8s.v1.cni.cncf.io/networks: sriov-net1 spec: containers: - name: appcntr1 image: centos/tools imagePullPolicy: IfNotPresent command: [ "/bin/bash", "-c", "--" ] args: [ "while true; do sleep 300000; done;" ] resources: requests: broadcom.com/netxtreme_sriov_rdma: '1' limits: broadcom.com/netxtreme_sriov_rdma: '1' EOF ## Create a second pod cat << EOF | kubectl create -f - apiVersion: v1 kind: Pod metadata: name: testpod2 annotations: k8s.v1.cni.cncf.io/networks: sriov-net1 spec: containers: - name: appcntr1 image: centos/tools imagePullPolicy: IfNotPresent command: [ "/bin/bash", "-c", "--" ] args: [ "while true; do sleep 300000; done;" ] resources: requests: broadcom.com/netxtreme_sriov_rdma: '1' limits: broadcom.com/netxtreme_sriov_rdma: '1' EOF
-
创建了两个 pod,我们应该看到它们都在运行。快速测试:
## Verify that both pods have two interfaces. An `eth0` on the overlay and a `net1` which is the VF. kubectl exec -it testpod1 -- ip addr show kubectl exec -it testpod2 -- ip addr show ## Checkout the routes kubectl exec -it testpod1 -- route -n kubectl exec -it testpod2 -- route -n ## test communication kubectl exec -it testpod1 -- ping <IP for net1 on pod2>
相关链接
确认
- 作者 - 首席产品经理 Jeevan Joseph
更多学习资源
探索 docs.oracle.com/learn 上的其他实验室,或者访问 Oracle Learning YouTube 频道上的更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 成为 Oracle Learning Explorer。
有关产品文档,请访问 Oracle 帮助中心。
Configure SR-IOV interfaces for pods on OKE using Multus CNI
F75772-01
January 2023
Copyright © 2023, Oracle and/or its affiliates.