All Policies

PodDisruptionBudget maxUnavailable Non-Zero with Deployments

A PodDisruptionBudget which sets its maxUnavailable value to zero prevents all voluntary evictions including Node drains which may impact maintenance tasks. This may be acceptable if there are no matching controllers, but if there are then creation of such a PDB could allow unintended disruption. This policy enforces that a PodDisruptionBudget may not specify the maxUnavailable field as zero if there are any existing matching Deployments having greater than zero replicas.

Policy Definition

/other/pdb-maxunavailable-with-deployments/pdb-maxunavailable-with-deployments.yaml

 1apiVersion: kyverno.io/v1
 2kind: ClusterPolicy
 3metadata:
 4  name: pdb-maxunavailable-with-deployments
 5  annotations:
 6    policies.kyverno.io/title: PodDisruptionBudget maxUnavailable Non-Zero with Deployments
 7    policies.kyverno.io/category: Other
 8    kyverno.io/kyverno-version: 1.11.4
 9    kyverno.io/kubernetes-version: "1.27"
10    policies.kyverno.io/subject: PodDisruptionBudget, Deployment
11    policies.kyverno.io/description: >-
12      A PodDisruptionBudget which sets its maxUnavailable value to zero prevents
13      all voluntary evictions including Node drains which may impact maintenance tasks.
14      This may be acceptable if there are no matching controllers, but if there are then
15      creation of such a PDB could allow unintended disruption. This policy enforces that
16      a PodDisruptionBudget may not specify the maxUnavailable field as zero if there are
17      any existing matching Deployments having greater than zero replicas.
18spec:
19  validationFailureAction: Audit
20  background: false
21  rules:
22  - name: pdb-maxunavailable
23    match:
24      any:
25      - resources:
26          kinds:
27          - PodDisruptionBudget
28          operations:
29          - CREATE
30          - UPDATE
31    context:
32    - name: deploymentreplicas
33      apiCall:
34        jmesPath: items[?label_match(`{{request.object.spec.selector.matchLabels}}`, spec.template.metadata.labels)] || `[]`
35        urlPath: /apis/apps/v1/namespaces/{{request.namespace}}/deployments
36    preconditions:
37      all:
38      - key: '{{ regex_match(''^[0-9]+$'', ''{{ request.object.spec.maxUnavailable || ''''}}'') }}'
39        operator: Equals
40        value: true
41      - key: '{{ length(deploymentreplicas) }}'
42        operator: GreaterThan
43        value: 0
44    validate:
45      message: >-
46        PodDisruptionBudget must not specify maxUnavailable as zero if there are any existing matching Deployments which
47        have replicas numbering greater than zero. There are {{ length(deploymentreplicas) }} Deployments which match this labelSelector
48        having {{ deploymentreplicas[*].spec.replicas }} replicas.
49      foreach:
50      - list: deploymentreplicas
51        deny:
52          conditions:
53            all:
54            - key: "{{ request.object.spec.maxUnavailable }}"
55              operator: LessThan
56              value: "{{ element.spec.replicas }}"