第 8 章 硬件网络

8.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 集群中的其他网络搭配,用于需要高带宽或低延迟的应用程序。

8.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 来禁用。

8.1.1.1. 支持的设备

OpenShift Container Platform 支持以下网络接口卡 (NIC) 模式:

  • Intel XXV710-DA2 25G 卡,厂商 ID 0x8086,设备 ID 0x158b
  • Mellanox MT27710 系列 [ConnectX-4 Lx] 25G 卡,厂商 ID 0x15b3,设备 ID 0x1015
  • Mellanox MT27800 系列 [ConnectX-5] 100G 卡,厂商 ID 0x15b3,设备 ID 0x1017

8.1.1.2. 在 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 工作负载。

8.1.2. 后续步骤