Skip to content

Commit 6089afc

Browse files
committed
feat(helm): add hostNetwork and port configuration to charts
The kubewarden-controller chart gains a hostNetwork toggle and a ports block (webhook, healthProbe, metrics) that feed into both the Deployment template and the Service definitions, so every port is configurable from values.yaml rather than hardcoded. A new "kubewarden-controller.effectiveAffinity" helper injects a required podAntiAffinity rule that prevents two controller replicas from landing on the same node when hostNetwork is enabled, avoiding port collisions on the host interface. When the user supplies their own affinity the helper uses it verbatim, preserving full operator control. The kubewarden-defaults chart is extended in the same way: the default PolicyServer template now passes webhookPort, readinessProbePort, and metricsPort through to the CRD when set, and its values.yaml documents the fields with commented-out examples and their defaults. Both charts include JSON schema additions and Helm unit tests covering the new values, hostNetwork toggling, anti-affinity injection, and service port rendering. Assisted-by: Github Copilot Signed-off-by: José Guilherme Vanz <jguilhermevanz@suse.com>
1 parent d365441 commit 6089afc

11 files changed

Lines changed: 344 additions & 8 deletions

File tree

charts/kubewarden-controller/templates/_helpers.tpl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,42 @@ are configured.
181181
- {{ .Values.auditScanner.reportCRDsKind }}
182182
{{- end -}}
183183
{{- end -}}
184+
185+
{{/*
186+
Compute the effective affinity for the controller deployment.
187+
When hostNetwork is enabled, a required podAntiAffinity rule is injected to
188+
forbid multiple controller pods from being scheduled on the same node, avoiding
189+
host-port conflicts between controller replicas. The rule matches only
190+
controller pods using the chart's selector labels.
191+
192+
PolicyServer anti-affinity (same-PS replicas, cross-PS conflicts, and
193+
controller-PS port overlap) is managed separately by the controller reconciler
194+
at runtime, not by this helper.
195+
196+
When global.affinity is provided by the user:
197+
- podAntiAffinity fully replaces the auto-generated rule.
198+
- podAffinity and nodeAffinity are carried through unchanged.
199+
When hostNetwork is disabled, global.affinity is passed through as-is.
200+
*/}}
201+
{{- define "kubewarden-controller.effectiveAffinity" -}}
202+
{{- if .Values.hostNetwork -}}
203+
{{- $matchLabels := (include "kubewarden-controller.selectorLabels" . | fromYaml) -}}
204+
{{- $affinityTerm := dict "labelSelector" (dict "matchLabels" $matchLabels) "topologyKey" "kubernetes.io/hostname" -}}
205+
{{- $autoAntiAffinity := dict "requiredDuringSchedulingIgnoredDuringExecution" (list $affinityTerm) -}}
206+
{{- $affinity := dict "podAntiAffinity" $autoAntiAffinity -}}
207+
{{- if .Values.global.affinity -}}
208+
{{- if hasKey .Values.global.affinity "podAntiAffinity" -}}
209+
{{- $_ := set $affinity "podAntiAffinity" .Values.global.affinity.podAntiAffinity -}}
210+
{{- end -}}
211+
{{- if hasKey .Values.global.affinity "podAffinity" -}}
212+
{{- $_ := set $affinity "podAffinity" .Values.global.affinity.podAffinity -}}
213+
{{- end -}}
214+
{{- if hasKey .Values.global.affinity "nodeAffinity" -}}
215+
{{- $_ := set $affinity "nodeAffinity" .Values.global.affinity.nodeAffinity -}}
216+
{{- end -}}
217+
{{- end -}}
218+
{{- toYaml $affinity -}}
219+
{{- else if .Values.global.affinity -}}
220+
{{- toYaml .Values.global.affinity -}}
221+
{{- end -}}
222+
{{- end -}}

charts/kubewarden-controller/templates/deployment.yaml

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ spec:
3232
{{- include "imagePullSecrets" .Values.imagePullSecrets | nindent 8 }}
3333
{{- end }}
3434
serviceAccountName: {{ include "kubewarden-controller.serviceAccountName" . }}
35-
{{- if .Values.global.affinity }}
36-
affinity: {{ .Values.global.affinity | toYaml | nindent 8 }}
35+
{{- $effectiveAffinity := include "kubewarden-controller.effectiveAffinity" . }}
36+
{{- if $effectiveAffinity }}
37+
affinity: {{ $effectiveAffinity | nindent 8 }}
3738
{{- end }}
3839
{{- if .Values.global.tolerations }}
3940
tolerations: {{ .Values.global.tolerations | toYaml | nindent 8 }}
@@ -45,12 +46,19 @@ spec:
4546
{{- if .Values.global.priorityClassName }}
4647
priorityClassName: {{ .Values.global.priorityClassName | toYaml | nindent 8 }}
4748
{{- end }}
49+
{{- if .Values.hostNetwork }}
50+
hostNetwork: true
51+
dnsPolicy: ClusterFirstWithHostNet
52+
{{- end }}
4853
containers:
4954
- name: controller
5055
args:
5156
- --leader-elect
5257
- --deployments-namespace={{ .Release.Namespace }}
5358
- --webhook-service-name={{ include "kubewarden-controller.fullname" . }}-webhook-service
59+
- --webhook-server-port={{ .Values.ports.webhook }}
60+
- --health-probe-bind-address=:{{ .Values.ports.healthProbe }}
61+
- --metrics-bind-address=:{{ .Values.ports.metrics }}
5462
{{- if .Values.alwaysAcceptAdmissionReviewsOnDeploymentsNamespace }}
5563
- --always-accept-admission-reviews-on-deployments-namespace
5664
{{- end }}
@@ -62,6 +70,9 @@ spec:
6270
{{- if $imagePullSecretNames }}
6371
- --image-pull-secrets={{ $imagePullSecretNames }}
6472
{{- end }}
73+
{{- if .Values.hostNetwork }}
74+
- --host-network
75+
{{- end }}
6576
{{- if or .Values.telemetry.metrics .Values.telemetry.tracing }}
6677
{{- if eq .Values.telemetry.mode "sidecar" }}
6778
- --enable-otel-sidecar
@@ -117,13 +128,13 @@ spec:
117128
livenessProbe:
118129
httpGet:
119130
path: /healthz
120-
port: 8081
131+
port: {{ .Values.ports.healthProbe }}
121132
initialDelaySeconds: 15
122133
periodSeconds: 20
123134
readinessProbe:
124135
httpGet:
125136
path: /readyz
126-
port: 8081
137+
port: {{ .Values.ports.healthProbe }}
127138
initialDelaySeconds: 5
128139
periodSeconds: 10
129140
{{- if and .Values.resources .Values.resources.controller }}
@@ -154,7 +165,7 @@ spec:
154165
readOnly: true
155166
{{- end }}
156167
ports:
157-
- containerPort: 9443
168+
- containerPort: {{ .Values.ports.webhook }}
158169
name: webhook-server
159170
protocol: TCP
160171
volumes:

charts/kubewarden-controller/templates/service.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ spec:
1313
{{- if .Values.telemetry.metrics }}
1414
- name: metrics
1515
port: 8080
16-
targetPort: 8080
16+
targetPort: {{ .Values.ports.metrics }}
1717
{{- end}}
1818
- name: https
1919
port: 8443
20-
targetPort: https
20+
targetPort: {{ .Values.ports.webhook }}
2121
selector:
2222
{{- include "kubewarden-controller.selectorLabels" . | nindent 4 }}
2323
---
@@ -33,6 +33,6 @@ metadata:
3333
spec:
3434
ports:
3535
- port: 443
36-
targetPort: 9443
36+
targetPort: {{ .Values.ports.webhook }}
3737
selector:
3838
{{- include "kubewarden-controller.selectorLabels" . | nindent 4 }}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
suite: host-network configuration
2+
templates:
3+
- deployment.yaml
4+
tests:
5+
- it: "should not set hostNetwork and should not pass --host-network flag by default"
6+
asserts:
7+
- notExists:
8+
path: spec.template.spec.hostNetwork
9+
- notExists:
10+
path: spec.template.spec.dnsPolicy
11+
- notContains:
12+
path: spec.template.spec.containers[0].args
13+
content: "--host-network"
14+
any: true
15+
16+
- it: "should set hostNetwork, dnsPolicy and pass --host-network flag when hostNetwork is true"
17+
set:
18+
hostNetwork: true
19+
asserts:
20+
- equal:
21+
path: spec.template.spec.hostNetwork
22+
value: true
23+
- equal:
24+
path: spec.template.spec.dnsPolicy
25+
value: ClusterFirstWithHostNet
26+
- contains:
27+
path: spec.template.spec.containers[0].args
28+
content: "--host-network"
29+
30+
- it: "should inject required podAntiAffinity using controller selector labels when hostNetwork is true"
31+
set:
32+
hostNetwork: true
33+
asserts:
34+
- equal:
35+
path: spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[0].topologyKey
36+
value: kubernetes.io/hostname
37+
- equal:
38+
path: spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[0].labelSelector.matchLabels["app.kubernetes.io/name"]
39+
value: kubewarden-controller
40+
- exists:
41+
path: spec.template.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[0].labelSelector.matchLabels["app.kubernetes.io/instance"]
42+
43+
- it: "should not inject podAntiAffinity when hostNetwork is false and no affinity is set"
44+
asserts:
45+
- notExists:
46+
path: spec.template.spec.affinity
47+
48+
- it: "should use custom ports when overridden in values"
49+
set:
50+
ports.webhook: 10443
51+
ports.healthProbe: 10081
52+
ports.metrics: 10088
53+
asserts:
54+
- equal:
55+
path: spec.template.spec.containers[0].ports[0].containerPort
56+
value: 10443
57+
- equal:
58+
path: spec.template.spec.containers[0].livenessProbe.httpGet.port
59+
value: 10081
60+
- equal:
61+
path: spec.template.spec.containers[0].readinessProbe.httpGet.port
62+
value: 10081
63+
- contains:
64+
path: spec.template.spec.containers[0].args
65+
content:
66+
--webhook-server-port=10443
67+
- contains:
68+
path: spec.template.spec.containers[0].args
69+
content:
70+
--health-probe-bind-address=:10081
71+
- contains:
72+
path: spec.template.spec.containers[0].args
73+
content:
74+
--metrics-bind-address=:10088
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
suite: service ports configuration
2+
templates:
3+
- service.yaml
4+
tests:
5+
- it: "should use default ports in services"
6+
set:
7+
telemetry.metrics: true
8+
asserts:
9+
# Webhook service
10+
- equal:
11+
path: spec.ports[0].port
12+
value: 443
13+
documentIndex: 1
14+
- equal:
15+
path: spec.ports[0].targetPort
16+
value: 9443
17+
documentIndex: 1
18+
# Metrics service - metrics port
19+
- equal:
20+
path: spec.ports[0].port
21+
value: 8080
22+
documentIndex: 0
23+
- equal:
24+
path: spec.ports[0].targetPort
25+
value: 8088
26+
documentIndex: 0
27+
# Metrics service - https port
28+
- equal:
29+
path: spec.ports[1].port
30+
value: 8443
31+
documentIndex: 0
32+
- equal:
33+
path: spec.ports[1].targetPort
34+
value: 9443
35+
documentIndex: 0
36+
37+
- it: "should use custom webhook port in both webhook and metrics services"
38+
set:
39+
ports.webhook: 10443
40+
telemetry.metrics: true
41+
asserts:
42+
# Webhook service
43+
- equal:
44+
path: spec.ports[0].targetPort
45+
value: 10443
46+
documentIndex: 1
47+
# Metrics service - https port
48+
- equal:
49+
path: spec.ports[1].targetPort
50+
value: 10443
51+
documentIndex: 0
52+
53+
- it: "should use custom metrics port in metrics service"
54+
set:
55+
ports.metrics: 10088
56+
telemetry.metrics: true
57+
asserts:
58+
# Metrics service - metrics port
59+
- equal:
60+
path: spec.ports[0].targetPort
61+
value: 10088
62+
documentIndex: 0
63+
64+
- it: "should not include metrics port when telemetry is disabled"
65+
set:
66+
telemetry.metrics: false
67+
asserts:
68+
- equal:
69+
path: spec.ports[0].name
70+
value: https
71+
documentIndex: 0
72+
- equal:
73+
path: spec.ports[0].port
74+
value: 8443
75+
documentIndex: 0

charts/kubewarden-controller/values.schema.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,34 @@
108108
"fullnameOverride": {
109109
"type": "string"
110110
},
111+
"hostNetwork": {
112+
"type": "boolean",
113+
"description": "Enables host network mode for the controller pod and all PolicyServer pods. WARNING: increases attack surface."
114+
},
115+
"ports": {
116+
"type": "object",
117+
"description": "Network ports used by the controller pod. Override these when hostNetwork is enabled to avoid conflicts with other workloads.",
118+
"properties": {
119+
"webhook": {
120+
"type": "integer",
121+
"minimum": 1,
122+
"maximum": 65535,
123+
"description": "Port the controller webhook server listens on."
124+
},
125+
"healthProbe": {
126+
"type": "integer",
127+
"minimum": 1,
128+
"maximum": 65535,
129+
"description": "Port for liveness and readiness probes."
130+
},
131+
"metrics": {
132+
"type": "integer",
133+
"minimum": 1,
134+
"maximum": 65535,
135+
"description": "Port for the Prometheus metrics endpoint."
136+
}
137+
}
138+
},
111139
"global": {
112140
"type": "object",
113141
"properties": {

charts/kubewarden-controller/values.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,23 @@ preDeleteHook:
151151
# evaluations that could interfere with the Kubewarden stack running in the
152152
# admission controller namespace.
153153
alwaysAcceptAdmissionReviewsOnDeploymentsNamespace: true
154+
# hostNetwork enables host network mode for the controller pod and all
155+
# PolicyServer pods managed by this controller.
156+
# WARNING: enabling this increases the attack surface by exposing webhook
157+
# endpoints on the host network and giving pods visibility of all node network
158+
# interfaces. Use only when the Kubernetes API server cannot reach pod-network
159+
# webhook endpoints (e.g. clusters using a non-VPC CNI with NAT).
160+
hostNetwork: false
161+
# ports configures the network ports used by the controller pod.
162+
# These are especially important when hostNetwork is enabled, because each port
163+
# is bound on the host network interface and must not clash with other workloads.
164+
ports:
165+
# Port the controller webhook server listens on.
166+
webhook: 9443
167+
# Port for the controller liveness and readiness probes.
168+
healthProbe: 8081
169+
# Port for the controller Prometheus metrics endpoint.
170+
metrics: 8088
154171
# Verbosity of logging. Can be one of 'debug', 'info', 'error'.
155172
logLevel: info
156173
# open-telemetry options

charts/kubewarden-defaults/templates/policyserver-default.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,13 @@ spec:
7777
{{- if .Values.policyServer.securityContexts }}
7878
securityContexts: {{ toYaml .Values.policyServer.securityContexts | nindent 4 }}
7979
{{- end }}
80+
{{- if .Values.policyServer.webhookPort }}
81+
webhookPort: {{ .Values.policyServer.webhookPort }}
82+
{{- end }}
83+
{{- if .Values.policyServer.readinessProbePort }}
84+
readinessProbePort: {{ .Values.policyServer.readinessProbePort }}
85+
{{- end }}
86+
{{- if .Values.policyServer.metricsPort }}
87+
metricsPort: {{ .Values.policyServer.metricsPort }}
88+
{{- end }}
8089
{{- end }}

0 commit comments

Comments
 (0)