Bug Description
When multiple DNS zones in OpenStack Designate match the configured --domain-filter (for example, a parent zone example.com. and a subdomain zone sub.example.com.), the webhook non-deterministically selects different zones across reconcile cycles for hostnames where zone lengths evaluate equally or during map iteration.
This causes external-dns (running with --policy=sync) to continuously delete records in one zone and recreate them in another zone on "random" sync loop, leading to massive DNS record flapping/churn.
Root Cause Analysis
In internal/designate/provider/provider.go:
func getHostZoneID(hostname string, managedZones map[string]string) string {
longestZoneLength := 0
resultID := ""
for zoneID, zoneName := range managedZones {
if !strings.HasSuffix(hostname, "."+zoneName) && hostname != zoneName {
continue
}
ln := len(zoneName)
if ln > longestZoneLength {
resultID = zoneID
longestZoneLength = ln
}
}
return resultID
}
Since managedZones is a Go map[string]string, iterating over it with for zoneID, zoneName := range managedZones yields a randomized iteration order in Go at runtime.
When multiple zones match with identical host/zone length criteria or overlap during filtering, the returned resultID changes randomly between reconcile cycles depending on map iteration order.
Bug Description
When multiple DNS zones in OpenStack Designate match the configured
--domain-filter(for example, a parent zoneexample.com.and a subdomain zonesub.example.com.), the webhook non-deterministically selects different zones across reconcile cycles for hostnames where zone lengths evaluate equally or during map iteration.This causes
external-dns(running with--policy=sync) to continuously delete records in one zone and recreate them in another zone on "random" sync loop, leading to massive DNS record flapping/churn.Root Cause Analysis
In
internal/designate/provider/provider.go:Since
managedZonesis a Gomap[string]string, iterating over it withfor zoneID, zoneName := range managedZonesyields a randomized iteration order in Go at runtime.When multiple zones match with identical host/zone length criteria or overlap during filtering, the returned
resultIDchanges randomly between reconcile cycles depending on map iteration order.