{{- /* ONE PodDisruptionBudget PER NODE GROUP, and that is the whole difference from the precedent. keycloak.pdb.yaml (Gitea #83, README guideline 11) set the convention this file follows; what it did not have to deal with is a chart whose replica count is a property of a GROUP rather than of the release. So the condition is evaluated per group, and with full: 2 / mx: 1 exactly one object is rendered. WHY IT EXISTS: with two replicas in a group a node drain is otherwise free to take both at once - and a drain is the most common reason a pod moves, because it is what a node upgrade does. Without this object the second replica buys nothing against the failure it was added for. The chart's topology spread constraint and this budget are two halves of one answer: the constraint decides that the two pods sit on different nodes, the budget decides that only one of those nodes may be emptied at a time. minAvailable rather than maxUnavailable, as in keycloak: the promise wanted is about the service - at least one node of this group keeps answering throughout the drain - and not about the size of the disruption. AND WHY IT IS NOT RENDERED BELOW TWO EFFECTIVE REPLICAS. This is the trap that makes a PDB worth a condition rather than an unconditional object, quoted from the precedent because it has not changed: minAvailable: 1 with exactly ONE replica forbids every voluntary eviction, so `kubectl drain` blocks forever on a pod nothing is allowed to move - and the message then names the PDB and not the replica count, which sends the reader to the wrong file. The same holds for scaleDown: true, where the group has no pods at all and the object would only describe a promise about nothing. The count is therefore the COMPUTED one (stalwart.replicas), not the raw nodes..replicas, which is what makes scaleDown: true remove the budget rather than leave it behind. NOTES.txt prints, per group, which of the cases applied, so an operator does not have to infer it from `kubectl get pdb`. THE SELECTOR COMES FROM stalwart.groupLabels, the same definition the pod template's labels come from. A PDB whose selector matches no pod does not fail: it reports its arithmetic over zero pods, never blocks an eviction, and a drain takes the whole group while the object sits there looking like protection. ci/run-selector-match-test.sh holds this selector against the rendered pod templates on every pull request for exactly that reason. */ -}} {{- $root := . -}} {{- range $group, $spec := fromYaml (include "stalwart.nodes" .) }} {{- $name := printf "%s-%s" (include "stalwart.fullname" $root) $group }} {{- $replicas := int (include "stalwart.replicas" (dict "scaleDown" $root.Values.scaleDown "replicas" $spec.replicas)) }} {{- $settings := fromYaml (include "stalwart.groupSettings" (dict "group" $group "given" $spec)) }} {{- if and $settings.podDisruptionBudget.enabled (ge $replicas 2) }} --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: {{ $name }}-pdb labels: app: {{ $name }}-sfs {{- include "stalwart.groupLabels" (dict "root" $root "group" $group) | nindent 4 }} spec: minAvailable: {{ $settings.podDisruptionBudget.minAvailable | int64 }} selector: matchLabels: {{- include "stalwart.groupLabels" (dict "root" $root "group" $group) | nindent 6 }} {{- end }} {{- end }}