11.2. 置备实时和低延迟工作负载

很多行业和机构需要非常高的计算性能,并需要低且可预测的延迟,特别是银行和电信业。对于这些行业,它们有不同的要求,OpenShift Container Platform 提供了 Node Tuning Operator 来实现自动性能优化,以便为 OpenShift Container Platform 应用程序实现低延迟性能和响应时间。

集群管理员可以使用此性能配置集配置以更可靠的方式进行这些更改。管理员可以指定是否将内核更新至 kernel-rt(实时),为集群和操作系统日常任务保留 CPU,包括 pod infra 容器,隔离 CPU 来运行工作负载,以及禁用未使用的 CPU 减少功耗。

警告

将执行探测与需要保证 CPU 的应用配合使用可能会导致延迟激增。建议使用其他探测(如正确配置的一组网络探测作为替代方案)。

注意

在早期版本的 OpenShift Container Platform 中,Performance Addon Operator 用来实现自动性能优化,以便为 OpenShift 应用程序实现低延迟性能。在 OpenShift Container Platform 4.11 及更高版本中,这些功能是 Node Tuning Operator 的一部分。

11.2.1. 已知的实时限制

注意

在大多数部署中,只有使用具有三个 control plane 节点和三个 worker 节点的标准集群时,仅在 worker 节点上支持 kernel-rt。OpenShift Container Platform 部署中的紧凑和单一节点会有例外。对于在单一节点上的安装, kernel-rt 在单个 control plane 节点上被支持。

要充分利用实时模式,容器必须使用升级的权限运行。如需了解有关授予特权的信息,请参阅为容器设置能力

OpenShift Container Platform 会限制允许的功能,因此您可能需要创建 SecurityContext

注意

使用 Red Hat Enterprise Linux CoreOS(RHCOS)系统的裸机安装完全支持此步骤。

在确定正确的性能预期时,应该意识到实时内核并不是万能的。它的目的是提供一个持续的、低延迟的确定性机制,从而提供可预测的响应时间。在系统中,会存在与实时内核关联的额外内核开销。这是因为在单独调度的线程中处理硬件中断。某些增加的工作负载开销会导致整个吞吐量下降。实际的影响依赖于特定的负载,范围从 0% 到 30%。然而,这是获得确定性所需要付出的代价。

11.2.2. 使用实时功能置备 worker

  1. 可选:在 OpenShift Container Platform 集群中添加节点。请参阅为系统调整设置 BIOS 参数
  2. 使用 oc 命令将标签 worker-rt 添加到需要实时功能的 worker 节点。
  3. 为实时节点创建新机器配置池:

    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfigPool
    metadata:
      name: worker-rt
      labels:
        machineconfiguration.openshift.io/role: worker-rt
    spec:
      machineConfigSelector:
        matchExpressions:
          - {
               key: machineconfiguration.openshift.io/role,
               operator: In,
               values: [worker, worker-rt],
            }
      paused: false
      nodeSelector:
        matchLabels:
          node-role.kubernetes.io/worker-rt: ""

    请注意,为具有标签 worker-rt 标签的节点组创建一个机器配置池 worker-rt

  4. 使用节点角色标签将节点添加到正确的机器配置池。

    注意

    您必须决定使用实时工作负载配置哪些节点。您可以配置集群中的所有节点,或配置节点的子集。期望所有节点都是专用机器配置池的一部分的 Node Tuning Operator。如果使用所有节点,您必须将 Node Tuning Operator 指向 worker 节点角色标签。如果使用子集,您必须将节点分组到新机器配置池中。

  5. 使用正确的 housekeeping 内核和 realTimeKernel: enabled: true 创建 PerformanceProfile
  6. 您必须在 PerformanceProfile 中设置 MachineConfigPoolSelector

      apiVersion: performance.openshift.io/v2
      kind: PerformanceProfile
      metadata:
       name: example-performanceprofile
      spec:
      ...
        realTimeKernel:
          enabled: true
        nodeSelector:
           node-role.kubernetes.io/worker-rt: ""
        machineConfigPoolSelector:
           machineconfiguration.openshift.io/role: worker-rt
  7. 验证匹配的机器配置池是否存在一个标签:

    $ oc describe mcp/worker-rt

    输出示例

    Name:         worker-rt
    Namespace:
    Labels:       machineconfiguration.openshift.io/role=worker-rt

  8. OpenShift Container Platform 将开始配置节点,这可能涉及多次重启。等待节点处于稳定状态。这个过程所需要的时间取决于您所使用的具体硬件,预计每个节点需要 20 分钟。
  9. 验证所有内容是否按预期工作。

11.2.3. 验证实时内核安装

使用这个命令确定安装了实时内核:

$ oc get node -o wide

注意 worker-rt 角色 worker-rt,其中包含字符串 4.18.0-305.30.1.rt7.102.el8_4.x86_64 cri-o://1.25.0-99.rhaos4.10.gitc3131de.el8:

NAME                               	STATUS   ROLES           	AGE 	VERSION                  	INTERNAL-IP
EXTERNAL-IP   OS-IMAGE                                       	KERNEL-VERSION
CONTAINER-RUNTIME
rt-worker-0.example.com	          Ready	 worker,worker-rt   5d17h   v1.25.0
128.66.135.107   <none>    	        Red Hat Enterprise Linux CoreOS 46.82.202008252340-0 (Ootpa)
4.18.0-305.30.1.rt7.102.el8_4.x86_64   cri-o://1.25.0-99.rhaos4.10.gitc3131de.el8
[...]

11.2.4. 创建一个实时工作负载

使用以下步骤准备一个使用实时功能的工作负载。

流程

  1. 创建带有 Guaranteed 类 QoS 类的 pod。
  2. 可选:禁用 DPDK 的 CPU 负载均衡。
  3. 分配正确的节点选择器。

在编写应用程序时,请遵循应用程序调整和部署中的常规建议。

11.2.5. 创建带有 Guaranteed 类 QoS 类的 pod

在创建带有 Guaranteed 类的 QoS 类的 pod 时请注意以下几点:

  • pod 中的每个容器都必须具有内存限制和内存请求,且它们必须相同。
  • pod 中的每个容器都必须具有 CPU 限制和 CPU 请求,且它们必须相同。

以下示例显示了一个容器的 pod 的配置文件。容器设置了内存限制和内存请求,均为 200 MiB。容器具有 CPU 限制和 CPU 请求,均为 1 CPU。

apiVersion: v1
kind: Pod
metadata:
  name: qos-demo
  namespace: qos-example
spec:
  containers:
  - name: qos-demo-ctr
    image: <image-pull-spec>
    resources:
      limits:
        memory: "200Mi"
        cpu: "1"
      requests:
        memory: "200Mi"
        cpu: "1"
  1. 创建 pod:

    $ oc  apply -f qos-pod.yaml --namespace=qos-example
  2. 查看有关 pod 的详细信息:

    $ oc get pod qos-demo --namespace=qos-example --output=yaml

    输出示例

    spec:
      containers:
        ...
    status:
      qosClass: Guaranteed

    注意

    如果容器指定了自己的内存限值,但没有指定内存请求,OpenShift Container Platform 会自动分配与限制匹配的内存请求。同样,如果容器指定了自己的 CPU 限值,但没有指定 CPU 请求,OpenShift Container Platform 会自动分配与限制匹配的 CPU 请求。

11.2.6. 可选:禁用 DPDK 的 CPU 负载均衡

禁用或启用 CPU 负载均衡的功能在 CRI-O 级别实现。CRI-O 下的代码仅在满足以下要求时禁用或启用 CPU 负载均衡。

  • pod 必须使用 performance-<profile-name> 运行时类。您可以通过查看性能配置集的状态来获得正确的名称,如下所示:

    apiVersion: performance.openshift.io/v2
    kind: PerformanceProfile
    ...
    status:
      ...
      runtimeClass: performance-manual
注意

目前,cgroup v2 不支持禁用 CPU 负载均衡。

Node Tuning Operator 负责在相关节点下创建高性能运行时处理器配置片断,并在集群下创建高性能运行时类。它具有与默认运行时处理相同的内容,但它启用了 CPU 负载均衡配置功能。

要禁用 pod 的 CPU 负载均衡,Pod 规格必须包括以下字段:

apiVersion: v1
kind: Pod
metadata:
  ...
  annotations:
    ...
    cpu-load-balancing.crio.io: "disable"
    ...
  ...
spec:
  ...
  runtimeClassName: performance-<profile_name>
  ...
注意

仅在启用了 CPU 管理器静态策略,以及带有保证 QoS 使用整个 CPU 的 pod 时,禁用 CPU 负载均衡。否则,禁用 CPU 负载均衡会影响集群中其他容器的性能。

11.2.7. 分配适当的节点选择器

为节点分配 pod 的首选方法是使用与性能配置集相同的节点选择器,如下所示:

apiVersion: v1
kind: Pod
metadata:
  name: example
spec:
  # ...
  nodeSelector:
    node-role.kubernetes.io/worker-rt: ""

如需更多信息,请参阅使用节点选择器将 pod 放置到特定的节点上

11.2.8. 将工作负载调度到具有实时功能的 worker

使用与附加到机器配置池的节点匹配的标签选择器,这些选择器是为低延迟配置的。如需更多信息,请参阅将 pod 分配给节点

11.2.9. 通过使 CPU 离线减少电源消耗

您通常可以预计电信工作负载。如果不需要所有 CPU 资源,Node Tuning Operator 允许您让未使用的 CPU 离线,以通过手动更新性能配置集来降低功耗。

要使未使用的 CPU 离线,您必须执行以下任务:

  1. 在性能配置集中设置离线 CPU 并保存 YAML 文件的内容:

    带有离线 CPU 的性能配置集示例

    apiVersion: performance.openshift.io/v2
    kind: PerformanceProfile
    metadata:
      name: performance
    spec:
      additionalKernelArgs:
      - nmi_watchdog=0
      - audit=0
      - mce=off
      - processor.max_cstate=1
      - intel_idle.max_cstate=0
      - idle=poll
      cpu:
        isolated: "2-23,26-47"
        reserved: "0,1,24,25"
        offlined: "48-59" 1
      nodeSelector:
        node-role.kubernetes.io/worker-cnf: ""
      numa:
        topologyPolicy: single-numa-node
      realTimeKernel:
        enabled: true

    1
    可选。您可以在 offlined 字段中列出 CPU,使指定的 CPU 离线。
  2. 运行以下命令来应用更新的配置集:

    $ oc apply -f my-performance-profile.yaml

11.2.10. 可选:节能配置

您可以为带有低优先级工作负载的节点实现节能,而不影响高优先级工作负载的延迟或吞吐量。无需修改工作负载本身即可进行节能。

重要

Intel Ice Lake 及更新的 Intel CPU 支持该功能。处理器的功能可能会影响高优先级工作负载的延迟和吞吐量。

当您使用节能配置配置节点时,您必须使用 pod 级别的性能配置高优先级工作负载,这意味着配置适用于 pod 使用的所有内核。

通过在 pod 级别上禁用 P-states 和 C-states,您可以配置高优先级工作负载以获得最佳性能和最低延迟。

表 11.1. 配置高优先级工作负载

注解描述
annotations:
  cpu-c-states.crio.io: "disable"
  cpu-freq-governor.crio.io: "<governor>"

通过禁用 C-states 并为 CPU 扩展指定调控器类型,为 pod 提供最佳性能。对于高优先级的工作负载,建议使用 performance governor。

先决条件

  • 在 BIOS 中启用了 C-states 和 OS 控制的 P-states

流程

  1. 使用将每个 pod-power-management 设置为 true 来生成 PerformanceProfile

    $ podman run --entrypoint performance-profile-creator -v \
    /must-gather:/must-gather:z registry.redhat.io/openshift4/ose-cluster-node-tuning-operator:v4.12 \
    --mcp-name=worker-cnf --reserved-cpu-count=20 --rt-kernel=true \
    --split-reserved-cpus-across-numa=false --topology-manager-policy=single-numa-node \
    --must-gather-dir-path /must-gather -power-consumption-mode=low-latency \ 1
    --per-pod-power-management=true > my-performance-profile.yaml
    1
    当将 per-pod-power-management 设置为 true 时,power-consumption-mode 必须是 defaultlow-latency

    带有 perPodPowerManagementPerformanceProfile 示例

    apiVersion: performance.openshift.io/v2
    kind: PerformanceProfile
    metadata:
         name: performance
    spec:
        [.....]
        workloadHints:
            realTime: true
            highPowerConsumption: false
            perPodPowerManagement: true

  2. PerformanceProfile 自定义资源(CR) 中将默认 cpufreq 调控器设置为附加内核参数:

    apiVersion: performance.openshift.io/v2
    kind: PerformanceProfile
    metadata:
         name: performance
    spec:
        ...
        additionalKernelArgs:
        - cpufreq.default_governor=schedutil 1
    1
    建议使用 schedutil 管理器,但您可以使用其他监管器,如 ondemandpowersave governors。
  3. Tuned PerformancePatch CR 中设置最大 CPU 频率:

    spec:
      profile:
      - data: |
          [sysfs]
          /sys/devices/system/cpu/intel_pstate/max_perf_pct = <x> 1
    1
    max_perf_pct 控制 cpufreq 驱动程序的最大频率,以最大百分比的形式设置支持的 cpu 频率。这个值适用于所有 CPU。您可以检查 /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq 中的最大支持频率。作为起点,您可以使用以 All Cores Turbo 频率封装所有 CPU 的百分比。All Cores Turbo 频率是所有内核在运行的频率,当内核完全占用时。
  4. 将所需的注解添加到高优先级工作负载 pod。注解会覆盖默认设置。

    高优先级工作负载注解示例

    apiVersion: v1
    kind: Pod
    metadata:
      ...
      annotations:
        ...
        cpu-c-states.crio.io: "disable"
        cpu-freq-governor.crio.io: "<governor>"
        ...
      ...
    spec:
      ...
      runtimeClassName: performance-<profile_name>
      ...

  5. 重启 pod。

其他资源

11.2.11. 管理设备中断处理保证 pod 隔离 CPU

Node Tuning Operator 可以通过将主机 CPU 划分为保留的 CPU 来管理主机 CPU,以进行集群和操作系统日常任务(包括 pod infra 容器),以及用于应用程序容器运行工作负载的隔离 CPU。这可让您将低延迟工作负载的 CPU 设置为隔离状态。

设备中断在所有隔离和保留 CPU 之间平衡负载,以避免出现 CPU 超载问题,但运行有保证 pod 的 CPU 除外。当为 pod 设置相关注解时,保证 pod CPU 无法处理设备中断。

在性能配置集中,globallyDisableIrqLoadBalancing 用于管理设备中断是否被处理。对于某些工作负载,保留 CPU 并不总是足以处理设备中断,因此不会在隔离的 CPU 上禁用设备中断。默认情况下,Node Tuning Operator 不会禁用隔离 CPU 上的设备中断。

要实现低延迟,有些(而非全部)pod 需要它们运行的 CPU 不处理设备中断。pod 注解 irq-load-balancing.crio.io 用于定义是否处理设备中断。配置后,CRI-O 仅在 pod 正在运行时禁用设备中断。

11.2.11.1. 禁用 CPU CFS 配额

要减少单独保证 pod 的 CPU 节流,创建一个带有注解 cpu-quota.crio.io: "disable" 的 pod 规格。此注释在 pod 运行时禁用 CPU 完全公平调度程序(CFS)配额。以下 pod 规格包含此注解:

apiVersion: v1
kind: Pod
metadata:
  annotations:
      cpu-quota.crio.io: "disable"
spec:
    runtimeClassName: performance-<profile_name>
...
注意

仅在启用了 CPU 管理器静态策略,以及带有保证 QoS 使用整个 CPU 的 pod 时禁用 CPU CFS 配额。否则,禁用 CPU CFS 配额可能会影响集群中其他容器的性能。

11.2.11.2. 禁用 Node Tuning Operator 中的全局设备中断处理

要将 Node Tuning Operator 配置为禁用隔离 CPU 集的全局设备中断,将 performance 配置集中的 globallyDisableIrqLoadBalancing 字段设置为 true。在为 true 时,会忽略有冲突的 pod 注解。在为 false 时,IRQ 负载会在所有 CPU 之间平衡。

一个性能配置集片段演示了这个设置:

apiVersion: performance.openshift.io/v2
kind: PerformanceProfile
metadata:
  name: manual
spec:
  globallyDisableIrqLoadBalancing: true
...

11.2.11.3. 禁用单个 pod 的中断处理

要禁用单个 pod 的中断处理,确保在性能配置集中将 globallyDisableIrqLoadBalancing 设置为 false。然后,在 pod 规格中,将 irq-load-balancing.crio.io pod 注解设置为 disable。以下 pod 规格包含此注解:

apiVersion: performance.openshift.io/v2
kind: Pod
metadata:
  annotations:
      irq-load-balancing.crio.io: "disable"
spec:
    runtimeClassName: performance-<profile_name>
...

11.2.12. 升级性能配置集以使用设备中断处理

当您将 Node Tuning Operator 性能配置集自定义资源定义(CRD)从 v1 或 v1alpha1 升级到 v2 时,现有配置集会将 globallyDisableIrqLoadBalancing 设置为 true

注意

globallyDisableIrqLoadBalancing 切换用于 Isolated CPU 集是否禁用了 IRQ 负载均衡。当选项设置为 true 时,它会禁用 Isolated CPU 集的 IRQ 负载均衡。将选项设置为 false 允许在所有 CPU 之间平衡 IRQ。

11.2.12.1. 支持的 API 版本

Node Tuning Operator 在性能配置集 apiVersion 字段中支持 v2v1v1alpha1。v1 和 v1alpha1 API 相同。v2 API 包括一个可选的布尔值项 globallyDisableIrqLoadBalancing,默认值为 false

11.2.12.1.1. 将 Node Tuning Operator API 从 v1alpha1 升级到 v1

当将 Node Tuning Operator API 版本从 v1alpha1 升级到 v1 时,,v1alpha1 性能配置集会通过"None" Conversion 策略自行转换,并提供给带有 API 版本 v1 的 Performance Addon Operator。

11.2.12.1.2. 将 Node Tuning Operator API 从 v1alpha1 或 v1 升级到 v2

当从旧的 Node Tuning Operator API 版本升级时,现有的 v1 和 v1alpha1 性能配置集将使用转换 Webhook 转换,它将注入 globallyDisableIrqLoadBalancing 字段,值为 true