×

在 DPDK 模式下使用英特尔网卡的虚拟函数

先决条件
  • 安装 OpenShift CLI(oc)。

  • 安装 SR-IOV 网络操作符。

  • 以具有 cluster-admin 权限的用户身份登录。

步骤
  1. 创建以下 SriovNetworkNodePolicy 对象,然后将 YAML 保存到 intel-dpdk-node-policy.yaml 文件中。

    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetworkNodePolicy
    metadata:
      name: intel-dpdk-node-policy
      namespace: openshift-sriov-network-operator
    spec:
      resourceName: intelnics
      nodeSelector:
        feature.node.kubernetes.io/network-sriov.capable: "true"
      priority: <priority>
      numVfs: <num>
      nicSelector:
        vendor: "8086"
        deviceID: "158b"
        pfNames: ["<pf_name>", ...]
        rootDevices: ["<pci_bus_id>", "..."]
      deviceType: vfio-pci (1)
    1 将虚拟函数的驱动程序类型指定为 vfio-pci

    请参阅“配置 SR-IOV 网络设备”部分,了解 SriovNetworkNodePolicy 中每个选项的详细说明。

    应用 SriovNetworkNodePolicy 对象中指定的配置时,SR-IOV 操作符可能会驱逐节点,在某些情况下还会重新启动节点。配置更改的应用可能需要几分钟时间。请确保您的集群中有足够的可用节点来处理预先驱逐的工作负载。

    应用配置更新后,openshift-sriov-network-operator 命名空间中的所有 Pod 将变为 运行中 状态。

  2. 运行以下命令创建 SriovNetworkNodePolicy 对象

    $ oc create -f intel-dpdk-node-policy.yaml
  3. 创建以下 SriovNetwork 对象,然后将 YAML 保存到 intel-dpdk-network.yaml 文件中。

    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetwork
    metadata:
      name: intel-dpdk-network
      namespace: openshift-sriov-network-operator
    spec:
      networkNamespace: <target_namespace>
      ipam: |-
    # ... (1)
      vlan: <vlan>
      resourceName: intelnics
    1 将 IPAM CNI 插件的配置对象指定为 YAML 块标量。该插件管理附件定义的 IP 地址分配。

    请参阅“配置 SR-IOV 附加网络”部分,了解 SriovNetwork 中每个选项的详细说明。

    可选库 app-netutil 提供了几种 API 方法,用于收集有关容器的父 Pod 的网络信息。

  4. 运行以下命令创建 SriovNetwork 对象

    $ oc create -f intel-dpdk-network.yaml
  5. 创建以下 Pod 规范,然后将 YAML 保存到 intel-dpdk-pod.yaml 文件中。

    apiVersion: v1
    kind: Pod
    metadata:
      name: dpdk-app
      namespace: <target_namespace> (1)
      annotations:
        k8s.v1.cni.cncf.io/networks: intel-dpdk-network
    spec:
      containers:
      - name: testpmd
        image: <DPDK_image> (2)
        securityContext:
          runAsUser: 0
          capabilities:
            add: ["IPC_LOCK","SYS_RESOURCE","NET_RAW"] (3)
        volumeMounts:
        - mountPath: /mnt/huge (4)
          name: hugepage
        resources:
          limits:
            openshift.io/intelnics: "1" (5)
            memory: "1Gi"
            cpu: "4" (6)
            hugepages-1Gi: "4Gi" (7)
          requests:
            openshift.io/intelnics: "1"
            memory: "1Gi"
            cpu: "4"
            hugepages-1Gi: "4Gi"
        command: ["sleep", "infinity"]
      volumes:
      - name: hugepage
        emptyDir:
          medium: HugePages
    1 指定与创建 SriovNetwork 对象 intel-dpdk-networktarget_namespace 相同的命名空间。如果您想在不同的命名空间中创建 Pod,请更改 Pod 规范和 SriovNetwork 对象中的 target_namespace
    2 指定包含您的应用程序和应用程序使用的 DPDK 库的 DPDK 镜像。
    3 指定容器内应用程序所需的附加功能,用于巨页分配、系统资源分配和网络接口访问。
    4 将巨页卷挂载到 /mnt/huge 下的 DPDK Pod。巨页卷由 emptyDir 卷类型支持,介质为 Hugepages
    5 可选:指定分配给 DPDK Pod 的 DPDK 设备数量。如果没有显式指定,则 SR-IOV 网络资源注入器会自动添加此资源请求和限制。SR-IOV 网络资源注入器是由 SR-IOV 操作符管理的准入控制器组件。它默认启用,可以通过在默认 SriovOperatorConfig CR 中将 enableInjector 选项设置为 false 来禁用。
    6 指定 CPU 数量。DPDK Pod 通常需要从 kubelet 分配专用 CPU。这是通过将 CPU 管理器策略设置为 static 并创建具有 Guaranteed QoS 的 Pod 来实现的。
    7 指定巨页大小 hugepages-1Gihugepages-2Mi 以及将分配给 DPDK Pod 的巨页数量。分别配置 2Mi1Gi 巨页。配置 1Gi 巨页需要向节点添加内核参数。例如,添加内核参数 default_hugepagesz=1GBhugepagesz=1Ghugepages=16 将导致在系统启动期间分配 16*1Gi 巨页。
  6. 运行以下命令创建 DPDK Pod

    $ oc create -f intel-dpdk-pod.yaml

在 DPDK 模式下使用 Mellanox 网卡的虚拟函数

您可以使用 DPDK 模式下的虚拟函数和 Mellanox 网卡创建网络节点策略和数据平面开发套件 (DPDK) Pod。

先决条件
  • 您已安装 OpenShift CLI(oc)。

  • 您已安装单根 I/O 虚拟化 (SR-IOV) 网络操作符。

  • 您已以具有 cluster-admin 权限的用户身份登录。

步骤
  1. 将以下 SriovNetworkNodePolicy YAML 配置保存到 mlx-dpdk-node-policy.yaml 文件中

    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetworkNodePolicy
    metadata:
      name: mlx-dpdk-node-policy
      namespace: openshift-sriov-network-operator
    spec:
      resourceName: mlxnics
      nodeSelector:
        feature.node.kubernetes.io/network-sriov.capable: "true"
      priority: <priority>
      numVfs: <num>
      nicSelector:
        vendor: "15b3"
        deviceID: "1015" (1)
        pfNames: ["<pf_name>", ...]
        rootDevices: ["<pci_bus_id>", "..."]
      deviceType: netdevice (2)
      isRdma: true (3)
    1 指定 SR-IOV 网络设备的设备十六进制代码。
    2 将虚拟函数的驱动程序类型指定为 netdevice。Mellanox SR-IOV 虚拟函数 (VF) 可以在 DPDK 模式下工作,无需使用 vfio-pci 设备类型。VF 设备显示为容器内的内核网络接口。
    3 启用远程直接内存访问 (RDMA) 模式。Mellanox 网卡在 DPDK 模式下工作需要此模式。

    请参阅“配置 SR-IOV 网络设备”了解 SriovNetworkNodePolicy 对象中每个选项的详细说明。

    应用 SriovNetworkNodePolicy 对象中指定的配置时,SR-IOV 操作符可能会驱逐节点,在某些情况下还会重新启动节点。配置更改的应用可能需要几分钟时间。请确保您的集群中有足够的可用节点来处理预先驱逐的工作负载。

    应用配置更新后,openshift-sriov-network-operator 命名空间中的所有 Pod 将变为 运行中 状态。

  2. 运行以下命令创建 SriovNetworkNodePolicy 对象

    $ oc create -f mlx-dpdk-node-policy.yaml
  3. 将以下 SriovNetwork YAML 配置保存到 mlx-dpdk-network.yaml 文件中

    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetwork
    metadata:
      name: mlx-dpdk-network
      namespace: openshift-sriov-network-operator
    spec:
      networkNamespace: <target_namespace>
      ipam: |- (1)
    ...
      vlan: <vlan>
      resourceName: mlxnics
    1 将 IP 地址管理 (IPAM) 容器网络接口 (CNI) 插件的配置对象指定为 YAML 块标量。该插件管理附件定义的 IP 地址分配。

    请参阅“配置 SR-IOV 网络设备”了解 SriovNetwork 对象中每个选项的详细说明。

    app-netutil 可选库提供了几种 API 方法,用于收集有关容器的父 Pod 的网络信息。

  4. 运行以下命令创建 SriovNetwork 对象

    $ oc create -f mlx-dpdk-network.yaml
  5. 将以下 Pod YAML 配置保存到 mlx-dpdk-pod.yaml 文件中

    apiVersion: v1
    kind: Pod
    metadata:
      name: dpdk-app
      namespace: <target_namespace> (1)
      annotations:
        k8s.v1.cni.cncf.io/networks: mlx-dpdk-network
    spec:
      containers:
      - name: testpmd
        image: <DPDK_image> (2)
        securityContext:
          runAsUser: 0
          capabilities:
            add: ["IPC_LOCK","SYS_RESOURCE","NET_RAW"] (3)
        volumeMounts:
        - mountPath: /mnt/huge (4)
          name: hugepage
        resources:
          limits:
            openshift.io/mlxnics: "1" (5)
            memory: "1Gi"
            cpu: "4" (6)
            hugepages-1Gi: "4Gi" (7)
          requests:
            openshift.io/mlxnics: "1"
            memory: "1Gi"
            cpu: "4"
            hugepages-1Gi: "4Gi"
        command: ["sleep", "infinity"]
      volumes:
      - name: hugepage
        emptyDir:
          medium: HugePages
    1 指定与创建 SriovNetwork 对象 mlx-dpdk-networktarget_namespace 相同的命名空间。要在不同的命名空间中创建 Pod,请更改 Pod 规范和 SriovNetwork 对象中的 target_namespace
    2 指定包含您的应用程序和应用程序使用的 DPDK 库的 DPDK 镜像。
    3 指定容器内应用程序所需的附加功能,用于巨页分配、系统资源分配和网络接口访问。
    4 将巨页卷挂载到 /mnt/huge 下的 DPDK Pod。巨页卷由 emptyDir 卷类型支持,介质为 Hugepages
    5 可选:指定分配给 DPDK Pod 的 DPDK 设备数量。如果没有显式指定,则 SR-IOV 网络资源注入器会自动添加此资源请求和限制。SR-IOV 网络资源注入器是由 SR-IOV 操作符管理的准入控制器组件。它默认启用,可以通过在默认 SriovOperatorConfig CR 中将 enableInjector 选项设置为 false 来禁用。
    6 指定 CPU 数量。DPDK Pod 通常需要从 kubelet 分配专用 CPU。为此,请将 CPU 管理器策略设置为 static 并创建具有 Guaranteed 服务质量 (QoS) 的 Pod。
    7 指定巨页大小为hugepages-1Gihugepages-2Mi,以及将分配给DPDK pod的巨页数量。分别配置2Mi1Gi巨页。配置1Gi巨页需要向节点添加内核参数。
  6. 运行以下命令创建 DPDK Pod

    $ oc create -f mlx-dpdk-pod.yaml

使用TAP CNI运行具有内核访问权限的无根DPDK工作负载

DPDK应用程序可以使用virtio-user作为异常路径,将某些类型的分组(例如日志消息)注入内核进行处理。有关此功能的更多信息,请参见Virtio_user作为异常路径

在OpenShift Container Platform 4.14及更高版本中,您可以使用非特权Pod来运行DPDK应用程序以及tap CNI插件。要启用此功能,需要通过在SriovNetworkNodePolicy对象中将needVhostNet参数设置为true来挂载vhost-net设备。

DPDK and TAP plugin
图1. DPDK和TAP示例配置
先决条件
  • 您已安装 OpenShift CLI(oc)。

  • 您已安装SR-IOV网络操作员。

  • 您已以具有cluster-admin权限的用户身份登录。

  • 确保在所有节点上以root用户身份设置setsebools container_use_devices=on

    使用Machine Config Operator设置此SELinux布尔值。

步骤
  1. 创建一个文件,例如test-namespace.yaml,内容如下例所示

    apiVersion: v1
    kind: Namespace
    metadata:
      name: test-namespace
      labels:
        pod-security.kubernetes.io/enforce: privileged
        pod-security.kubernetes.io/audit: privileged
        pod-security.kubernetes.io/warn: privileged
        security.openshift.io/scc.podSecurityLabelSync: "false"
  2. 通过运行以下命令创建新的Namespace对象

    $ oc apply -f test-namespace.yaml
  3. 创建一个文件,例如sriov-node-network-policy.yaml,内容如下例所示:

    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetworkNodePolicy
    metadata:
     name: sriovnic
     namespace: openshift-sriov-network-operator
    spec:
     deviceType: netdevice (1)
     isRdma: true (2)
     needVhostNet: true (3)
     nicSelector:
       vendor: "15b3" (4)
       deviceID: "101b" (5)
       rootDevices: ["00:05.0"]
     numVfs: 10
     priority: 99
     resourceName: sriovnic
     nodeSelector:
        feature.node.kubernetes.io/network-sriov.capable: "true"
    1 这表明该配置文件是专门为Mellanox网络接口控制器(NIC)定制的。
    2 仅当使用Mellanox NIC时,才需要将isRdma设置为true
    3 这会将/dev/net/tun/dev/vhost-net设备挂载到容器中,以便应用程序可以创建tap设备并将tap设备连接到DPDK工作负载。
    4 SR-IOV网络设备的供应商十六进制代码。值15b3与Mellanox NIC相关联。
    5 SR-IOV网络设备的设备十六进制代码。
  4. 运行以下命令创建 SriovNetworkNodePolicy 对象

    $ oc create -f sriov-node-network-policy.yaml
  5. 创建以下SriovNetwork对象,然后将YAML保存到sriov-network-attachment.yaml文件中

    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetwork
    metadata:
     name: sriov-network
     namespace: openshift-sriov-network-operator
    spec:
     networkNamespace: test-namespace
     resourceName: sriovnic
     spoofChk: "off"
     trust: "on"

    请参阅“配置 SR-IOV 附加网络”部分,了解 SriovNetwork 中每个选项的详细说明。

    一个可选库app-netutil提供了一些API方法,用于收集有关容器父Pod的网络信息。

  6. 运行以下命令创建 SriovNetwork 对象

    $ oc create -f sriov-network-attachment.yaml
  7. 创建一个文件,例如tap-example.yaml,该文件定义网络附件定义,内容如下例所示

    apiVersion: "k8s.cni.cncf.io/v1"
    kind: NetworkAttachmentDefinition
    metadata:
     name: tap-one
     namespace: test-namespace (1)
    spec:
     config: '{
       "cniVersion": "0.4.0",
       "name": "tap",
       "plugins": [
         {
            "type": "tap",
            "multiQueue": true,
            "selinuxcontext": "system_u:system_r:container_t:s0"
         },
         {
           "type":"tuning",
           "capabilities":{
             "mac":true
           }
         }
       ]
     }'
    1 指定与创建SriovNetwork对象相同的target_namespace
  8. 通过运行以下命令创建NetworkAttachmentDefinition对象

    $ oc apply -f tap-example.yaml
  9. 创建一个文件,例如dpdk-pod-rootless.yaml,内容如下例所示

    apiVersion: v1
    kind: Pod
    metadata:
      name: dpdk-app
      namespace: test-namespace (1)
      annotations:
        k8s.v1.cni.cncf.io/networks: '[
          {"name": "sriov-network", "namespace": "test-namespace"},
          {"name": "tap-one", "interface": "ext0", "namespace": "test-namespace"}]'
    spec:
      nodeSelector:
        kubernetes.io/hostname: "worker-0"
      securityContext:
          fsGroup: 1001 (2)
          runAsGroup: 1001 (3)
          seccompProfile:
            type: RuntimeDefault
      containers:
      - name: testpmd
        image: <DPDK_image> (4)
        securityContext:
          capabilities:
            drop: ["ALL"] (5)
            add: (6)
              - IPC_LOCK
              - NET_RAW #for mlx only (7)
          runAsUser: 1001 (8)
          privileged: false (9)
          allowPrivilegeEscalation: true (10)
          runAsNonRoot: true (11)
        volumeMounts:
        - mountPath: /mnt/huge (12)
          name: hugepages
        resources:
          limits:
            openshift.io/sriovnic: "1" (13)
            memory: "1Gi"
            cpu: "4" (14)
            hugepages-1Gi: "4Gi" (15)
          requests:
            openshift.io/sriovnic: "1"
            memory: "1Gi"
            cpu: "4"
            hugepages-1Gi: "4Gi"
        command: ["sleep", "infinity"]
      runtimeClassName: performance-cnf-performanceprofile (16)
      volumes:
      - name: hugepages
        emptyDir:
          medium: HugePages
    1 指定与创建SriovNetwork对象相同的target_namespace。如果要在不同的命名空间中创建Pod,请更改Pod规范和SriovNetwork对象中的target_namespace
    2 设置在这些卷中创建的卷装载目录和文件的组所有权。
    3 指定用于运行容器的主组ID。
    4 指定包含您的应用程序和应用程序使用的DPDK库的DPDK镜像。
    5 从容器的securityContext中删除所有功能(ALL)意味着容器除了正常运行所需的功能外,没有其他特殊权限。
    6 指定容器内应用程序分配巨页、系统资源分配和网络接口访问所需的附加功能。这些功能也必须使用setcap命令在二进制文件中设置。
    7 Mellanox网络接口控制器(NIC)需要NET_RAW功能。
    8 指定用于运行容器的用户ID。
    9 此设置表示不应向Pod中的容器或容器授予对主机系统的特权访问。
    10 此设置允许容器将权限提升到其最初分配的非root权限之外。
    11 此设置确保容器以非root用户身份运行。这有助于强制执行最小权限原则,限制破坏容器的潜在影响并减少攻击面。
    12 将巨页卷挂载到 /mnt/huge 下的 DPDK Pod。巨页卷由 emptyDir 卷类型支持,介质为 Hugepages
    13 可选:指定分配给 DPDK Pod 的 DPDK 设备数量。如果没有显式指定,则 SR-IOV 网络资源注入器会自动添加此资源请求和限制。SR-IOV 网络资源注入器是由 SR-IOV 操作符管理的准入控制器组件。它默认启用,可以通过在默认 SriovOperatorConfig CR 中将 enableInjector 选项设置为 false 来禁用。
    14 指定 CPU 数量。DPDK Pod 通常需要从 kubelet 分配专用 CPU。这是通过将 CPU 管理器策略设置为 static 并创建具有 Guaranteed QoS 的 Pod 来实现的。
    15 指定巨页大小 hugepages-1Gihugepages-2Mi 以及将分配给 DPDK Pod 的巨页数量。分别配置 2Mi1Gi 巨页。配置 1Gi 巨页需要向节点添加内核参数。例如,添加内核参数 default_hugepagesz=1GBhugepagesz=1Ghugepages=16 将导致在系统启动期间分配 16*1Gi 巨页。
    16 如果您的性能配置文件名称不是cnf-performance profile,请将其替换为正确的性能配置文件名称。
  10. 运行以下命令创建 DPDK Pod

    $ oc create -f dpdk-pod-rootless.yaml

实现特定DPDK线速率概述

要实现特定数据平面开发套件(DPDK)线速率,请部署节点调优操作符并配置单根I/O虚拟化(SR-IOV)。您还必须为以下资源调整DPDK设置

  • 隔离的CPU

  • 巨页

  • 拓扑调度器

在以前的OpenShift Container Platform版本中,性能附加组件操作符用于实现自动调优,以实现OpenShift Container Platform应用程序的低延迟性能。在OpenShift Container Platform 4.11及更高版本中,此功能是节点调优操作符的一部分。

DPDK测试环境

下图显示了流量测试环境的组件

DPDK test environment
  • 流量生成器:可以生成大量分组流量的应用程序。

  • 支持SR-IOV的NIC:与SR-IOV兼容的网络接口卡。该卡在一个物理接口上运行多个虚拟功能。

  • 物理功能(PF):支持SR-IOV接口的网络适配器的PCI Express(PCIe)功能。

  • 虚拟功能(VF):支持SR-IOV的网络适配器上的轻量级PCIe功能。VF与网络适配器上的PCIe PF相关联。VF表示网络适配器的虚拟化实例。

  • 交换机:网络交换机。节点也可以背对背连接。

  • testpmd:DPDK附带的一个示例应用程序。testpmd应用程序可用于在分组转发模式下测试DPDK。testpmd应用程序也是如何使用DPDK软件开发套件(SDK)构建完整应用程序的示例。

  • worker 0worker 1:OpenShift Container Platform节点。

使用SR-IOV和节点调优操作符实现DPDK线速率

您可以使用节点调优操作符配置隔离的CPU、巨页和拓扑调度器。然后,您可以将节点调优操作符与单根I/O虚拟化(SR-IOV)结合使用,以实现特定数据平面开发套件(DPDK)线速率。

先决条件
  • 您已安装 OpenShift CLI(oc)。

  • 您已安装SR-IOV网络操作员。

  • 您已以具有 cluster-admin 权限的用户身份登录。

  • 您已部署独立的节点调优操作符。

    在以前的OpenShift Container Platform版本中,性能附加组件操作符用于实现自动调优,以实现OpenShift应用程序的低延迟性能。在OpenShift Container Platform 4.11及更高版本中,此功能是节点调优操作符的一部分。

步骤
  1. 根据以下示例创建一个PerformanceProfile对象

    apiVersion: performance.openshift.io/v2
    kind: PerformanceProfile
    metadata:
      name: performance
    spec:
      globallyDisableIrqLoadBalancing: true
      cpu:
        isolated: 21-51,73-103 (1)
        reserved: 0-20,52-72 (2)
      hugepages:
        defaultHugepagesSize: 1G (3)
        pages:
          - count: 32
            size: 1G
      net:
        userLevelNetworking: true
      numa:
        topologyPolicy: "single-numa-node"
      nodeSelector:
        node-role.kubernetes.io/worker-cnf: ""
    1 如果系统启用了超线程,请将相关的符号链接分配给isolatedreserved CPU组。如果系统包含多个非统一内存访问节点(NUMA),请从两个NUMA分配CPU到这两个组。您也可以为此任务使用性能配置文件创建器。有关更多信息,请参见创建性能配置文件
    2 您还可以指定一个设备列表,这些设备的队列将设置为保留的CPU计数。有关更多信息,请参见使用节点调优操作符减少NIC队列
    3 分配所需的巨页数量和大小。您可以指定巨页的NUMA配置。默认情况下,系统会向系统上的每个NUMA节点分配偶数个。如果需要,您可以请求对节点使用实时内核。有关更多信息,请参见配置具有实时功能的工作节点
  2. yaml文件保存为mlx-dpdk-perfprofile-policy.yaml

  3. 使用以下命令应用性能配置文件

    $ oc create -f mlx-dpdk-perfprofile-policy.yaml

虚拟函数的 SR-IOV 网络操作示例

您可以使用单根 I/O 虚拟化 (SR-IOV) 网络操作符来分配和配置来自节点上支持 SR-IOV 的物理功能网卡的虚拟函数 (VF)。

有关部署操作符的更多信息,请参阅安装 SR-IOV 网络操作符。有关配置 SR-IOV 网络设备的更多信息,请参阅配置 SR-IOV 网络设备

在英特尔 VF 和Mellanox VF 上运行数据平面开发套件 (DPDK) 工作负载之间存在一些差异。本节提供两种 VF 类型的对象配置示例。以下是用于在英特尔网卡上运行 DPDK 应用程序的sriovNetworkNodePolicy 对象示例

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: dpdk-nic-1
  namespace: openshift-sriov-network-operator
spec:
  deviceType: vfio-pci (1)
  needVhostNet: true (2)
  nicSelector:
    pfNames: ["ens3f0"]
  nodeSelector:
    node-role.kubernetes.io/worker-cnf: ""
  numVfs: 10
  priority: 99
  resourceName: dpdk_nic_1
---
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: dpdk-nic-1
  namespace: openshift-sriov-network-operator
spec:
  deviceType: vfio-pci
  needVhostNet: true
  nicSelector:
    pfNames: ["ens3f1"]
  nodeSelector:
  node-role.kubernetes.io/worker-cnf: ""
  numVfs: 10
  priority: 99
  resourceName: dpdk_nic_2
1 对于英特尔网卡,deviceType 必须为 vfio-pci
2 如果需要内核与 DPDK 工作负载进行通信,请添加 needVhostNet: true。这会将/dev/net/tun/dev/vhost-net 设备挂载到容器中,以便应用程序可以创建虚拟接口设备并将虚拟接口设备连接到 DPDK 工作负载。

以下是 Mellanox 网卡的sriovNetworkNodePolicy 对象示例

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: dpdk-nic-1
  namespace: openshift-sriov-network-operator
spec:
  deviceType: netdevice (1)
  isRdma: true (2)
  nicSelector:
    rootDevices:
      - "0000:5e:00.1"
  nodeSelector:
    node-role.kubernetes.io/worker-cnf: ""
  numVfs: 5
  priority: 99
  resourceName: dpdk_nic_1
---
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: dpdk-nic-2
  namespace: openshift-sriov-network-operator
spec:
  deviceType: netdevice
  isRdma: true
  nicSelector:
    rootDevices:
      - "0000:5e:00.0"
  nodeSelector:
    node-role.kubernetes.io/worker-cnf: ""
  numVfs: 5
  priority: 99
  resourceName: dpdk_nic_2
1 对于 Mellanox 设备,deviceType 必须为 netdevice
2 对于 Mellanox 设备,isRdma 必须为 true。Mellanox 网卡使用流分叉连接到 DPDK 应用程序。此机制将流量在 Linux 用户空间和内核空间之间分割,并可以增强线路速率处理能力。

SR-IOV 网络操作示例

以下是sriovNetwork 对象的示例定义。在本例中,英特尔和 Mellanox 配置相同

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: dpdk-network-1
  namespace: openshift-sriov-network-operator
spec:
  ipam: '{"type": "host-local","ranges": [[{"subnet": "10.0.1.0/24"}]],"dataDir":
   "/run/my-orchestrator/container-ipam-state-1"}' (1)
  networkNamespace: dpdk-test (2)
  spoofChk: "off"
  trust: "on"
  resourceName: dpdk_nic_1 (3)
---
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: dpdk-network-2
  namespace: openshift-sriov-network-operator
spec:
  ipam: '{"type": "host-local","ranges": [[{"subnet": "10.0.2.0/24"}]],"dataDir":
   "/run/my-orchestrator/container-ipam-state-1"}'
  networkNamespace: dpdk-test
  spoofChk: "off"
  trust: "on"
  resourceName: dpdk_nic_2
1 您可以使用不同的 IP 地址管理 (IPAM) 实现,例如 Whereabouts。有关更多信息,请参阅使用 Whereabouts 进行动态 IP 地址分配配置
2 您必须请求将创建网络附加定义的networkNamespace。您必须在openshift-sriov-network-operator 命名空间下创建sriovNetwork CR。
3 resourceName 值必须与在sriovNetworkNodePolicy 下创建的resourceName 值匹配。

DPDK 基础工作负载示例

以下是数据平面开发套件 (DPDK) 容器的示例

apiVersion: v1
kind: Namespace
metadata:
  name: dpdk-test
---
apiVersion: v1
kind: Pod
metadata:
  annotations:
    k8s.v1.cni.cncf.io/networks: '[ (1)
     {
      "name": "dpdk-network-1",
      "namespace": "dpdk-test"
     },
     {
      "name": "dpdk-network-2",
      "namespace": "dpdk-test"
     }
   ]'
    irq-load-balancing.crio.io: "disable" (2)
    cpu-load-balancing.crio.io: "disable"
    cpu-quota.crio.io: "disable"
  labels:
    app: dpdk
  name: testpmd
  namespace: dpdk-test
spec:
  runtimeClassName: performance-performance (3)
  containers:
    - command:
        - /bin/bash
        - -c
        - sleep INF
      image: registry.redhat.io/openshift4/dpdk-base-rhel8
      imagePullPolicy: Always
      name: dpdk
      resources: (4)
        limits:
          cpu: "16"
          hugepages-1Gi: 8Gi
          memory: 2Gi
        requests:
          cpu: "16"
          hugepages-1Gi: 8Gi
          memory: 2Gi
      securityContext:
        capabilities:
          add:
            - IPC_LOCK
            - SYS_RESOURCE
            - NET_RAW
            - NET_ADMIN
        runAsUser: 0
      volumeMounts:
        - mountPath: /mnt/huge
          name: hugepages
  terminationGracePeriodSeconds: 5
  volumes:
    - emptyDir:
        medium: HugePages
      name: hugepages
1 请求您需要的 SR-IOV 网络。设备资源将自动注入。
2 禁用 CPU 和 IRQ 负载均衡基础。有关更多信息,请参阅禁用单个 Pod 的中断处理
3 runtimeClass 设置为performance-performance。不要将runtimeClass 设置为HostNetworkprivileged
4 请求请求和限制数量相同的资源,以使用“保证”服务质量 (QoS) 启动 Pod。

不要先启动 Pod 为SLEEP状态,然后进入 Pod 以启动 testpmd 或 DPDK 工作负载。因为exec 进程未绑定到任何 CPU,所以这可能会添加额外中断。

testpmd 脚本示例

以下是运行testpmd 的示例脚本

#!/bin/bash
set -ex
export CPU=$(cat /sys/fs/cgroup/cpuset/cpuset.cpus)
echo ${CPU}

dpdk-testpmd -l ${CPU} -a ${PCIDEVICE_OPENSHIFT_IO_DPDK_NIC_1} -a ${PCIDEVICE_OPENSHIFT_IO_DPDK_NIC_2} -n 4 -- -i --nb-cores=15 --rxd=4096 --txd=4096 --rxq=7 --txq=7 --forward-mode=mac --eth-peer=0,50:00:00:00:00:01 --eth-peer=1,50:00:00:00:00:02

此示例使用两个不同的sriovNetwork CR。环境变量包含为 Pod 分配的虚拟函数 (VF) PCI 地址。如果您在 Pod 定义中使用相同的网络,则必须拆分pciAddress。配置流量生成器的正确 MAC 地址非常重要。此示例使用自定义 MAC 地址。

在 RDMA 模式下使用 Mellanox 网卡的虚拟函数

融合以太网上的 RDMA (RoCE) 仅是技术预览功能。技术预览功能不受 Red Hat 生产服务级别协议 (SLA) 的支持,并且可能功能不完整。Red Hat 不建议在生产环境中使用它们。这些功能可让您抢先体验即将推出的产品功能,从而能够在开发过程中测试功能并提供反馈。

有关 Red Hat 技术预览功能的支持范围的更多信息,请参阅技术预览功能支持范围

在 OpenShift Container Platform 上使用 RDMA 时,融合以太网上的 RDMA (RoCE) 是唯一受支持的模式。

先决条件
  • 安装 OpenShift CLI(oc)。

  • 安装 SR-IOV 网络操作符。

  • 以具有 cluster-admin 权限的用户身份登录。

步骤
  1. 创建以下SriovNetworkNodePolicy 对象,然后将 YAML 保存到mlx-rdma-node-policy.yaml 文件中。

    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetworkNodePolicy
    metadata:
      name: mlx-rdma-node-policy
      namespace: openshift-sriov-network-operator
    spec:
      resourceName: mlxnics
      nodeSelector:
        feature.node.kubernetes.io/network-sriov.capable: "true"
      priority: <priority>
      numVfs: <num>
      nicSelector:
        vendor: "15b3"
        deviceID: "1015" (1)
        pfNames: ["<pf_name>", ...]
        rootDevices: ["<pci_bus_id>", "..."]
      deviceType: netdevice (2)
      isRdma: true (3)
    1 指定 SR-IOV 网络设备的设备十六进制代码。
    2 将虚拟函数的驱动程序类型指定为netdevice
    3 启用 RDMA 模式。

    请参阅“配置 SR-IOV 网络设备”部分,了解 SriovNetworkNodePolicy 中每个选项的详细说明。

    应用 SriovNetworkNodePolicy 对象中指定的配置时,SR-IOV 操作符可能会驱逐节点,在某些情况下还会重新启动节点。配置更改的应用可能需要几分钟时间。请确保您的集群中有足够的可用节点来处理预先驱逐的工作负载。

    应用配置更新后,openshift-sriov-network-operator 命名空间中的所有 Pod 将变为 运行中 状态。

  2. 运行以下命令创建 SriovNetworkNodePolicy 对象

    $ oc create -f mlx-rdma-node-policy.yaml
  3. 创建以下SriovNetwork 对象,然后将 YAML 保存到mlx-rdma-network.yaml 文件中。

    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetwork
    metadata:
      name: mlx-rdma-network
      namespace: openshift-sriov-network-operator
    spec:
      networkNamespace: <target_namespace>
      ipam: |- (1)
    # ...
      vlan: <vlan>
      resourceName: mlxnics
    1 将 IPAM CNI 插件的配置对象指定为 YAML 块标量。该插件管理附件定义的 IP 地址分配。

    请参阅“配置 SR-IOV 附加网络”部分,了解 SriovNetwork 中每个选项的详细说明。

    可选库 app-netutil 提供了几种 API 方法,用于收集有关容器的父 Pod 的网络信息。

  4. 运行以下命令创建 SriovNetworkNodePolicy 对象

    $ oc create -f mlx-rdma-network.yaml
  5. 创建以下Pod规范,然后将 YAML 保存到mlx-rdma-pod.yaml 文件中。

    apiVersion: v1
    kind: Pod
    metadata:
      name: rdma-app
      namespace: <target_namespace> (1)
      annotations:
        k8s.v1.cni.cncf.io/networks: mlx-rdma-network
    spec:
      containers:
      - name: testpmd
        image: <RDMA_image> (2)
        securityContext:
          runAsUser: 0
          capabilities:
            add: ["IPC_LOCK","SYS_RESOURCE","NET_RAW"] (3)
        volumeMounts:
        - mountPath: /mnt/huge (4)
          name: hugepage
        resources:
          limits:
            memory: "1Gi"
            cpu: "4" (5)
            hugepages-1Gi: "4Gi" (6)
          requests:
            memory: "1Gi"
            cpu: "4"
            hugepages-1Gi: "4Gi"
        command: ["sleep", "infinity"]
      volumes:
      - name: hugepage
        emptyDir:
          medium: HugePages
    1 指定创建SriovNetwork 对象mlx-rdma-network 的相同target_namespace。如果您想在不同的命名空间中创建 Pod,请更改Pod规范和SriovNetwork 对象中的target_namespace
    2 指定包含应用程序和应用程序使用的 RDMA 库的 RDMA 镜像。
    3 指定容器内应用程序所需的附加功能,用于巨页分配、系统资源分配和网络接口访问。
    4 将巨页卷挂载到/mnt/huge 下的 RDMA Pod。巨页卷由使用Hugepages 介质的 emptyDir 卷类型支持。
    5 指定 CPU 数量。RDMA Pod 通常需要从 kubelet 分配独占 CPU。这是通过将 CPU 管理策略设置为static 并使用Guaranteed QoS 创建 Pod 来实现的。
    6 指定巨页大小hugepages-1Gihugepages-2Mi以及将分配给 RDMA Pod 的巨页数量。分别配置2Mi1Gi 巨页。配置1Gi 巨页需要向节点添加内核参数。
  6. 运行以下命令创建 RDMA Pod

    $ oc create -f mlx-rdma-pod.yaml

在 OpenStack 上使用 OVS-DPDK 的集群的测试 Pod 模板

以下testpmd Pod 演示了使用巨页、保留的 CPU 和 SR-IOV 端口创建容器。

testpmd Pod 示例
apiVersion: v1
kind: Pod
metadata:
  name: testpmd-dpdk
  namespace: mynamespace
  annotations:
    cpu-load-balancing.crio.io: "disable"
    cpu-quota.crio.io: "disable"
# ...
spec:
  containers:
  - name: testpmd
    command: ["sleep", "99999"]
    image: registry.redhat.io/openshift4/dpdk-base-rhel8:v4.9
    securityContext:
      capabilities:
        add: ["IPC_LOCK","SYS_ADMIN"]
      privileged: true
      runAsUser: 0
    resources:
      requests:
        memory: 1000Mi
        hugepages-1Gi: 1Gi
        cpu: '2'
        openshift.io/dpdk1: 1 (1)
      limits:
        hugepages-1Gi: 1Gi
        cpu: '2'
        memory: 1000Mi
        openshift.io/dpdk1: 1
    volumeMounts:
      - mountPath: /mnt/huge
        name: hugepage
        readOnly: False
  runtimeClassName: performance-cnf-performanceprofile (2)
  volumes:
  - name: hugepage
    emptyDir:
      medium: HugePages
1 此示例中的名称dpdk1 是用户创建的SriovNetworkNodePolicy 资源。您可以将此名称替换为您创建的资源的名称。
2 如果您的性能配置文件名称不是cnf-performance profile,请将其替换为正确的性能配置文件名称。

在 OpenStack 上使用 OVS 硬件卸载的集群的测试 Pod 模板

以下testpmd Pod 演示了在 Red Hat OpenStack Platform (RHOSP) 上进行 Open vSwitch (OVS) 硬件卸载。

testpmd Pod 示例
apiVersion: v1
kind: Pod
metadata:
  name: testpmd-sriov
  namespace: mynamespace
  annotations:
    k8s.v1.cni.cncf.io/networks: hwoffload1
spec:
  runtimeClassName: performance-cnf-performanceprofile (1)
  containers:
  - name: testpmd
    command: ["sleep", "99999"]
    image: registry.redhat.io/openshift4/dpdk-base-rhel8:v4.9
    securityContext:
      capabilities:
        add: ["IPC_LOCK","SYS_ADMIN"]
      privileged: true
      runAsUser: 0
    resources:
      requests:
        memory: 1000Mi
        hugepages-1Gi: 1Gi
        cpu: '2'
      limits:
        hugepages-1Gi: 1Gi
        cpu: '2'
        memory: 1000Mi
    volumeMounts:
      - mountPath: /mnt/huge
        name: hugepage
        readOnly: False
  volumes:
  - name: hugepage
    emptyDir:
      medium: HugePages
1 如果您的性能配置文件名称不是cnf-performance profile,请将其替换为正确的性能配置文件名称。