You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Refresh stale Kyverno reports after policy exemptions #3155
The production PolicyReport for Deployment kube-system/cluster-autoscaler-hetzner-cluster-autoscaler still records a validate-replica-floor/require-replica-floor failure even though live ClusterPolicy generation 17 explicitly exempts that stable workload name. The stale result keeps the platform compliance aggregate at fail: 1 and makes the zero-and-hold signal inaccurate.
Steps to Reproduce
Aggregate policyreports.wgpolicyk8s.io and clusterpolicyreports.wgpolicyk8s.io in production; observe 1 failure.
Read PolicyReport kube-system/64721e4c-c0f6-4fbd-9e63-9be4915a6645; its failing result predates the current policy and belongs to the cluster-autoscaler Deployment.
Read live ClusterPolicy validate-replica-floor; generation 17 includes cluster-autoscaler-hetzner-cluster-autoscaler in the stable AnyNotIn exemption.
Expected Behavior
A policy update that changes an existing workload result from fail to exempt refreshes the background report to skip, and the aggregate returns to zero failures.
Actual Behavior
The old failure remains in the report after the exemption is live and Ready, so Policy Reporter continues to expose a false current violation.
Workload: 1 available replica with a maxUnavailable: 1 PDB; intentionally singleton
Additional Context
Acceptance requires a declarative refresh or reconciliation path, a regression guard proving an exemption change supersedes the prior fail result, and a live read-back showing the policy-report aggregate at zero failures. Do not clear the signal by deleting reports manually or weakening the policy.
#2985 - fix(k8s): gate deploy health on a serving CNPG cluster instead of a fully-ready one [merged] #3037 - fix(cilium): refuse a zero-count gate release and correct the runbook order [merged] #3109 - fix(deploy): avoid redundant GHCR node reboots [merged]
📝 Issue Planner
Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.
Create Plan
🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your .coderabbit.yaml:
issue_enrichment:
auto_enrich:
enabled: false
💬 Have feedback or questions? Drop into our discord!
The read-only production aggregate still reports 1 fail, 0 warn across 685 policy reports. The sole failure remains validate-replica-floor/require-replica-floor; there are no non-ready nodes, Deployments, StatefulSets, or DaemonSets in the accompanying health snapshot.
This confirms the hard-zero signal is still blocked by the stale result described here, rather than by a current workload availability regression. No report was deleted or otherwise mutated. The issue remains actionable with its existing declarative-refresh acceptance criteria.
Read-only production recheck, 2026-09-27. The stale result is still there, and the cause is narrower than the exemption.
The exemption works. I exported the live validate-replica-floor ClusterPolicy (now generation 19) and the live cluster-autoscaler-hetzner-cluster-autoscaler Deployment, then ran kyverno apply 1.19.1 (the cluster's version) on them locally. The result was skip: 1, with no fail. So the policy no longer fails this workload.
The report has not been rewritten since June. Both of its results are from June: require-replica-floor fail at 2026-06-16T15:20Z and cap-workload-replicas pass at 2026-06-17T23:35Z. The policy has changed generation several times since then, and background scanning is on (--backgroundScan=true, --backgroundScanInterval=1h, 2 workers). A background scan would rewrite at least the timestamps, so this resource is not being re-scanned at all.
It is not only this report. Grouped by each report's newest result: 538 reports are under a day old, 75 are 1–7 days old, and 206 are more than 30 days old. Some of those may just hold unchanged results, but this one provably should have changed, so a stale aggregate is a real possibility beyond this single workload.
The platform-wide failure count is still 1: this result, and nothing current. The next step is to find out why the reports controller skips re-scanning this resource. Candidates are its per-resource policy-hash bookkeeping (ephemeral reports) and the controller's resource filters. Relevant to #3156, whose coverage gap may share this cause. Nothing was mutated or deleted.
Root cause found: nothing scans kube-system at all, so this report can never be rewritten.
The reports controller runs with --skipResourceFilters=false (fix(kyverno): curb reports-controller memory growth via resource filters #2134, merged 2026-06-17 23:12Z), so background scans honour Kyverno's resource filters, and the chart's defaults include [*/*,kube-system,*] (plus kube-public, kube-node-lease and kyverno). Those filters also apply at admission.
Read-only on prod: all 35 kube-system reports and all 29 kyverno-namespace reports have their newest result at 2026-06-17 23:35Z, the last scan before fix(kyverno): curb reports-controller memory growth via resource filters #2134 rolled out. 56 kube-system pods and one Deployment created since then have no report at all.
So the exemption was never the problem (it evaluates to skip locally, as noted above), and no scan interval will fix it.
#4227 adds a declarative prune for reports in those four namespaces once nothing has written to them for a day (a report that is written again is never touched), corrects the docs that said those reports are written at admission, and extends the kind proof to check that a kube-system resource gets no report before relying on it. Simulated against live reports: it removes exactly those 64 reports, including the platform's one failing result, and nothing else.
Restoring Kyverno coverage of the system namespaces is a separate decision, filed as #4228.
Correction to my comment above: the prune does not work, and #4227 no longer ships it.
The kind proof's positive control settled it. With the DeletingPolicy's namespace list extended to the test namespace, a day-old report there was deleted on the next run, while the identical report in kube-system survived five minutes of per-minute runs. Kyverno's cleanup controller skips the same resource-filtered namespaces as admission and background scans, so no Kyverno policy can clear these reports.
What remains true: the 64 reports in those namespaces are June snapshots, and this issue's failing result is one of them. Manual deletion is not a recovery mechanism here, so the result clears when Kyverno covers the namespace again, which is #4228's decision. #4227 now corrects the docs and adds the proof that a kube-system resource gets no report (#4229).
Activity
coderabbitai commentedon Aug 15, 2026
🔗 Related PRs
#2985 - fix(k8s): gate deploy health on a serving CNPG cluster instead of a fully-ready one [merged]
#3037 - fix(cilium): refuse a zero-count gate release and correct the runbook order [merged]
#3109 - fix(deploy): avoid redundant GHCR node reboots [merged]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
chore: agent-claim #3155 nonce=d6defbd0da2e25976969b9c0cd212818
devantler commentedon Aug 22, 2026
Production recheck — 2026-08-22
The read-only production aggregate still reports 1 fail, 0 warn across 685 policy reports. The sole failure remains
validate-replica-floor/require-replica-floor; there are no non-ready nodes, Deployments, StatefulSets, or DaemonSets in the accompanying health snapshot.This confirms the hard-zero signal is still blocked by the stale result described here, rather than by a current workload availability regression. No report was deleted or otherwise mutated. The issue remains actionable with its existing declarative-refresh acceptance criteria.
devantler commentedon Sep 27, 2026
Read-only production recheck, 2026-09-27. The stale result is still there, and the cause is narrower than the exemption.
validate-replica-floorClusterPolicy (now generation 19) and the livecluster-autoscaler-hetzner-cluster-autoscalerDeployment, then rankyverno apply1.19.1 (the cluster's version) on them locally. The result wasskip: 1, with no fail. So the policy no longer fails this workload.require-replica-floor failat 2026-06-16T15:20Z andcap-workload-replicas passat 2026-06-17T23:35Z. The policy has changed generation several times since then, and background scanning is on (--backgroundScan=true,--backgroundScanInterval=1h, 2 workers). A background scan would rewrite at least the timestamps, so this resource is not being re-scanned at all.The platform-wide failure count is still 1: this result, and nothing current. The next step is to find out why the reports controller skips re-scanning this resource. Candidates are its per-resource policy-hash bookkeeping (ephemeral reports) and the controller's resource filters. Relevant to #3156, whose coverage gap may share this cause. Nothing was mutated or deleted.
chore: agent-claim #3155 nonce=7802c84e01d58df46dba437db506c102
devantler commentedon Sep 27, 2026
Root cause found: nothing scans kube-system at all, so this report can never be rewritten.
--skipResourceFilters=false(fix(kyverno): curb reports-controller memory growth via resource filters #2134, merged 2026-06-17 23:12Z), so background scans honour Kyverno's resource filters, and the chart's defaults include[*/*,kube-system,*](plus kube-public, kube-node-lease and kyverno). Those filters also apply at admission.skiplocally, as noted above), and no scan interval will fix it.#4227 adds a declarative prune for reports in those four namespaces once nothing has written to them for a day (a report that is written again is never touched), corrects the docs that said those reports are written at admission, and extends the kind proof to check that a kube-system resource gets no report before relying on it. Simulated against live reports: it removes exactly those 64 reports, including the platform's one failing result, and nothing else.
Restoring Kyverno coverage of the system namespaces is a separate decision, filed as #4228.
devantler commentedon Sep 27, 2026
Correction to my comment above: the prune does not work, and #4227 no longer ships it.
The kind proof's positive control settled it. With the DeletingPolicy's namespace list extended to the test namespace, a day-old report there was deleted on the next run, while the identical report in kube-system survived five minutes of per-minute runs. Kyverno's cleanup controller skips the same resource-filtered namespaces as admission and background scans, so no Kyverno policy can clear these reports.
What remains true: the 64 reports in those namespaces are June snapshots, and this issue's failing result is one of them. Manual deletion is not a recovery mechanism here, so the result clears when Kyverno covers the namespace again, which is #4228's decision. #4227 now corrects the docs and adds the proof that a kube-system resource gets no report (#4229).
chore: agent-claim #3155 nonce=1c021b569868c39af03d013d132020b2
chore: agent-claim #3155 nonce=06811f6b33baa751025f9765c8a55f78