Skip to content

Commit c4688aa

Browse files
authored
feat(helm): add certificate hook pod labels and annotations (#4895)
Signed-off-by: Brooke Storm <brookes@nvidia.com>
1 parent f571c8e commit c4688aa

7 files changed

Lines changed: 138 additions & 2 deletions

File tree

‎deploy/helm/openshell/README.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,23 @@ namespace. The gateway and workspace releases can then be upgraded and removed
1717
independently. Use Kubernetes `operator` workspace mode when one gateway serves
1818
multiple pre-provisioned workspace namespaces.
1919

20+
## Certificate hook metadata
21+
22+
Use `pkiInitJob.podLabels` and `pkiInitJob.podAnnotations` to add metadata to the
23+
Pod templates of the `<fullname>-certgen` and `<fullname>-certgen-backend-ca`
24+
Jobs. These settings apply to both hooks when enabled and do not affect gateway
25+
or sandbox Pods. Chart-owned Pod labels take precedence when custom keys
26+
conflict.
27+
28+
For example, disable Istio sidecar injection for the hook Pods in an injected
29+
namespace:
30+
31+
```yaml
32+
pkiInitJob:
33+
podAnnotations:
34+
sidecar.istio.io/inject: "false"
35+
```
36+
2037
## Cluster-scoped vs namespaced objects
2138
2239
Most objects in this chart are namespaced and land in the release namespace.
@@ -450,6 +467,8 @@ discovery endpoint or its TLS CA.
450467
| openshiftRoute.host | string | `""` | Hostname for the Route. Must match a SAN on the gateway's server cert. |
451468
| pkiInitJob.enabled | bool | `true` | Run a pre-install/pre-upgrade Job that creates gateway and client mTLS Secrets. When certManager.enabled=true, cert-manager owns TLS and this same hook runs in JWT-only mode even if pkiInitJob.enabled remains true. |
452469
| pkiInitJob.failOnTimeout | bool | `true` | Fail the helm install/upgrade if cert-manager does not issue the certificate within the polling timeout. When true (default), the install fails immediately if the timeout is reached, providing clear feedback that BackendTLSPolicy is non-functional. When false, the hook succeeds with a warning and you can run `helm upgrade` after cert-manager issues the certificate to create the backend CA ConfigMap. If you set this to false and see "TLS error: Secret is not supplied by SDS" when connecting to the gateway, check if the TLS secret exists and run `helm upgrade` to create the ConfigMap. |
470+
| pkiInitJob.podAnnotations | object | `{}` | Additional annotations on both certificate hook Pods. |
471+
| pkiInitJob.podLabels | object | `{}` | Additional labels on both certificate hook Pods. Chart-owned labels take precedence. |
453472
| pkiInitJob.securityContext.allowPrivilegeEscalation | bool | `false` | Whether the certgen hook container can gain additional privileges. |
454473
| pkiInitJob.securityContext.capabilities.drop | list | `["ALL"]` | Linux capabilities dropped from the certgen hook container. |
455474
| pkiInitJob.securityContext.runAsNonRoot | bool | `true` | Require the certgen hook container to run as a non-root user. |

‎deploy/helm/openshell/README.md.gotmpl‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,23 @@ namespace. The gateway and workspace releases can then be upgraded and removed
1717
independently. Use Kubernetes `operator` workspace mode when one gateway serves
1818
multiple pre-provisioned workspace namespaces.
1919

20+
## Certificate hook metadata
21+
22+
Use `pkiInitJob.podLabels` and `pkiInitJob.podAnnotations` to add metadata to the
23+
Pod templates of the `<fullname>-certgen` and `<fullname>-certgen-backend-ca`
24+
Jobs. These settings apply to both hooks when enabled and do not affect gateway
25+
or sandbox Pods. Chart-owned Pod labels take precedence when custom keys
26+
conflict.
27+
28+
For example, disable Istio sidecar injection for the hook Pods in an injected
29+
namespace:
30+
31+
```yaml
32+
pkiInitJob:
33+
podAnnotations:
34+
sidecar.istio.io/inject: "false"
35+
```
36+
2037
## Cluster-scoped vs namespaced objects
2138

2239
Most objects in this chart are namespaced and land in the release namespace.

‎deploy/helm/openshell/templates/certgen.yaml‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
{{- if or .Values.pkiInitJob.enabled .Values.certManager.enabled }}
55
{{- $hookName := printf "%s-certgen" (include "openshell.fullname" .) }}
66
{{- $ns := .Release.Namespace }}
7+
{{- $podLabels := merge (include "openshell.certgenPodLabels" . | fromYaml) (.Values.pkiInitJob.podLabels | default dict) }}
78
apiVersion: v1
89
kind: ServiceAccount
910
metadata:
@@ -75,7 +76,11 @@ spec:
7576
template:
7677
metadata:
7778
labels:
78-
{{- include "openshell.certgenPodLabels" . | nindent 8 }}
79+
{{- toYaml $podLabels | nindent 8 }}
80+
{{- with .Values.pkiInitJob.podAnnotations }}
81+
annotations:
82+
{{- toYaml . | nindent 8 }}
83+
{{- end }}
7984
spec:
8085
restartPolicy: OnFailure
8186
serviceAccountName: {{ $hookName }}
@@ -143,7 +148,11 @@ spec:
143148
template:
144149
metadata:
145150
labels:
146-
{{- include "openshell.certgenPodLabels" . | nindent 8 }}
151+
{{- toYaml $podLabels | nindent 8 }}
152+
{{- with .Values.pkiInitJob.podAnnotations }}
153+
annotations:
154+
{{- toYaml . | nindent 8 }}
155+
{{- end }}
147156
spec:
148157
restartPolicy: OnFailure
149158
serviceAccountName: {{ $hookName }}

‎deploy/helm/openshell/tests/certgen_test.yaml‎

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,77 @@ tests:
192192
app.kubernetes.io/instance: openshell
193193
app.kubernetes.io/component: certgen
194194
documentIndex: 4
195+
196+
- it: adds configured metadata to both certificate hook Pod templates
197+
template: templates/certgen.yaml
198+
set:
199+
certManager.enabled: true
200+
grpcRoute.backendTLSPolicy.enabled: true
201+
pkiInitJob.podLabels:
202+
example.com/workload: certificate-bootstrap
203+
pkiInitJob.podAnnotations:
204+
sidecar.istio.io/inject: "false"
205+
asserts:
206+
- equal:
207+
path: spec.template.metadata.labels["example.com/workload"]
208+
value: certificate-bootstrap
209+
documentIndex: 3
210+
- equal:
211+
path: spec.template.metadata.annotations["sidecar.istio.io/inject"]
212+
value: "false"
213+
documentIndex: 3
214+
- notExists:
215+
path: metadata.labels["example.com/workload"]
216+
documentIndex: 3
217+
- notExists:
218+
path: metadata.annotations["sidecar.istio.io/inject"]
219+
documentIndex: 3
220+
- equal:
221+
path: spec.template.metadata.labels["example.com/workload"]
222+
value: certificate-bootstrap
223+
documentIndex: 4
224+
- equal:
225+
path: spec.template.metadata.annotations["sidecar.istio.io/inject"]
226+
value: "false"
227+
documentIndex: 4
228+
- notExists:
229+
path: metadata.labels["example.com/workload"]
230+
documentIndex: 4
231+
- notExists:
232+
path: metadata.annotations["sidecar.istio.io/inject"]
233+
documentIndex: 4
234+
235+
- it: preserves chart-owned Pod labels when custom keys conflict
236+
template: templates/certgen.yaml
237+
set:
238+
certManager.enabled: true
239+
grpcRoute.backendTLSPolicy.enabled: true
240+
pkiInitJob.podLabels:
241+
app.kubernetes.io/name: openshell
242+
app.kubernetes.io/instance: custom-release
243+
app.kubernetes.io/component: gateway
244+
asserts:
245+
- equal:
246+
path: spec.template.metadata.labels["app.kubernetes.io/name"]
247+
value: openshell-certgen
248+
documentIndex: 3
249+
- equal:
250+
path: spec.template.metadata.labels["app.kubernetes.io/instance"]
251+
value: openshell
252+
documentIndex: 3
253+
- equal:
254+
path: spec.template.metadata.labels["app.kubernetes.io/component"]
255+
value: certgen
256+
documentIndex: 3
257+
- equal:
258+
path: spec.template.metadata.labels["app.kubernetes.io/name"]
259+
value: openshell-certgen
260+
documentIndex: 4
261+
- equal:
262+
path: spec.template.metadata.labels["app.kubernetes.io/instance"]
263+
value: openshell
264+
documentIndex: 4
265+
- equal:
266+
path: spec.template.metadata.labels["app.kubernetes.io/component"]
267+
value: certgen
268+
documentIndex: 4

‎deploy/helm/openshell/values.yaml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,10 @@ pkiInitJob:
661661
# Secrets. When certManager.enabled=true, cert-manager owns TLS and this same
662662
# hook runs in JWT-only mode even if pkiInitJob.enabled remains true.
663663
enabled: true
664+
# -- Additional labels on both certificate hook Pods. Chart-owned labels take precedence.
665+
podLabels: {}
666+
# -- Additional annotations on both certificate hook Pods.
667+
podAnnotations: {}
664668
# -- Extra DNS SANs to append to the server certificate.
665669
serverDnsNames: []
666670
# -- Extra IP SANs to append to the server certificate.

‎docs/kubernetes/setup.mdx‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,18 @@ helm upgrade --install openshell \
118118

119119
The chart automatically generates PKI secrets on first install using pre-install Helm hooks. No manual secret creation is required.
120120

121+
To add labels or annotations to both certificate hook Pod templates, use
122+
`pkiInitJob.podLabels` and `pkiInitJob.podAnnotations`. Chart-owned Pod labels
123+
take precedence when custom keys conflict.
124+
For example, disable sidecar injection for hook Pods in an Istio-injected
125+
namespace:
126+
127+
```yaml
128+
pkiInitJob:
129+
podAnnotations:
130+
sidecar.istio.io/inject: "false"
131+
```
132+
121133
The default Kubernetes driver puts all workspaces in one sandbox namespace. To
122134
have the gateway create a namespace for each workspace, follow
123135
[Workspace on Kubernetes](/kubernetes/workspaces).

‎skills/debug-openshell-cluster/SKILL.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,7 @@ credential failures.
12791279
| `helm upgrade` fails with an `autoscaling.*` message | HPA values invalid: missing `resources.requests` (or `resources.limits`), `maxReplicas` above 1 without `server.externalDbSecret` (or on a StatefulSet without `workload.allowMultiReplicaStatefulSet`), no metric target, or min/max out of order. "`minReplicas` and `maxReplicas` are not set" means `--reuse-values` kept a release without the chart's autoscaling defaults | Fix the values named in the error; upgrade with `--reset-then-reuse-values` instead of `--reuse-values` |
12801280
| HPA shows `<unknown>` targets | No metrics-server for CPU/memory, or the metrics adapter does not serve the custom metric | `kubectl -n openshell describe hpa openshell`, `kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1` |
12811281
| One replica holds most sessions after a rollout | Expected: sessions stay where they reconnected | `openshell_server_supervisor_sessions` per pod; it fades as sandboxes are recreated |
1282+
| Certificate hook Job stays active after `certgen` exits successfully | An injected sidecar is still running in the hook Pod | Inspect all container statuses. Configure `pkiInitJob.podLabels` or `pkiInitJob.podAnnotations` as required by the injector, then retry the Helm install or upgrade to recreate the hook Pods |
12821283
| Gateway or `<release>-certgen` hook pod rejected with `violates PodSecurity "restricted:latest"` | The rendered container lacks `runAsNonRoot` or `seccompProfile`: an older chart version does not set them, or an override in `securityContext` / `pkiInitJob.securityContext` unset them | `kubectl -n openshell get events --field-selector reason=FailedCreate`; upgrade the chart, then remove overrides that unset those fields |
12831284
| OpenShift gateway pod fails to start with an SCC/`runAsUser` error (e.g. `unable to validate against any security context constraint`) | Chart's default `podSecurityContext`/`securityContext` hardcodes `runAsUser`/`fsGroup`, which the restricted-v2 SCC rejects; it must instead inject the namespace-assigned UID/GID range | `oc -n openshell describe pod <pod>`; deploy with `podSecurityContext: null` and clear `securityContext.runAsUser` (see `deploy/helm/openshell/ci/values-openshift-scc.yaml`) |
12841285
| OpenShift `<release>-supervisor` Deployment never creates pods after setting `supervisor_topology = "gateway"` (SCC `runAsUser`/`fsGroup` not in the namespace range) | `supervisor.podSecurityContext` defaults `runAsUser`, `runAsGroup`, and `fsGroup` to 65534, outside the namespace's assigned UID/GID ranges | `kubectl -n openshell get events --field-selector reason=FailedCreate`; compare with the `openshift.io/sa.scc.*` annotations from `oc describe ns openshell`; set `supervisor.podSecurityContext.runAsUser`, `.runAsGroup`, and `.fsGroup` to `null`, as `deploy/helm/openshell/ci/values-openshift-scc.yaml` does, and keep `runAsNonRoot` and `seccompProfile` |

0 commit comments

Comments
 (0)