Generate backfill overwrites user-owned NetworkPolicies
Kyverno 1.12 manages 240 namespaces. A ClusterPolicy named default-deny-networkpolicy has a generate rule that triggers on Namespace CREATE and creates a NetworkPolicy named default-deny in the new namespace. The rule sets synchronize: true and uses the namespace name in the NetworkPolicy name. The policy was installed after 180 namespaces already existed; only the 60 namespaces created afterward have the generated NetworkPolicy. The security audit fails. An engineer edits the policy to add generateExisting: true and reapplies it. The 180 missing NetworkPolicies appear, but within an hour users report that their own NetworkPolicy named default-deny was overwritten, and a manually edited generated policy keeps reverting. The platform team asks how to backfill safely and whether synchronize should stay on.
1. Why were the 180 existing namespaces missed, and what does generateExisting: true change?
Read the worked answer
Generate rules are triggered by admission events on the trigger resource. When the policy was created, the 180 existing Namespaces did not generate a new admission event, so no downstream NetworkPolicy was created. The 60 namespaces created after the policy was installed did trigger it. generateExisting: true, placed under the rule's generate block, tells Kyverno to process the existing trigger resources when the policy is created or updated. That is what backfilled the 180. It is a reconciliation action, not a reason to leave synchronize on by itself. Check the installed Kyverno version's field name and behavior; older versions used generateExistingOnPolicyUpdate for policy updates, so do not assume the same field semantics across versions.
2. Explain the overwrite and revert symptoms and how to change the policy to avoid clobbering user resources.
Read the worked answer
synchronize: true means Kyverno treats the generated resource as owned by the policy and reconciles it to the desired spec. If a user edits the generated NetworkPolicy, Kyverno can revert it. The generated object also shares the name default-deny with user-authored policies, so the two objects collide; with synchronization enabled Kyverno enforces its generated spec. Fix the collision first: generate a uniquely named object such as kyverno-default-deny and add labels and annotations that mark Kyverno ownership. Do not reuse a name that application teams own. Then decide synchronization intentionally: keep synchronize: true if the policy must prevent drift and Kyverno truly owns the object; set it to false if users must be able to edit the generated object after creation, accepting that Kyverno will not revert changes. Document the ownership rule. A generate rule cannot safely merge with an arbitrary user-authored policy of the same name; use a distinct name and, if needed, a separate policy that validates user policies.
3. How would you validate the backfill and prevent recurrence?
Read the worked answer
Before enabling on all 240 namespaces, run it in a staging copy or use a namespace selector to canary a few namespaces. List namespaces without the expected generated policy with kubectl get ns and kubectl get networkpolicy -A. Enable generateExisting on the canary, then check kubectl get policyreport -A for generate failures and kubectl get networkpolicy -n <ns> for the new object. Verify that an existing user policy with the old name is not overwritten. After the canary, expand the match. To prevent recurrence, keep the policy with generateExisting: true so newly created namespaces are covered automatically, add a CI check that counts namespaces without the generated policy, and alert on generate failures in PolicyReports.