--- # ============================================================================ # CPU-REQUEST RELIEF — TOGGLEABLE CLUSTER POLICY # ============================================================================ # Emergency relief for CPU-saturated scenarios # # When ENABLED, this Kyverno ClusterPolicy removes the `resources.requests.cpu` # field from every Pod created/updated in the cluster (except Kyverno's own pods, # critical kube-system control-plane pods, and the Longhorn instance-manager / # engine-image / longhorn-manager, which must keep guarantees so admission and # the storage layer keep working). With no CPU request, pods schedule onto # whatever capacity is free and burst freely. # # === TOGGLE === # The policy is ACTIVE by default (failurePolicy: Ignore = mutate, never block). # # DISABLE relief (restore the per-app CPU requests on next Flux reconcile): # kubectl patch clusterpolicy.kyverno.io strip-cpu-requests --type=merge \ # -p '{"spec":{"failurePolicy":"Never"}}' # # failurePolicy: Never tells Kyverno to skip the rule without mutating, so the # # original CPU requests from each HelmRelease are restored on next reconcile. # # RE-ENABLE relief (strip requests again): # kubectl patch clusterpolicy.kyverno.io strip-cpu-requests --type=merge \ # -p '{"spec":{"failurePolicy":"Ignore"}}' # ============================================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: strip-cpu-requests annotations: policies.kyverno.io/title: Strip CPU Requests (Emergency Relief) policies.kyverno.io/category: Other policies.kyverno.io/severity: low policies.kyverno.io/subject: Pod policies.kyverno.io/description: >- Removes resources.requests.cpu AND resources.limits.cpu from pods so they can be scheduled on an overloaded single-node cluster. Limits must be stripped too: the LimitRanger admission plugin defaults requests.cpu = limits.cpu whenever a limit exists without a request, so stripping only the request is a no-op. Toggle via spec.failurePolicy: Ignore = active (strip), Never = inactive (restore). spec: # Never block a pod if Kyverno admission is itself under pressure. failurePolicy: Ignore # background: true so the backgroundController also mutates ALREADY-EXISTING # pods (not just new/updated ones at admission). This makes the relief take # effect immediately on flip-on, without waiting for a pod restart. background: true rules: - name: remove-cpu-request-from-containers match: any: - resources: kinds: - Pod # Keep guarantees for things that must keep running so admission and the # storage layer keep working even while everything else is bursting. exclude: any: - resources: namespaces: - kyverno - resources: namespaces: - kube-system names: # Control-plane static pods (apiserver, scheduler, controller-manager) - kube-apiserver-* - kube-scheduler-* - kube-controller-manager-* - resources: namespaces: - longhorn-system selector: matchLabels: app: longhorn-manager - resources: namespaces: - longhorn-system selector: matchLabels: app: instance-manager - resources: namespaces: - longhorn-system selector: matchLabels: app: engine-image mutate: # `request.object` is available in BOTH admission and background modes: # the backgroundController synthesizes an admission-like request for # existing resources, so the same foreach works for both. # NOTE 1: inside `foreach`, patchStrategicMerge must be an INLINE YAML # mapping — a `|` block scalar is parsed as a string and fails with # "wrong node kind: expected MappingNode but got ScalarNode". # NOTE 2: limits.cpu MUST be stripped together with requests.cpu. # The LimitRanger admission plugin defaults requests.cpu = limits.cpu # whenever a container has a limit but no request, so stripping only # the request is a no-op for any container that declares a limit. foreach: - list: "request.object.spec.containers" patchStrategicMerge: spec: containers: - name: "{{ element.name }}" resources: requests: cpu: null limits: cpu: null - list: "request.object.spec.initContainers || `[]`" patchStrategicMerge: spec: initContainers: - name: "{{ element.name }}" resources: requests: cpu: null limits: cpu: null