跳到内容跳到页面导航:上一页 [access key p]/下一页 [access key n]
documentation.suse.com / SUSE Edge 文档 / 产品文档 / 电信功能配置

30 电信功能配置

本章将阐释部署了 ATIP 的群集上特定于电信的功能配置。

将使用有关 ATIP 自动置备的一章(第 31 章 “全自动定向网络置备)中所述的定向网络置备部署方法。

本章涵盖以下主题:

30.1 实时内核映像

实时内核映像不一定比标准内核更好。它是针对特定用例进行微调的另一种内核。经过微调的实时内核可以降低延迟,但代价是降低了吞吐量。不建议将实时内核用于一般用途,但在本例中,它是建议用于电信工作负载的内核,因为其中的延迟是一项关键考虑因素。

实时内核有四大特性:

  • 确定性执行:

    获得更高的可预测性 — 确保关键业务流程每次都能及时完成并提供高质量的服务,即使在承受繁重的系统负载情况下也能如此。通过围隔出关键系统资源供高优先级流程使用,可以确保为时间敏感型应用程序提供更高的可预测性。

  • 低抖动:

    基于高确定性技术的低抖动有助于应用程序与现实世界保持同步。这可以为那些需要持续重复计算的服务提供帮助。

  • 优先级继承:

    优先级继承是指当较高优先级的进程在完成其任务之前需要先等待较低优先级的进程完成时,较低优先级的进程可以提升为较高优先级的功能。SUSE Linux Enterprise Real Time 解决了任务关键型进程的优先级倒置问题。

  • 线程中断:

    在通用操作系统中以中断模式运行的进程不可抢占。在 SUSE Linux Enterprise Real Time 中,这些中断已由可中断的内核线程封装,并允许用户定义的较高优先级进程抢占硬中断和软中断。

    在本例中,如果您已安装 SLE Micro RT 之类的实时映像,则就已经安装了实时内核。可以从 SUSE Customer Center 下载实时内核映像。

    注意
    注意

    有关实时内核的详细信息,请访问 SUSE Real Time

30.2 CPU 已微调配置

使用 CPU 已微调配置可以隔离 CPU 核心供实时内核使用。必须防止操作系统与实时内核使用相同的核心,因为操作系统有可能会使用这些核心,导致提高实时内核的延迟。

要启用和配置此功能,首先应该为我们想要隔离的 CPU 核心创建一个配置文件。在本例中,我们将隔离核心 1-3033-62

$ echo "export tuned_params" >> /etc/grub.d/00_tuned

$ echo "isolated_cores=1-30,33-62" >> /etc/tuned/cpu-partitioning-variables.conf

$ tuned-adm profile cpu-partitioning
Tuned (re)started, changes applied.

然后我们需要修改 GRUB 选项来隔离 CPU 核心和其他重要的 CPU 使用参数。请务必根据您的当前硬件规格自定义以下选项:

参数说明

isolcpus

1-30,33-62

隔离核心 1-30 和 33-62

skew_tick

1

此选项允许内核在隔离的 CPU 之间偏斜计时器中断。

nohz

on

此选项允许内核在系统空闲时在单个 CPU 上运行计时器滴答周期。

nohz_full

1-30,33-62

内核引导参数是当前用于配置完整 dynticks 及 CPU 隔离的主接口。

rcu_nocbs

1-30,33-62

此选项允许内核在系统空闲时在单个 CPU 上运行 RCU 回调。

kthread_cpus

0,31,32,63

此选项允许内核在系统空闲时在单个 CPU 上运行 kthreads。

irqaffinity

0,31,32,63

此选项允许内核在系统空闲时在单个 CPU 上运行中断。

processor.max_cstate

1

此选项防止 CPU 在空闲时进入休眠状态

intel_idle.max_cstate

0

此选项禁用 intel_idle 驱动程序并允许使用 acpi_idle

我们将使用上面所示的值隔离 60 个核心,并将其中 4 个核心用于操作系统。

以下命令修改 GRUB 配置并应用上述更改,以便下次引导时使用更改的配置:

编辑 /etc/default/grub 文件,在其中添加上述参数:

GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"

更新 GRUB 配置:

$ transactional-update grub.cfg
$ reboot

要验证重引导后是否应用了这些参数,可使用以下命令检查内核命令行:

$ cat /proc/cmdline

30.3 CNI 配置

30.3.1 Cilium

Cilium 是 ATIP 的默认 CNI 插件。要在 RKE2 群集上启用 Cilium 作为默认插件,需要在 /etc/rancher/rke2/config.yaml 文件中进行以下配置:

cni:
- cilium

也可以使用命令行参数来指定此配置,即,将 --cni=cilium 添加到 /etc/systemd/system/rke2-server 文件的 server 行中。

要使用下一节(第 30.4 节 “SR-IOV”)中所述的 SR-IOV 网络操作器,请将 Multus 与另一个 CNI 插件(例如 CiliumCalico)一起用作辅助插件。

cni:
- multus
- cilium
注意
注意

有关 CNI 插件的详细信息,请访问网络选项

30.4 SR-IOV

设备(例如网络适配器)可以通过 SR-IOV 在各种 PCIe 硬件功能之间分离对其资源的访问。可以通过多种方式部署 SR-IOV,本节将介绍两种不同的选项:

  • 选项 1:使用 SR-IOV CNI 设备插件和配置映射来正确配置 SR-IOV。

  • 选项 2(建议):使用 Rancher Prime 中的 SR-IOV Helm chart 来轻松完成此部署。

选项 1 - 安装 SR-IOV CNI 设备插件并准备配置映射来正确配置 SR-IOV

  • 为设备插件准备配置映射

使用 lspci 命令获取用于填充配置映射的信息:

$ lspci | grep -i acc
8a:00.0 Processing accelerators: Intel Corporation Device 0d5c

$ lspci | grep -i net
19:00.0 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.1 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.2 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.3 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
51:00.0 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 02)
51:00.1 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 02)
51:01.0 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.1 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.2 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.3 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.0 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.1 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.2 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.3 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)

配置映射由一个 JSON 文件组成,该文件使用用于发现的过滤器来描述设备,并创建接口组。此处的关键在于理解过滤器和组。过滤器用于发现设备,组用于创建接口。

可以设置过滤器:

  • vendorID:8086 (Intel)

  • deviceID:0d5c(加速卡)

  • driver:vfio-pci(驱动程序)

  • pfNames:p2p1(物理接口名称)

还可以设置过滤器来匹配更复杂的接口语法,例如:

  • pfNames:["eth1#1,2,3,4,5,6"][eth1#1-6](物理接口名称)

对于组,我们可为 FEC 卡创建一个组,为 Intel 卡创建另一个组,甚至可以根据用例创建一个前缀:

  • resourceName:pci_sriov_net_bh_dpdk

  • resourcePrefix:Rancher.io

可以发现许多组合,并创建资源组来为 Pod 分配一些 VF

注意
注意

有关过滤器和组的详细信息,请访问 sr-iov 网络设备插件

根据硬件和用例设置用于匹配接口的过滤器和组后,以下配置映射会显示要使用的示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: sriovdp-config
  namespace: kube-system
data:
  config.json: |
    {
        "resourceList": [
            {
                "resourceName": "intel_fec_5g",
                "devicetype": "accelerator",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["0d5d"]
                }
            },
            {
                "resourceName": "intel_sriov_odu",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["1889"],
                    "drivers": ["vfio-pci"],
                    "pfNames": ["p2p1"]
                }
            },
            {
                "resourceName": "intel_sriov_oru",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["1889"],
                    "drivers": ["vfio-pci"],
                    "pfNames": ["p2p2"]
                }
            }
        ]
    }
  • 准备 daemonset 文件以部署设备插件。

设备插件支持多种体系结构(armamdppc64le),因此同一文件可用于不同的体系结构,以便为每个体系结构部署多个 daemonset

apiVersion: v1
kind: ServiceAccount
metadata:
  name: sriov-device-plugin
  namespace: kube-system
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-sriov-device-plugin-amd64
  namespace: kube-system
  labels:
    tier: node
    app: sriovdp
spec:
  selector:
    matchLabels:
      name: sriov-device-plugin
  template:
    metadata:
      labels:
        name: sriov-device-plugin
        tier: node
        app: sriovdp
    spec:
      hostNetwork: true
      nodeSelector:
        kubernetes.io/arch: amd64
      tolerations:
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      serviceAccountName: sriov-device-plugin
      containers:
      - name: kube-sriovdp
        image: rancher/hardened-sriov-network-device-plugin:v3.5.1-build20231009-amd64
        imagePullPolicy: IfNotPresent
        args:
        - --log-dir=sriovdp
        - --log-level=10
        securityContext:
          privileged: true
        resources:
          requests:
            cpu: "250m"
            memory: "40Mi"
          limits:
            cpu: 1
            memory: "200Mi"
        volumeMounts:
        - name: devicesock
          mountPath: /var/lib/kubelet/
          readOnly: false
        - name: log
          mountPath: /var/log
        - name: config-volume
          mountPath: /etc/pcidp
        - name: device-info
          mountPath: /var/run/k8s.cni.cncf.io/devinfo/dp
      volumes:
        - name: devicesock
          hostPath:
            path: /var/lib/kubelet/
        - name: log
          hostPath:
            path: /var/log
        - name: device-info
          hostPath:
            path: /var/run/k8s.cni.cncf.io/devinfo/dp
            type: DirectoryOrCreate
        - name: config-volume
          configMap:
            name: sriovdp-config
            items:
            - key: config.json
              path: config.json
  • 应用配置映射和 daemonset 后,将部署设备插件,发现接口并将其提供给 Pod 使用。

    $ kubectl get pods -n kube-system | grep sriov
    kube-system  kube-sriov-device-plugin-amd64-twjfl  1/1  Running  0  2m
  • 检查节点中发现的并可供 Pod 使用的接口:

    $ kubectl get $(kubectl get nodes -oname) -o jsonpath='{.status.allocatable}' | jq
    {
      "cpu": "64",
      "ephemeral-storage": "256196109726",
      "hugepages-1Gi": "40Gi",
      "hugepages-2Mi": "0",
      "intel.com/intel_fec_5g": "1",
      "intel.com/intel_sriov_odu": "4",
      "intel.com/intel_sriov_oru": "4",
      "memory": "221396384Ki",
      "pods": "110"
    }
  • FECintel.com/intel_fec_5g,值为 1。

  • 如果您使用设备插件和配置映射但未使用 Helm chart 部署了 SR-IOV,则 VFintel.com/intel_sriov_oduintel.com/intel_sriov_oru

重要
重要

如果此处没有接口,则继续操作就意义不大,因为 Pod 没有可用的接口。请先检查配置映射和过滤器来解决问题。

选项 2(建议)- 使用 Rancher 和 Helm chart 安装 SR-IOV CNI 和设备插件

  • 获取 Helm(如果没有):

$ curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
  • 安装 SR-IOV。

可以通过两种方式完成此操作:使用 CLI 或使用 Rancher UI

从 CLI 安装 Operator
helm repo add suse-edge https://suse-edge.github.io/charts
helm install sriov-crd suse-edge/sriov-crd -n sriov-network-operator
helm install install sriov-network-operator suse-edge/sriov-network-operator -n sriov-network-operator
从 Rancher UI 安装 Operator

安装群集后,如果您可以访问 Rancher UI,则可以通过 Rancher UI 中的应用程序选项卡安装 SR-IOV Operator

注意
注意

确保选择正确的名称空间来安装 Operator,例如 sriov-network-operator

+ image::features_sriov.png[sriov.png]

  • 检查已部署的资源 CRD 和 Pod:

$ kubectl get crd
$ kubectl -n sriov-network-operator get pods
  • 检查节点中的标签。

所有资源都运行后,标签会自动出现在您的节点中:

$ kubectl get nodes -oyaml | grep feature.node.kubernetes.io/network-sriov.capable

feature.node.kubernetes.io/network-sriov.capable: "true"
  • 查看 daemonset,您会看到新的 sriov-network-config-daemonsriov-rancher-nfd-worker 处于活动状态并已准备就绪:

$ kubectl get daemonset -A
NAMESPACE             NAME                            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                                           AGE
calico-system            calico-node                     1         1         1       1            1           kubernetes.io/os=linux                                  15h
sriov-network-operator   sriov-network-config-daemon     1         1         1       1            1           feature.node.kubernetes.io/network-sriov.capable=true   45m
sriov-network-operator   sriov-rancher-nfd-worker        1         1         1       1            1           <none>                                                  45m
kube-system              rke2-ingress-nginx-controller   1         1         1       1            1           kubernetes.io/os=linux                                  15h
kube-system              rke2-multus-ds                  1         1         1       1            1           kubernetes.io/arch=amd64,kubernetes.io/os=linux         15h

几分钟后(最多可能需要 10 分钟才会更新),将检测到节点,其上已配置了 SR-IOV 功能:

$ kubectl get sriovnetworknodestates.sriovnetwork.openshift.io -A
NAMESPACE             NAME     AGE
sriov-network-operator   xr11-2   83s
  • 检查已检测到的接口。

发现的接口应使用网络设备的 PCI 地址。请在主机中使用 lspci 命令检查此信息。

$ kubectl get sriovnetworknodestates.sriovnetwork.openshift.io -n kube-system -oyaml
apiVersion: v1
items:
- apiVersion: sriovnetwork.openshift.io/v1
  kind: SriovNetworkNodeState
  metadata:
    creationTimestamp: "2023-06-07T09:52:37Z"
    generation: 1
    name: xr11-2
    namespace: sriov-network-operator
    ownerReferences:
    - apiVersion: sriovnetwork.openshift.io/v1
      blockOwnerDeletion: true
      controller: true
      kind: SriovNetworkNodePolicy
      name: default
      uid: 80b72499-e26b-4072-a75c-f9a6218ec357
    resourceVersion: "356603"
    uid: e1f1654b-92b3-44d9-9f87-2571792cc1ad
  spec:
    dpConfigVersion: "356507"
  status:
    interfaces:
    - deviceID: "1592"
      driver: ice
      eSwitchMode: legacy
      linkType: ETH
      mac: 40:a6:b7:9b:35:f0
      mtu: 1500
      name: p2p1
      pciAddress: "0000:51:00.0"
      totalvfs: 128
      vendor: "8086"
    - deviceID: "1592"
      driver: ice
      eSwitchMode: legacy
      linkType: ETH
      mac: 40:a6:b7:9b:35:f1
      mtu: 1500
      name: p2p2
      pciAddress: "0000:51:00.1"
      totalvfs: 128
      vendor: "8086"
    syncStatus: Succeeded
kind: List
metadata:
  resourceVersion: ""
注意
注意

如果此处未检测到您的接口,请确保该接口在下一个配置映射中存在:

$ kubectl get cm supported-nic-ids -oyaml -n sriov-network-operator

如果此处未检测到您的设备,请编辑配置映射,添加要发现的正确值(如有必要,请重启动 sriov-network-config-daemon daemonset)。

  • 创建 NetworkNode 策略来配置 VF

将在设备 (rootDevices) 中创建一些 VF (numVfs),并在其上配置驱动程序 deviceTypeMTU

注意
注意

resourceName 字段不得包含任何特殊字符,并且在整个群集中必须唯一。该示例使用 deviceType: vfio-pci,因为 dpdk 将与 sr-iov 结合使用。如果您不使用 dpdk,则 deviceType 应为 deviceType: netdevice(默认值)。

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: policy-dpdk
  namespace: sriov-network-operator
spec:
  nodeSelector:
    feature.node.kubernetes.io/network-sriov.capable: "true"
  resourceName: intelnicsDpdk
  deviceType: vfio-pci
  numVfs: 8
  mtu: 1500
  nicSelector:
    deviceID: "1592"
    vendor: "8086"
    rootDevices:
    - 0000:51:00.0
  • 验证配置:

$ kubectl get $(kubectl get nodes -oname) -o jsonpath='{.status.allocatable}' | jq
{
  "cpu": "64",
  "ephemeral-storage": "256196109726",
  "hugepages-1Gi": "60Gi",
  "hugepages-2Mi": "0",
  "intel.com/intel_fec_5g": "1",
  "memory": "200424836Ki",
  "pods": "110",
  "rancher.io/intelnicsDpdk": "8"
}
  • 创建 sr-iov 网络(可选操作,仅在需要不同的网络时才执行):

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: network-dpdk
  namespace: sriov-network-operator
spec:
  ipam: |
    {
      "type": "host-local",
      "subnet": "192.168.0.0/24",
      "rangeStart": "192.168.0.20",
      "rangeEnd": "192.168.0.60",
      "routes": [{
        "dst": "0.0.0.0/0"
      }],
      "gateway": "192.168.0.1"
    }
  vlan: 500
  resourceName: intelnicsDpdk
  • 检查创建的网络:

$ kubectl get network-attachment-definitions.k8s.cni.cncf.io -A -oyaml

apiVersion: v1
items:
- apiVersion: k8s.cni.cncf.io/v1
  kind: NetworkAttachmentDefinition
  metadata:
    annotations:
      k8s.v1.cni.cncf.io/resourceName: rancher.io/intelnicsDpdk
    creationTimestamp: "2023-06-08T11:22:27Z"
    generation: 1
    name: network-dpdk
    namespace: sriov-network-operator
    resourceVersion: "13124"
    uid: df7c89f5-177c-4f30-ae72-7aef3294fb15
  spec:
    config: '{ "cniVersion":"0.3.1", "name":"network-dpdk","type":"sriov","vlan":500,"vlanQoS":0,"ipam":{"type":"host-local","subnet":"192.168.0.0/24","rangeStart":"192.168.0.10","rangeEnd":"192.168.0.60","routes":[{"dst":"0.0.0.0/0"}],"gateway":"192.168.0.1"}
      }'
kind: List
metadata:
  resourceVersion: ""

30.5 DPDK

DPDK(数据平面开发包)是一组用于实现快速包处理的库和驱动程序。它用于加速各种 CPU 体系结构上运行的包处理工作负载。DPDK 包含以下组件的数据平面库和优化的网络接口控制器 (NIC) 驱动程序:

  1. 队列管理器实现无锁队列。

  2. 缓冲区管理器预先分配固定大小的缓冲区。

  3. 内存管理器在内存中分配对象池,并使用环来存储空闲对象;确保对象均匀分布在所有 DRAM 通道上。

  4. 轮询模式驱动程序 (PMD) 可以在没有异步通知的情况下运行,从而降低了开销。

  5. 包框架以一组库的形式提供,可帮助开发包处理解决方案。

以下步骤说明如何启用 DPDK,以及如何从 NIC 创建供 DPDK 接口使用的 VF

  • 安装 DPDK 软件包:

$ transactional-update pkg install dpdk22 dpdk22-tools libdpdk-23
$ reboot
  • 内核参数:

要使用 DPDK,请采用一些驱动程序来启用内核中的某些参数:

参数说明

iommu

pt

此选项允许为 DPDK 接口使用 vfio 驱动程序。

intel_iommu

on

此选项允许为 VF 使用 vfio

要启用这些参数,请将其添加到 /etc/default/grub 文件中:

GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"

更新 GRUB 配置,并重引导系统以应用更改:

$ transactional-update grub.cfg
$ reboot
  • 加载 vfio-pci 内核模块,并在 NIC 上启用 SR-IOV

$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  • NIC 创建一些虚拟功能 (VF)。

例如,要为两个不同的 NIC 创建 VF,需要运行以下命令:

$ echo 4 > /sys/bus/pci/devices/0000:51:00.0/sriov_numvfs
$ echo 4 > /sys/bus/pci/devices/0000:51:00.1/sriov_numvfs
  • 将新的 VF 绑定到 vfio-pci 驱动程序:

$ dpdk-devbind.py -b vfio-pci 0000:51:01.0 0000:51:01.1 0000:51:01.2 0000:51:01.3 \
                              0000:51:11.0 0000:51:11.1 0000:51:11.2 0000:51:11.3
  • 检查是否正确应用了配置:

$ dpdk-devbind.py -s

Network devices using DPDK-compatible driver
============================================
0000:51:01.0 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.1 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.2 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.3 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.0 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:11.1 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:21.2 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:31.3 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio

Network devices using kernel driver
===================================
0000:19:00.0 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em1 drv=bnxt_en unused=igb_uio,vfio-pci *Active*
0000:19:00.1 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em2 drv=bnxt_en unused=igb_uio,vfio-pci
0000:19:00.2 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em3 drv=bnxt_en unused=igb_uio,vfio-pci
0000:19:00.3 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em4 drv=bnxt_en unused=igb_uio,vfio-pci
0000:51:00.0 'Ethernet Controller E810-C for QSFP 1592' if=eth13 drv=ice unused=igb_uio,vfio-pci
0000:51:00.1 'Ethernet Controller E810-C for QSFP 1592' if=rename8 drv=ice unused=igb_uio,vfio-pci

30.6 vRAN 加速 (Intel ACC100/ACC200)

随着通讯服务提供商从 4G 过渡到 5G 网络,有许多提供商正在采用虚拟化无线接入网络 (vRAN) 体系结构来提高信道容量及简化基于边缘的服务和应用程序的部署。vRAN 解决方案非常适合用于提供低延迟服务,并可以根据实时流量和网络需求灵活地增加或减少容量。

计算密集程度最高的 4G 和 5G 工作负载之一是 RAN 第 1 层 (L1) FEC,它可以解决不可靠或高干扰信道上的数据传输错误。FEC 技术可以检测并纠正 4G 或 5G 数据中有限数量的错误,因此消除了重新传输的需要。由于 FEC 加速事务不包含单元状态信息,因此可以轻松虚拟化,从而带来了池化优势并可实现轻松的单元迁移。

  • 内核参数

要启用 vRAN 加速,需要启用以下内核参数(如果尚未启用):

参数说明

iommu

pt

此选项允许为 DPDK 接口使用 vfio。

intel_iommu

on

此选项允许为 VF 使用 vfio。

修改 GRUB 文件 /etc/default/grub,以将这些参数添加到内核命令行:

GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"

更新 GRUB 配置,并重引导系统以应用更改:

$ transactional-update grub.cfg
$ reboot

要校验重引导后是否应用了这些参数,请检查命令行:

$ cat /proc/cmdline
  • 加载 vfio-pci 内核模块以启用 vRAN 加速:

$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  • 获取 Acc100 接口信息:

$ lspci | grep -i acc
8a:00.0 Processing accelerators: Intel Corporation Device 0d5c
  • 将物理接口 (PF) 绑定到 vfio-pci 驱动程序:

$ dpdk-devbind.py -b vfio-pci 0000:8a:00.0
  • 从物理接口 (PF) 创建虚拟功能 (VF)。

PF 创建 2 个 VF,并按照以下步骤将其绑定到 vfio-pci

$ echo 2 > /sys/bus/pci/devices/0000:8a:00.0/sriov_numvfs
$ dpdk-devbind.py -b vfio-pci 0000:8b:00.0
  • 使用建议的配置文件配置 acc100:

$ pf_bb_config ACC100 -c /opt/pf-bb-config/acc100_config_vf_5g.cfg
Tue Jun  6 10:49:20 2023:INFO:Queue Groups: 2 5GUL, 2 5GDL, 2 4GUL, 2 4GDL
Tue Jun  6 10:49:20 2023:INFO:Configuration in VF mode
Tue Jun  6 10:49:21 2023:INFO: ROM version MM 99AD92
Tue Jun  6 10:49:21 2023:WARN:* Note: Not on DDR PRQ version  1302020 != 10092020
Tue Jun  6 10:49:21 2023:INFO:PF ACC100 configuration complete
Tue Jun  6 10:49:21 2023:INFO:ACC100 PF [0000:8a:00.0] configuration complete!
  • 检查从 FEC PF 创建的新 VF:

$ dpdk-devbind.py -s
Baseband devices using DPDK-compatible driver
=============================================
0000:8a:00.0 'Device 0d5c' drv=vfio-pci unused=
0000:8b:00.0 'Device 0d5d' drv=vfio-pci unused=

Other Baseband devices
======================
0000:8b:00.1 'Device 0d5d' unused=

30.7 大页

当某个进程使用 RAM 时,CPU 会将 RAM 标记为已由该进程使用。为提高效率,CPU 会以区块的形式分配 RAM,在许多平台上,默认的区块大小值为 4K 字节。这些区块称为页。页可以交换到磁盘等位置。

由于进程地址空间是虚拟的,CPU 和操作系统需要记住哪些页属于哪个进程,以及每个页存储在哪个位置。页数越多,内存映射的搜索时间就越长。当某个进程使用 1 GB 内存时,需要查找 262144 个项 (1 GB / 4 K)。如果一个页表项占用 8 个字节,则需要查找 2 MB 内存 (262144 * 8)。

当前的大多数 CPU 体系结构都支持大于默认值的页,因此减少了 CPU/操作系统需要查找的项。

  • 内核参数

要启用大页,应添加以下内核参数:

参数说明

hugepagesz

1G

此选项允许将大页的大小设置为 1 G

hugepages

40

这是先前定义的大页数量

default_hugepagesz

1G

这是用于获取大页的默认值

修改 GRUB 文件 /etc/default/grub,以将这些参数添加到内核命令行:

GRUB_CMDLINE_LINUX="intel_iommu=on intel_pstate=passive processor.max_cstate=1 intel_idle.max_cstate=0 iommu=pt usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 crashkernel=auto softlockup_panic=0 audit=0 mce=off hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 default_hugepagesz=1G kthread_cpus=0,31,32,63 irqaffinity=0,31,32,63 isolcpus=1-30,33-62 skew_tick=1 nohz_full=1-30,33-62 rcu_nocbs=1-30,33-62 rcu_nocb_poll"

更新 GRUB 配置,并重引导系统以应用更改:

$ transactional-update grub.cfg
$ reboot

要验证重引导后是否应用了这些参数,可以检查命令行:

$ cat /proc/cmdline
  • 使用大页

要使用大页,需要挂载它们:

$ mkdir -p /hugepages
$ mount -t hugetlbfs nodev /hugepages

部署 Kubernetes 工作负载,并创建资源和卷:

...
 resources:
   requests:
     memory: "24Gi"
     hugepages-1Gi: 16Gi
     intel.com/intel_sriov_oru: '4'
   limits:
     memory: "24Gi"
     hugepages-1Gi: 16Gi
     intel.com/intel_sriov_oru: '4'
...
...
volumeMounts:
  - name: hugepage
    mountPath: /hugepages
...
volumes:
  - name: hugepage
    emptyDir:
      medium: HugePages
...

30.8 CPU 固定配置

  • 要求

    1. 必须根据第 30.2 节 “CPU 已微调配置”一节中所述的性能配置文件微调 CPU

    2. 必须使用 CPU 管理参数配置 RKE2 群集 kubelet,为此请将以下块(示例)添加到 /etc/rancher/rke2/config.yaml 文件中:

kubelet-arg:
- "cpu-manager=true"
- "cpu-manager-policy=static"
- "cpu-manager-policy-options=full-pcpus-only=true"
- "cpu-manager-reconcile-period=0s"
- "kubelet-reserved=cpu=1"
- "system-reserved=cpu=1"
  • 在 Kubernetes 上使用 CPU 固定

根据您在工作负载上定义的请求和限制,可以用三种方式通过 kubelet 中定义的静态策略来使用该功能:

  1. BestEffort QoS 类:如果您没有为 CPU 定义任何请求或限制,则 Pod 将调度到系统中第一个可用的 CPU 上。

    使用 BestEffort QoS 类的示例如下:

    spec:
      containers:
      - name: nginx
        image: nginx
  2. Burstable QoS 类:如果为 CPU 定义的请求不等于限制,或者没有 CPU 请求,请使用此方式。

    使用 Burstable QoS 类的示例如下:

    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "200Mi"
          requests:
            memory: "100Mi"

    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "200Mi"
            cpu: "2"
          requests:
            memory: "100Mi"
            cpu: "1"
  3. Guaranteed QoS 类:如果为 CPU 定义的请求等于限制,请使用此方式。

    使用 Guaranteed QoS 类的示例如下:

    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              memory: "200Mi"
              cpu: "2"
            requests:
              memory: "200Mi"
              cpu: "2"

30.9 可感知 NUMA 的调度

非统一内存访问或非统一内存体系结构 (NUMA) 是 SMP(多处理器)体系结构中使用的物理内存设计,其中内存访问时间取决于相对于处理器的内存位置。在 NUMA 下,与访问非本地内存(即,另一个处理器本地的内存,或者在处理器之间共享的内存)相比,处理器可以更快地访问自身的本地内存。

30.9.1 识别 NUMA 节点

要识别 NUMA 节点,请在系统上使用以下命令:

$ lscpu | grep NUMA
NUMA node(s):                       1
NUMA node0 CPU(s):                  0-63
注意
注意

对于此示例,只有一个 NUMA 节点显示了 64 个 CPU

需要在 BIOS 中启用 NUMA。如果 dmesg 在引导过程中没有 NUMA 初始化记录,则可能表示内核环缓冲区中的 NUMA 相关讯息已被重写。

30.10 MetalLB

MetalLB 是裸机 Kubernetes 群集的负载平衡器实现,使用 L2BGP 等标准路由协议作为广告协议。它是一个网络负载平衡器,可用于向外部公开 Kubernetes 群集中的服务(因为需要在裸机上使用 Kubernetes 服务类型 LoadBalancer)。

要在 RKE2 群集中启用 MetalLB,需要执行以下步骤:

  • 使用以下命令安装 MetalLB

$ kubectl apply <<EOF -f
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: metallb
  namespace: kube-system
spec:
  repo: https://metallb.github.io/metallb/
  chart: metallb
  targetNamespace: metallb-system
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: endpoint-copier-operator
  namespace: kube-system
spec:
  repo: https://suse-edge.github.io/endpoint-copier-operator
  chart: endpoint-copier-operator
  targetNamespace: endpoint-copier-operator
EOF
  • 创建 IpAddressPoolL2advertisement 配置:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: kubernetes-vip-ip-pool
  namespace: metallb-system
spec:
  addresses:
    - 10.168.200.98/32
  serviceAllocation:
    priority: 100
    namespaces:
      - default
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: ip-pool-l2-adv
  namespace: metallb-system
spec:
  ipAddressPools:
    - kubernetes-vip-ip-pool
  • 创建端点服务来公开 VIP

apiVersion: v1
kind: Service
metadata:
  name: kubernetes-vip
  namespace: default
spec:
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: rke2-api
    port: 9345
    protocol: TCP
    targetPort: 9345
  - name: k8s-api
    port: 6443
    protocol: TCP
    targetPort: 6443
  sessionAffinity: None
  type: LoadBalancer
  • 检查 VIP 是否已创建并且 MetalLB Pod 是否正在运行:

$ kubectl get svc -n default
$ kubectl get pods -n default

30.11 专用注册表配置

可以配置 Containerd 以连接到专用注册表,然后使用专用注册表提取每个节点上的专用映像。

启动时,RKE2 会检查 /etc/rancher/rke2/ 中是否存在 registries.yaml 文件,并指示 containerd 使用该文件中定义的任何注册表。如果您希望使用某个专用注册表,请在要使用该注册表的每个节点上以 root 身份创建此文件。

要添加专用注册表,请创建包含以下内容的 /etc/rancher/rke2/registries.yaml 文件:

mirrors:
  docker.io:
    endpoint:
      - "https://registry.example.com:5000"
configs:
  "registry.example.com:5000":
    auth:
      username: xxxxxx # this is the registry username
      password: xxxxxx # this is the registry password
    tls:
      cert_file:            # path to the cert file used to authenticate to the registry
      key_file:             # path to the key file for the certificate used to authenticate to the registry
      ca_file:              # path to the ca file used to verify the registry's certificate
      insecure_skip_verify: # may be set to true to skip verifying the registry's certificate

或者不设置身份验证:

mirrors:
  docker.io:
    endpoint:
      - "https://registry.example.com:5000"
configs:
  "registry.example.com:5000":
    tls:
      cert_file:            # path to the cert file used to authenticate to the registry
      key_file:             # path to the key file for the certificate used to authenticate to the registry
      ca_file:              # path to the ca file used to verify the registry's certificate
      insecure_skip_verify: # may be set to true to skip verifying the registry's certificate

要使注册表更改生效,需要在节点上启动 RKE2 之前配置此文件,或者在配置的每个节点上重启动 RKE2。

注意
注意

有关详细信息,请查看 RKE2 containerd 注册表配置