13.3. 使用性能配置集调整节点以实现低延迟
性能配置集可让您控制属于特定机器配置池的节点的延迟调整方面。指定设置后,PerformanceProfile
对象将编译为执行实际节点级别调整的多个对象:
-
操作节点的
MachineConfig
文件。 -
用于配置拓扑管理器、CPU Manager 和 OpenShift Container Platform 节点的
KubeletConfig
文件。 - 配置 Node Tuning Operator 的 Tuned 配置集。
您可以使用性能配置集指定是否将内核更新至 kernel-rt,分配大页面,以及划分 CPU 以执行内务处理或运行工作负载。
您可以手动创建 PerformanceProfile
对象,或使用 Performance Profile Creator (PPC) 生成性能配置集。有关 PPC 的更多信息,请参见以下的其他资源。
性能配置集示例
apiVersion: performance.openshift.io/v2 kind: PerformanceProfile metadata: name: performance spec: cpu: isolated: "4-15" 1 reserved: "0-3" 2 hugepages: defaultHugepagesSize: "1G" pages: - size: "1G" count: 16 node: 0 realTimeKernel: enabled: true 3 numa: 4 topologyPolicy: "best-effort" nodeSelector: node-role.kubernetes.io/worker-cnf: "" 5
其他资源
- 有关使用 Performance Profile Creator (PPC) 生成性能配置集的详情,请参考创建性能配置集。
13.3.1. 配置巨页
节点必须预先分配在 OpenShift Container Platform 集群中使用的巨页。使用 Node Tuning Operator 在特定节点中分配巨页。
OpenShift Container Platform 提供了创建和分配巨页的方法。Node Tuning Operator 提供了一种更易于使用性能配置集的方法。
例如,在性能配置集的 hugepages
pages
部分,您可以指定多个块的 size
、count
以及可选的 node
:
hugepages:
defaultHugepagesSize: "1G"
pages:
- size: "1G"
count: 4
node: 0 1
- 1
node
是分配巨页的 NUMA 节点。如果省略了node
,该页面将平均分布在所有 NUMA 节点中。
等待显示更新已完成的相关机器配置池状态。
这些是分配巨页的唯一配置步骤。
验证
要验证配置,请查看节点上的
/proc/meminfo
文件:$ oc debug node/ip-10-0-141-105.ec2.internal
# grep -i huge /proc/meminfo
输出示例
AnonHugePages: ###### ## ShmemHugePages: 0 kB HugePages_Total: 2 HugePages_Free: 2 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: #### ## Hugetlb: #### ##
使用
oc describe
报告新大小:$ oc describe node worker-0.ocp4poc.example.com | grep -i huge
输出示例
hugepages-1g=true hugepages-###: ### hugepages-###: ###
13.3.2. 分配多个巨页大小
您可以在同一容器下请求具有不同大小的巨页。这样,您可以定义由具有不同巨页大小的容器组成的更复杂的 pod。
例如,您可以把大小定义为 1G
和 2M
,Node Tuning Operator 会在节点上配置这两个大小,如下所示:
spec: hugepages: defaultHugepagesSize: 1G pages: - count: 1024 node: 0 size: 2M - count: 4 node: 1 size: 1G
13.3.3. 为 IRQ 动态负载平衡配置节点
为 IRQ 动态负载平衡配置集群节点,以控制哪些内核可以接收设备中断请求 (IRQ)。
先决条件
- 对于内核隔离,所有服务器硬件组件都必须支持 IRQ 关联性。要检查服务器的硬件组件是否支持 IRQ 关联性,请查看服务器的硬件规格或联系您的硬件供应商。
流程
- 以具有 cluster-admin 权限的用户身份登录 OpenShift Container Platform 集群。
-
将性能配置集
apiVersion
设置为使用performance.openshift.io/v2
。 -
删除
globallyDisableIrqLoadBalancing
字段,或把它设置为false
。 设置适当的隔离 CPU 和保留的 CPU。以下片段演示了保留 2 个 CPU 的配置集。对于在
isolated
CPU 集中运行的 pod,启用 IRQ 负载均衡:apiVersion: performance.openshift.io/v2 kind: PerformanceProfile metadata: name: dynamic-irq-profile spec: cpu: isolated: 2-5 reserved: 0-1 ...
注意当您配置保留的和隔离的 CPU 时,pod 中的 infra 容器将使用保留的 CPU,应用程序容器则使用隔离的 CPU。
创建使用独有 CPU 的 pod,并将
irq-load-balancing.crio.io
和cpu-quota.crio.io
注解设置为disable
。例如:apiVersion: v1 kind: Pod metadata: name: dynamic-irq-pod annotations: irq-load-balancing.crio.io: "disable" cpu-quota.crio.io: "disable" spec: containers: - name: dynamic-irq-pod image: "registry.redhat.io/openshift4/cnf-tests-rhel8:v4.13" command: ["sleep", "10h"] resources: requests: cpu: 2 memory: "200M" limits: cpu: 2 memory: "200M" nodeSelector: node-role.kubernetes.io/worker-cnf: "" runtimeClassName: performance-dynamic-irq-profile ...
-
以 performance-<profile_name> 格式输入 pod 的
runtimeClassName
,其中 <profile_name> 是来自PerformanceProfile
YAML 的name
,在本例中是performance-dynamic-irq-profile
。 - 将节点选择器设置为以 cnf-worker 为目标。
确保 pod 正确运行。状态应该为
running
,并应正确设置了 cnf-worker 节点:$ oc get pod -o wide
预期输出
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES dynamic-irq-pod 1/1 Running 0 5h33m <ip-address> <node-name> <none> <none>
获取为 IRQ 动态负载均衡配置的 pod 运行 CPU:
$ oc exec -it dynamic-irq-pod -- /bin/bash -c "grep Cpus_allowed_list /proc/self/status | awk '{print $2}'"
预期输出
Cpus_allowed_list: 2-3
确保正确应用节点配置。登录节点以验证配置。
$ oc debug node/<node-name>
预期输出
Starting pod/<node-name>-debug ... To use host binaries, run `chroot /host` Pod IP: <ip-address> If you don't see a command prompt, try pressing enter. sh-4.4#
验证可以使用节点文件系统:
sh-4.4# chroot /host
预期输出
sh-4.4#
确保默认系统 CPU 关联性掩码不包括
dynamic-irq-pod
CPU,如 CPU 2 和 3。$ cat /proc/irq/default_smp_affinity
输出示例
33
确定系统 IRQ 没有配置为在
dynamic-irq-pod
CPU 中运行:find /proc/irq/ -name smp_affinity_list -exec sh -c 'i="$1"; mask=$(cat $i); file=$(echo $i); echo $file: $mask' _ {} \;
输出示例
/proc/irq/0/smp_affinity_list: 0-5 /proc/irq/1/smp_affinity_list: 5 /proc/irq/2/smp_affinity_list: 0-5 /proc/irq/3/smp_affinity_list: 0-5 /proc/irq/4/smp_affinity_list: 0 /proc/irq/5/smp_affinity_list: 0-5 /proc/irq/6/smp_affinity_list: 0-5 /proc/irq/7/smp_affinity_list: 0-5 /proc/irq/8/smp_affinity_list: 4 /proc/irq/9/smp_affinity_list: 4 /proc/irq/10/smp_affinity_list: 0-5 /proc/irq/11/smp_affinity_list: 0 /proc/irq/12/smp_affinity_list: 1 /proc/irq/13/smp_affinity_list: 0-5 /proc/irq/14/smp_affinity_list: 1 /proc/irq/15/smp_affinity_list: 0 /proc/irq/24/smp_affinity_list: 1 /proc/irq/25/smp_affinity_list: 1 /proc/irq/26/smp_affinity_list: 1 /proc/irq/27/smp_affinity_list: 5 /proc/irq/28/smp_affinity_list: 1 /proc/irq/29/smp_affinity_list: 0 /proc/irq/30/smp_affinity_list: 0-5
13.3.4. 关于 IRQ 关联性设置的支持
有些 IRQ 控制器缺少对 IRQ 关联性设置的支持,并将始终将所有在线 CPU 公开为 IRQ 掩码。这些 IRQ 控制器在 CPU 0 上运行。
以下是红帽了解对 IRQ 关联性设置的支持的驱动程序和硬件示例。以下是相关的列表(并没有包括所有):
-
一些 RAID 控制器驱动程序,如
megaraid_sas
- 许多非易失性内存表达 (NVMe) 驱动程序
- 主板 (LOM) 网络控制器上的一些 LAN
-
驱动程序使用
managed_irqs
不支持 IRQ 关联性设置的原因可能与主板中的处理器类型、IRI 控制器或断路器连接等因素相关。
如果任何 IRQ 的有效关联性被设置为一个隔离的 CPU,则可能代表一些硬件或驱动程序不支持 IRQ 关联性设置。要查找有效的关联性,请登录到主机并运行以下命令:
$ find /proc/irq -name effective_affinity -printf "%p: " -exec cat {} \;
输出示例
/proc/irq/0/effective_affinity: 1 /proc/irq/1/effective_affinity: 8 /proc/irq/2/effective_affinity: 0 /proc/irq/3/effective_affinity: 1 /proc/irq/4/effective_affinity: 2 /proc/irq/5/effective_affinity: 1 /proc/irq/6/effective_affinity: 1 /proc/irq/7/effective_affinity: 1 /proc/irq/8/effective_affinity: 1 /proc/irq/9/effective_affinity: 2 /proc/irq/10/effective_affinity: 1 /proc/irq/11/effective_affinity: 1 /proc/irq/12/effective_affinity: 4 /proc/irq/13/effective_affinity: 1 /proc/irq/14/effective_affinity: 1 /proc/irq/15/effective_affinity: 1 /proc/irq/24/effective_affinity: 2 /proc/irq/25/effective_affinity: 4 /proc/irq/26/effective_affinity: 2 /proc/irq/27/effective_affinity: 1 /proc/irq/28/effective_affinity: 8 /proc/irq/29/effective_affinity: 4 /proc/irq/30/effective_affinity: 4 /proc/irq/31/effective_affinity: 8 /proc/irq/32/effective_affinity: 8 /proc/irq/33/effective_affinity: 1 /proc/irq/34/effective_affinity: 2
有些驱动程序使用 managed_irqs
,其关联性由内核在内部管理,用户空间无法更改关联性。在某些情况下,这些 IRQ 可能会分配给隔离的 CPU。有关 managed_irqs
的更多信息,请参阅 无法更改受管中断的关联性,即使它们目标隔离 CPU。
13.3.5. 为集群配置超线程
要为 OpenShift Container Platform 集群配置超线程,请将性能配置集中的 CPU 线程设置为为保留或隔离的 CPU 池配置的相同内核。
如果您配置了性能配置集,然后更改主机的超线程配置,请确保更新 PerformanceProfile
YAML 中的 CPU isolated
和 reserved
字段以匹配新配置。
禁用之前启用的主机超线程配置可能会导致 PerformanceProfile
YAML 中列出的 CPU 内核 ID 错误。此不正确的配置可能会导致节点不可用,因为无法找到列出的 CPU。
先决条件
-
使用具有
cluster-admin
角色的用户访问集群。 - 安装 OpenShift CLI(oc)。
流程
确定在您要配置的主机的 CPU 上运行哪些线程。
您可以通过登录到集群并运行以下命令来查看在主机 CPU 上运行哪些线程:
$ lscpu --all --extended
输出示例
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ MINMHZ 0 0 0 0 0:0:0:0 yes 4800.0000 400.0000 1 0 0 1 1:1:1:0 yes 4800.0000 400.0000 2 0 0 2 2:2:2:0 yes 4800.0000 400.0000 3 0 0 3 3:3:3:0 yes 4800.0000 400.0000 4 0 0 0 0:0:0:0 yes 4800.0000 400.0000 5 0 0 1 1:1:1:0 yes 4800.0000 400.0000 6 0 0 2 2:2:2:0 yes 4800.0000 400.0000 7 0 0 3 3:3:3:0 yes 4800.0000 400.0000
在这个示例中,在四个物理 CPU 内核中运行了八个逻辑 CPU 内核。CPU0 和 CPU4 在物理 Core0 中运行,CPU1 和 CPU5 在物理 Core 1 中运行,以此类推。
另外要查看为特定物理 CPU 内核设定的线程(以下示例中的
cpu0
),打开命令提示符并运行以下命令:$ cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list
输出示例
0-4
在
PerformanceProfile
YAML 中应用隔离和保留的 CPU。例如,您可以将逻辑内核 CPU0 和 CPU4 设置为isolated
;将逻辑内核 CPU1 到 CPU3 以及 CPU5 到 CPU7 设置为reserved
。当您配置保留的和隔离的 CPU 时,pod 中的 infra 容器将使用保留的 CPU,应用程序容器则使用隔离的 CPU。... cpu: isolated: 0,4 reserved: 1-3,5-7 ...
注意保留和隔离的 CPU 池不得重叠,并且必须一起跨越 worker 节点中的所有可用内核。
大多数 Intel 处理器上默认启用超线程。如果启用超线程,特定内核处理的所有线程都必须被隔离或者在同一个内核中处理。
13.3.5.1. 禁用低延迟应用程序超线程
在为低延迟进程配置集群时,请考虑是否要在部署集群前禁用超线程。要禁用超线程,请执行以下操作:
- 创建一个适合您的硬件和拓扑的性能配置集。
将
nosmt
设为附加内核参数。以下示例的性能配置集演示了此设置:apiVersion: performance.openshift.io/v2 kind: PerformanceProfile metadata: name: example-performanceprofile spec: additionalKernelArgs: - nmi_watchdog=0 - audit=0 - mce=off - processor.max_cstate=1 - idle=poll - intel_idle.max_cstate=0 - nosmt cpu: isolated: 2-3 reserved: 0-1 hugepages: defaultHugepagesSize: 1G pages: - count: 2 node: 0 size: 1G nodeSelector: node-role.kubernetes.io/performance: '' realTimeKernel: enabled: true
注意当您配置保留的和隔离的 CPU 时,pod 中的 infra 容器将使用保留的 CPU,应用程序容器则使用隔离的 CPU。
13.3.6. 了解工作负载提示
下表描述了节能和实时设置对延迟的影响。
可以手动配置以下工作负载提示。您还可以使用 Performance Profile Creator 来使用工作负载提示。有关性能配置集的更多信息,请参阅"创建性能配置集"部分。如果手动配置工作负载提示,并且未明确设置 realTime
工作负载提示,则默认为 true
。
性能配置集创建器设置 | 提示 | 环境 | 描述 |
---|---|---|---|
Default(默认) |
workloadHints: highPowerConsumption: false realTime: false | 没有延迟要求的高吞吐量集群 | 仅通过 CPU 分区实现的性能。 |
Low-latency |
workloadHints: highPowerConsumption: false realTime: true | 地区数据中心 | 节能和低延迟都需要考虑的:在电源管理、延迟和吞吐量之间进行妥当调节。 |
Ultra-low-latency |
workloadHints: highPowerConsumption: true realTime: true | 对于远边缘集群,对延迟非常敏感的工作负载 | 实现最小延迟和最大确定性会增加电源消耗的成本。 |
每个 pod 电源管理 |
workloadHints: realTime: true highPowerConsumption: false perPodPowerManagement: true | 关键和非关键工作负载 | 允许每个 pod 进行电源管理。 |
其他资源
- 有关使用 Performance Profile Creator (PPC) 生成性能配置集的详情,请参考创建性能配置集。
13.3.7. 手动配置工作负载提示
流程
-
按照 "Understanding workload hints" 的表,创建一个适合环境的硬件和拓扑的
PerformanceProfile
。调整配置集以匹配预期的工作负载。在这个示例中,我们针对最低的延迟进行优化。 添加
highPowerConsumption
和realTime
工作负载提示。这里两者都设为true
。apiVersion: performance.openshift.io/v2 kind: PerformanceProfile metadata: name: workload-hints spec: ... workloadHints: highPowerConsumption: true 1 realTime: true 2
当在性能配置集中将 realTime
工作负载 hint 标志设置为 true
时,将 cpu-quota.crio.io: disable
注解添加到带有固定 CPU 的每个保证 pod。此注解是防止 pod 中进程性能降级所必需的。如果没有显式设置 realTime
工作负载提示,则默认为 true
。
其他资源
- 有关减少单独保证 pod 的 CPU 节流的详情,请参考禁用 CPU CFS 配额。
13.3.8. 为 infra 和应用程序容器限制 CPU
通用内务处理和工作负载任务使用 CPU 的方式可能会影响对延迟敏感的进程。默认情况下,容器运行时使用所有在线 CPU 一起运行所有容器,这可能导致上下文切换和延迟激增。对 CPU 进行分区可防止无状态进程通过相互分离来干扰对延迟敏感的进程。下表描述了在使用 Node Tuning Operator 调整节点后在 CPU 上运行的进程:
进程类型 | 详情 |
---|---|
| 在除了运行低延迟工作负载外的任意 CPU 上运行 |
基础架构 pod | 在除了运行低延迟工作负载外的任意 CPU 上运行 |
中断 | 重定向到保留的 CPU(OpenShift Container Platform 4.7 及更新的版本中的可选) |
内核进程 | 固定保留的 CPU |
对延迟敏感的工作负载 pod | 固定到隔离池中的特定专用 CPU |
OS 进程/systemd 服务 | 固定保留的 CPU |
在一个节点上的对于所有 QoS 进程类型( Burstable
、BestEffort
或 Guaranteed
)的 pod 的可分配容量等于隔离池的容量。保留池的容量已从节点的总内核容量中删除,供集群和操作系统日常任务使用。
示例 1
节点具有 100 个内核的容量。通过使用性能配置集,集群管理员将 50 个内核分配给隔离池,将 50 个内核分配给保留池。集群管理员为 QoS 为 BestEffort
或 Burstable
的 pod 分配 25 个内核,为 Guaranteed
的 pod 分配 25 个内核。这与隔离池的容量匹配。
示例 2
节点具有 100 个内核的容量。通过使用性能配置集,集群管理员将 50 个内核分配给隔离池,将 50 个内核分配给保留池。集群管理员为 QoS 为 BestEffort
或 Burstable
的 pod 分配一个内核,为 Guaranteed
的 pod 分配 50 个内核。这超过了隔离池容量一个内核。Pod 调度因为 CPU 容量不足而失败。
使用的确切分区模式取决于许多因素,如硬件、工作负载特性和预期的系统负载。以下是一些用例示例:
- 如果对延迟敏感的工作负载使用特定的硬件,如网络接口控制器(NIC),请确保隔离池中的 CPU 尽可能地与这个硬件接近。至少,您应该将工作负载放在同一个非统一内存访问 (NUMA) 节点中。
- 保留的池用于处理所有中断。根据系统网络,分配一个足够大小的保留池来处理所有传入的数据包中断。在 4.13 及更高版本中,工作负载可以选择性地被标记为敏感版本。
在决定哪些特定 CPU 用于保留和隔离分区时,需要详细分析和测量。设备和内存的 NUMA 紧密度等因素扮演了角色。选择也取决于工作负载架构和具体的用例。
保留和隔离的 CPU 池不得重叠,并且必须一起跨越 worker 节点中的所有可用内核。
为确保内务处理任务和工作负载不会相互干扰,请在性能配置集的 spec
部分指定两组 CPU。
-
isolated
- 指定应用程序容器工作负载的 CPU。这些 CPU 的延迟最低。这个组中的进程没有中断,例如,可以达到更高的 DPDK 零数据包丢失带宽。 -
reserved
- 为集群和操作系统日常任务指定 CPU。reserved
组中的线程经常会比较繁忙。不要在reserved
组中运行对延迟敏感的应用程序。对延迟敏感的应用程序在isolated
组中运行。
流程
- 创建适合环境硬件和拓扑的性能配置集。
使用您想要为 infra 和应用程序容器保留和隔离的 CPU 添加
reserved
和isolated
参数:apiVersion: performance.openshift.io/v2 kind: PerformanceProfile metadata: name: infra-cpus spec: cpu: reserved: "0-4,9" 1 isolated: "5-8" 2 nodeSelector: 3 node-role.kubernetes.io/worker: ""