Skip to content

DNS

external-dns watches gateway-httproute and writes to Cloudflare.

domainFilters must name the Cloudflare zone, not the subdomain in use. A zone matches only if it equals the filter or is a subdomain of it, so cbc.gewis.nl excludes the gewis.nl zone — external-dns then finds no zone to write into and reports the very misleading "All records are already up to date". The filter is gewis.nl; scoping comes from ownership instead:

Setting Effect
txtOwnerId: cbc-test only touches records carrying its own ownership TXT
policy: upsert-only creates and updates its own records, never deletes them
txtPrefix: edns- keeps the ownership TXT off the CNAME's name, which Cloudflare forbids

upsert-only, not sync. Under sync a record disappears the moment its route does — and a route can vanish for reasons that have nothing to do with the hostname being retired, such as the Gateway API CRDs being replaced, which takes every HTTPRoute with them. Recreating the record afterwards is not symmetric: the gewis.nl SOA minimum is 1800 s, so every downstream resolver serves NODATA for up to half an hour after the name comes back, and the CNAME is correct in Cloudflare the whole time. A stale record left behind by a retired route is cheap in comparison — it is deletable by hand, and its ownership TXT says which cluster wrote it.

The DNS target is the external-dns.alpha.kubernetes.io/target annotation on the Gateway, not on each route — external-dns reads that override from the Gateway only, and ignores it on an HTTPRoute. It is set once in flux/config/gateway/gateway.yaml, so every route inherits it. The target is a hostname, so records are CNAMEs. Without it external-dns would publish the Gateway's own addresses, which in host network mode are the node addresses rather than one stable LoadBalancer address.

--cloudflare-record-comment tags every managed record; ownership itself is still the TXT, not the comment.