[Feature] Support dryRun / audit mode in CEL DeletingPolicy (policies.kyverno.io)
Problem Statement
Kyverno is migrating from legacy CleanupPolicy (kyverno.io/v2) to CEL based DeletingPolicy and NamespacedDeletingPolicy (policies.kyverno.io/v1beta1).
Currently, when a DeletingPolicy executes on its schedule in pkg/controllers/deleting/controller.go, every resource that matches the policy's matchConstraints and CEL conditions is immediately deleted from the cluster via client.DeleteResource(...).
In production environments, cleanup policies are destructive by design. If an operator writes a new DeletingPolicy (e.g. targeting completed pods, stale jobs, or orphaned secrets), an overly broad CEL condition or misconfigured object selector can inadvertently delete active production workloads.
Unlike ValidatingPolicy, which provides validationFailureAction: Audit | Enforce to safely stage and observe policies before enforcing them, DeletingPolicy currently has no dry run or audit mode. Administrators cannot safely observe which live resources would be affected before enabling actual deletion.
Solution Description
Add dry run / audit support to CEL DeletingPolicy and NamespacedDeletingPolicy:
- API Addition:
Add an optional
dryRun: boolfield (oraction: Audit | Delete, defaulting toDelete) toDeletingPolicySpecinpolicies.kyverno.io/v1beta1:
apiVersion: policies.kyverno.io/v1beta1
kind: DeletingPolicy
metadata:
name: delete-stale-pods
spec:
schedule: "0 0 * * *"
dryRun: true # Or action: Audit
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
conditions:
- name: is-completed
expression: "object.status.phase == 'Succeeded'"- Controller Behavior:
In
pkg/controllers/deleting/controller.go, whenspec.DryRunis true (or action isAudit):
- Evaluate matchConstraints and CEL conditions as normal.
- When a resource matches, skip calling
c.client.DeleteResource(...)(or invoke it withmetav1.DeleteOptions{DryRun: []string{metav1.DryRunAll}}). - Emit an informational Kubernetes event on the target resource and policy (e.g.
Reason: PolicyDryRunMatch, message:resource matched deleting policy and would be deleted). - Record Prometheus metrics for dry run matches so cluster operators can observe candidate counts in metrics before disabling dryRun.
Alternatives
- Offline CLI testing only (kubectl-kyverno apply): While the CLI can evaluate policies against local manifests, it cannot account for live cluster state, dynamically changing resource metadata, or complex controller interactions in real environments.
- Manual inspection via kubectl: Querying resources with custom kubectl commands or JSONPath is error prone and duplicates CEL logic already declared in the policy.
Additional Context
- Aligns DeletingPolicy with Kyverno's other CEL policy types (ValidatingPolicy audit mode).
- Matches native Kubernetes dry run conventions (metav1.DryRunAll).
- Significantly lowers the risk for enterprise platform teams adopting CEL deletion policies.
Slack discussion
No response
Research
- I have read and followed the documentation AND the troubleshooting guide.
- I have searched other issues in this repository and mine is not recorded.
Source: kyverno/kyverno