Skip to content

Non-deterministic zone selection in getHostZoneID when multiple zones match domain filter #99

Description

@jelinek-wgs

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions