41 电信功能配置 #
本章将阐释通过 SUSE Edge for Telco 部署的群集上与电信相关的功能配置。
将使用有关自动置备的一章(第 42 章 “全自动定向网络置备”)中所述的定向网络置备部署方法。
本章涵盖以下主题:
实时内核映像(第 41.1 节 “实时内核映像”):实时内核使用的内核映像。
实现低延迟和高性能需指定的内核参数(第 41.2 节 “实现低延迟和高性能需指定的内核参数”):为了在运行电信工作负载时实现最高性能和低延迟,实时内核需使用的内核参数。
通过 Tuned 和内核参数实现 CPU 绑定(第 41.3 节 “通过 Tuned 和内核参数实现 CPU 绑定”):通过内核参数和 Tuned 配置文件隔离 CPU。
CNI 配置(第 41.4 节 “CNI 配置”):Kubernetes 群集使用的 CNI 配置。
SR-IOV 配置(第 41.5 节 “SR-IOV”):Kubernetes 工作负载使用的 SR-IOV 配置。
DPDK 配置(第 41.6 节 “DPDK”):系统使用的 DPDK 配置。
vRAN 加速卡(第 41.7 节 “vRAN 加速 (
Intel ACC100/ACC200
)”):Kubernetes 工作负载使用的加速卡配置。大页(第 41.8 节 “大页”):Kubernetes 工作负载使用的大页配置。
Kubernetes 上的 CPU 绑定(第 41.9 节 “在 Kubernetes 上进行 CPU 绑定”):配置 Kubernetes 和应用程序以利用 CPU 绑定的优势。
可感知 NUMA 的调度配置(第 41.10 节 “可感知 NUMA 的调度”):Kubernetes 工作负载使用的可感知 NUMA 的调度配置。
MetalLB 配置(第 41.11 节 “MetalLB”):Kubernetes 工作负载使用的 MetalLB 配置。
专用注册表配置(第 41.12 节 “专用注册表配置”):Kubernetes 工作负载使用的专用注册表配置。
精确时间协议配置(第 41.13 节 “精确时间协议”):用于运行电信行业 PTP 配置的配置文件。
41.1 实时内核映像 #
实时内核映像不一定比标准内核更好。它是针对特定使用场景进行微调的另一种内核。经过微调的实时内核可以降低延迟,但代价是降低了吞吐量。不建议将实时内核用于一般用途,但在本例中,则建议为电信工作负载使用该内核,因为在该场景下,延迟是一项关键考虑因素。
实时内核有四大特性:
确定性执行:
获得更高的可预测性 — 确保关键业务流程每次都能及时完成并提供高质量的服务,即使系统负载极高的情况下也不例外。通过围隔出关键系统资源供高优先级流程使用,可以确保为时间敏感型应用程序提供更高的可预测性。
低抖动:
基于高确定性技术的低抖动有助于应用程序与现实世界保持同步。这可以为那些需要持续重复计算的服务提供帮助。
优先级继承:
优先级继承是指当较高优先级的进程在完成其任务之前需要先等待较低优先级的进程完成时,较低优先级的进程可以提升为较高优先级的功能。SUSE Linux Enterprise Real Time 解决了任务关键型进程的优先级倒置问题。
线程中断:
在通用操作系统中以中断模式运行的进程不可抢占。在 SUSE Linux Enterprise Real Time 中,这些中断已由可中断的内核线程封装,并允许用户定义的较高优先级进程抢占硬中断和软中断。
在本例中,如果您安装了
SUSE Linux Micro RT
之类的实时映像,那么就已经安装了实时内核。可以从 SUSE Customer Center 下载实时内核映像。
41.2 实现低延迟和高性能需指定的内核参数 #
内核参数必须进行配置,以便实时内核能够正常工作,从而为运行电信工作负载提供最佳性能和低延迟。在为此使用场景配置内核参数时,需要特别注意一些重要的概念:
使用 SUSE 实时内核时需去除
kthread_cpus
。此参数控制在哪些 CPU 上创建内核线程。它还控制允许哪些 CPU 用于 PID 1 及加载内核模块(由 kmod 用户空间辅助工具加载)。此参数无法被 SUSE 实时内核识别,因此没有任何效果。通过
isolcpus
、nohz_full
、rcu_nocbs
和irqaffinity
隔离 CPU 核心。有关 CPU 绑定技术的完整列表,请参见第 41.3 节 “通过 Tuned 和内核参数实现 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 net.ifnames=0 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 net.ifnames=0 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
41.3 通过 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.
然后我们需要修改用于隔离 CPU 核心的 GRUB 选项以及其他重要的 CPU 使用参数。请务必根据您的当前硬件规格自定义以下选项:
参数 | 值 | 说明 |
---|---|---|
isolcpus | domain,nohz,managed_irq,1-30,33-62 | 隔离核心 1-30 和 33-62。 |
skew_tick | 1 | 此选项允许内核在隔离的 CPU 之间错开定时器中断。 |
nohz | on | 启用后,内核的周期性定时器中断(即“节拍”)将在任何空闲的 CPU 核心上停止。这主要有益于系统管理
CPU( |
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 | 此选项会禁用软锁死看门狗,该看门狗通过运行在定时器硬中断上下文中的定时器实现。 |
以下命令会修改 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 net.ifnames=0 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 Edge for Telco 示例储存库中获得。
41.4 CNI 配置 #
41.4.1 Cilium #
Cilium
是 SUSE Edge for Telco 的默认 CNI 插件。要在 RKE2 群集上启用
Cilium 作为默认插件,需要在 /etc/rancher/rke2/config.yaml
文件中进行以下配置:
cni:
- cilium
也可以使用命令行参数来指定此配置,即,将 --cni=cilium
添加到
/etc/systemd/system/rke2-server
文件的 server 行中。
要使用下一节(第 41.5 节 “SR-IOV”)中所述的 SR-IOV
网络操作器,请将 Multus
与另一个 CNI 插件(例如 Cilium
或 Calico
)一起用作辅助插件。
cni:
- multus
- cilium
41.5 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
有很多组合方式可用于发现并创建资源组,以将一些 VF
分配给 Pod。
根据硬件和使用场景设置用于匹配接口的过滤器和组后,下面的配置映射展示了一个可使用的示例:
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
文件以部署设备插件。
设备插件支持多种体系结构(arm
、amd
、ppc64le
),因此同一文件可用于不同的体系结构,以便为每个体系结构部署多个
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.7.0-build20240816
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" }
FEC
为intel.com/intel_fec_5g
,值为 1。如果您部署 SR-IOV 时使用了设备插件和配置映射,但未使用 Helm chart,则
VF
为intel.com/intel_sriov_odu
或intel.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。
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
检查节点中的标签。
所有资源都运行后,标签会自动出现在您的节点中:
$ kubectl get nodes -oyaml | grep feature.node.kubernetes.io/network-sriov.capable
feature.node.kubernetes.io/network-sriov.capable: "true"
查看
daemonset
,您会看到新的sriov-network-config-daemon
和sriov-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
),并在其上配置驱动程序 deviceType
和
MTU
:
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.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: ""
41.6 DPDK #
DPDK
(数据平面开发包)是一组用于实现快速数据包处理的库和驱动程序。它用于加速各种 CPU
体系结构上运行的数据包处理工作负载。DPDK 包含以下组件的数据平面库和优化的网络接口控制器 (NIC
)
驱动程序:
队列管理器,实现无锁队列。
缓冲区管理器,预先分配固定大小的缓冲区。
内存管理器,在内存中分配对象池,并使用环来存储空闲对象;确保对象均匀分布在所有
DRAM
通道上。轮询模式驱动程序 (
PMD
),可在没有异步通知的情况下运行,从而降低开销。作为一组库提供的数据包框架,可帮助开发数据包处理解决方案。
以下步骤说明如何启用 DPDK
,以及如何从 NIC
创建供
DPDK
接口使用的 VF
:
安装
DPDK
软件包:
$ transactional-update pkg install dpdk dpdk-tools libdpdk-23
$ reboot
内核参数:
要使用 DPDK,请采用一些驱动程序来启用内核中的某些参数:
参数 | 值 | 说明 |
---|---|---|
iommu | pt | 此选项允许为 DPDK 接口使用 |
intel_iommu 或 amd_iommu | on | 此选项允许为 |
要启用这些参数,请将其添加到 /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 net.ifnames=0 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
:
$ 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
41.7 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 或 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 net.ifnames=0 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
加载 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=
41.8 大页 #
当某个进程使用 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
...
41.9 在 Kubernetes 上进行 CPU 绑定 #
41.9.1 先决条件 #
必须根据第 41.3 节 “通过 Tuned 和内核参数实现 CPU 绑定”一节中所述的性能配置文件微调
CPU
。
41.9.2 配置 Kubernetes 以进行 CPU 绑定 #
配置 kubelet 参数以在 RKE2
群集中实现 CPU 管理。将以下配置块(如下例所示)添加到
/etc/rancher/rke2/config.yaml
文件中。确保在
kubelet-reserved
和 system-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"
41.9.3 为工作负载使用绑定的 CPU #
根据您在工作负载上定义的请求和限制,可以用三种方式通过 kubelet 中定义的静态策略
来使用该功能:
BestEffort
QoS 类:如果没有定义任何CPU
请求或限制,则 Pod 将调度到系统中第一个可用的CPU
上。使用
BestEffort
QoS 类的示例如下:spec: containers: - name: nginx image: nginx
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"
Guaranteed
QoS 类:如果定义了 CPU 请求且该请求等于限制值,请使用此方式。使用
Guaranteed
QoS 类的示例如下:spec: containers: - name: nginx image: nginx resources: limits: memory: "200Mi" cpu: "2" requests: memory: "200Mi" cpu: "2"
41.10 可感知 NUMA 的调度 #
非统一内存访问或非统一内存体系结构 (NUMA
) 是
SMP
(多处理器)体系结构中使用的物理内存设计,其中内存访问时间取决于相对于处理器的内存位置。在
NUMA
下,与访问非本地内存(即,另一个处理器本地的内存,或者在处理器之间共享的内存)相比,处理器可以更快地访问自身的本地内存。
41.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
相关消息已被重写。
41.11 MetalLB #
MetalLB
是裸机 Kubernetes 群集的负载平衡器实现,使用
L2
和 BGP
等标准路由协议作为广告协议。它是一个网络负载平衡器,可用于向外部公开 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: 303.0.0+up0.14.9
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: 303.0.0+up0.2.1
createNamespace: true
EOF
创建
IpAddressPool
和L2advertisement
配置:
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
41.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。
41.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 Edge 上安装和配置 PTP,但以您已熟悉 PTP 的基本概念为前提。如需简要了解 PTP 以及 SUSE Edge for Telco 中包含的实现,请访问 https://documentation.suse.com/sles/html/SLES-all/cha-tuning-ptp.html。
41.13.1 安装 PTP 软件组件 #
在 SUSE Edge for Telco 中,PTP 功能通过 linuxptp
软件包实现,该软件包包含两个组件:
ptp4l
:控制 NIC 上的 PHC 并运行 PTP 协议的守护程序phc2sys
:将系统时钟与 NIC 上经 PTP 同步的 PHC 保持同步的守护程序
要使系统同步正常工作,就必须运行这两个守护程序,并且必须根据您的设置正确配置它们。相关信息,请参见第 41.13.2 节 “为电信部署配置 PTP”。
在下游群集中集成 PTP 最简单且最佳的方式是,在 Edge Image Builder (EIB) 定义文件的
packageList
下添加 linuxptp
软件包。这样,在群集置备期间就会自动安装 PTP 控制平面软件。有关安装软件包的详细信息,请参见 EIB 文档(第 3.3.4 节 “配置 RPM 软件包”)。
以下是包含 linuxptp
的 EIB 清单示例:
apiVersion: 1.0
image:
imageType: RAW
arch: x86_64
baseImage: {micro-base-rt-image-raw}
outputImageName: eibimage-slmicrort-telco.raw
operatingSystem:
time:
timezone: America/New_York
kernelArgs:
- ignition.platform.id=openstack
- net.ifnames=1
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-23
- pf-bb-config
- open-iscsi
- tuned
- cpupower
- linuxptp
sccRegistrationCode: ${SCC_REGISTRATION_CODE}
SUSE Edge for Telco 中包含的 linuxptp
软件包默认不会启用
ptp4l
和
phc2sys
。如果在置备时部署了针对特定系统的配置文件(请参见第 41.13.3 节 “Cluster API 集成”),则应启用它们。可通过将其添加到清单的 systemd
部分来实现,如上例所示。
按照 EIB 文档(第 3.4 节 “构建映像”)中所述的常规过程构建映像,并使用该映像部署群集。如果您是 EIB 新手,请从第 11 章 “Edge Image Builder”开始。
41.13.2 为电信部署配置 PTP #
许多电信应用场景要求严格保持偏差极小的相位和时间同步,为此定义了两个面向电信的配置文件:ITU-T G.8275.1 和 ITU-T
G.8275.2。这两个配置文件均设置了高频率同步消息,以及其他独特特性(如使用替代的最佳主时钟算法 (BMCA))。这种特性要求
ptp4l
所使用的配置文件中包含特定设置,以下几节将提供相关参考信息。
以下两节仅介绍时间接收器配置中的普通时钟场景。
对于任何此类配置文件,都必须在精心规划的 PTP 基础架构中使用。
要用于您的特定 PTP 网络,可能需要额外微调配置,请务必检查并根据需要调整所提供的示例。
41.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
41.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
41.13.2.3 phc2sys 的配置 #
建议在配置 phc2sys
之前先完成 ptp4l
的全部配置,不过这不是强制要求。phc2sys
不需要配置文件,其执行参数可通过
/etc/sysconfig/ptp4l
中的 OPTIONS=
变量单独控制,方式与 ptp4l
类似:
OPTIONS="-s $IFNAME -w"
其中,$IFNAME
是已在 ptp4l 中设置的接口名称,将用作系统时钟的同步源。此参数用于识别源 PHC。
41.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 对象(如第 42 章 “全自动定向网络置备”中所述)。
仅当群集中的硬件保持统一且所有主机都需要采用相同配置(包括接口名称)时,这种方法才适用。
也可以使用其他方法,未来版本中将会介绍相关内容。
至此,您的主机应已具备可正常运行的 PTP 堆栈,并将开始协商其 PTP 角色。