What happened
The Helm hook Job created by hook.upgradeCrd cannot be scheduled in a namespace that enforces the restricted Pod Security Standard, so the CustomResourceDefinition upgrade never runs there. There is no chart value that can fix it.
Details
charts/spark-operator-chart/templates/hook/job.yaml sets a container security context:
securityContext:
readOnlyRootFilesystem: true
privileged: false
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
The restricted profile additionally requires runAsNonRoot: true and a seccompProfile. Neither is set, there is no pod-level securityContext, and the hook: values block exposes only upgradeCrd, image, nodeSelector, affinity and tolerations — so an operator cannot supply them either.
The controller and webhook are unaffected: controller.podSecurityContext, controller.securityContext, webhook.podSecurityContext and webhook.securityContext all exist. The hook Job appears to be the one component that was missed.
Reproduction
kubectl create namespace spark-operator
kubectl label namespace spark-operator \
pod-security.kubernetes.io/enforce=restricted
helm upgrade --install spark-operator spark-operator/spark-operator \
--namespace spark-operator \
--set hook.upgradeCrd=true
The hook pod is rejected by admission, so helm upgrade does not complete.
A complication worth flagging
docker/Dockerfile.kubectl builds from alpine and sets no USER, so the image runs as UID 0. Adding runAsNonRoot: true alone would therefore make the pod fail to start with "container has runAsNonRoot and image will run as root". A fix needs a runAsUser as well, or a USER line in the Dockerfile.
Setting runAsUser in the chart looks viable — kubectl does not need root, readOnlyRootFilesystem is already enabled, and the service account token is world-readable — but it should be verified on a cluster rather than assumed.
Proposed change
Add hook.podSecurityContext and hook.securityContext values, wired into templates/hook/job.yaml with the same with pattern used by the controller and webhook templates.
One decision worth your input before I send a pull request:
- Restricted-compliant defaults — the hook works out of the box on hardened clusters, at the cost of changing current rendering.
- Empty
{} defaults — no behaviour change, and each operator opts in.
I lean towards the first, since the container already drops all capabilities and disallows privilege escalation, but it is your call.
Context
The Kubeflow Community Distribution is adding a Helm chart that wraps this one (kubeflow/community-distribution#3575). It ships with hook.upgradeCrd: false and documents that the definitions are not upgraded by helm upgrade, because the hook cannot run in the kubeflow namespace.
Happy to send the pull request, including helm-unittest coverage in tests/hook/job_test.yaml and a regenerated README.md, once you have indicated which default you prefer.
What happened
The Helm hook Job created by
hook.upgradeCrdcannot be scheduled in a namespace that enforces therestrictedPod Security Standard, so the CustomResourceDefinition upgrade never runs there. There is no chart value that can fix it.Details
charts/spark-operator-chart/templates/hook/job.yamlsets a container security context:The
restrictedprofile additionally requiresrunAsNonRoot: trueand aseccompProfile. Neither is set, there is no pod-levelsecurityContext, and thehook:values block exposes onlyupgradeCrd,image,nodeSelector,affinityandtolerations— so an operator cannot supply them either.The controller and webhook are unaffected:
controller.podSecurityContext,controller.securityContext,webhook.podSecurityContextandwebhook.securityContextall exist. The hook Job appears to be the one component that was missed.Reproduction
The hook pod is rejected by admission, so
helm upgradedoes not complete.A complication worth flagging
docker/Dockerfile.kubectlbuilds fromalpineand sets noUSER, so the image runs as UID 0. AddingrunAsNonRoot: truealone would therefore make the pod fail to start with "container has runAsNonRoot and image will run as root". A fix needs arunAsUseras well, or aUSERline in the Dockerfile.Setting
runAsUserin the chart looks viable —kubectldoes not need root,readOnlyRootFilesystemis already enabled, and the service account token is world-readable — but it should be verified on a cluster rather than assumed.Proposed change
Add
hook.podSecurityContextandhook.securityContextvalues, wired intotemplates/hook/job.yamlwith the samewithpattern used by the controller and webhook templates.One decision worth your input before I send a pull request:
{}defaults — no behaviour change, and each operator opts in.I lean towards the first, since the container already drops all capabilities and disallows privilege escalation, but it is your call.
Context
The Kubeflow Community Distribution is adding a Helm chart that wraps this one (kubeflow/community-distribution#3575). It ships with
hook.upgradeCrd: falseand documents that the definitions are not upgraded byhelm upgrade, because the hook cannot run in thekubeflownamespace.Happy to send the pull request, including helm-unittest coverage in
tests/hook/job_test.yamland a regeneratedREADME.md, once you have indicated which default you prefer.