Skip to content

Commit 561f55d

Browse files
jcpunkillume
authored andcommitted
charts: Add optional PodDisruptionBudget
Signed-off-by: Pat Riehecky <riehecky@fnal.gov>
1 parent 244d918 commit 561f55d

File tree

6 files changed

+291
-0
lines changed

6 files changed

+291
-0
lines changed

charts/headlamp/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,44 @@ env:
231231
value: "6443"
232232
```
233233

234+
### Pod Disruption Budget (PDB)
235+
236+
| Key | Type | Default | Description |
237+
|-----|------|---------|-------------|
238+
| podDisruptionBudget.enabled | bool | `false` | Create a PodDisruptionBudget resource |
239+
| podDisruptionBudget.minAvailable | integer \| string \| null | `0` | Minimum pods that must be available. Rendered only when set to a positive integer or a percentage string (e.g. `"1"` or `"50%"`). Schema default is 0, but the chart skips rendering `0`. |
240+
| podDisruptionBudget.maxUnavailable | integer \| string \| null | `null` | Maximum pods allowed to be unavailable. Accepts integer >= 0 or percentage string. Mutually exclusive with `minAvailable`; the template renders this field when set. |
241+
| podDisruptionBudget.unhealthyPodEvictionPolicy | string \| null | `null` | Eviction policy: `"IfHealthyBudget"` or `"AlwaysAllow"`. Emitted only on clusters running Kubernetes >= 1.27 and when explicitly set in values. |
242+
243+
Note: Ensure `minAvailable` and `maxUnavailable` are not both set (use `null` to disable one). To include `minAvailable` in the rendered PDB, set a positive integer or percentage; the template omits a `0` value.
244+
245+
Example, Require at least 1 pod available (ensure maxUnavailable is disabled):
246+
```yaml
247+
podDisruptionBudget:
248+
enabled: true
249+
minAvailable: 1
250+
maxUnavailable: null
251+
```
252+
253+
Example, Allow up to 50% of pods to be unavailable:
254+
```yaml
255+
podDisruptionBudget:
256+
enabled: true
257+
maxUnavailable: "50%"
258+
minAvailable: null
259+
```
260+
261+
Example, Set unhealthyPodEvictionPolicy (requires Kubernetes >= 1.27):
262+
```yaml
263+
podDisruptionBudget:
264+
enabled: true
265+
maxUnavailable: 1
266+
minAvailable: null
267+
unhealthyPodEvictionPolicy: "IfHealthyBudget"
268+
```
269+
270+
Ensure your replicaCount and maintenance procedures respect the configured PDB to avoid blocking intended operations.
271+
234272
## Contributing
235273

236274
We welcome contributions to the Headlamp Helm chart! To contribute:

charts/headlamp/templates/pdb.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{{- if .Values.podDisruptionBudget.enabled }}
2+
apiVersion: policy/v1
3+
kind: PodDisruptionBudget
4+
metadata:
5+
name: {{ include "headlamp.fullname" . }}
6+
labels:
7+
{{- include "headlamp.labels" . | nindent 4 }}
8+
spec:
9+
{{- with .Values.podDisruptionBudget.maxUnavailable }}
10+
maxUnavailable: {{ . }}
11+
{{- end }}
12+
{{- with .Values.podDisruptionBudget.minAvailable }}
13+
minAvailable: {{ . }}
14+
{{- end }}
15+
{{- if (semverCompare ">= 1.27-0" .Capabilities.KubeVersion.Version) }}
16+
{{- if hasKey .Values.podDisruptionBudget "unhealthyPodEvictionPolicy" }}
17+
{{- with .Values.podDisruptionBudget.unhealthyPodEvictionPolicy }}
18+
unhealthyPodEvictionPolicy: {{ . }}
19+
{{- end }}
20+
{{- end }}
21+
{{- end }}
22+
selector:
23+
matchLabels:
24+
{{- include "headlamp.selectorLabels" . | nindent 6 }}
25+
{{- end }}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
# Source: headlamp/templates/pdb.yaml
3+
apiVersion: policy/v1
4+
kind: PodDisruptionBudget
5+
metadata:
6+
name: headlamp
7+
labels:
8+
helm.sh/chart: headlamp-0.35.0
9+
app.kubernetes.io/name: headlamp
10+
app.kubernetes.io/instance: headlamp
11+
app.kubernetes.io/version: "0.35.0"
12+
app.kubernetes.io/managed-by: Helm
13+
spec:
14+
maxUnavailable: 1
15+
unhealthyPodEvictionPolicy: IfHealthyBudget
16+
selector:
17+
matchLabels:
18+
app.kubernetes.io/name: headlamp
19+
app.kubernetes.io/instance: headlamp
20+
---
21+
# Source: headlamp/templates/serviceaccount.yaml
22+
apiVersion: v1
23+
kind: ServiceAccount
24+
metadata:
25+
name: headlamp
26+
labels:
27+
helm.sh/chart: headlamp-0.35.0
28+
app.kubernetes.io/name: headlamp
29+
app.kubernetes.io/instance: headlamp
30+
app.kubernetes.io/version: "0.35.0"
31+
app.kubernetes.io/managed-by: Helm
32+
---
33+
# Source: headlamp/templates/secret.yaml
34+
apiVersion: v1
35+
kind: Secret
36+
metadata:
37+
name: oidc
38+
type: Opaque
39+
data:
40+
---
41+
# Source: headlamp/templates/clusterrolebinding.yaml
42+
apiVersion: rbac.authorization.k8s.io/v1
43+
kind: ClusterRoleBinding
44+
metadata:
45+
name: headlamp-admin
46+
labels:
47+
helm.sh/chart: headlamp-0.35.0
48+
app.kubernetes.io/name: headlamp
49+
app.kubernetes.io/instance: headlamp
50+
app.kubernetes.io/version: "0.35.0"
51+
app.kubernetes.io/managed-by: Helm
52+
roleRef:
53+
apiGroup: rbac.authorization.k8s.io
54+
kind: ClusterRole
55+
name: cluster-admin
56+
subjects:
57+
- kind: ServiceAccount
58+
name: headlamp
59+
namespace: default
60+
---
61+
# Source: headlamp/templates/service.yaml
62+
apiVersion: v1
63+
kind: Service
64+
metadata:
65+
name: headlamp
66+
labels:
67+
helm.sh/chart: headlamp-0.35.0
68+
app.kubernetes.io/name: headlamp
69+
app.kubernetes.io/instance: headlamp
70+
app.kubernetes.io/version: "0.35.0"
71+
app.kubernetes.io/managed-by: Helm
72+
spec:
73+
type: ClusterIP
74+
75+
ports:
76+
- port: 80
77+
targetPort: http
78+
protocol: TCP
79+
name: http
80+
selector:
81+
app.kubernetes.io/name: headlamp
82+
app.kubernetes.io/instance: headlamp
83+
---
84+
# Source: headlamp/templates/deployment.yaml
85+
# This block of code is used to extract the values from the env.
86+
# This is done to check if the values are non-empty and if they are, they are used in the deployment.yaml.
87+
88+
apiVersion: apps/v1
89+
kind: Deployment
90+
metadata:
91+
name: headlamp
92+
labels:
93+
helm.sh/chart: headlamp-0.35.0
94+
app.kubernetes.io/name: headlamp
95+
app.kubernetes.io/instance: headlamp
96+
app.kubernetes.io/version: "0.35.0"
97+
app.kubernetes.io/managed-by: Helm
98+
spec:
99+
replicas: 1
100+
selector:
101+
matchLabels:
102+
app.kubernetes.io/name: headlamp
103+
app.kubernetes.io/instance: headlamp
104+
template:
105+
metadata:
106+
labels:
107+
app.kubernetes.io/name: headlamp
108+
app.kubernetes.io/instance: headlamp
109+
spec:
110+
serviceAccountName: headlamp
111+
automountServiceAccountToken: true
112+
securityContext:
113+
{}
114+
containers:
115+
- name: headlamp
116+
securityContext:
117+
privileged: false
118+
runAsGroup: 101
119+
runAsNonRoot: true
120+
runAsUser: 100
121+
image: "ghcr.io/headlamp-k8s/headlamp:v0.35.0"
122+
imagePullPolicy: IfNotPresent
123+
124+
env:
125+
args:
126+
- "-in-cluster"
127+
- "-plugins-dir=/headlamp/plugins"
128+
# Check if externalSecret is disabled
129+
ports:
130+
- name: http
131+
containerPort: 4466
132+
protocol: TCP
133+
livenessProbe:
134+
httpGet:
135+
path: "/"
136+
port: http
137+
readinessProbe:
138+
httpGet:
139+
path: "/"
140+
port: http
141+
resources:
142+
{}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
podDisruptionBudget:
2+
enabled: true
3+
maxUnavailable: 1
4+
unhealthyPodEvictionPolicy: IfHealthyBudget
5+
minAvailable: null

charts/headlamp/values.schema.json

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,66 @@
429429
}
430430
}
431431
},
432+
"podDisruptionBudget": {
433+
"type": "object",
434+
"properties": {
435+
"enabled": {
436+
"type": "boolean",
437+
"default": false,
438+
"description": "Enable PodDisruptionBudget. See: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/"
439+
},
440+
"minAvailable": {
441+
"oneOf": [
442+
{
443+
"type": "null"
444+
},
445+
{
446+
"type": "integer",
447+
"minimum": 0
448+
},
449+
{
450+
"type": "string",
451+
"pattern": "^([0-9]+%?|[0-9]*\\.[0-9]+%)$"
452+
}
453+
],
454+
"default": 0,
455+
"description": "Minimum number/percentage of pods that should remain scheduled. When it's set, maxUnavailable must be disabled by `maxUnavailable: null`"
456+
},
457+
"maxUnavailable": {
458+
"oneOf": [
459+
{
460+
"type": "null"
461+
},
462+
{
463+
"type": "integer",
464+
"minimum": 0
465+
},
466+
{
467+
"type": "string",
468+
"pattern": "^([0-9]+%?|[0-9]*\\.[0-9]+%)$"
469+
}
470+
],
471+
"default": null,
472+
"description": "Maximum number/percentage of pods that may be made unavailable"
473+
},
474+
"unhealthyPodEvictionPolicy": {
475+
"oneOf": [
476+
{
477+
"type": "null"
478+
},
479+
{
480+
"type": "string",
481+
"enum": [
482+
"IfHealthyBudget",
483+
"AlwaysAllow"
484+
]
485+
}
486+
],
487+
"default": null,
488+
"description": "How are unhealthy, but running, pods counted for eviction"
489+
}
490+
}
491+
},
432492
"extraManifests": {
433493
"type": "array",
434494
"description": "Extra manifests to apply to the deployment",

charts/headlamp/values.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,27 @@ pluginsManager:
262262
# cpu: "1000m"
263263
# memory: "4096Mi"
264264

265+
podDisruptionBudget:
266+
# -- enable PodDisruptionBudget
267+
# ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/
268+
enabled: false
269+
# @schema
270+
# type: [null, integer, string]
271+
# @schema
272+
# -- Minimum number/percentage of pods that should remain scheduled.
273+
# When it's set, maxUnavailable must be disabled by `maxUnavailable: null`
274+
minAvailable: 0
275+
# @schema
276+
# type: [null, integer, string]
277+
# @schema
278+
# -- Maximum number/percentage of pods that may be made unavailable
279+
maxUnavailable: null
280+
# @schema
281+
# type: [null, string]
282+
# @schema
283+
# -- How are unhealthy, but running, pods counted for eviction
284+
unhealthyPodEvictionPolicy: null
285+
265286
# -- Additional Kubernetes manifests to be deployed. Include the manifest as nested YAML.
266287
extraManifests: []
267288
# - |

0 commit comments

Comments
 (0)