From 32db6760cc2558255c8c13158fba5ff9de741636 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Sun, 17 May 2026 00:32:06 +0000 Subject: [PATCH] keel: use +() anchors on policy/match-tag so per-workload overrides stick MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without the anchor, each policy update fires mutateExistingOnPolicyUpdate, which OVERWRITES existing keel.sh/policy annotations back to 'force'. That broke the phased rollout — bulk-setting workloads to 'never' didn't stick because the next policy update reset them. With +() anchors, the mutate only adds the annotation if missing. New workloads (in enrolled namespaces) get force+match-tag; existing workloads with explicit policy=never (out-of-band, for phased rollout) stay never. Phase 1 rollout state (2026-05-17): - 10 workloads on force+match-tag in 10 namespaces (Phase 1) enrolled via keel.sh/enrolled=true namespace label: linkwarden, excalidraw, diun, echo, foolery, city-guesser, jsoncrack, privatebin, ntfy, speedtest - 216 workloads on policy=never (out-of-band kubectl annotate) - 31 critical namespaces excluded at policy level Expand to Phase 2 by labeling more namespaces `keel.sh/enrolled=true` and clearing the `never` annotation off their workloads. Co-Authored-By: Claude Opus 4.7 --- stacks/kyverno/modules/kyverno/keel-annotations.tf | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/stacks/kyverno/modules/kyverno/keel-annotations.tf b/stacks/kyverno/modules/kyverno/keel-annotations.tf index 4af50641..891a354c 100644 --- a/stacks/kyverno/modules/kyverno/keel-annotations.tf +++ b/stacks/kyverno/modules/kyverno/keel-annotations.tf @@ -165,8 +165,13 @@ resource "kubernetes_manifest" "policy_inject_keel_annotations" { # to bypass this mutation) # Per-namespace opt-out: # Remove the `keel.sh/enrolled=true` namespace label. - "keel.sh/policy" = "force" - "keel.sh/match-tag" = "true" + # `+(...)` anchor — only add if not present. This preserves + # per-workload overrides set out-of-band (e.g. `never` for + # phased rollout). Without the anchor, every policy update + # would overwrite existing annotations, breaking the phased + # rollout state. + "+(keel.sh/policy)" = "force" + "+(keel.sh/match-tag)" = "true" "+(keel.sh/trigger)" = "poll" "+(keel.sh/pollSchedule)" = "@every 1h" }