From 8aa05770ae3f1e2e439bf72fd8caa35354472c17 Mon Sep 17 00:00:00 2001 From: Aidan Reilly <74046732+aireilly@users.noreply.github.com> Date: Wed, 13 Apr 2022 15:44:33 +0100 Subject: [PATCH] TELCODOCS-374: Updates for CNF-3107 NUMA-aware scheduling --- _topic_maps/_topic_map.yml | 2 + ...enShift_Topology-aware_Scheduling_0222.png | Bin 0 -> 89856 bytes modules/cnf-about-numa-aware-scheduling.adoc | 23 ++ ...nf-checking-numa-aware-scheduler-logs.adoc | 146 ++++++++++++ modules/cnf-creating-nrop-cr.adoc | 88 ++++++++ ...nf-deploying-the-numa-aware-scheduler.adoc | 112 ++++++++++ ...nstalling-numa-resources-operator-cli.adoc | 101 +++++++++ ...lling-numa-resources-operator-console.adoc | 33 +++ .../cnf-scheduling-numa-aware-workloads.adoc | 185 ++++++++++++++++ ...oubleshooting-missing-rte-config-maps.adoc | 116 ++++++++++ ...-troubleshooting-numa-aware-workloads.adoc | 208 ++++++++++++++++++ ...roubleshooting-resource-topo-exporter.adoc | 92 ++++++++ .../cnf-numa-aware-scheduling.adoc | 43 ++++ 13 files changed, 1149 insertions(+) create mode 100644 images/216_OpenShift_Topology-aware_Scheduling_0222.png create mode 100644 modules/cnf-about-numa-aware-scheduling.adoc create mode 100644 modules/cnf-checking-numa-aware-scheduler-logs.adoc create mode 100644 modules/cnf-creating-nrop-cr.adoc create mode 100644 modules/cnf-deploying-the-numa-aware-scheduler.adoc create mode 100644 modules/cnf-installing-numa-resources-operator-cli.adoc create mode 100644 modules/cnf-installing-numa-resources-operator-console.adoc create mode 100644 modules/cnf-scheduling-numa-aware-workloads.adoc create mode 100644 modules/cnf-troubleshooting-missing-rte-config-maps.adoc create mode 100644 modules/cnf-troubleshooting-numa-aware-workloads.adoc create mode 100644 modules/cnf-troubleshooting-resource-topo-exporter.adoc create mode 100644 scalability_and_performance/cnf-numa-aware-scheduling.adoc diff --git a/_topic_maps/_topic_map.yml b/_topic_maps/_topic_map.yml index 74afa36b87..33d59309f9 100644 --- a/_topic_maps/_topic_map.yml +++ b/_topic_maps/_topic_map.yml @@ -2269,6 +2269,8 @@ Topics: Distros: openshift-origin,openshift-enterprise - Name: Using Topology Manager File: using-topology-manager +- Name: Scheduling NUMA-aware workloads + File: cnf-numa-aware-scheduling Distros: openshift-origin,openshift-enterprise - Name: Scaling the Cluster Monitoring Operator File: scaling-cluster-monitoring-operator diff --git a/images/216_OpenShift_Topology-aware_Scheduling_0222.png b/images/216_OpenShift_Topology-aware_Scheduling_0222.png new file mode 100644 index 0000000000000000000000000000000000000000..510a625a02041de243f4c213394a9da2ea70a39b GIT binary patch literal 89856 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 z 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 ZoZS2B%*}@7LI9dCygguN8r&}b_8;rF@>l=> literal 0 HcmV?d00001 diff --git a/modules/cnf-about-numa-aware-scheduling.adoc b/modules/cnf-about-numa-aware-scheduling.adoc new file mode 100644 index 0000000000..a488189a78 --- /dev/null +++ b/modules/cnf-about-numa-aware-scheduling.adoc @@ -0,0 +1,23 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/cnf-numa-aware-scheduling.adoc + +:_content-type: CONCEPT +[id="cnf-about-numa-aware-scheduling_{context}"] += About NUMA-aware scheduling + +Non-Uniform Memory Access (NUMA) is a compute platform architecture that allows different CPUs to access different regions of memory at different speeds. NUMA resource topology refers to the locations of CPUs, memory, and PCI devices relative to each other in the compute node. Co-located resources are said to be in the same _NUMA zone_. For high-performance applications, the cluster needs to process pod workloads in a single NUMA zone. + +NUMA architecture allows a CPU with multiple memory controllers to use any available memory across CPU complexes, regardless of where the memory is located. This allows for increased flexibility at the expense of performance. A CPU processing a workload using memory that is outside its NUMA zone is slower than a workload processed in a single NUMA zone. Also, for I/O-constrained workloads, the network interface on a distant NUMA zone slows down how quickly information can reach the application. High-performance workloads, such as telecommunications workloads, cannot operate to specification under these conditions. NUMA-aware scheduling aligns the requested cluster compute resources (CPUs, memory, devices) in the same NUMA zone to process latency-sensitive or high-performance workloads efficiently. NUMA-aware scheduling also improves pod density per compute node for greater resource efficiency. + +The default {product-title} pod scheduler scheduling logic considers the available resources of the entire compute node, not individual NUMA zones. If the most restrictive resource alignment is requested in the kubelet topology manager, error conditions can occur when admitting the pod to a node. Conversely, if the most restrictive resource alignment is not requested, the pod can be admitted to the node without proper resource alignment, leading to worse or unpredictable performance. For example, runaway pod creation with `Topology Affinity Error` statuses can occur when the pod scheduler makes suboptimal scheduling decisions for guaranteed pod workloads by not knowing if the pod's requested resources are available. Scheduling mismatch decisions can cause indefinite pod startup delays. Also, depending on the cluster state and resource allocation, poor pod scheduling decisions can cause extra load on the cluster because of failed startup attempts. + +The NUMA Resources Operator deploys a custom NUMA resources secondary scheduler and other resources to mitigate against the shortcomings of the default {product-title} pod scheduler. The following diagram provides a high-level overview of NUMA-aware pod scheduling. + +.NUMA-aware scheduling overview +image::216_OpenShift_Topology-aware_Scheduling_0222.png[Diagram of NUMA-aware scheduling that shows how the various components interact with each other in the cluster] + +NodeResourceTopology API:: The `NodeResourceTopology` API describes the available NUMA zone resources in each compute node. +NUMA-aware scheduler:: The NUMA-aware secondary scheduler receives information about the available NUMA zones from the `NodeResourceTopology` API and schedules high-performance workloads on a node where it can be optimally processed. +Node topology exporter:: The node topology exporter exposes the available NUMA zone resources for each compute node to the `NodeResourceTopology` API. The node topology exporter daemon tracks the resource allocation from the kubelet by using the `PodResources` API. +PodResources API:: The `PodResources` API is local to each node and exposes the resource topology and available resources to the kubelet. diff --git a/modules/cnf-checking-numa-aware-scheduler-logs.adoc b/modules/cnf-checking-numa-aware-scheduler-logs.adoc new file mode 100644 index 0000000000..bd55eb24ec --- /dev/null +++ b/modules/cnf-checking-numa-aware-scheduler-logs.adoc @@ -0,0 +1,146 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/cnf-numa-aware-scheduling.adoc + +:_module-type: PROCEDURE +[id="cnf-checking-numa-aware-scheduler-logs_{context}"] += Checking the NUMA-aware scheduler logs + +Troubleshoot problems with the NUMA-aware scheduler by reviewing the logs. If required, you can increase the scheduler log level by modifying the `spec.logLevel` field of the `NUMAResourcesScheduler` resource. Acceptable values are `Normal`, `Debug`, and `Trace`, with `Trace` being the most verbose option. + +[NOTE] +==== +To change the log level of the secondary scheduler, delete the running scheduler resource and re-deploy it with the changed log level. The scheduler is unavailable for scheduling new workloads during this downtime. +==== + +.Prerequisites + +* Install the OpenShift CLI (`oc`). +* Log in as a user with `cluster-admin` privileges. + +.Procedure + +. Delete the currently running `NUMAResourcesScheduler` resource: + +.. Get the active `NUMAResourcesScheduler` by running the following command: ++ +[source,terminal] +---- +$ oc get NUMAResourcesScheduler +---- ++ +.Example output +[source,terminal] +---- +NAME AGE +numaresourcesscheduler 90m +---- + +.. Delete the secondary scheduler resource by running the following command: ++ +[source,terminal] +---- +$ oc delete NUMAResourcesScheduler numaresourcesscheduler +---- ++ +.Example output +[source,terminal] +---- +numaresourcesscheduler.nodetopology.openshift.io "numaresourcesscheduler" deleted +---- + +. Save the following YAML in the file `nro-scheduler-debug.yaml`. This example changes the log level to `Debug`: ++ +[source,yaml] +---- +apiVersion: nodetopology.openshift.io/v1alpha1 +kind: NUMAResourcesScheduler +metadata: + name: numaresourcesscheduler +spec: + imageSpec: "registry.redhat.io/openshift4/noderesourcetopology-scheduler-container-rhel8:v4.10" + logLevel: Debug +---- + +. Create the updated `Debug` logging `NUMAResourcesScheduler` resource by running the following command: ++ +[source,terminal] +---- +$ oc create -f nro-scheduler-debug.yaml +---- ++ +.Example output +[source,terminal] +---- +numaresourcesscheduler.nodetopology.openshift.io/numaresourcesscheduler created +---- + +.Verification steps + +. Check that the NUMA-aware scheduler was successfully deployed: + +.. Run the following command to check that the CRD is created succesfully: ++ +[source,terminal] +---- +$ oc get crd | grep numaresourcesschedulers +---- ++ +.Example output +[source,terminal] +---- +NAME CREATED AT +numaresourcesschedulers.nodetopology.openshift.io 2022-02-25T11:57:03Z +---- + +.. Check that the new custom scheduler is available by running the following command: ++ +[source,terminal] +---- +$ oc get numaresourcesschedulers.nodetopology.openshift.io +---- ++ +.Example output +[source,terminal] +---- +NAME AGE +numaresourcesscheduler 3h26m +---- + +. Check that the logs for the scheduler shows the increased log level: + +.. Get the list of pods running in the `openshift-numaresources` namespace by running the following command: ++ +[source,terminal] +---- +$ oc get pods -n openshift-numaresources +---- ++ +.Example output +[source,terminal] +---- +NAME READY STATUS RESTARTS AGE +numaresources-controller-manager-d87d79587-76mrm 1/1 Running 0 46h +numaresourcesoperator-worker-5wm2k 2/2 Running 0 45h +numaresourcesoperator-worker-pb75c 2/2 Running 0 45h +secondary-scheduler-7976c4d466-qm4sc 1/1 Running 0 21m +---- + +.. Get the logs for the secondary scheduler pod by running the following command: ++ +[source,terminal] +---- +$ oc logs secondary-scheduler-7976c4d466-qm4sc -n openshift-numaresources +---- ++ +.Example output +[source,terminal] +---- +... +I0223 11:04:55.614788 1 reflector.go:535] k8s.io/client-go/informers/factory.go:134: Watch close - *v1.Namespace total 11 items received +I0223 11:04:56.609114 1 reflector.go:535] k8s.io/client-go/informers/factory.go:134: Watch close - *v1.ReplicationController total 10 items received +I0223 11:05:22.626818 1 reflector.go:535] k8s.io/client-go/informers/factory.go:134: Watch close - *v1.StorageClass total 7 items received +I0223 11:05:31.610356 1 reflector.go:535] k8s.io/client-go/informers/factory.go:134: Watch close - *v1.PodDisruptionBudget total 7 items received +I0223 11:05:31.713032 1 eventhandlers.go:186] "Add event for scheduled pod" pod="openshift-marketplace/certified-operators-thtvq" +I0223 11:05:53.461016 1 eventhandlers.go:244] "Delete event for scheduled pod" pod="openshift-marketplace/certified-operators-thtvq" +---- diff --git a/modules/cnf-creating-nrop-cr.adoc b/modules/cnf-creating-nrop-cr.adoc new file mode 100644 index 0000000000..bcefe6caa3 --- /dev/null +++ b/modules/cnf-creating-nrop-cr.adoc @@ -0,0 +1,88 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/cnf-numa-aware-scheduling.adoc + +:_module-type: PROCEDURE +[id="cnf-creating-nrop-cr_{context}"] += Creating the NUMAResourcesOperator custom resource + +When you have installed the NUMA Resources Operator, then create the `NUMAResourcesOperator` custom resource (CR) that instructs the NUMA Resources Operator to install all the cluster infrastructure needed to support the NUMA-aware scheduler, including daemon sets and APIs. + +.Prerequisites + +* Install the OpenShift CLI (`oc`). +* Log in as a user with `cluster-admin` privileges. +* Install the NUMA Resources Operator. + +.Procedure + +. Create the `MachineConfigPool` custom resource that enables custom kubelet configurations for worker nodes: + +.. Save the following YAML in the `nro-machineconfig.yaml` file: ++ +[source,yaml] +---- +apiVersion: machineconfiguration.openshift.io/v1 +kind: MachineConfigPool +metadata: + labels: + cnf-worker-tuning: enabled + machineconfiguration.openshift.io/mco-built-in: "" + pools.operator.machineconfiguration.openshift.io/worker: "" + name: worker +spec: + machineConfigSelector: + matchLabels: + machineconfiguration.openshift.io/role: worker + nodeSelector: + matchLabels: + node-role.kubernetes.io/worker: "" +---- + +.. Create the `MachineConfigPool` CR by running the following command: ++ +[source,terminal] +---- +$ oc create -f nro-machineconfig.yaml +---- + +. Create the `NUMAResourcesOperator` custom resource: + +.. Save the following YAML in the `nrop.yaml` file: ++ +[source,yaml] +---- +apiVersion: nodetopology.openshift.io/v1alpha1 +kind: NUMAResourcesOperator +metadata: + name: numaresourcesoperator +spec: + nodeGroups: + - machineConfigPoolSelector: + matchLabels: + pools.operator.machineconfiguration.openshift.io/worker: "" <1> +---- +<1> Should match the label applied to worker nodes in the related `MachineConfigPool` CR. + +.. Create the `NUMAResourcesOperator` CR by running the following command: ++ +[source,terminal] +---- +$ oc create -f nrop.yaml +---- + +.Verification + +Verify that the NUMA Resources Operator deployed successfully by running the following command: + +[source,terminal] +---- +$ oc get numaresourcesoperators.nodetopology.openshift.io +---- + +.Example output +[source,terminal] +---- +NAME AGE +numaresourcesoperator 10m +---- diff --git a/modules/cnf-deploying-the-numa-aware-scheduler.adoc b/modules/cnf-deploying-the-numa-aware-scheduler.adoc new file mode 100644 index 0000000000..47459acafe --- /dev/null +++ b/modules/cnf-deploying-the-numa-aware-scheduler.adoc @@ -0,0 +1,112 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/cnf-numa-aware-scheduling.adoc + +:_module-type: PROCEDURE +[id="cnf-deploying-the-numa-aware-scheduler_{context}"] += Deploying the NUMA-aware secondary pod scheduler + +After you install the NUMA Resources Operator, do the following to deploy the NUMA-aware secondary pod scheduler: + +* Configure the pod admittance policy for the required machine profile + +* Create the required machine config pool + +* Deploy the NUMA-aware secondary scheduler + +.Prerequisites + +* Install the OpenShift CLI (`oc`). + +* Log in as a user with `cluster-admin` privileges. + +* Install the NUMA Resources Operator. + +.Procedure +. Create the `KubeletConfig` custom resource that configures the pod admittance policy for the machine profile: + +.. Save the following YAML in the `nro-kubeletconfig.yaml` file: ++ +[source,yaml] +---- +apiVersion: machineconfiguration.openshift.io/v1 +kind: KubeletConfig +metadata: + name: cnf-worker-tuning +spec: + machineConfigPoolSelector: + matchLabels: + cnf-worker-tuning: enabled + kubeletConfig: + cpuManagerPolicy: "static" + cpuManagerReconcilePeriod: "5s" + reservedSystemCPUs: "0,1" + memoryManagerPolicy: "Static" + evictionHard: + memory.available: "100Mi" + kubeReserved: + memory: "512Mi" + reservedMemory: + - numaNode: 0 + limits: + memory: "1124Mi" + systemReserved: + memory: "512Mi" + topologyManagerPolicy: "single-numa-node" <1> +---- +<1> `topologyManagerPolicy` must be set to `single-numa-node`. + +.. Create the `KubeletConfig` custom resource (CR) by running the following command: ++ +[source,terminal] +---- +$ oc create -f nro-kubeletconfig.yaml +---- + +. Create the `NUMAResourcesScheduler` custom resource that deploys the NUMA-aware custom pod scheduler: + +.. Save the following YAML in the `nro-scheduler.yaml` file: ++ +[source,yaml] +---- +apiVersion: nodetopology.openshift.io/v1alpha1 +kind: NUMAResourcesScheduler +metadata: + name: numaresourcesscheduler +spec: + imageSpec: "registry.redhat.io/openshift4/noderesourcetopology-scheduler-container-rhel8:v4.10" +---- + +.. Create the `NUMAResourcesScheduler` CR by running the following command: ++ +[source,terminal] +---- +$ oc create -f nro-scheduler.yaml +---- + +.Verification + +Verify that the required resources deployed successfully by running the following command: + +[source,terminal] +---- +$ oc get all -n openshift-numaresources +---- + +.Example output +[source,terminal] +---- +NAME READY STATUS RESTARTS AGE +pod/numaresources-controller-manager-7575848485-bns4s 1/1 Running 0 13m +pod/numaresourcesoperator-worker-dvj4n 2/2 Running 0 16m +pod/numaresourcesoperator-worker-lcg4t 2/2 Running 0 16m +pod/secondary-scheduler-56994cf6cf-7qf4q 1/1 Running 0 16m +NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE +daemonset.apps/numaresourcesoperator-worker 2 2 2 2 2 node-role.kubernetes.io/worker= 16m +NAME READY UP-TO-DATE AVAILABLE AGE +deployment.apps/numaresources-controller-manager 1/1 1 1 13m +deployment.apps/secondary-scheduler 1/1 1 1 16m +NAME DESIRED CURRENT READY AGE +replicaset.apps/numaresources-controller-manager-7575848485 1 1 1 13m +replicaset.apps/secondary-scheduler-56994cf6cf 1 1 1 16m +---- diff --git a/modules/cnf-installing-numa-resources-operator-cli.adoc b/modules/cnf-installing-numa-resources-operator-cli.adoc new file mode 100644 index 0000000000..0bebeebb71 --- /dev/null +++ b/modules/cnf-installing-numa-resources-operator-cli.adoc @@ -0,0 +1,101 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/cnf-numa-aware-scheduling.adoc + +:_content-type: PROCEDURE +[id="cnf-installing-numa-resources-operator-cli_{context}"] += Installing the NUMA Resources Operator using the CLI + +As a cluster administrator, you can install the Operator using the CLI. + +.Prerequisites + +* Install the OpenShift CLI (`oc`). + +* Log in as a user with `cluster-admin` privileges. + +.Procedure + +. Create a namespace for the NUMA Resources Operator: + +.. Save the following YAML in the `nro-namespace.yaml` file: ++ +[source,yaml] +---- +apiVersion: v1 +kind: Namespace +metadata: + name: openshift-numaresources +---- + +.. Create the `Namespace` CR by running the following command: ++ +[source,terminal] +---- +$ oc create -f nro-namespace.yaml +---- + +. Create the operator group for the NUMA Resources Operator: + +.. Save the following YAML in the `nro-operatorgroup.yaml` file: ++ +[source,yaml] +---- +apiVersion: operators.coreos.com/v1 +kind: OperatorGroup +metadata: + name: numaresources-operator + namespace: openshift-numaresources +spec: + targetNamespaces: + - openshift-numaresources +---- + +.. Create the `OperatorGroup` CR by running the following command: ++ +[source,terminal] +---- +$ oc create -f nro-operatorgroup.yaml +---- + +. Create the subscription for the NUMA Resources Operator: + +.. Save the following YAML in the `nro-sub.yaml` file: ++ +[source,yaml] +---- +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription +metadata: + name: numaresources-operator + namespace: openshift-numaresources +spec: + channel: "{product-version}" + name: numaresources-operator + source: redhat-operators + sourceNamespace: openshift-marketplace +---- + +.. Create the `Subscription` CR by running the following command: ++ +[source,terminal] +---- +$ oc create -f nro-sub.yaml +---- + +.Verification + +. Verify that the installation succeeded by inspecting the CSV resource in the `openshift-numaresources` namespace. Run the following command: ++ +[source,terminal] +---- +$ oc get csv -n openshift-numaresources +---- ++ +.Example output + +[source,terminal] +---- +NAME DISPLAY VERSION REPLACES PHASE +numaresources-operator.v4.10.0 NUMA Resources Operator 4.10.0 Succeeded +---- diff --git a/modules/cnf-installing-numa-resources-operator-console.adoc b/modules/cnf-installing-numa-resources-operator-console.adoc new file mode 100644 index 0000000000..b793ee53dc --- /dev/null +++ b/modules/cnf-installing-numa-resources-operator-console.adoc @@ -0,0 +1,33 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/cnf-numa-aware-scheduling.adoc + +:_content-type: PROCEDURE +[id="cnf-installing-numa-resources-operator-console_{context}"] += Installing the NUMA Resources Operator using the web console + +As a cluster administrator, you can install the NUMA Resources Operator using the web console. + +.Procedure + +. Install the NUMA Resources Operator using the {product-title} web console: + +.. In the {product-title} web console, click *Operators* -> *OperatorHub*. + +.. Choose *NUMA Resources Operator* from the list of available Operators, and then click *Install*. + +. Optional: Verify that the NUMA Resources Operator installed successfully: + +.. Switch to the *Operators* -> *Installed Operators* page. + +.. Ensure that *NUMA Resources Operator* is listed in the *default* project with a *Status* of *InstallSucceeded*. ++ +[NOTE] +==== +During installation an Operator might display a *Failed* status. If the installation later succeeds with an *InstallSucceeded* message, you can ignore the *Failed* message. +==== ++ +If the Operator does not appear as installed, to troubleshoot further: ++ +* Go to the *Operators* -> *Installed Operators* page and inspect the *Operator Subscriptions* and *Install Plans* tabs for any failure or errors under *Status*. +* Go to the *Workloads* -> *Pods* page and check the logs for pods in the `default` project. diff --git a/modules/cnf-scheduling-numa-aware-workloads.adoc b/modules/cnf-scheduling-numa-aware-workloads.adoc new file mode 100644 index 0000000000..997a4f0aea --- /dev/null +++ b/modules/cnf-scheduling-numa-aware-workloads.adoc @@ -0,0 +1,185 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/cnf-numa-aware-scheduling.adoc + +:_content-type: PROCEDURE +[id="cnf-scheduling-numa-aware-workloads_{context}"] += Scheduling workloads with the NUMA-aware scheduler + +You can schedule workloads with the NUMA-aware scheduler using `Deployment` CRs that specify the minimum required resources to process the workload. + +The following example deployment uses NUMA-aware scheduling for a sample workload. + +.Prerequisites + +* Install the OpenShift CLI (`oc`). + +* Log in as a user with `cluster-admin` privileges. + +* Install the NUMA Resources Operator and deploy the NUMA-aware secondary scheduler. + +.Procedure + +. Get the name of the NUMA-aware scheduler that is deployed in the cluster by running the following command: ++ +[source,terminal] +---- +$ oc get numaresourcesschedulers.nodetopology.openshift.io numaresourcesscheduler -o json | jq '.status.schedulerName' +---- ++ +.Example output +[source,terminal] +---- +topo-aware-scheduler +---- + +. Create a `Deployment` CR that uses scheduler named `topo-aware-scheduler`, for example: + +.. Save the following YAML in the `nro-deployment.yaml` file: ++ +[source,yaml] +---- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: numa-deployment-1 + namespace: openshift-numaresources +spec: + replicas: 1 + selector: + matchLabels: + app: test + template: + metadata: + labels: + app: test + spec: + schedulerName: topo-aware-scheduler <1> + containers: + - name: ctnr + image: quay.io/openshifttest/hello-openshift:openshift + imagePullPolicy: IfNotPresent + resources: + limits: + memory: "100Mi" + cpu: "10" + requests: + memory: "100Mi" + cpu: "10" + - name: ctnr2 + image: gcr.io/google_containers/pause-amd64:3.0 + imagePullPolicy: IfNotPresent + command: ["/bin/sh", "-c"] + args: [ "while true; do sleep 1h; done;" ] + resources: + limits: + memory: "100Mi" + cpu: "8" + requests: + memory: "100Mi" + cpu: "8" +---- +<1> `schedulerName` must match the name of the NUMA-aware scheduler that is deployed in your cluster, for example `topo-aware-scheduler`. + +.. Create the `Deployment` CR by running the following command: ++ +[source,terminal] +---- +$ oc create -f nro-deployment.yaml +---- + +.Verification + +. Verify that the deployment was successful: ++ +[source,terminal] +---- +$ oc get pods -n openshift-numaresources +---- ++ +.Example output +[source,terminal] +---- +NAME READY STATUS RESTARTS AGE +numa-deployment-1-56954b7b46-pfgw8 2/2 Running 0 129m +numaresources-controller-manager-7575848485-bns4s 1/1 Running 0 15h +numaresourcesoperator-worker-dvj4n 2/2 Running 0 18h +numaresourcesoperator-worker-lcg4t 2/2 Running 0 16h +secondary-scheduler-56994cf6cf-7qf4q 1/1 Running 0 18h +---- + +. Verify that the `topo-aware-scheduler` is scheduling the deployed pod by running the following command: ++ +[source,terminal] +---- +$ oc describe pod numa-deployment-1-56954b7b46-pfgw8 -n openshift-numaresources +---- ++ +.Example output +[source,terminal] +---- +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Scheduled 130m topo-aware-scheduler Successfully assigned openshift-numaresources/numa-deployment-1-56954b7b46-pfgw8 to compute-0.example.com +---- ++ +[NOTE] +==== +Deployments that request more resources than is available for scheduling will fail with a `MinimumReplicasUnavailable` error. The deployment succeeds when the required resources become available. Pods remain in the `Pending` state until the required resources are available. +==== + +. Verify that the expected allocated resources are listed for the node. Run the following command: ++ +[source,terminal] +---- +$ oc describe noderesourcetopologies.topology.node.k8s.io +---- ++ +.Example output +[source,terminal] +---- +... + +Zones: + Costs: + Name: node-0 + Value: 10 + Name: node-1 + Value: 21 + Name: node-0 + Resources: + Allocatable: 39 + Available: 21 <1> + Capacity: 40 + Name: cpu + Allocatable: 6442450944 + Available: 6442450944 + Capacity: 6442450944 + Name: hugepages-1Gi + Allocatable: 134217728 + Available: 134217728 + Capacity: 134217728 + Name: hugepages-2Mi + Allocatable: 262415904768 + Available: 262206189568 + Capacity: 270146007040 + Name: memory + Type: Node +---- +<1> The `Available` capacity is reduced because of the resources that have been allocated to the guaranteed pod. ++ +Resources consumed by guaranteed pods are subtracted from the available node resources listed under `noderesourcetopologies.topology.node.k8s.io`. + +. Resource allocations for pods with a `Best-effort` or `Burstable` quality of service (`qosClass`) are not reflected in the NUMA node resources under `noderesourcetopologies.topology.node.k8s.io`. If a pod's consumed resources are not reflected in the node resource calculation, verify that the pod has `qosClass` of `Guaranteed` by running the following command: ++ +[source,terminal] +---- +$ oc get pod -n -o jsonpath="{ .status.qosClass }" +---- ++ +.Example output +[source,terminal] +---- +Guaranteed +---- diff --git a/modules/cnf-troubleshooting-missing-rte-config-maps.adoc b/modules/cnf-troubleshooting-missing-rte-config-maps.adoc new file mode 100644 index 0000000000..3421bf9bb7 --- /dev/null +++ b/modules/cnf-troubleshooting-missing-rte-config-maps.adoc @@ -0,0 +1,116 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/cnf-numa-aware-scheduling.adoc + +:_module-type: PROCEDURE +[id="cnf-troubleshooting-missing-rte-config-maps_{context}"] += Correcting a missing resource topology exporter config map + +If you install the NUMA Resources Operator in a cluster with misconfigured cluster settings, in some circumstances, the Operator is shown as active but the logs of the resource topology exporter (RTE) daemon set pods show that the configuration for the RTE is missing, for example: + +[source,text] +---- +Info: couldn't find configuration in "/etc/resource-topology-exporter/config.yaml" +---- + +This log message indicates that the `kubeletconfig` with the required configuration was not properly applied in the cluster, resulting in a missing RTE `configmap`. For example, the following cluster is missing a `numaresourcesoperator-worker` `configmap` custom resource (CR): + +[source,terminal] +---- +$ oc get configmap +---- + +.Example output +[source,terminal] +---- +NAME DATA AGE +0e2a6bd3.openshift-kni.io 0 6d21h +kube-root-ca.crt 1 6d21h +openshift-service-ca.crt 1 6d21h +topo-aware-scheduler-config 1 6d18h +---- + +In a correctly configured cluster, `oc get configmap` also returns a `numaresourcesoperator-worker` `configmap` CR. + +.Prerequisites + +* Install the {product-title} CLI (`oc`). + +* Log in as a user with cluster-admin privileges. + +* Install the NUMA Resources Operator and deploy the NUMA-aware secondary scheduler. + +.Procedure + +. Compare the values for `spec.machineConfigPoolSelector.matchLabels` in `kubeletconfig` and +`metadata.labels` in the `MachineConfigPool` (`mcp`) worker CR using the following commands: + +.. Check the `kubeletconfig` labels by running the following command: ++ +[source,terminal] +---- +$ oc get kubeletconfig -o yaml +---- ++ +.Example output +[source,yaml] +---- +machineConfigPoolSelector: + matchLabels: + cnf-worker-tuning: enabled +---- + +.. Check the `mcp` labels by running the following command: ++ +[source,terminal] +---- +$ oc get mcp worker -o yaml +---- ++ +.Example output +[source,yaml] +---- +labels: + machineconfiguration.openshift.io/mco-built-in: "" + pools.operator.machineconfiguration.openshift.io/worker: "" +---- ++ +The `cnf-worker-tuning: enabled` label is not present in the `MachineConfigPool` object. + +. Edit the `MachineConfigPool` CR to include the missing label, for example: ++ +[source,terminal] +---- +$ oc edit mcp worker -o yaml +---- ++ +.Example output +[source,yaml] +---- +labels: + machineconfiguration.openshift.io/mco-built-in: "" + pools.operator.machineconfiguration.openshift.io/worker: "" + cnf-worker-tuning: enabled +---- + +. Apply the label changes and wait for the cluster to apply the updated configuration. Run the following command: + +.Verification + +* Check that the missing `numaresourcesoperator-worker` `configmap` CR is applied: ++ +[source,terminal] +---- +$ oc get configmap +---- ++ +.Example output +[source,terminal] +---- +NAME DATA AGE +0e2a6bd3.openshift-kni.io 0 6d21h +kube-root-ca.crt 1 6d21h +numaresourcesoperator-worker 1 5m +openshift-service-ca.crt 1 6d21h +topo-aware-scheduler-config 1 6d18h +---- diff --git a/modules/cnf-troubleshooting-numa-aware-workloads.adoc b/modules/cnf-troubleshooting-numa-aware-workloads.adoc new file mode 100644 index 0000000000..ef549fd37a --- /dev/null +++ b/modules/cnf-troubleshooting-numa-aware-workloads.adoc @@ -0,0 +1,208 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/cnf-numa-aware-scheduling.adoc + +:_content-type: PROCEDURE +[id="cnf-troubleshooting-numa-aware-workloads_{context}"] += Troubleshooting NUMA-aware scheduling + +To troubleshoot common problems with NUMA-aware pod scheduling, perform the following steps. + +.Prerequisites + +* Install the {product-title} CLI (`oc`). + +* Log in as a user with cluster-admin privileges. + +* Install the NUMA Resources Operator and deploy the NUMA-aware secondary scheduler. + +.Procedure + +. Verify that the `noderesourcetopologies` CRD is deployed in the cluster by running the following command: ++ +[source,terminal] +---- +$ oc get crd | grep noderesourcetopologies +---- ++ +.Example output +[source,terminal] +---- +NAME CREATED AT +noderesourcetopologies.topology.node.k8s.io 2022-01-18T08:28:06Z +---- + +. Check that the NUMA-aware scheduler name matches the name specified in your NUMA-aware workloads by running the following command: ++ +[source,terminal] +---- +$ oc get numaresourcesschedulers.nodetopology.openshift.io numaresourcesscheduler -o json | jq '.status.schedulerName' +---- ++ +.Example output +[source,terminal] +---- +topo-aware-scheduler +---- + +. Verify that NUMA-aware scheduable nodes have the `noderesourcetopologies` CR applied to them. Run the following command: ++ +[source,terminal] +---- +$ oc get noderesourcetopologies.topology.node.k8s.io +---- ++ +.Example output +[source,terminal] +---- +NAME AGE +compute-0.example.com 17h +compute-1.example.com 17h +---- ++ +[NOTE] +==== +The number of nodes should equal the number of worker nodes that are configured by the machine config pool (`mcp`) worker definition. +==== + +. Verify the NUMA zone granularity for all scheduable nodes by running the following command: ++ +[source,terminal] +---- +$ oc get noderesourcetopologies.topology.node.k8s.io -o yaml +---- ++ +.Example output +[source,yaml] +---- +apiVersion: v1 +items: +- apiVersion: topology.node.k8s.io/v1alpha1 + kind: NodeResourceTopology + metadata: + annotations: + k8stopoawareschedwg/rte-update: periodic + creationTimestamp: "2022-06-16T08:55:38Z" + generation: 63760 + name: worker-0 + resourceVersion: "8450223" + uid: 8b77be46-08c0-4074-927b-d49361471590 + topologyPolicies: + - SingleNUMANodeContainerLevel + zones: + - costs: + - name: node-0 + value: 10 + - name: node-1 + value: 21 + name: node-0 + resources: + - allocatable: "38" + available: "38" + capacity: "40" + name: cpu + - allocatable: "134217728" + available: "134217728" + capacity: "134217728" + name: hugepages-2Mi + - allocatable: "262352048128" + available: "262352048128" + capacity: "270107316224" + name: memory + - allocatable: "6442450944" + available: "6442450944" + capacity: "6442450944" + name: hugepages-1Gi + type: Node + - costs: + - name: node-0 + value: 21 + - name: node-1 + value: 10 + name: node-1 + resources: + - allocatable: "268435456" + available: "268435456" + capacity: "268435456" + name: hugepages-2Mi + - allocatable: "269231067136" + available: "269231067136" + capacity: "270573244416" + name: memory + - allocatable: "40" + available: "40" + capacity: "40" + name: cpu + - allocatable: "1073741824" + available: "1073741824" + capacity: "1073741824" + name: hugepages-1Gi + type: Node +- apiVersion: topology.node.k8s.io/v1alpha1 + kind: NodeResourceTopology + metadata: + annotations: + k8stopoawareschedwg/rte-update: periodic + creationTimestamp: "2022-06-16T08:55:37Z" + generation: 62061 + name: worker-1 + resourceVersion: "8450129" + uid: e8659390-6f8d-4e67-9a51-1ea34bba1cc3 + topologyPolicies: + - SingleNUMANodeContainerLevel + zones: <1> + - costs: + - name: node-0 + value: 10 + - name: node-1 + value: 21 + name: node-0 + resources: <2> + - allocatable: "38" + available: "38" + capacity: "40" + name: cpu + - allocatable: "6442450944" + available: "6442450944" + capacity: "6442450944" + name: hugepages-1Gi + - allocatable: "134217728" + available: "134217728" + capacity: "134217728" + name: hugepages-2Mi + - allocatable: "262391033856" + available: "262391033856" + capacity: "270146301952" + name: memory + type: Node + - costs: + - name: node-0 + value: 21 + - name: node-1 + value: 10 + name: node-1 + resources: + - allocatable: "40" + available: "40" + capacity: "40" + name: cpu + - allocatable: "1073741824" + available: "1073741824" + capacity: "1073741824" + name: hugepages-1Gi + - allocatable: "268435456" + available: "268435456" + capacity: "268435456" + name: hugepages-2Mi + - allocatable: "269192085504" + available: "269192085504" + capacity: "270534262784" + name: memory + type: Node +kind: List +metadata: + resourceVersion: "" + selfLink: "" +---- +<1> Each stanza under `zones` describes the resources for a single NUMA zone. +<2> `resources` describes the current state of the NUMA zone resources. Check that resources listed under `items.zones.resources.available` correspond to the exclusive NUMA zone resources allocated to each guaranteed pod. diff --git a/modules/cnf-troubleshooting-resource-topo-exporter.adoc b/modules/cnf-troubleshooting-resource-topo-exporter.adoc new file mode 100644 index 0000000000..c25952cd3c --- /dev/null +++ b/modules/cnf-troubleshooting-resource-topo-exporter.adoc @@ -0,0 +1,92 @@ +// Module included in the following assemblies: +// +// *scalability_and_performance/cnf-numa-aware-scheduling.adoc + +:_module-type: PROCEDURE +[id="cnf-troubleshooting-resource-topo-exporter_{context}"] += Troubleshooting the resource topology exporter + +Troubleshoot `noderesourcetopologies` objects where unexpected results are occurring by inspecting the corresponding `resource-topology-exporter` logs. + +[NOTE] +==== +It is recommended that NUMA resource topology exporter instances in the cluster are named for nodes they refer to. For example, a worker node with the name `worker` should have a corresponding `noderesourcetopologies` object called `worker`. +==== + +.Prerequisites + +* Install the OpenShift CLI (`oc`). +* Log in as a user with `cluster-admin` privileges. + +.Procedure + +. Get the daemonsets managed by the NUMA Resources Operator. Each daemonset has a corresponding `nodeGroup` in the `NUMAResourcesOperator` CR. Run the following command: ++ +[source,terminal] +---- +$ oc get numaresourcesoperators.nodetopology.openshift.io numaresourcesoperator -o jsonpath="{.status.daemonsets[0]}" +---- ++ +.Example output +[source,json] +---- +{"name":"numaresourcesoperator-worker","namespace":"openshift-numaresources"} +---- + +. Get the label for the daemonset of interest using the value for `name` from the previous step: ++ +[source,terminal] +---- +$ oc get ds -n openshift-numaresources numaresourcesoperator-worker -o jsonpath="{.spec.selector.matchLabels}" +---- ++ +.Example output +[source,json] +---- +{"name":"resource-topology"} +---- + +. Get the pods using the `resource-topology` label by running the following command: ++ +[source,terminal] +---- +$ oc get pods -n openshift-numaresources -l name=resource-topology -o wide +---- ++ +.Example output +[source,terminal] +---- +NAME READY STATUS RESTARTS AGE IP NODE +numaresourcesoperator-worker-5wm2k 2/2 Running 0 2d1h 10.135.0.64 compute-0.example.com +numaresourcesoperator-worker-pb75c 2/2 Running 0 2d1h 10.132.2.33 compute-1.example.com +---- + +. Examine the logs of the `resource-topology-exporter` container running on the worker pod that corresponds to the node you are troubleshooting. Run the following command: ++ +[source,terminal] +---- +$ oc logs -n openshift-numaresources -c resource-topology-exporter numaresourcesoperator-worker-pb75c +---- ++ +.Example output +[source,terminal] +---- +I0221 13:38:18.334140 1 main.go:206] using sysinfo: +reservedCpus: 0,1 +reservedMemory: + "0": 1178599424 +I0221 13:38:18.334370 1 main.go:67] === System information === +I0221 13:38:18.334381 1 sysinfo.go:231] cpus: reserved "0-1" +I0221 13:38:18.334493 1 sysinfo.go:237] cpus: online "0-103" +I0221 13:38:18.546750 1 main.go:72] +cpus: allocatable "2-103" +hugepages-1Gi: + numa cell 0 -> 6 + numa cell 1 -> 1 +hugepages-2Mi: + numa cell 0 -> 64 + numa cell 1 -> 128 +memory: + numa cell 0 -> 45758Mi + numa cell 1 -> 48372Mi +---- diff --git a/scalability_and_performance/cnf-numa-aware-scheduling.adoc b/scalability_and_performance/cnf-numa-aware-scheduling.adoc new file mode 100644 index 0000000000..3c83a828c4 --- /dev/null +++ b/scalability_and_performance/cnf-numa-aware-scheduling.adoc @@ -0,0 +1,43 @@ +:_content-type: ASSEMBLY +[id="cnf-numa-aware-scheduling"] += Scheduling NUMA-aware workloads +include::_attributes/common-attributes.adoc[] +:context: numa-aware + +toc::[] + +Learn about NUMA-aware scheduling and how you can use it to deploy high performance workloads in an {product-title} cluster. + +:FeatureName: NUMA-aware scheduling +include::snippets/technology-preview.adoc[leveloffset=+1] + +The NUMA Resources Operator allows you to schedule high-performance workloads in the same NUMA zone. It deploys a node resources exporting agent that reports on available cluster node NUMA resources, and a secondary scheduler that manages the workloads. + +include::modules/cnf-about-numa-aware-scheduling.adoc[leveloffset=+1] + +.Additional resources + +* For more information about running secondary pod schedulers in your cluster and how to deploy pods with a secondary pod scheduler, see xref:../nodes/scheduling/secondary_scheduler/nodes-secondary-scheduler-configuring.adoc#secondary-scheduler-configuring[Scheduling pods using a secondary scheduler]. + +[id="installing-the-numa-resources-operator_{context}"] +== Installing the NUMA Resources Operator + +NUMA Resources Operator deploys resources that allow you to schedule NUMA-aware workloads and deployments. You can install the NUMA Resources Operator using the {product-title} CLI or the web console. + +include::modules/cnf-installing-numa-resources-operator-cli.adoc[leveloffset=+2] + +include::modules/cnf-installing-numa-resources-operator-console.adoc[leveloffset=+2] + +include::modules/cnf-creating-nrop-cr.adoc[leveloffset=+1] + +include::modules/cnf-deploying-the-numa-aware-scheduler.adoc[leveloffset=+1] + +include::modules/cnf-scheduling-numa-aware-workloads.adoc[leveloffset=+1] + +include::modules/cnf-troubleshooting-numa-aware-workloads.adoc[leveloffset=+1] + +include::modules/cnf-checking-numa-aware-scheduler-logs.adoc[leveloffset=+2] + +include::modules/cnf-troubleshooting-resource-topo-exporter.adoc[leveloffset=+2] + +include::modules/cnf-troubleshooting-missing-rte-config-maps.adoc[leveloffset=+2]