SUSE Edge 文档|SUSE Telco Cloud 文档|电信功能配置

42 电信功能配置

本章将阐释通过 SUSE Telco Cloud 部署的群集上与电信相关的功能配置。

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

本章涵盖以下主题:

42.1 实时内核映像

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

实时内核有四大特性:

  • 确定性执行:

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

  • 低抖动:

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

  • 优先级继承:

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

  • 线程中断:

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

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

    注意
    注意

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

42.2 实现低延迟和高性能需指定的内核参数

内核参数必须进行配置,以便实时内核能够正常工作,从而为运行电信工作负载提供最佳性能和低延迟。在为此使用场景配置内核参数时,需要特别注意一些重要的概念:

  • 使用 SUSE 实时内核时需去除 kthread_cpus。此参数控制在哪些 CPU 上创建内核线程。它还控制允许哪些 CPU 用于 PID 1 及加载内核模块(由 kmod 用户空间辅助工具加载)。此参数无法被 SUSE 实时内核识别,因此没有任何效果。

  • 通过 isolcpusnohz_fullrcu_nocbsirqaffinity 实现 CPU 核心隔离。有关 CPU 绑定技术的完整列表,请参见第 42.3 节 “主机端的 CPU 绑定”

  • domain,nohz,managed_irq 标志添加到 isolcpus 内核参数。如果没有任何标志,isolcpus 相当于只指定 domain 标志。这将导致指定的 CPU 无法进行调度,包括内核任务。nohz 标志会停止指定 CPU 上运行的调度器节拍(如果一个 CPU 上只有一个任务可运行),managed_irq 标志可避免在指定 CPU 上路由受管理的外部(设备)中断。需要注意的是,NVMe 设备的中断请求 (IRQ) 线路由内核全权管理,因此会被路由至非隔离(系统管理)核心。例如,本节末尾提供的命令行会导致系统中仅分配 4 个队列(外加 1 个管理/控制队列):

    for I in $(grep nvme0 /proc/interrupts | cut -d ':' -f1); do cat /proc/irq/${I}/effective_affinity_list; done | column
    39      0       19      20      39

    此行为可防止磁盘 I/O 对运行在隔离核心上的任何时间敏感型应用程序造成干扰,但可能需要对以存储为重点的工作负载进行关注和精心设计。

  • 调整节拍(内核的周期性定时器中断):

    • skew_tick=1:内核时钟节拍有时会同步触发。指定 skew_tick=1 可让所有 CPU 的定时器节拍在略有偏移的时间点触发,而非完全同步,有助于减少系统抖动,实现更稳定、更低的中断响应时间(这是对延迟敏感型应用程序的关键要求)。

    • nohz=on:停止空闲 CPU 上的周期性定时器节拍。

    • nohz_full=<cpu-cores>:停止专用于实时应用程序的指定 CPU 上的周期性定时器节拍。

  • 通过指定 mce=off 禁用计算机检查异常 (MCE) 处理。MCE 是处理器检测到的硬件错误,禁用它们可以避免产生冗余日志。

  • 添加 nowatchdog 以禁用软锁死看门狗,该看门狗通过运行在定时器硬中断上下文中的定时器实现。当定时器到期时(即检测到软锁死),它会(在硬中断上下文中)打印警告,违背所有延迟目标。即便从未到期,它也会加入定时器列表,略微增加每次定时器中断的开销。此选项还会禁用 NMI 看门狗,因此 NMI 不会造成干扰。

  • nmi_watchdog=0 会禁用 NMI(不可屏蔽中断)看门狗。当使用 nowatchdog 时,可以省略此设置。

  • RCU(读取 - 复制 - 更新)是一种内核机制,允许多个读取器以无锁方式并发访问共享数据。RCU 回调是在“宽限期”后触发的函数,确保所有先前的读取器都已完成操作,从而可以安全地回收旧数据。我们对 RCU 进行微调,特别是针对敏感工作负载,将这些回调从专用(绑定的)CPU 卸载,防止内核操作干扰关键的时间敏感型任务。

    • rcu_nocbs 中指定绑定的 CPU,使 RCU 回调不会在这些 CPU 上运行。这有助于减轻实时工作负载的抖动和延迟。

    • rcu_nocb_poll 会使无回调 CPU 定期“轮询”,以确定是否需要处理回调。这可以减少中断开销。

    • rcupdate.rcu_cpu_stall_suppress=1 会抑制 RCU CPU 停滞警告,在高负载实时系统中,这些警告有时可能是误报。

    • rcupdate.rcu_expedited=1 会加速 RCU 操作的宽限期,使读取端关键部分的响应更加迅速。

    • rcupdate.rcu_normal_after_boot=1 与 rcu_expedited 一起使用时,允许 RCU 在系统引导后恢复到正常(非加速)操作模式。

    • rcupdate.rcu_task_stall_timeout=0 会禁用 RCU 任务停滞检测器,防止长时间运行的 RCU 任务可能引发的警告或系统暂停。

    • rcutree.kthread_prio=99 会将 RCU 回调内核线程的优先级设置为可能的最高值 (99),确保在需要时能够及时调度该线程并处理 RCU 回调。

  • 为使 Metal3 和 Cluster API 成功置备/取消置备群集,请添加 ignition.platform.id=openstack。该配置供 Metal3 Python 代理使用,该代理源自 OpenStack Ironic。

  • 去除 intel_pstate=passive。此选项将 intel_pstate 配置为与通用 cpufreq 调节器搭配工作,但缺点是,为了实现这一点,它会禁用硬件管理的 P 状态 (HWP)。为了减少硬件延迟,不建议将此选项用于实时工作负载。

  • intel_idle.max_cstate=0 processor.max_cstate=1 替换为 idle=poll。为了避免 C 状态转换,使用 idle=poll 选项来禁用 C 状态转换并将 CPU 保持在最高 C 状态。intel_idle.max_cstate=0 选项会禁用 intel_idle,因此使用 acpi_idle,然后 acpi_idle.max_cstate=1 会为 acpi_idl 设置最大 C 状态。在 AMD64/Intel 64 体系结构上,第一个 ACPI C 状态始终是轮询,但它使用 poll_idle() 函数,这可能会因为定期读取时钟并在超时后重启 do_idle() 中的主循环(也涉及清除和设置 TIF_POLL 任务标志)而导致一些细微的延迟。相比之下,idle=poll 以紧凑循环运行,通过忙等待方式等待任务被重新调度。这最大限度地减少了由退出空闲状态造成的延迟,但代价是 CPU 在空闲线程中也要保持全速运行。

  • 在 BIOS 中禁用 C1E。此选项对于禁用 BIOS 中的 C1E 状态非常重要,可以避免 CPU 在空闲时进入 C1E 状态。C1E 状态是一种低功耗状态,可能会在 CPU 空闲时造成延迟。

本文档的其余部分介绍了其他参数,包括大页和 IOMMU。

以下是一个包含上述调整的 32 核 Intel 服务器的内核参数示例:

$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll

以下是一个 64 核 AMD 服务器的配置示例。在 128 个逻辑处理器 (0-127) 中,前 8 个核心 (0-7) 用于系统管理,而其余 120 个核心 (8-127) 专用于运行应用程序:

$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=575291cf-74e8-42cf-8f2c-408a20dc00b8 skew_tick=1 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack amd_iommu=on iommu=pt irqaffinity=0-7 isolcpus=domain,nohz,managed_irq,8-127 nohz_full=8-127 rcu_nocbs=8-127 mce=off nohz=on nowatchdog nmi_watchdog=0 nosoftlockup quiet rcu_nocb_poll rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll

42.3 主机端的 CPU 绑定

CPU 绑定,也称为处理器亲和性,是将进程或线程绑定到特定 CPU 核心的技术,可防止操作系统的调度器将其迁移到其他核心。通过确保进程始终在同一核心上运行,进程能更快地访问保存在该核心缓存中的数据。该方法可显著提升性能并减少系统开销,因而广泛应用于高性能计算环境中。

42.3.1 通过 TuneD 实现 CPU 隔离

Tuned 是一个系统调优工具,它通过各种预定义配置文件监控系统状况以优化性能。其关键特性之一是能够为特定工作负载(如实时应用程序)隔离 CPU 核心。这可防止操作系统使用这些核心,从而避免潜在的延迟增加。

要启用和配置此功能,首先应该为我们想要隔离的 CPU 核心创建一个配置文件。在本示例中,64 个核心中,我们将 60 个核心(1-30 和 33-62)专用于应用程序,剩余 4 个核心用于系统管理。需要注意的是,隔离 CPU 的设计在很大程度上取决于实时应用程序的需求。

$ 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.

42.3.2 通过内核参数实现 CPU 隔离

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

参数说明

isolcpus

domain,nohz,​managed_irq,1-30,33-62

隔离核心 1-30 和 33-62。domain 表示这些 CPU 属于隔离域。nohz 在这些隔离的 CPU 空闲时启用无节拍操作,以减少中断。managed_irq 使绑定的 CPU 免受 IRQ 干扰。这考虑了 irqaffinity=0-7,它已将大多数 IRQ 定向到系统管理核心。

skew_tick

1

此选项允许内核在隔离的 CPU 之间错开定时器中断。

nohz

on

启用后,内核的周期性定时器中断(即“节拍”)将在任何空闲的 CPU 核心上停止。这主要有益于系统管理 CPU(0、31、32、63)。这可节省电力并减少这些通用核心上不必要的唤醒。

nohz_full

1-30,33-62

对于隔离的核心,这会停止节拍,即使 CPU 运行单个活动任务,也不例外。这意味着它使 CPU 以完全无节拍模式(或“动态节拍”)运行。内核仅在实际需要时才会传递定时器中断。

rcu_nocbs

1-30,33-62

此选项会将 RCU 回调处理从指定的 CPU 核心卸载。

rcu_nocb_poll

 

如果设置此选项,无 RCU 回调的 CPU 将定期“轮询”以确定是否需要处理回调,而不是由其他 CPU 显式唤醒。这可以减少中断开销。

irqaffinity

0,31,32,63

此选项允许内核在系统管理核心上运行中断。

idle

poll

最大限度减少因退出空闲状态造成的延迟,但代价是 CPU 在空闲线程中也要保持全速运行。

nmi_watchdog

0

此选项仅禁用 NMI 看门狗。如果设置了 nowatchdog,则可以省略此选项。

nowatchdog

 

此选项会禁用软锁死看门狗,该看门狗通过运行在定时器硬中断上下文中的定时器实现。

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

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

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll"

更新 GRUB 配置:

$ transactional-update grub.cfg
$ reboot

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

$ cat /proc/cmdline

另外还有一个脚本可用于调整 CPU 配置,它主要执行以下步骤:

  • 将 CPU 调节器设置为 performance

  • 取消将定时器迁移到隔离 CPU 的设置。

  • 将 kdaemon 线程迁移到管家 CPU。

  • 将隔离的 CPU 延迟设置为尽可能低的值。

  • 将 vmstat 更新延迟到 300 秒。

该脚本可在 SUSE Telco Cloud 示例代码库中获得。

42.4 Kubernetes 端的 CPU 绑定

42.4.1 RKE2 版本 < v1.32

您可以编辑 RKE2 配置文件,在您的 RKE2 群集中启用 CPU 绑定功能。请在/etc/rancher/rke2/config.yaml 文件中添加以下 kubelet 参数,并务必在 kubelet-reservedsystem-reserved 参数中指定系统管理 CPU 核心:

kubelet-arg:
- "cpu-manager-policy=static"
- "cpu-manager-policy-options=full-pcpus-only=true"
- "cpu-manager-reconcile-period=0s"
- "kubelet-reserved=cpu=0,31,32,63"
- "system-reserved=cpu=0,31,32,63"

42.4.2 RKE2 版本 >= v1.32

如果您的 RKE2 为 1.32 或更高版本,遵循上游 Kubernetes 实践将无法通过命令行参数配置 kubelet。您需要创建 kubelet 配置文件来实现 CPU 绑定。请参见 RKE2 官方文档

创建新的 kubelet 配置文件(例如 01-cpu-pinning.conf),并将其放置在 /var/lib/rancher/rke2/agent/etc/kubelet.conf.d/ 目录中:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cpuManagerPolicy: static
reservedSystemCPUs: 0,31,32,63
topologyManagerPolicy: single-numa-node

配置更改后,需要重启相应的 RKE2 服务(server 或 agent)才能使其生效。该操作会短暂中断主机上的 RKE2 服务。请根据节点类型,仅运行以下任一命令:

# If the node is RKE2 agent
systemctl restart rke2-agent
# Else if the node is RKE2 server
systemctl restart rke2-server

42.4.3 部署利用绑定 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"

42.5 CNI 配置

42.5.1 Cilium

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

cni:
- cilium

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

要将第 42.6.2 节 “方法二(推荐):SR-IOV 网络操作器”中所述的 SR-IOV 网络与 Cilium 结合使用,需要部署 multus 元插件,并确保 multus 在所有 CNI 插件中优先加载。

cni:
- multus
- cilium

42.5.2 Calico

Calico 是 SUSE Edge for Telco 的另一款 CNI 插件。要在 RKE2 群集上启用 Calico 作为默认插件,需要在 /etc/rancher/rke2/config.yaml 文件中进行以下配置:

cni:
- calico

也可通过命令行参数指定此配置,即在 /etc/systemd/system/rke2-server 文件的 server 行中添加 --cni=calico

要将第 42.6.2 节 “方法二(推荐):SR-IOV 网络操作器”中所述的 SR-IOV 网络与 Calico 结合使用,需要部署 multus 元插件,并确保 multus 在所有 CNI 插件中优先加载。

cni:
- multus
- calico
注意
注意

有关 CNI 插件的详细信息,请参见 Network Options

42.5.3 Bond CNI

通常而言,绑定是一种将多个网络接口聚合为单个逻辑“绑定”接口的方法。这通常用于通过引入冗余网络路径提高服务可用性,也可在特定绑定模式下用于提高带宽。以下 CNI 插件支持与 multus 结合使用的 Bond CNI 插件:

  • MACVLAN

  • Host Device

  • SR-IOV

42.5.3.1 Bond CNI 与 MACVLAN 结合使用

要将 Bond CNI 插件与 MACVLAN 结合使用,容器中需要有两个空闲接口。本示例使用“enp8s0”和“enp9s0”。首先为它们创建网络附加定义:

NetworkAttachmentDefinition enp8s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp8s0-conf
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "macvlan",
          "capabilities": { "ips": true },
          "master": "enp8s0",
          "mode": "bridge",
          "ipam": {}
        }, {
          "capabilities": { "mac": true },
          "type": "tuning"
        }
      ]
    }'

NetworkAttachmentDefinition enp9s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp9s0-conf
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "macvlan",
          "capabilities": { "ips": true },
          "master": "enp9s0",
          "mode": "bridge",
          "ipam": {}
        }, {
          "capabilities": { "mac": true },
          "type": "tuning"
        }
      ]
    }'

之后,为绑定本身添加网络附加定义。

NetworkAttachmentDefinition bond

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: bond-net1
spec:
  config: '{
  "type": "bond",
  "cniVersion": "0.3.1",
  "name": "bond-net1",
  "mode": "active-backup",
  "failOverMac": 1,
  "linksInContainer": true,
  "miimon": "100",
  "mtu": 1500,
  "links": [
     {"name": "net1"},
     {"name": "net2"}
  ],
  "ipam": {
    "type": "static",
    "addresses": [
      {
        "address": "192.168.200.100/24",
        "gateway": "192.168.200.1"
      }
    ],
    "subnet": "192.168.200.0/24",
    "routes": [{
      "dst": "0.0.0.0/0"
    }]
  }
}'

此处采用的是静态 IP 地址分配方式,将绑定的地址定义为 /24 网络上的“192.168.200.100”,网关位于该网络的第一个可用地址。在绑定的网络附加定义中,我们还定义了所需的绑定类型,本示例中为 active-backup。

要使用此绑定,Pod 需要了解所有接口。以下是 Pod 定义示例:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  annotations:
        k8s.v1.cni.cncf.io/networks: '[
{"name": "enp8s0-conf",
"interface": "net1"
},
{"name": "enp9s0-conf",
"interface": "net2"
},
{"name": "bond-net1",
"interface": "bond0"
}]'
spec:
  restartPolicy: Never
  containers:
  - name: bond-test
    image: alpine:latest
    command:
      - /bin/sh
      - "-c"
      - "sleep 60m"
    imagePullPolicy: IfNotPresent

请注意注解如何引用所有网络,以及如何定义接口“enp8s0 → net1”和“enp9s0 → net2”之间的映射关系。

42.5.3.2 Bond CNI 与 Host Device 结合使用

要将 Bond CNI 插件与 Host Device 结合使用,主机上需要有两个空闲接口。这些接口随后会映射到容器中。本示例使用“enp8s0”和“enp9s0”。首先为它们创建网络附加定义:

NetworkAttachmentDefinition enp8s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp8s0-hostdev
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "host-device",
          "name": "host0",
          "device": "enp8s0",
          "ipam": {}
        }]
    }'

NetworkAttachmentDefinition enp9s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp9s0-hostdev
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "host-device",
          "name": "host0",
          "device": "enp9s0",
          "ipam": {}
        }]
    }'

之后,为绑定本身添加网络附加定义,此过程与 MACVLAN 场景类似。

NetworkAttachmentDefinition bond

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: bond-net1
spec:
  config: '{
  "type": "bond",
  "cniVersion": "0.3.1",
  "name": "bond-net1",
  "mode": "active-backup",
  "failOverMac": 1,
  "linksInContainer": true,
  "miimon": "100",
  "mtu": 1500,
  "links": [
     {"name": "net1"},
     {"name": "net2"}
  ],
  "ipam": {
    "type": "static",
    "addresses": [
      {
        "address": "192.168.200.100/24",
        "gateway": "192.168.200.1"
      }
    ],
    "subnet": "192.168.200.0/24",
    "routes": [{
      "dst": "0.0.0.0/0"
    }]
  }
}'

此处采用的是静态 IP 地址分配方式,将绑定的地址定义为 /24 网络上的“192.168.200.100”,网关位于该网络的第一个可用地址。在绑定的网络附加定义中,定义绑定类型,本示例中为 active-backup。

要使用此绑定,Pod 需要了解所有接口。以下是结合 Host Device 使用绑定的 Pod 定义示例:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  annotations:
        k8s.v1.cni.cncf.io/networks: '[
{"name": "enp8s0-hostdev",
"interface": "net1"
},
{"name": "enp9s0-hostdev",
"interface": "net2"
},
{"name": "bond-net1",
"interface": "bond0"
}]'
spec:
  restartPolicy: Never
  containers:
  - name: bond-test
    image: alpine:latest
    command:
      - /bin/sh
      - "-c"
      - "sleep 60m"
    imagePullPolicy: IfNotPresent

42.5.3.3 Bond CNI 与 SR-IOV 结合使用

将 Bond CNI 与 SR-IOV 结合使用的操作相当简单。有关如何设置 SR-IOV 的详细信息,请参见第 42.6 节 “SR-IOV”。如前文所述,您需要创建 SriovNetworkNodePolicies,在其中定义 resourceNames 以及虚拟功能的数量等。resourceNamesSriovNetwork 使用,SriovNetwork 在 Pod 定义中用作接口。绑定定义与 MACVLAN 和 Host Device 场景完全相同。

注意
注意

Bond CNI 与 SR-IOV 结合使用这种方式仅适用于使用内核驱动程序的 SRIOV 虚拟功能。用户空间驱动程序 VF(如 DPDK 工作负载中使用的 VF)无法通过 Bond CNI 进行绑定。

42.6 SR-IOV

单根 I/O 虚拟化 (SR-IOV) 允许单个物理设备(如网络适配器)将其资源拆分分配给多个 PCIe 硬件功能,使各类应用程序能够直接访问硬件资源。

我们提供两种不同的方法,在您的群集中部署 SR-IOV 功能:

在少数场景中,如果需要同时使用两种方案(通过网络操作器管理网络设备,通过设备插件管理 vRAN 加速卡),则必须将它们部署在不同的 Kubernetes 名称空间中。该隔离措施是避免两个部署流程发生冲突的关键。

42.6.1 方法一:SR-IOV 网络设备插件守护程序集和配置映射

SR-IOV 网络设备插件可在 Kubernetes 主机上发现并公布网络资源,包括 PCI 物理功能 (PF) 及其虚拟功能 (VF)。

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

您需要创建配置映射以定义 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)

SR-IOV 设备插件通过包含 JSON 文件的配置映射,定义 Kubernetes 需要公布的硬件资源。该配置基于两个核心概念:选择器(用于硬件发现)和资源(用于 Kubernetes 资源公布)。

资源是 Pod 可申请使用的命名实体(例如 rancher.io/intel_fec_5g)。资源可定义为以下两种类型之一:

  • accelerator:用于 vRAN 加速卡(如 ACC100/vRAN Boost)。

  • netdevice:用于标准网络接口 (NIC)。

您可以通过选择器过滤节点上的硬件,来定义目标设备:

  • vendors8086 (Intel)

  • devices0d5d(FEC 卡)、1889 (NIC)

  • driversvfio-pci

  • pfNamesp2p1(物理接口名称)

对于网络卡,还可从单个物理功能中选择一部分虚拟功能 (VF):

  • pfNames["eth1#1,2,3,4,5,6"][eth1#1-6]

为允许 Pod 申请使用设备,每个资源必须设置名称,名称由前缀和标识名组成:

  • resourceNamepci_sriov_net_bh_dpdk

  • resourcePrefixRancher.io

Pod 可使用组合的资源名称申请资源,例如 rancher.io/pci_sriov_net_bh_dpdk

注意
注意

本文档未列出所有可用的选择器。不同的资源类型支持不同的选择器集合。有关完整信息,请参见 SR-IOV 网络设备插件代码库

以下配置映射示例将创建三个资源:一个用于 vRAN 加速卡 (FEC),另外两个分别用于两个不同的 NIC 端口。

配置 FEC 卡时,需要先检索设备 ID 和 VFIO 令牌,请参见第 42.8 节 “vRAN 加速 (Intel ACC100/ACC200)”中的说明了解先决条件。

apiVersion: v1
kind: ConfigMap
metadata:
  name: sriovdp-config
  namespace: kube-system
data:
  config.json: |
    {
        "resourceList": [
            {
            	"resourcePrefix": "rancher.io",
                "resourceName": "intel_fec_5g",
                "deviceType": "accelerator",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["0d5d"]
                },
        		"additionalInfo": {
          			"*": {
            			"VFIO_TOKEN": "00112233-4455-6677-8899-aabbccddeeff"
          			}
          		}
            },
            {
            	"resourcePrefix": "rancher.io",
                "resourceName": "intel_sriov_odu",
                "deviceType": "netdevice",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["1889"],
                    "drivers": ["vfio-pci"],
                    "pfNames": ["p2p1"]
                }
            },
            {
            	"resourcePrefix": "rancher.io",
                "resourceName": "intel_sriov_oru",
                "deviceType": "netdevice",
                "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: registry.suse.com/rancher/hardened-sriov-network-device-plugin:v3.9.0-build20250425
        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 nodes -o json | jq '.items[] | {name: .metadata.name, allocatable: .status.allocatable}'
    {
      "name": "node1.suse.edge.com",
      "allocatable": {
    	  "cpu": "64",
    	  "ephemeral-storage": "256196109726",
    	  "hugepages-1Gi": "40Gi",
    	  "hugepages-2Mi": "0",
    	  "rancher.io/intel_fec_5g": "16",
    	  "rancher.io/intel_sriov_odu": "4",
    	  "rancher.io/intel_sriov_oru": "4",
    	  "memory": "221396384Ki",
    	  "pods": "110"
      }
    }
  • FEC 加速卡对应的 resourceName 为 rancher.io/intel_fec_5g,共提供 16 个可用的 VF。

  • NIC 卡对应的 resourceName 为 rancher.io/intel_sriov_odurancher.io/intel_sriov_oru。每个资源各提供 4 个 VF。

重要
重要

如果 Kubernetes 节点中未检测到可分配的网络接口资源,必须及时解决该问题。常见原因是配置映射的规范存在错误,建议检查配置映射及其选择器。

42.6.2 方法二(推荐):SR-IOV 网络操作器

  • 获取 Helm(如果没有):

$ curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
  • sriov-network-operator 名称空间中安装 SR-IOV 网络操作器:

helm install sriov-crd oci://registry.suse.com/edge/charts/sriov-crd -n sriov-network-operator
helm install sriov-network-operator oci://registry.suse.com/edge/charts/sriov-network-operator -n sriov-network-operator
  • 检查已部署的 CRD 和 Pod:

$ kubectl get crd
$ kubectl -n sriov-network-operator get pods
  • 检查节点是否已添加 SR-IOV 标签。

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

$ 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 -n sriov-network-operator
NAMESPACE             NAME                            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                                           AGE
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

等待数分钟后,系统将检测到所有节点并完全完成 SR-IOV 功能配置。该更新过程有时可能需要长达 10 分钟:

$ kubectl get sriovnetworknodestates -A
NAMESPACE             NAME     AGE
sriov-network-operator   xr11-2   83s
  • 检查网络接口是否已被检测到。

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

$ kubectl get sriovnetworknodestates -n sriov-network-operator -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 Pod,使配置更新生效。

  • 创建 SriovNetworkNodePolicy 配置 VF

该策略将创建供 Pod 使用的 intelnicsDpdk,同时将 vfio-pci 驱动程序绑定至提供的 PCI 设备,并创建 8 个最大传输单元 (MTU) 为 1500 的 VF:

注意
注意

resourceName 字段不得包含任何特殊字符,且在整个群集中必须唯一。该示例使用 deviceType: vfio-pci,因为 dpdk 将与 SR-IOV 结合使用。如果您不使用 dpdk,可配置 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
  • 在所有节点上验证配置是否生效:

通过预定义的 resourcePrefix rancher.io,系统将发现包含 8 个 VF 的 rancher.io/intelnicsDpdk 资源。

$ kubectl get nodes -o jsonpath='{"items": [ { "name": @.metadata.name, "allocatable": @.status.allocatable } ]}' | jq
{
  "name": "node1.suse.edge.com",
  "allocatable": {
	  "cpu": "64",
	  "ephemeral-storage": "256196109726",
	  "hugepages-1Gi": "60Gi",
	  "hugepages-2Mi": "0",
	  "rancher.io/intel_fec_5g": "16",
	  "memory": "200424836Ki",
	  "pods": "110",
	  "rancher.io/intelnicsDpdk": "8"
  }
}
  • (可选)创建 sriovnetwork

该步骤为可选操作,仅在需要自定义网络定义时执行。目的是指定要绑定至之前创建的节点策略的 resourceName

如果设置了 networkNamespace,该网络将仅对该名称空间中的 Pod 开放;如果未设置,该网络将在网络操作器的安装名称空间中开放。

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: network-dpdk
  namespace: sriov-network-operator		# where SRIOV Operator is installed
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
  networkNamespace: default 		# where workloads are deployed
  • 如果更新操作成功,目标群集中将创建 NetworkAttachmentDefinition (NAD)。

$ kubectl get net-attach-def -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: default
    resourceVersion: "13124"
    uid: df7c89f5-177c-4f30-ae72-7aef3294fb15
  spec:
    config: '{ "cniVersion":"0.4.0", "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: ""

工作负载 Pod 可通过 resourceName rancher.io/intelnicsDpdk 使用网络接口的 VF。

42.7 DPDK

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

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

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

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

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

  5. 作为一组库提供的数据包框架,可帮助开发数据包处理解决方案。

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

  • 安装 DPDK 软件包:

$ transactional-update pkg install dpdk dpdk-tools libdpdk-25
$ reboot
  • 内核参数:

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

参数说明

iommu

pt

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

intel_iommu 或 amd_iommu

on

此选项允许为 VF 使用 vfio

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

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll"

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

$ transactional-update grub.cfg
$ reboot
  • 加载 vfio-pci 内核模块并在 NIC 上启用 SR-IOV。第一个参数用于指定 vfio-pci 驱动程序支持 SR-IOV,第二个参数用于防止 PCI 设备在空闲时进入低功耗状态:

$ 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

42.8 vRAN 加速 (Intel ACC100/ACC200)

随着通信服务提供商从 4G 网络向 5G 网络升级,许多企业开始采用虚拟化无线接入网 (vRAN) 架构,以实现更高的信道容量,并更便捷地部署边缘侧服务和应用程序。vRAN 解决方案可根据网络的实时流量和需求变化灵活调整容量,是部署低延迟服务的理想选择。

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

过去,Intel 推出了 ACC100 vRAN 加速卡,用于快速执行一层前向纠错 FEC 算法,释放主 CPU 的处理能力。如今,Intel 已将该技术直接集成至新一代 CPU 中,从 Sapphire Rapids 系列开始,将其命名为 Intel vRAN Boost(也称为 ACC200)。Intel vRAN Boost 作为 CPU 内置的分流加速卡,已不再需要额外的硬件加速卡。本章节将详细介绍如何配置 SUSE Telco Cloud,使工作负载能够利用 ACC100 或 Intel vRAN Boost 加速功能。

42.8.1 内核参数

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

参数说明

iommu

pt

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

intel_iommu 或 amd_iommu

on

此选项允许为 VF 使用 vfio。

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

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll"

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

$ transactional-update grub.cfg
$ reboot

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

$ cat /proc/cmdline

42.8.2 在 FEC 加速卡上配置 SR-IOV

  • 加载 vfio-pci 内核模块以启用 vRAN 加速功能。第一个参数用于指定 vfio-pci 模块支持 SR-IOV,第二个参数用于防止 PCI 设备在空闲时进入低功耗状态。

$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  • 检索 FEC 加速卡的 PCI 设备地址:

$ 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)。

检查加速卡支持的最大 VF 数量,随后配置加速卡以开放所需数量的 VF,不得超过最大支持数量。本示例中将加速卡配置为开放其全部 16 个 VF:

$ cat /sys/bus/pci/devices/0000:8a:00.0/sriov_totalvfs
16
$ echo 16 > /sys/bus/pci/devices/0000:8a:00.0/sriov_numvfs
  • 为加速卡及其虚拟功能配置 4G 或 5G 配置文件。必须提供唯一的 VF 令牌 (UUID)。工作负载将通过该 VF 令牌利用加速卡的 FEC 加速功能:

$ pf_bb_config ACC200 -c /opt/pf-bb-config/acc200_config_vf_5g.cfg -v 00112233-4455-6677-8899-aabbccddeeff
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 ACC200 configuration complete
Tue Jun  6 10:49:21 2023:INFO:ACC200 PF [0000:8a:00.0] configuration complete!
  • 验证基于 FEC 物理功能 (PF) 创建的新虚拟功能 (VF)。注意这些 VF 的设备 ID 为 0d5d,在下一步中,将这些 VF 公布为 Kubernetes 资源时需要用到该信息:

$ 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=

42.8.3 配置 Kubernetes 以利用 FEC 加速功能

最后一步是通过 SR-IOV 设备插件,将 VF 公布至 Kubernetes 中。使用上一步获取的 VF 设备 ID 创建配置映射,并安装 SR-IOV 设备插件。当 Kubernetes 节点将 FEC VF 显示为可分配资源时,群集即完成准备,工作负载可享受 FEC 加速功能。

请按照第 42.6 节 “SR-IOV”中的方法一执行操作,SR-IOV 网络操作器不适用于 FEC 加速卡,因此方法二不适用。

42.9 大页

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

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

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

  • 内核参数

要启用大页,我们应添加以下内核参数。在此例中,我们配置了 40 个 1G 页面,不过大页大小和确切数量应根据应用程序的内存需求进行调整:

参数说明

hugepagesz

1G

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

hugepages

40

这是先前定义的大页数量

default_hugepagesz

1G

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

修改 GRUB 文件 /etc/default/grub,在 GRUB_CMDLINE_LINUX 中添加这些参数:

default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0

更新 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
...

42.10 可感知 NUMA 的调度

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

42.10.1 识别 NUMA 节点

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

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

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

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

42.11 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:
  chart: oci://registry.suse.com/edge/charts/metallb
  targetNamespace: metallb-system
  version: 305.0.1+up0.15.2
  createNamespace: true
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: endpoint-copier-operator
  namespace: kube-system
spec:
  chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
  targetNamespace: endpoint-copier-operator
  version: 305.0.1+up0.3.0
  createNamespace: true
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

42.12 专用仓库配置

可以配置 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 仓库配置

42.13 精确时间协议

精确时间协议 (PTP) 是由电气和电子工程师协会 (IEEE) 开发的一种网络协议,旨在实现计算机网络中的亚微秒级时间同步。自诞生以来的几十年里,PTP 已在许多行业广泛应用。近年来,随着其作为 5G 网络关键要素的重要性凸显,在电信网络中的采用率不断提升。尽管 PTP 协议相对简单,但其配置会因应用场景的不同而有显著差异。为此,已定义并标准化多个配置文件。

本节仅介绍专用于电信行业的配置文件。因此,假设 NIC 具备时间戳能力和 PTP 硬件时钟 (PHC)。如今,所有电信级网络适配器均在硬件层面支持 PTP,但您可以通过以下命令验证此类功能:

# ethtool -T p1p1
Time stamping parameters for p1p1:
Capabilities:
        hardware-transmit
        software-transmit
        hardware-receive
        software-receive
        software-system-clock
        hardware-raw-clock
PTP Hardware Clock: 0
Hardware Transmit Timestamp Modes:
        off
        on
Hardware Receive Filter Modes:
        none
        all

p1p1 替换为用于 PTP 的接口名称。

以下章节将提供有关如何在 SUSE Telco Cloud 中安装和配置 PTP 的指导,但要求您已熟悉基本的 PTP 概念。如需简要了解 PTP 以及 SUSE Telco Cloud 中包含的 PTP 实现,请访问 https://documentation.suse.com/sles/html/SLES-all/cha-tuning-ptp.html

42.13.1 安装 PTP 软件组件

在 SUSE Telco Cloud 中,PTP 功能通过 linuxptp 软件包实现,该软件包包含两个组件:

  • ptp4l:控制 NIC 上的 PHC 并运行 PTP 协议的守护程序

  • phc2sys:将系统时钟与 NIC 上经 PTP 同步的 PHC 保持同步的守护程序

要使系统同步正常工作,就必须运行这两个守护程序,并且必须根据您的设置正确配置它们。相关信息,请参见第 42.13.2 节 “为电信部署配置 PTP”

在下游群集中集成 PTP 最简单且最佳的方式是,在 Edge Image Builder (EIB) 定义文件的 packageList 下添加 linuxptp 软件包。这样,在群集置备期间就会自动安装 PTP 控制平面软件。有关安装软件包的详细信息,请参见 EIB 文档(第 3.3.6 节 “配置 RPM 软件包”)。

以下是包含 linuxptp 的 EIB 清单示例:

apiVersion: 1.3
image:
  imageType: RAW
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-Base-RT-GM.raw
  outputImageName: eibimage-slmicrort-telco.raw
operatingSystem:
  time:
    timezone: America/New_York
  kernelArgs:
    - ignition.platform.id=openstack
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
      - fstrim
      - time-sync.target
    enable:
      - ptp4l
      - phc2sys
  users:
    - username: root
      encryptedPassword: $ROOT_PASSWORD
  packages:
    packageList:
      - jq
      - dpdk
      - dpdk-tools
      - libdpdk-25
      - pf-bb-config
      - open-iscsi
      - tuned
      - cpupower
      - linuxptp
    sccRegistrationCode: $SCC_REGISTRATION_CODE
注意
注意

SUSE Telco Cloud 中包含的 linuxptp 软件包默认不会启用 ptp4lphc2sys。如果在置备时部署了针对特定系统的配置文件(请参见第 42.13.3 节 “Cluster API 集成”),则应启用它们。可通过将其添加到清单的 systemd 部分来实现,如上例所示。

按照 EIB 文档(第 3.4 节 “构建映像”)中所述的常规过程构建映像,并使用该映像部署群集。如果您是 EIB 新手,请从第 11 章 “Edge Image Builder开始。

42.13.2 为电信部署配置 PTP

许多电信应用场景要求严格保持偏差极小的相位和时间同步,为此定义了两个面向电信的配置文件:ITU-T G.8275.1 和 ITU-T G.8275.2。这两个配置文件均设置了高频率同步消息,以及其他独特特性(如使用替代的最佳主时钟算法 (BMCA))。这种特性要求 ptp4l 所使用的配置文件中包含特定设置,以下几节将提供相关参考信息。

注意
注意
  • 以下两节仅介绍时间接收器配置中的普通时钟场景。

  • 对于任何此类配置文件,都必须在精心规划的 PTP 基础架构中使用。

  • 要用于您的特定 PTP 网络,可能需要额外微调配置,请务必检查并根据需要调整所提供的示例。

42.13.2.1 PTP 配置文件 ITU-T G.8275.1

G.8275.1 配置文件具有以下特点:

  • 直接运行在以太网上,需要完整的网络支持(相邻节点/交换机必须支持 PTP)。

  • 默认域设置为 24。

  • 数据集比较基于 G.8275.x 算法及其在 priority2 之后的 localPriority 值。

将以下内容复制到名为 /etc/ptp4l-G.8275.1.conf 的文件中:

# Telecom G.8275.1 example configuration
[global]
domainNumber                    24
priority2			255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             -3
logSyncInterval                 -4
logMinDelayReqInterval          -4
announceReceiptTimeout		3
serverOnly                      0
ptp_dst_mac                     01:80:C2:00:00:0E
network_transport               L2

创建好文件后,必须在 /etc/sysconfig/ptp4l 中引用该文件,才能使守护程序正确启动。可通过将 OPTIONS= 行更改为以下内容实现:

OPTIONS="-f /etc/ptp4l-G.8275.1.conf -i $IFNAME --message_tag ptp-8275.1"

具体说明:

  • -f 指定要使用的配置文件名称(此处为 /etc/ptp4l-G.8275.1.conf)。

  • -i 指定要使用的接口名称,请将 $IFNAME 替换为实际接口名称。

  • --message_tag 可用于在系统日志中更好地识别 ptp4l 输出,这是可选参数。

完成上述步骤后,必须(重新)启动 ptp4l 守护程序:

# systemctl restart ptp4l

运行以下命令,通过观察日志来检查同步状态:

# journalctl -e -u ptp4l

42.13.2.2 PTP 配置文件 ITU-T G.8275.2

G.8275.2 配置文件具有以下特点:

  • 运行在 IP 上,不需要完整的网络支持(相邻节点/交换机可以不支持 PTP)。

  • 默认域设置为 44。

  • 数据集比较基于 G.8275.x 算法及其在 priority2 之后的 localPriority 值。

将以下内容复制到名为 /etc/ptp4l-G.8275.2.conf 的文件中:

# Telecom G.8275.2 example configuration
[global]
domainNumber                    44
priority2			255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             0
serverOnly                      0
hybrid_e2e                      1
inhibit_multicast_service       1
unicast_listen                  1
unicast_req_duration            60
logSyncInterval                 -5
logMinDelayReqInterval          -4
announceReceiptTimeout		2
#
# Customize the following for slave operation:
#
[unicast_master_table]
table_id                        1
logQueryInterval                2
UDPv4                           $PEER_IP_ADDRESS
[$IFNAME]
unicast_master_table            1

请确保替换以下占位符:

  • $PEER_IP_ADDRESS - 要与之通信的下一个 PTP 节点的 IP 地址,例如提供同步的主时钟或边界时钟。

  • $IFNAME - 告知 ptp4l 使用哪个接口进行 PTP。

创建好文件后,必须在 /etc/sysconfig/ptp4l 中引用该文件以及 PTP 所用接口的名称,才能使守护程序正确启动。可通过将 OPTIONS= 行更改为以下内容实现:

OPTIONS="-f /etc/ptp4l-G.8275.2.conf --message_tag ptp-8275.2"

具体说明:

  • -f 指定要使用的配置文件名称(此处为 /etc/ptp4l-G.8275.2.conf)。

  • --message_tag 可用于在系统日志中更好地识别 ptp4l 输出,这是可选参数。

完成上述步骤后,必须(重新)启动 ptp4l 守护程序:

# systemctl restart ptp4l

运行以下命令,通过观察日志来检查同步状态:

# journalctl -e -u ptp4l

42.13.2.3 phc2sys 的配置

建议在配置 phc2sys 之前先完成 ptp4l 的全部配置,不过这不是强制要求。phc2sys 不需要配置文件,其执行参数可通过 /etc/sysconfig/ptp4l 中的 OPTIONS= 变量单独控制,方式与 ptp4l 类似:

OPTIONS="-s $IFNAME -w"

其中,$IFNAME 是已在 ptp4l 中设置的接口名称,将用作系统时钟的同步源。此参数用于识别源 PHC。

42.13.3 Cluster API 集成

当通过管理群集和定向网络置备部署群集时,可在置备时将配置文件和 /etc/sysconfig 中的两个配置变量都部署到主机上。以下是群集定义的片段,重点展示经过修改的 RKE2ControlPlane 对象,该对象会在所有主机上部署相同的 G.8275.1 配置文件:

apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  registrationMethod: "control-plane-endpoint"
  serverConfig:
    cni: canal
  agentConfig:
    format: ignition
    cisProfile: cis
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        systemd:
          units:
            - name: rke2-preinstall.service
              enabled: true
              contents: |
                [Unit]
                Description=rke2-preinstall
                Wants=network-online.target
                Before=rke2-install.service
                ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
                [Service]
                Type=oneshot
                User=root
                ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
                ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
                ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                ExecStartPost=/bin/sh -c "umount /mnt"
                [Install]
                WantedBy=multi-user.target
        storage:
          files:
            - path: /etc/ptp4l-G.8275.1.conf
              overwrite: true
              contents:
                inline: |
                  # Telecom G.8275.1 example configuration
                  [global]
                  domainNumber                    24
                  priority2                       255
                  dataset_comparison              G.8275.x
                  G.8275.portDS.localPriority     128
                  G.8275.defaultDS.localPriority  128
                  maxStepsRemoved                 255
                  logAnnounceInterval             -3
                  logSyncInterval                 -4
                  logMinDelayReqInterval          -4
                  announceReceiptTimeout          3
                  serverOnly                      0
                  ptp_dst_mac                     01:80:C2:00:00:0E
                  network_transport               L2
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /etc/sysconfig/ptp4l
              overwrite: true
              contents:
                inline: |
                  ## Path:           Network/LinuxPTP
                  ## Description:    Precision Time Protocol (PTP): ptp4l settings
                  ## Type:           string
                  ## Default:        "-i eth0 -f /etc/ptp4l.conf"
                  ## ServiceRestart: ptp4l
                  #
                  # Arguments when starting ptp4l(8).
                  #
                  OPTIONS="-f /etc/ptp4l-G.8275.1.conf -i $IFNAME --message_tag ptp-8275.1"
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /etc/sysconfig/phc2sys
              overwrite: true
              contents:
                inline: |
                  ## Path:           Network/LinuxPTP
                  ## Description:    Precision Time Protocol (PTP): phc2sys settings
                  ## Type:           string
                  ## Default:        "-s eth0 -w"
                  ## ServiceRestart: phc2sys
                  #
                  # Arguments when starting phc2sys(8).
                  #
                  OPTIONS="-s $IFNAME -w"
              mode: 0644
              user:
                name: root
              group:
                name: root
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"

除了其他变量外,必须为上述定义补全接口名称及其他 Cluster API 对象(如第 43 章 “全自动定向网络置备中所述)。

注意
注意
  • 仅当群集中的硬件保持统一且所有主机都需要采用相同配置(包括接口名称)时,这种方法才适用。

  • 也可以使用其他方法,未来版本中将会介绍相关内容。

至此,您的主机应已具备可正常运行的 PTP 堆栈,并将开始协商其 PTP 角色。