You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For gateway v4. / v6. hostnames, NSO ends up with two writers on the same FQDN: Gateway DNS creates CNAMEs to the apex, while another path (ExternalDNS off gateway addresses) creates A/AAAA. PowerDNS rejects the CNAME (422 Conflicts with pre-existing RRset), and dnsrecordset-powerdns retries forever.
Staging hit this on project datum-cloud (claude-test-connector-proxy, customer-api-l06tj1). Live resolution still works via the A/AAAA records; the damage is a stuck reconcile loop that trips ControllerReconcileErrorRatioCritical for dnsrecordset-powerdns (alert coverage expanded in #306 / NSO alerts applied 2026-07-22).
How we got here (staging)
Both CNAME and A/AAAA existed for the same v4. / v6. names (messy dual ownership; CNAME side already failing).
2026-07-10 ~11:35 UTC — Domain RDAP refresh for prism.staging.env.datum.net briefly set status.nameservers to parent *.datumdomains.net (no overlap with DNSZone *.datum-staging.net). HasDNSAuthority failed, so garbageCollectDNSRecordSets deleted the four CNAMEs even though Gateway listeners/addresses had not changed.
2026-07-11 ~14:54 UTC — next RDAP refresh restored the correct NS. Authority returned; NSO recreated the CNAMEs into the still-present A/AAAAs. Hot loop continues.
Actors for the Jul 10–11 delete/recreate were controllers only (control@networking.datumapis.com). No human edited the DNSRecordSets in that window.
Root cause
Two bugs that compound:
Dual-write. Gateway DNS (gateway_dns_controller.go) programs CNAMEs for claimed hostnames including v4. / v6. from status addresses. ExternalDNS (or the A/AAAA path feeding it) also programs those same names as address records. Conflict detection only flags same-hostname DNSRecordSets with a differentmanaged-by, so same-FQDN A/AAAA from the other path do not block CNAME create.
GC on a single authority miss.ensureDNSRecordSets omits hostnames from desiredRecordSetNames when HasDNSAuthority is false, then GC deletes them. A transient Domain NS flap is enough to reap records the Gateway still wants.
dns-operator surfaces this as repeated 422s (related: datum-cloud/dns-operator#56 for cross-type conflict handling). Stopping the dual-write and softening GC is the NSO-side prevention.
Acceptance
Exactly one writer owns v4. / v6. gateway hostnames (CNAME-to-apex or A/AAAA, not both). Prefer documenting which path is canonical and disabling the other.
Conflict detection treats any conflicting RRset / DNSRecordSet at the same FQDN as a blocker (or clears it deliberately), not only differently-labeled peers.
Transient Domain authority loss does not delete Gateway DNSRecordSets on a single failed check (sustained failure / backoff, or pause programming without reap).
Unit or e2e coverage: recreate-after-authority-restore does not produce CNAME+A/AAAA at the same name; optional case that a Domain NS blip does not GC wanted CNAMEs.
Summary
For gateway
v4./v6.hostnames, NSO ends up with two writers on the same FQDN: Gateway DNS creates CNAMEs to the apex, while another path (ExternalDNS off gateway addresses) creates A/AAAA. PowerDNS rejects the CNAME (422 Conflicts with pre-existing RRset), anddnsrecordset-powerdnsretries forever.Staging hit this on project
datum-cloud(claude-test-connector-proxy,customer-api-l06tj1). Live resolution still works via the A/AAAA records; the damage is a stuck reconcile loop that tripsControllerReconcileErrorRatioCriticalfordnsrecordset-powerdns(alert coverage expanded in #306 / NSO alerts applied 2026-07-22).How we got here (staging)
v4./v6.names (messy dual ownership; CNAME side already failing).prism.staging.env.datum.netbriefly setstatus.nameserversto parent*.datumdomains.net(no overlap with DNSZone*.datum-staging.net).HasDNSAuthorityfailed, sogarbageCollectDNSRecordSetsdeleted the four CNAMEs even though Gateway listeners/addresses had not changed.Actors for the Jul 10–11 delete/recreate were controllers only (
control@networking.datumapis.com). No human edited the DNSRecordSets in that window.Root cause
Two bugs that compound:
gateway_dns_controller.go) programs CNAMEs for claimed hostnames includingv4./v6.from status addresses. ExternalDNS (or the A/AAAA path feeding it) also programs those same names as address records. Conflict detection only flags same-hostname DNSRecordSets with a differentmanaged-by, so same-FQDN A/AAAA from the other path do not block CNAME create.ensureDNSRecordSetsomits hostnames fromdesiredRecordSetNameswhenHasDNSAuthorityis false, then GC deletes them. A transient Domain NS flap is enough to reap records the Gateway still wants.dns-operator surfaces this as repeated 422s (related: datum-cloud/dns-operator#56 for cross-type conflict handling). Stopping the dual-write and softening GC is the NSO-side prevention.
Acceptance
v4./v6.gateway hostnames (CNAME-to-apex or A/AAAA, not both). Prefer documenting which path is canonical and disabling the other.Related
ControllerReconcileErrorRatioCritical)