Fix authoritative secondary replication (TSIG transfer + stable primary)
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful

Secondaries never replicated any member zone: the master's catalog zone
requires key-authenticated AXFR (allow-transfer { key "transfer-key"; }),
but the rendered secondary config transferred without presenting the key,
so every catalog transfer was REFUSED and no member zones provisioned.
Two further gaps compounded it: member zones had no allow-transfer at all,
and secondaries pointed at the primary's pod IP, which dies on restart.

- Render the catalog transfer key into the secondary catalog-zones
  default-primaries and the secondary catalog zone primaries, so
  key-authenticated AXFR from the primary is accepted.
- Add allow-transfer { key "<transfer-key>"; } to catalog member primary
  zones (when the zone does not set an explicit allow-transfer), so
  secondaries can pull them; applied to existing zones via modzone.
- Point secondaries at the stable primary Service ClusterIP instead of the
  primary pod IP, so replication survives primary pod restarts (falls back
  to the pod IP when no primary Service exists).
This commit is contained in:
2026-07-12 19:42:38 +10:00
parent 9ab475532c
commit ea330bd767
5 changed files with 100 additions and 15 deletions
@@ -168,10 +168,11 @@ func (r *BindClusterReconciler) reconcileKeysSecret(ctx context.Context, c *bind
}
func (r *BindClusterReconciler) reconcileConfigMap(ctx context.Context, c *bindv1alpha1.BindCluster) error {
// BIND primaries/default-primaries need the primary's IP address, not a DNS
// name, so render with pod-0's current IP (empty until it is scheduled; the
// Pod watch re-renders when it appears or changes).
in := bind.RenderInput{Cluster: c, PrimaryAddress: primaryPodIP(ctx, r.Client, c)}
// BIND primaries/default-primaries need an IP address, not a DNS name. Use
// the stable primary Service ClusterIP so secondaries keep transferring
// across primary pod restarts (falls back to the pod IP when no primary
// Service exists; the Pod/Service watches re-render when it changes).
in := bind.RenderInput{Cluster: c, PrimaryAddress: primaryTransferAddress(ctx, r.Client, c)}
var acls bindv1alpha1.BindACLList
if err := r.List(ctx, &acls, client.InNamespace(c.Namespace)); err == nil {