15.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"
reserved: "0-3"
hugepages:
defaultHugepagesSize: "1G"
pages:
- size: "1G"
count: 16
node: 0
realTimeKernel:
enabled: true
numa:
topologyPolicy: "best-effort"
nodeSelector:
node-role.kubernetes.io/worker-cnf: ""
15.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
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-###: ###
15.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
15.3.3. 为 IRQ 动态负载平衡配置节点 复制链接链接已复制到粘贴板!
要将集群节点配置为处理 IRQ 动态负载平衡,请执行以下操作:
- 以具有 cluster-admin 权限的用户身份登录 OpenShift Container Platform 集群。
-
将性能配置集
apiVersion设置为使用performance.openshift.io/v2。 -
删除
globallyDisableIrqLoadBalancing字段,或把它设置为false。 设置适当的隔离 CPU 和保留的 CPU。以下片段演示了保留 2 个 CPU 的配置集。对于在
isolatedCPU 集中运行的 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.11" 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> 是来自PerformanceProfileYAML 的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确保正确应用节点配置。SSH 到节点以验证配置。
$ 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-podCPU,如 CPU 2 和 3。$ cat /proc/irq/default_smp_affinity输出示例
33确定系统 IRQ 没有配置为在
dynamic-irq-podCPU 中运行: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
一些 IRQ 控制器不支持 IRQ 重新平衡,并将始终将所有在线 CPU 公开为 IRQ 掩码。这些 IRQ 控制器在 CPU 0 上运行。如需了解主机配置的更多信息,请 SSH 到主机并运行以下命令,将 <irq-num> 替换为您要查询的 CPU 号码:
$ cat /proc/irq/<irq-num>/effective_affinity
15.3.4. 为集群配置超线程 复制链接链接已复制到粘贴板!
要为 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在
PerformanceProfileYAML 中应用隔离和保留的 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 处理器上默认启用超线程。如果启用超线程,特定内核处理的所有线程都必须被隔离或者在同一个内核中处理。
15.3.4.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。
15.3.5. 了解工作负载提示 复制链接链接已复制到粘贴板!
下表描述了节能和实时设置对延迟的影响。
可以手动配置以下工作负载提示。您还可以使用 Performance Profile Creator 来使用工作负载提示。有关性能配置集的更多信息,请参阅"创建性能配置集"部分。如果手动配置工作负载提示,并且未明确设置 realTime 工作负载提示,则默认为 true。
| 性能配置集创建器设置 | 提示 | 环境 | 描述 |
|---|---|---|---|
| Default(默认) |
| 没有延迟要求的高吞吐量集群 | 仅通过 CPU 分区实现的性能。 |
| Low-latency |
| 地区数据中心 | 节能和低延迟都需要考虑的:在电源管理、延迟和吞吐量之间进行妥当调节。 |
| Ultra-low-latency |
| 对于远边缘集群,对延迟非常敏感的工作负载 | 实现最小延迟和最大确定性会增加电源消耗的成本。 |
| 每个 pod 电源管理 |
| 关键和非关键工作负载 | 允许每个 pod 进行电源管理。 |
15.3.6. 手动配置工作负载提示 复制链接链接已复制到粘贴板!
流程
-
按照 "Understanding workload hints" 的表,创建一个适合环境的硬件和拓扑的
PerformanceProfile。调整配置集以匹配预期的工作负载。在这个示例中,我们针对最低的延迟进行优化。 添加
highPowerConsumption和realTime工作负载提示。这里两者都设为true。apiVersion: performance.openshift.io/v2 kind: PerformanceProfile metadata: name: workload-hints spec: ... workloadHints: highPowerConsumption: true1 realTime: true2
当在性能配置集中将 realTime 工作负载 hint 标志设置为 true 时,将 cpu-quota.crio.io: disable 注解添加到带有固定 CPU 的每个保证 pod。此注解是防止 pod 中进程性能降级所必需的。如果没有显式设置 realTime 工作负载提示,则默认为 true。
15.3.7. 为 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.11 及更新的版本中,工作负载可以被标记为敏感。
在决定哪些特定 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: ""