mirror of
https://github.com/vhaudiquet/homeprod.git
synced 2026-09-21 16:36:05 +00:00
122 lines
5.1 KiB
YAML
122 lines
5.1 KiB
YAML
---
|
|
# ============================================================================
|
|
# 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
|