Configure CPU Manager Policies with Karpenter
Kubernetes CPU manager policies control how CPUs are allocated to containers running on a node. With Karpenter on Exoscale SKS, you can configure the kubelet CPU manager through the ExoscaleNodeClass resource and apply the configuration to all nodes provisioned from that node class.
Prerequisites
As a prerequisite for the following documentation, you need:
- An Exoscale SKS cluster on the Pro plan with the Karpenter addon enabled.
- Access to your cluster with
kubectl. - A Karpenter
NodePooland anExoscaleNodeClassconfigured for Karpenter. - Basic Kubernetes and YAML knowledge.
If you do not have access to an SKS cluster, follow the Quick Start Guide.
Understanding CPU manager policies
The Kubernetes CPU manager allocates CPUs to containers that request CPU resources. It can improve CPU affinity and reduce contention for workloads that are sensitive to latency or require predictable CPU performance.
Kubernetes supports the following CPU manager policies:
none: the default policy. CPU resources are managed by the standard scheduler and container runtime mechanisms.static: allows eligible containers with an integer CPU request to receive exclusive CPUs. Other containers continue to use the shared CPU pool.
For more information about CPU manager policies, CPU requests, and exclusive CPUs, see the official Kubernetes documentation.
Important
The static policy is useful only when workloads request CPU resources correctly. A container must request an integer number of CPUs to be eligible for exclusive CPU allocation.
Configure CPU manager on Karpenter nodes
CPU manager settings are configured in the spec.kubelet section of an ExoscaleNodeClass. The settings are applied when Karpenter provisions a node from that node class.
The following example enables the static policy, reserves CPU for Kubernetes and system components, and changes the CPU manager reconciliation period:
apiVersion: karpenter.exoscale.com/v1
kind: ExoscaleNodeClass
metadata:
name: cpu-static
spec:
imageTemplateSelector: {}
kubelet:
cpuManagerPolicy: static
cpuManagerReconcilePeriod: 10s
kubeReserved:
cpu: "200m"
systemReserved:
cpu: "100m"cpuManagerPolicy accepts none or static. The default is none. The static policy requires a non-zero CPU reservation in either kubeReserved.cpu or systemReserved.cpu; the ExoscaleNodeClass validation rejects the resource if this requirement is not met.
cpuManagerReconcilePeriod controls how often the kubelet reconciles CPU assignments. Its default value is 10s, so it can usually be omitted.
Configure static policy options
The static policy can be fine-tuned with cpuManagerPolicyOptions. Karpenter supports the following options:
full-pcpus-onlydistribute-cpus-across-numaprefer-align-cpus-by-uncorecachestrict-cpu-reservationalign-by-socketdistribute-cpus-across-cores
For example:
apiVersion: karpenter.exoscale.com/v1
kind: ExoscaleNodeClass
metadata:
name: cpu-static
spec:
imageTemplateSelector: {}
kubelet:
cpuManagerPolicy: static
cpuManagerPolicyOptions:
- full-pcpus-only
- distribute-cpus-across-numa
kubeReserved:
cpu: "200m"
systemReserved:
cpu: "100m"These options are valid only when cpuManagerPolicy is set to static. The Kubernetes version running on the node must support the selected options. Refer to the Kubernetes CPU manager documentation for their behavior and compatibility.
Deploy the configuration
Apply the ExoscaleNodeClass before applying or updating a NodePool that references it:
kubectl apply -f exoscale-nodeclass.yaml
kubectl apply -f nodepool.yamlA NodePool must reference the node class through nodeClassRef:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: cpu-optimized
spec:
template:
spec:
nodeClassRef:
group: karpenter.exoscale.com
kind: ExoscaleNodeClass
name: cpu-static
requirements:
- key: node.kubernetes.io/instance-type
operator: In
values:
- standard.medium
- standard.largeNew nodes provisioned for this NodePool use the configured CPU manager policy. Existing nodes are not reconfigured in place. When the CPU manager configuration changes, Karpenter detects the drift and replaces affected nodes when disruption policies allow it.
Verify the configuration
Check that the node class and node pool are ready:
kubectl get exoscalenodeclass cpu-static
kubectl get nodepool cpu-optimized
kubectl get nodeclaim -o wideAfter a node has been provisioned, inspect its kubelet configuration:
kubectl get node <node-name> -o yamlYou can also check the kubelet logs on the node to confirm that the CPU manager started with the expected policy. The exact log output depends on the SKS node image and Kubernetes version.
To test exclusive CPU allocation, deploy a pod with an integer CPU request and limit:
apiVersion: v1
kind: Pod
metadata:
name: cpu-manager-test
spec:
restartPolicy: Never
containers:
- name: test
image: registry.k8s.io/pause:3.10
resources:
requests:
cpu: "1"
limits:
cpu: "1"The pod must be scheduled on a node using the static policy. Pods with fractional CPU requests, such as 500m, use the shared CPU pool and are not assigned exclusive CPUs.
Warning
Changing CPU manager settings affects node allocation and will cause Karpenter to replace nodes. Plan the change around your workload disruption budgets and verify that enough capacity remains available during the replacement.