Sort render inputs so config is deterministic (stop restart loop) #11

Merged
benvin merged 1 commits from benvin/deterministic-render into main 2026-07-12 23:09:34 +10:00
Owner

Why — urgent

After v0.2.2 (config-hash), bind-resolvers-2 is stuck in an endless rolling restart. Root cause: the rendered config is non-deterministic. client.List returns cache-ordered results, so the resolver's ~20 forward zones (and DNSSEC policies) reshuffle between reconciles. Before the config hash this was invisible; now a reshuffled render rewrites the ConfigMap → flips bind.unkin.net/config-hash → the StatefulSet re-rolls the pod, forever.

Confirmed on-cluster: the config-hash annotation and ConfigMap resourceVersion change every reconcile (~3s).

Fix

Sort every list rendered into named.conf (ACLs, views, forward zones, policies, DNSSEC policies) before rendering, so identical inputs always produce byte-identical config and the hash is stable. ACLs/views were already sorted locally; forward zones and DNSSEC policies were not.

Tests

  • TestRenderDeterministicWithShuffledForwards: two different forward-zone input orders render byte-identical output. Full suite green.

Deploy

Needs v0.2.3 + argocd bump. Once the deterministic operator reconciles, the ConfigMap stops churning, the hash stabilizes, and the stuck resolver rolling update completes.

## Why — urgent After v0.2.2 (config-hash), `bind-resolvers-2` is stuck in an **endless rolling restart**. Root cause: the rendered config is **non-deterministic**. `client.List` returns cache-ordered results, so the resolver's ~20 forward zones (and DNSSEC policies) reshuffle between reconciles. Before the config hash this was invisible; now a reshuffled render rewrites the ConfigMap → flips `bind.unkin.net/config-hash` → the StatefulSet re-rolls the pod, forever. Confirmed on-cluster: the config-hash annotation and ConfigMap resourceVersion change every reconcile (~3s). ## Fix Sort every list rendered into `named.conf` (ACLs, views, forward zones, policies, DNSSEC policies) before rendering, so identical inputs always produce byte-identical config and the hash is stable. ACLs/views were already sorted locally; forward zones and DNSSEC policies were not. ## Tests - `TestRenderDeterministicWithShuffledForwards`: two different forward-zone input orders render byte-identical output. Full suite green. ## Deploy Needs v0.2.3 + argocd bump. Once the deterministic operator reconciles, the ConfigMap stops churning, the hash stabilizes, and the stuck resolver rolling update completes.
unkinben added 1 commit 2026-07-12 23:03:01 +10:00
Sort render inputs so config is deterministic (stop restart loop)
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
59612f157a
client.List returns cache-ordered (non-deterministic) results, so the
forward zones (and DNSSEC policies) reshuffled between reconciles. Before
the config-hash change this was harmless, but now a reshuffled render
rewrites the ConfigMap, flips the pod-template config hash, and the
StatefulSet rolls forever (observed: resolver forward zones churn every
reconcile, pod endlessly recreated).

Sort every list rendered into named.conf (ACLs, views, forward zones,
policies, DNSSEC policies) before rendering, so identical inputs always
produce byte-identical config and the hash is stable.
benvin merged commit 243e776b59 into main 2026-07-12 23:09:34 +10:00
benvin deleted branch benvin/deterministic-render 2026-07-12 23:09:34 +10:00
Sign in to join this conversation.