第 9 章 硬件网络
9.1. 关于单根 I/O 虚拟化(SR-IOV)硬件网络
Single Root I/O 虚拟化 (SR-IOV) 规范是针对一类 PCI 设备分配的标准,可与多个 pod 共享单个设备。
通过 SR-IOV,您可以将主机节点上识别为物理功能 (PF) 的兼容网络设备分段为多个虚拟功能 (VF)。VF 和其它网络设备一样使用。该设备的 SR-IOV 设备驱动程序决定了如何公开容器中的 VF:
-
netdevice
驱动程序: 容器netns
中的常规内核网络设备 -
vfio-pci
驱动程序: 挂载到容器中的字符设备
您可以将 SR-IOV 网络设备与 OpenShift Container Platform 集群中的其他网络搭配,用于需要高带宽或低延迟的应用程序。
9.1.1. 负责管理 SR-IOV 网络设备的组件
SR-IOV Network Operator 会创建和管理 SR-IOV 堆栈的组件。它执行以下功能:
- 编配 SR-IOV 网络设备的发现和管理
-
为 SR-IOV Container Network Interface(CNI)生成
NetworkAttachmentDefinition
自定义资源 - 创建和更新 SR-IOV 网络设备插件的配置
-
创建节点特定的
SriovNetworkNodeState
自定义资源 -
更新每个
SriovNetworkNodeState
自定义资源中的spec.interfaces
字段
Operator 置备以下组件:
- SR-IOV 网络配置守护进程
- SR-IOV Operator 启动时在 worker 节点上部署的 DaemonSet。守护进程负责在集群中发现和初始化 SR-IOV 网络设备。
- SR-IOV Operator Webhook
- 这是动态准入控制器 Webhook,用于验证 Operator 自定义资源,并为未设置的字段设置适当的默认值。
- SR-IOV Network Resources Injector(网络资源注入器)。
- 这是一个动态准入控制器 Webhook,它提供通过请求和限制为自定义网络资源(如 SR-IOV VF)应用 Kubernetes pod 规格的功能。
- SR-IOV 网络设备插件
- 这个设备插件用于发现、公告并分配 SR-IOV 网络虚拟功能 (VF) 资源。在 Kubernetes 中使用设备插件能够利用有限的资源,这些资源通常为于物理设备中。设备插件可以使 Kubernetes 调度程序了解资源可用性,因此调度程序可以在具有足够资源的节点上调度 pod。
- SR-IOV CNI 插件
- SR-IOV CNI 插件会附加从 SR-IOV 设备插件中直接分配给 pod 的 VF 接口。
SR-IOV Network resources injector 和 SR-IOV Operator Webhook 会被默认启用,可通过编辑 default
SriovOperatorConfig
CR 来禁用。
9.1.1.1. 支持的设备
OpenShift Container Platform 支持以下网络接口卡 (NIC) 模式:
-
Intel XXV710 25GbE SFP28 卡,厂商 ID
0x8086
,设备 ID0x158b
-
Mellanox MT27710 系列 [ConnectX-4 Lx] 25G dual-port SFP28 卡,厂商 ID
0x15b3
,设备 ID0x1015
-
Mellanox MT27800 系列 [ConnectX-5] 25GbE dual-port SFP28 卡,厂商 ID
0x15b3
,设备 ID0x1017
-
Mellanox MT27800 系列 [ConnectX-5] 100GbE 卡,厂商 ID
0x15b3
,设备 ID0x1017
9.1.1.2. 自动发现 SR-IOV 网络设备
SR-IOV Network Operator 将搜索集群以获取 worker 节点上的 SR-IOV 功能网络设备。Operator 会为每个提供兼容 SR-IOV 网络设备的 worker 节点创建并更新一个 SriovNetworkNodeState 自定义资源 (CR) 。
为 CR 分配了与 worker 节点相同的名称。status.interfaces
列表提供有关节点上网络设备的信息。
不要修改 SriovNetworkNodeState
对象。Operator 会自动创建和管理这些资源。
9.1.1.2.1. SriovNetworkNodeState
对象示例
以下 YAML 是由 SR-IOV Network Operator 创建的 SriovNetworkNodeState
对象的示例:
一 个 SriovNetworkNodeState 对象
apiVersion: sriovnetwork.openshift.io/v1 kind: SriovNetworkNodeState metadata: name: node-25 1 namespace: openshift-sriov-network-operator ownerReferences: - apiVersion: sriovnetwork.openshift.io/v1 blockOwnerDeletion: true controller: true kind: SriovNetworkNodePolicy name: default spec: dpConfigVersion: "39824" status: interfaces: 2 - deviceID: "1017" driver: mlx5_core mtu: 1500 name: ens785f0 pciAddress: "0000:18:00.0" totalvfs: 8 vendor: 15b3 - deviceID: "1017" driver: mlx5_core mtu: 1500 name: ens785f1 pciAddress: "0000:18:00.1" totalvfs: 8 vendor: 15b3 - deviceID: 158b driver: i40e mtu: 1500 name: ens817f0 pciAddress: 0000:81:00.0 totalvfs: 64 vendor: "8086" - deviceID: 158b driver: i40e mtu: 1500 name: ens817f1 pciAddress: 0000:81:00.1 totalvfs: 64 vendor: "8086" - deviceID: 158b driver: i40e mtu: 1500 name: ens803f0 pciAddress: 0000:86:00.0 totalvfs: 64 vendor: "8086" syncStatus: Succeeded
9.1.1.3. 在 pod 中使用虚拟功能的示例
您可以在附加了 SR-IOV VF 的 pod 中运行远程直接内存访问 (RDMA) 或 Data Plane Development Kit (DPDK) 应用程序。
本示例演示了在 RDMA 模式中使用虚拟功能 (VF) 的 pod:
使用 RDMA 模式的 Pod
规格
apiVersion: v1 kind: Pod metadata: name: rdma-app annotations: k8s.v1.cni.cncf.io/networks: sriov-rdma-mlnx spec: containers: - name: testpmd image: <RDMA_image> imagePullPolicy: IfNotPresent securityContext: capabilities: add: ["IPC_LOCK"] command: ["sleep", "infinity"]
以下示例演示了在 DPDK 模式中使用 VF 的 pod:
使用 DPDK 模式的 Pod
规格
apiVersion: v1 kind: Pod metadata: name: dpdk-app annotations: k8s.v1.cni.cncf.io/networks: sriov-dpdk-net spec: containers: - name: testpmd image: <DPDK_image> securityContext: capabilities: add: ["IPC_LOCK"] volumeMounts: - mountPath: /dev/hugepages name: hugepage resources: limits: memory: "1Gi" cpu: "2" hugepages-1Gi: "4Gi" requests: memory: "1Gi" cpu: "2" hugepages-1Gi: "4Gi" command: ["sleep", "infinity"] volumes: - name: hugepage emptyDir: medium: HugePages
可以使用一个可选的库来协助容器中运行的应用程序收集与 pod 关联的网络信息。这个程序库名为 'app-netutil'。这个库的源代码包括在 app-netutil
GitHub repo 中。
这个库的目的是简化将 SR-IOV VF 整合到 DPDK 模式中的操作。该程序库提供 GO API 和 C API,并包括了使用这两种语言的示例。
还有一个 Docker 镜像示例 'dpdk-app-centos',它可以根据 pod-spec: l2fwd 、l3wd 或 testpmd 中的环境变量运行以下 DPDK 示例应用程序之一。这个 Docker 镜像提供了将 'app-netutil' 整合到容器镜像本身的示例。这个库也可以整合到初始容器(init-container)中,该容器收集所需数据并将数据传递给现有的 DPDK 工作负载。