Skip to content

Move the platform's auto-vpa to the shared GeneratingPolicy form #5130

Open

Description

@devantler

🤖 Generated by the Agentic Engineer

Evidence

Prod runs Kyverno 1.19.1 and still sizes workloads through the classic auto-vpa ClusterPolicy. Kyverno plans to remove classic generate rules in 1.20. The shared catalog registers the GeneratingPolicy replacement (devantler-tech/kyverno-policies#1, item 3). The two prerequisites are merged: the guards admit the catalog's shape (#5105) with a system-namespace exclusion (#5127), and the VPA updater runs with --min-replicas=1 (#5086).

Read-only readback, 2026-10-20 ~16:15Z: 88 VPAs are labelled generate.kyverno.io/policy-name=auto-vpa (107 VPAs in total). Many running pods carry VPA-raised memory limits well above their authored ones. Examples: flux-operator 4.4Gi live against 1Gi authored, crossplane 1.5Gi against 512Mi, keda-operator 1.4Gi against 1000Mi.

Audience and problem

Platform operator: the platform has to move off the classic form before the Kyverno upgrade that removes it. The catalog's rollout moves a cluster in two separately reconciled steps, and the platform's classic VPAs are named <name>, not <name>-<kind>. So running both forms at once would put two VPAs on every workload.

Plan

  1. Unregister the classic policy and let it reconcile. Confirm that no policy-name=auto-vpa VPA remains.
  2. Register the catalog's three GeneratingPolicy objects, excluding kube-system, kube-public, kube-node-lease and kyverno, where prod ships static VPAs. Confirm that every matching workload has exactly one VPA, and that a deleted workload's VPA is removed (the catalog relies on synchronize, not owner references).

Keep the gap between the two steps short: a pod that restarts with no VPA comes back at its authored limits.

Acceptance criteria

  • Step 1 deployed; 0 VPAs labelled generate.kyverno.io/policy-name=auto-vpa.
  • Step 2 deployed; every Deployment, StatefulSet and DaemonSet outside the four system namespaces has exactly one generated VPA, and none of those namespaces gets one.
  • The coroot alert autosuppressor's auto-vpa write-conflict exemption is updated or retired for the new policy names.
  • Rollback is documented: the classic file stays registered-off until the move is verified.

Success signal

Both steps verified live with no duplicate or missing VPAs and no OOM restarts attributable to the gap.

Activity

  1. added theissue type on Oct 20, 2026
  2. moved this to 📥 Backlog in 🌊 Project Boardon Oct 20, 2026
  3. moved this from 📥 Backlog to 🏃🏻‍♂️ In Progress in 🌊 Project Boardon Oct 20, 2026
  4. devantler commented on Oct 20, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Step 1 deployed and verified (17:16Z). #5132 merged through the queue. Read-only readback after the deploy:

    • ClusterPolicy/auto-vpa: NotFound.
    • VPAs labelled generate.kyverno.io/policy-name=auto-vpa: 0, down from 88.
    • Remaining VPAs: 19, the static system VPAs. They are untouched.

    Step 2 (#5134) is merged up to current main, re-validated, and its CI was green before the update. Codex's three P2 findings are refuted with live evidence: the updater already runs --min-replicas=1, the longest workload name is 48 characters, and the owner-reference difference stays on this issue's delete check. Step 2 waits only on a green review at the new head.

  5. devantler commented on Oct 20, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Step 2 deployed and verified (#5134 merged 18:36Z). Read-only readback after the deploy:

    Check Result
    GeneratingPolicy auto-vpa-deployment / -statefulset / -daemonset all Ready
    Generated VPAs 76 deployment + 5 statefulset + 7 daemonset = 88, the same count the classic policy had
    Deployments, StatefulSets and DaemonSets outside the four system namespaces 88: 88 with exactly one VPA, 0 with none, 0 with more than one
    Generated VPAs in kube-system / kube-public / kube-node-lease / kyverno 0
    Static VPAs 19, unchanged

    Two items stay open on this issue:

    1. Delete case. The engineer's cluster access is read-only, so I cannot delete a workload to test it. Instead I will watch for orphans: a generated VPA whose target no longer exists. The baseline is 0 orphans now (88 VPAs, each with a live target). I will re-read it at the next runs, after natural workload churn.
    2. Coroot autosuppressor exemption 3 still matches only ClusterPolicy/auto-vpa events, which can no longer occur. I will check whether the new policies produce a write-conflict event shape before retiring or retargeting it.
  6. moved this from 🏃🏻‍♂️ In Progress to 📊 Verifying in 🌊 Project Boardon Oct 20, 2026
  7. added a commit that references this issue on Oct 20, 2026
  8. devantler commented on Oct 20, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Orphan watch, 19:2xZ (~45 min after Step 2): read-only check of every VPA in the cluster against its target. 107 VPAs in total (88 generated + 19 static); 0 orphans — each targetRef resolves to an existing Deployment, StatefulSet or DaemonSet. The remaining open item on this issue is the autosuppressor exemption, which platform#5137 retires.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    Priority

    None yet

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions