Repository navigation
feat(charts,ci): every chart passes Pod Security restricted by default, and CI checks it - #447
Merged
Merged
Conversation
…t, and CI checks it
Phase 3 (chart side) of the "Kates on any cluster" plan, decision D1: chart
defaults pass PSS restricted, a CPU and memory requests plus memory limit
policy, and an image tag policy, with no separate profile file.
Every chart's pods, Helm test pods, hooks and jobs included, get a
RuntimeDefault seccomp profile, a non-root user their image runs as, no
privilege escalation, every capability dropped, and requests with a memory
limit. The Strimzi CR charts write the same settings into the pod templates
the operator fills, so the pods pass on a shared operator; strimzi-operator
also runs Strimzi's restricted pod security provider. A podLabels value
reaches every pod each chart renders (the chart's labels win a clash), and
global.imageRegistry and the pull-secret values reach every image and pod,
pull secrets as plain names or {name: ...}.
The kates and kates-chaos charts take kyvernoPolicy.exceptions, rendered as a
PolicyException in the release namespace; their ClusterPolicies render nothing
under rbac.scope=namespace. CPU_STRESS and IO_STRESS run a pinned,
configurable image (kates.chaos.stress-image, chaos.stressImage) as the
target's own user, else 65534, under a restricted security context.
scripts/check-chart-policies.sh renders every chart with defaults and with
optional workloads on, and runs four sample policies from .github/kyverno/
(restricted, requests and limits, image tag, a team label on every pod) with
named exceptions for the host-level node-exporter and Velero node agent and
for the Litmus operator, whose subchart takes no security context. It
replaces the Kyverno CI job, which matched nothing.
Workloads that cannot pass are documented with their switches: node-exporter,
Velero's node agent and label-namespace Job, the Litmus operator and
exporter, SeaweedFS with the values the chart ships, and its bucket hook.
…has the shell they need The GameDay Job and both helm test pods ran their checks with sh in registry.k8s.io/kubectl, which has no shell, so they ended in StartError and helm test and gameday.enabled always failed. They now run images.tester, ghcr.io/bmscomp/kates-tester:1.28.0, as its own uid and gid 1000, and scripts/check-versions.sh holds that pin to the kates appVersion like the Strimzi charts' test images. images.kubectl is the installer Job's image only.
…nstalls Kyverno Policy Validation failed on the three workloads with a named PolicyException (the Litmus operator, node-exporter, Velero's node agent): CLI v1.13.0 ignores the podSecurity controls those exceptions lift, so they failed pss-restricted anyway. v1.16.4, the version of the kyverno chart 3.6.4 that kates deploy installs, applies them: every chart passes. On it, kyverno apply -o writes one file per mutated resource into a directory, so the own-policies step gives it one.
This was referenced Oct 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
This is Phase 3 (chart side) of the "Kates on any cluster" plan, decision D1: chart defaults should pass a Kyverno-governed cluster's usual policies, with no separate profile to pick.
Measured on
main, every chart failed somewhere. Most failures were helm test pods with no resources or seccomp profile; the rest were the kafka-ui Deployment, PostgreSQL's seccomp profile, the kates init container, the chaos experiments Job, and the monitoring subcharts' resources. The repository's Kyverno CI job couldn't catch any of this: it applied the kates policies to a manifest in another namespace, so nothing ever matched.What changes
Restricted by default. Every pod each chart renders, including helm test pods, hooks and jobs, now gets:
RuntimeDefaultseccomp profile and a non-root user its image runs as;allowPrivilegeEscalation: falseanddrop: [ALL];These are all values, under each chart's existing names.
Strimzi-managed pods:
strimzi-operatorturns on Strimzi's restricted pod security provider. This is a minor bump, because every operand rolls once.podLabelsreaches every pod each chart renders; the chart's own labels win a clash. Where a subchart has its own key, the chart documents it, as on the monitoring and Litmus subcharts.Registry and pull secrets.
global.imageRegistryand the pull-secret values reach every image and pod. Pull secrets are accepted as plain names or as{name: …}.Policy exceptions.
kyvernoPolicy.exceptionsonkatesandkates-chaosrenders a PolicyException in the release namespace; onkates-chaosit is narrowed to the Litmus pods. The charts' own ClusterPolicies render nothing underrbac.scope=namespace.Chaos stress.
CPU_STRESSandIO_STRESSnow:kates.chaos.stress-image, set by the chart'schaos.stressImage, defaultdocker.io/polinux/stress:1.0.4;CI.
scripts/check-chart-policies.shreplaces the Kyverno job, which never matched anything. It renders every chart with defaults and with its optional workloads on, and checks every render against four sample policies in.github/kyverno/policies/, including ateamlabel on every pod. It fails on any violation, and on a render the policies don't match at all. The only exceptions are named files: the host-level node-exporter, the Velero node agent, and the Litmus operator and exporter, whose subchart has no security-context value. CI's Kyverno CLI moves from v1.13.0 to v1.16.4 (third commit), the version of the Kyverno thatkates deployinstalls. v1.13.0 ignores the Pod Security controls those exceptions lift, so the job failed on exactly those three workloads.Can't pass, and documented with their switches:
The book also gives the SeaweedFS subchart values that do pass, for a new install.
Versions. Each chart is bumped past v1.28.0 with a changes entry: kafka-cluster 1.0.12, connect-cluster 2.1.10, mirror-maker2 0.11.8, kafka-common 0.1.1, kates 0.13.0, kates-chaos 2.3.0, strimzi-operator 0.4.0, monitoring 1.7.0, kates-platform 0.8.3, apicurio-registry 0.4.1, kafka-ui 0.3.1, headlamp 0.2.1, legacy-kafka 0.2.1 and velero 11.3.4. kates-platform's subchart floors move to these versions, and its entry says ACTION REQUIRED:
make platform-chart-deps.kates-chaos GameDay and Helm tests (second commit). They ran
shinregistry.k8s.io/kubectl, which has no shell, so they ended inStartErrorandhelm testandgameday.enabledalways failed. This bug was already onmain. They now runimages.tester,ghcr.io/bmscomp/kates-tester:1.28.0, as its uid and gid 1000.scripts/check-versions.shholds that pin to the kates appVersion, so the release pin PR moves it with the others.Book: 17-security (what each chart sets, what can't pass, the check), 20-installation-guide, appendix C (the CI job), and appendices A, B and D. Two MCP caveat refs into
charts/kates/values.yamlare re-pointed, plus one into monitoring'sChart.yaml.Behaviour changes for existing users
runAsNonRoot(kates-chaos 2.3.0, among others).global.imageRegistryon kates. It is now put in front of every image the kates chart names, so an image value that already names the mirror gets it twice (kates 0.13.0).How it was built and checked
scripts/check-chart-policies.sh: 13 charts pass, 0 fail.helm linton every chart, and kates-platform's render with the new floors.gen-chart-table.sh --check,gen-version-matrix.sh --check,check-versions.sh.ci.yml.go test ./cmd(caveat refs), andgolangci-lint --new-from-revwith 0 issues.KubernetesChaosProviderTestwith Spotless.kind-panda, in a scratch namespace labelledpod-security.kubernetes.io/enforce=restricted:rbac.scope=namespace) was admitted, and PostgreSQL ran Ready.main's chart restarts the same way in an unlabelled namespace, with the same messaging error in the logs.Forbiddenfor the default service account).Not done
helm unittest, because the plugin isn't installed here; CI runs it for kafka-cluster.kates preflightthat reads installed Kyverno policies, and restricted CLI diagnostic pods) and feeding.labelsintopodLabelscome next.