Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions _topic_maps/_topic_map.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3517,6 +3517,9 @@ Topics:
File: cnf-understanding-low-latency
- Name: Tuning nodes for low latency with the performance profile
File: cnf-tuning-low-latency-nodes-with-perf-profile
- Name: Reserve CPUs for OVS-DPDK
File: cnf-reserving-cpus-for-ovs-dpdk
Distros: openshift-origin,openshift-enterprise
- Name: Tuning hosted control planes for low latency with the performance profile
File: cnf-tuning-low-latency-hosted-cp-nodes-with-perf-profile
- Name: Provisioning real-time and low latency workloads
Expand Down
91 changes: 91 additions & 0 deletions modules/cnf-configuring-ovs-dpdk-cpus.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Module included in the following assemblies:
//
// * scalability_and_performance/cnf-reserving-cpus-for-ovs-dpdk.adoc

:_mod-docs-content-type: PROCEDURE
[id="cnf-configuring-ovs-dpdk-cpus_{context}"]
= Reserve OVS-DPDK CPUs with a performance profile

[role="_abstract"]
Create or update a `PerformanceProfile` custom resource (CR) that reserves CPUs for OVS-DPDK by setting `spec.cpu.ovsDpdk`. You can optionally add the load-balancing annotation in the same CR; see _Disable load balancing on OVS-DPDK CPUs_ for when that extra hardening is useful.

.Prerequisites

* You have access to the cluster as a user with the `cluster-admin` role.
* You have installed the OpenShift CLI (`oc`).
* You have identified the CPU topology and NUMA locality of the OVS-DPDK NICs on the target nodes.
* Workload partitioning is enabled, or the `kubelet` CPU Manager `strict-cpu-reservation` policy option is configured on the target nodes.
* You understand that this feature is Technology Preview.

.Procedure

. Optional: Inspect CPU and NUMA topology on a target node:
+
[source,terminal]
----
$ oc debug node/<node_name> -- chroot /host lscpu
----

. Plan the CPU budget so that the `reserved`, `ovsDpdk`, and `isolated` sets do not overlap, cover the online CPUs that you intend to use, and leave enough reserved capacity for platform components. On single-node {product-title}, ensure that `reserved` can host both system daemons and control plane workloads.

. Create a `PerformanceProfile` CR that includes `spec.cpu.ovsDpdk`.
+
.Example performance profile with OVS-DPDK CPUs
[source,yaml]
----
apiVersion: performance.openshift.io/v2
kind: PerformanceProfile
metadata:
name: ovs-dpdk-isolation
annotations:
performance.openshift.io/cpu-load-balancing-ovs-dpdk: "disable"
spec:
cpu:
reserved: "0-1"
ovsDpdk: "2-3"
isolated: "4-7"
nodeSelector:
node-role.kubernetes.io/worker: ""
----
+
where:

* `performance.openshift.io/cpu-load-balancing-ovs-dpdk: "disable"` is optional. Set it only when you need stronger scheduler isolation for PMD threads. Omit the annotation for the base reservation. For why and when to use this annotation, see _Disable load balancing on OVS-DPDK CPUs_.
* `spec.cpu.reserved` lists CPUs for operating system and platform components.
* `spec.cpu.ovsDpdk` lists CPUs reserved for OVS-DPDK PMD threads. Do not reuse this set for unrelated DPDK applications.
* `spec.cpu.isolated` lists CPUs for `Guaranteed` application pods.
+
[IMPORTANT]
====
The Performance Profile Creator (PPC) tool does not currently generate the `ovsDpdk` field. Create or edit the performance profile YAML manually.
====

. Apply the performance profile:
+
[source,terminal]
----
$ oc apply -f performance-profile-ovs-dpdk.yaml
----

. Wait for the Machine Config Operator to apply the configuration and for the target nodes to reboot. Confirm that the relevant machine config pool has finished updating:
+
[source,terminal]
----
$ oc get mcp
----
+
The pool that matches your profile selector must show `UPDATED=True` and `UPDATING=False`.

. Verify that the performance profile is available:
+
[source,terminal]
----
$ oc get performanceprofile ovs-dpdk-isolation -o yaml
----
+
Confirm that the `Available` condition is `True`. If the profile is `Degraded` with reason `OvsDpdkCPUsPrerequisiteNotMet`, enable workload partitioning or `strict-cpu-reservation` and reapply the profile.

.Verification

* Confirm that the `PerformanceProfile` status shows `Available=True`.
* Complete the checks in _Verify OVS-DPDK CPU isolation_ to confirm node-level configuration.
62 changes: 62 additions & 0 deletions modules/cnf-performance-profile-ovs-dpdk-reference.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Module included in the following assemblies:
//
// * scalability_and_performance/cnf-reserving-cpus-for-ovs-dpdk.adoc

:_mod-docs-content-type: REFERENCE
[id="cnf-performance-profile-ovs-dpdk-reference_{context}"]
= OVS-DPDK performance profile fields

[role="_abstract"]
Use the following reference when you reserve OVS-DPDK CPUs in a `PerformanceProfile` custom resource (CR).

== API fields and annotations

[cols="2,1,3"]
|===
|Field or annotation |Type |Description

|`spec.cpu.ovsDpdk`
|string (CPU set)
|Optional. CPUs reserved for OVS-DPDK PMD threads. Example value: `"2-3,8-9"`. Must not overlap `reserved`, `isolated`, or `offlined`.

|`metadata.annotations["performance.openshift.io/cpu-load-balancing-ovs-dpdk"]`
|string
|Optional. Set to `disable` to exclude `ovsDpdk` CPUs from kernel scheduler load balancing and scheduling domains, and to set the OVS-DPDK cgroup partition to `isolated`. Omit the annotation or set `enable` to keep the default `member` partition.
|===

== Validation and status

* The `ovsDpdk` CPU set must not overlap the `reserved`, `isolated`, or `offlined` CPU sets.
* Workload partitioning or `kubelet` `strict-cpu-reservation` is required. If the prerequisite is missing, the profile becomes `Degraded` with reason `OvsDpdkCPUsPrerequisiteNotMet`.
* The Node Tuning Operator adds `ovsDpdk` CPUs to `kubelet` `reservedSystemCPUs` together with `reserved`, and to TuneD `isolated_cores` together with `isolated`.

== Day-2 changes

* When you change `spec.cpu.ovsDpdk`, keep all CPU sets disjoint, wait for the MCO and node reboot, and re-verify isolation for the new set. CPUs that leave `ovsDpdk` must return to their new role without leftover IRQ bans or exclusive cgroup assignment.
* When you remove `spec.cpu.ovsDpdk` and the optional annotation, expect full cleanup of OVS-DPDK isolation artifacts, including `ovsdpdk.slice`. See _Update or remove OVS-DPDK CPU reservation_.

== Example configuration

[source,yaml]
----
apiVersion: performance.openshift.io/v2
kind: PerformanceProfile
metadata:
name: ovs-dpdk-isolation
annotations:
performance.openshift.io/cpu-load-balancing-ovs-dpdk: "disable"
spec:
cpu:
reserved: "0-1"
ovsDpdk: "2-3"
isolated: "4-7"
nodeSelector:
node-role.kubernetes.io/worker: ""
----

== Limitations

* Technology Preview support only.
* Specific to OVS-DPDK. Not a generic dedicated-CPU pool for other DPDK applications.
* The Performance Profile Creator (PPC) tool does not generate `spec.cpu.ovsDpdk` in this release. Edit the performance profile manually.
* Full effect of `performance.openshift.io/cpu-load-balancing-ovs-dpdk: "disable"` depends on matching OVS-side support.
63 changes: 63 additions & 0 deletions modules/cnf-understanding-ovs-dpdk-cpu-isolation.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Module included in the following assemblies:
//
// * scalability_and_performance/cnf-reserving-cpus-for-ovs-dpdk.adoc

:_mod-docs-content-type: CONCEPT
[id="cnf-understanding-ovs-dpdk-cpu-isolation_{context}"]
= OVS-DPDK CPU isolation

[role="_abstract"]
OVS-DPDK poll mode driver (PMD) threads busy-poll the NIC on the host and need exclusive CPUs. Use `spec.cpu.ovsDpdk` in a `PerformanceProfile` custom resource (CR) when `reserved` and `isolated` alone cannot protect those threads from jitter.

OVS-DPDK PMD threads run as host processes outside the pod scheduling path. Interruption from the kernel, system daemons, or other workloads can introduce jitter and reduce throughput. A performance profile already defines the following CPU sets, which do not fully cover that case:

* `reserved`:: CPUs for operating system daemons and Kubernetes infrastructure. Without additional controls, `Burstable` and `BestEffort` pods can still run on reserved CPUs.
* `isolated`:: CPUs for `Guaranteed` application pods that the `kubelet` schedules. Isolated CPUs are not intended for host processes such as OVS-DPDK.

Because OVS-DPDK is not a `Guaranteed` pod workload, the profile needs a third CPU set that is excluded from `kubelet` scheduling and from host interference sources.

When you set `spec.cpu.ovsDpdk`, the Node Tuning Operator configures the following CPU roles on matching nodes:

[cols="1,2,2"]
|===
|CPU set |Typical use |Isolation behavior

|`reserved`
|System daemons and platform components
|`Guaranteed` application pods are not placed on these CPUs. Workload partitioning or related policies can further protect them.

|`ovsDpdk`
|OVS-DPDK PMD threads on the host
|Pods of any QoS class are not placed on these CPUs. The Node Tuning Operator also bans them from `irqbalance`, removes them from systemd CPU affinity, adds them to kernel isolation parameters, and places them under the OVS cgroup hierarchy.

|`isolated`
|`Guaranteed` latency-sensitive pods
|The `kubelet` can place `Guaranteed` workloads that request exclusive CPUs on this set.
|===

[IMPORTANT]
====
The `ovsDpdk` CPU set is specific to OVS-DPDK. Do not use it as a generic pool for other DPDK applications. The Node Tuning Operator places these CPUs under the existing `ovs.slice` hierarchy for `ovs-vswitchd`.
====

== What the Node Tuning Operator configures

For CPUs listed in `spec.cpu.ovsDpdk`, the Node Tuning Operator applies configuration across several layers, including the following:

* Adds the CPUs to the `kubelet` `reservedSystemCPUs` set together with `spec.cpu.reserved`.
* Adds the CPUs to TuneD `isolated_cores` together with `spec.cpu.isolated`.
* Includes the CPUs in kernel boot parameters such as `isolcpus`, `nohz_full`, and `rcu_nocbs`.
* Excludes the CPUs from `systemd.cpu_affinity`.
* Updates `IRQBALANCE_BANNED_CPUS` so that hardware IRQs are not balanced onto those CPUs.
* Creates and configures `ovsdpdk.slice` under `ovs.slice/ovs-vswitchd.service`, including exclusive CPU assignment for OVS-DPDK.

== Prerequisites for isolation

Workload partitioning (`CPUPartitioningAllNodes`) or the `kubelet` CPU Manager `strict-cpu-reservation` policy option is required. If neither is enabled, the Node Tuning Operator marks the performance profile as `Degraded` with the reason `OvsDpdkCPUsPrerequisiteNotMet` and does not complete the configuration.

Without one of those prerequisites, `Burstable` and `BestEffort` pods can still be scheduled on the OVS-DPDK CPUs and break isolation.

[NOTE]
====
You must choose NUMA-aligned CPUs for your OVS-DPDK NICs. The Operator does not automatically assign CPUs based on NIC locality.
====
47 changes: 47 additions & 0 deletions modules/cnf-understanding-ovs-dpdk-cpu-load-balancing.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Module included in the following assemblies:
//
// * scalability_and_performance/cnf-reserving-cpus-for-ovs-dpdk.adoc

:_mod-docs-content-type: CONCEPT
[id="cnf-understanding-ovs-dpdk-cpu-load-balancing_{context}"]
= Disable load balancing on OVS-DPDK CPUs

[role="_abstract"]
After you reserve CPUs with `spec.cpu.ovsDpdk`, you can optionally disable kernel CPU load balancing on the same set. Use this when PMD threads still risk scheduler interference and your OVS-DPDK stack supports the matching OVS-side configuration.

== Why disable load balancing on OVS-DPDK CPUs

OVS-DPDK PMD threads typically pin to specific CPUs and busy-poll the NIC. Latency and packet loss increase when anything else runs on those CPUs, even briefly.

The `spec.cpu.ovsDpdk` field applies multi-layer reservation: `kubelet` does not schedule pods on the CPUs, IRQ balancing excludes them, and the Node Tuning Operator places them under the OVS cgroup hierarchy. By default, those CPUs can still remain in the kernel scheduler load-balancing pool (`cpuset.cpus.partition=member`).

Disabling load balancing removes the CPUs from that shared scheduler pool (`cpuset.cpus.partition=isolated`). Those CPUs are also removed from kernel scheduling domains. The exclusion is persistent for the `ovsDpdk` set: it does not depend on `Guaranteed` pod lifecycle the way the pod annotation `cpu-load-balancing.crio.io=disable` does.

The advantage is stronger exclusive ownership for PMD threads: the kernel is less likely to migrate or run unrelated tasks on the same CPUs, which helps keep poll-loop timing stable.

Use the annotation when you need that extra scheduler isolation and your OVS-DPDK stack supports the matching OVS-side configuration. If you only need the base reservation, set `spec.cpu.ovsDpdk` and omit the annotation.

== Annotation behavior

Set the following annotation on the `PerformanceProfile` custom resource (CR):

[source,yaml]
----
metadata:
annotations:
performance.openshift.io/cpu-load-balancing-ovs-dpdk: "disable"
----

Valid values are as follows:

* `disable`:: Exclude `ovsDpdk` CPUs from the kernel scheduler load-balancing pool and from kernel scheduling domains. The Operator configures the OVS-DPDK cgroup partition as `isolated`.
* `enable`, or omit the annotation:: Keep the default behavior. The Operator configures the OVS-DPDK cgroup partition as `member`. The CPUs remain reserved for OVS-DPDK, but they are not removed from scheduling domains by this annotation.

== Why the control is an annotation

Full effect of disabling load balancing depends on matching support in the OVS process. The Node Tuning Operator exposes the control as an optional annotation so that base CPU reservation with `spec.cpu.ovsDpdk` stays independent of this extra hardening step.

[NOTE]
====
This annotation controls kernel CPU load balancing for the `ovsDpdk` CPU set. It is not the same as the pod annotation `cpu-load-balancing.crio.io`, and it is not the same as OVN-Kubernetes dynamic CPU affinity management for OVS services.
====
64 changes: 64 additions & 0 deletions modules/cnf-updating-or-removing-ovs-dpdk-cpus.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Module included in the following assemblies:
//
// * scalability_and_performance/cnf-reserving-cpus-for-ovs-dpdk.adoc

:_mod-docs-content-type: PROCEDURE
[id="cnf-updating-or-removing-ovs-dpdk-cpus_{context}"]
= Update or remove OVS-DPDK CPU reservation

[role="_abstract"]
Change the `spec.cpu.ovsDpdk` CPU set on a day-2 retune, or remove the field when you no longer need OVS-DPDK CPU isolation. Keep CPU sets disjoint, wait for the Machine Config Operator (MCO) to apply changes, and re-verify isolation or cleanup on the node.

.Prerequisites

* You have access to the cluster as a user with the `cluster-admin` role.
* You have installed the OpenShift CLI (`oc`).
* A `PerformanceProfile` custom resource (CR) with `spec.cpu.ovsDpdk` is already applied.
* Workload partitioning is enabled, or the `kubelet` CPU Manager `strict-cpu-reservation` policy option is configured on the target nodes.

.Procedure

. To change the OVS-DPDK CPU set, edit the performance profile and replace `spec.cpu.ovsDpdk` with the new CPU list. Adjust `spec.cpu.isolated` and `spec.cpu.reserved` so that the sets do not overlap.
+
.Example expand of the OVS-DPDK set
[source,yaml]
----
spec:
cpu:
reserved: "0-1"
ovsDpdk: "2-3"
isolated: "4-7"
----
+
After the MCO applies the change and the node reboots, confirm that isolation reflects the new set:

* Kernel parameters, `reservedSystemCPUs`, `IRQBALANCE_BANNED_CPUS`, and `ovsdpdk.slice` `cpuset.cpus.exclusive` include the new `ovsDpdk` CPUs.
* CPUs that left the `ovsDpdk` set are no longer banned or exclusively assigned for OVS-DPDK, and they match their new role in `isolated` or `reserved`.

. To remove OVS-DPDK CPU reservation, edit the performance profile, delete `spec.cpu.ovsDpdk`, remove the `performance.openshift.io/cpu-load-balancing-ovs-dpdk` annotation if present, and move the former OVS-DPDK CPUs into `isolated` or another appropriate set so that your CPU layout remains valid.
+
After the MCO applies the change and the node reboots, confirm cleanup:

* `reservedSystemCPUs` no longer includes the former `ovsDpdk` CPUs (unless those CPUs were moved into `reserved`).
* `IRQBALANCE_BANNED_CPUS` and `default_smp_affinity` no longer isolate those CPUs for OVS-DPDK.
* The `ovsdpdk.slice` directory under `ovs.slice/ovs-vswitchd.service/` is gone.
* Former `ovsDpdk` CPUs behave according to their new role in the performance profile.

. Apply the updated performance profile by running the following command
+
[source,terminal]
----
$ oc apply -f performance-profile-ovs-dpdk.yaml
----

. Run the following command to check on the progress of the machine config updating and node reboot. Wait until the `MCP` is `Updated` and the node is `Ready` before proceeding:
+
[source,terminal]
----
$ oc get mcp -w
----

.Verification

* For an updated `ovsDpdk` set, complete the checks in _Verify OVS-DPDK CPU isolation_ against the new CPU list.
* For a removed `ovsDpdk` field, confirm that no OVS-DPDK isolation artifacts remain for the former CPU set.
Loading