What happened:
When the TXT registry name exceeds the 63-character DNS label limit, the error is logged and the execution proceeds. So the parent A/AAAA endpoint is pushed to the provider with no ownership TXT companion. Once the source disappears, there is nothing in the TXT registry to match, so the parent record becomes an orphan.
Trigger conditions is when the source FQDN's leftmost label fits in 63 chars, but <txt-prefix><recordType-prefix><leftmost-source-label> does not.
What you expected to happen:
When the registry TXT cannot be created, the parent record should not be applied either.
How to reproduce it (as minimally and precisely as possible):
Validated against external-dns v0.20.0, provider=aws, in a private Route53 zone, using a single Service object so no ingress controller or load balancer is needed. Process flags: --source=service --source=ingress --registry=txt --policy=sync --provider=aws --aws-zone-type=private.
- Apply this Service. The leftmost label is exactly 63 chars — passes the source-side check; the registry TXT name becomes
a-<63chars> = 65 chars and fails.
apiVersion: v1
kind: Service
metadata:
name: bug-repro-extdns-overflow
namespace: default
annotations:
external-dns.alpha.kubernetes.io/hostname: bug-repro-extdns-overflow-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.example.com
external-dns.alpha.kubernetes.io/target: "192.0.2.1"
external-dns.alpha.kubernetes.io/ttl: "60"
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
app: nonexistent
- Wait one reconcile cycle. external-dns logs at ERROR severity:
level=error msg="label a-bug-repro-extdns-overflow-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa in a-bug-repro-extdns-overflow-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.example.com is longer than 63 characters. Cannot create endpoint"
- Inspect the DNS provider. The parent A exists; no
a- TXT companion exists.
$ aws route53 list-resource-record-sets --hosted-zone-id <ZONE_ID> \
--query 'ResourceRecordSets[?contains(Name,`bug-repro`)]'
[
{
"Name": "bug-repro-extdns-overflow-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.example.com.",
"Type": "A",
"TTL": 60,
"ResourceRecords": [{"Value": "192.0.2.1"}]
}
]
-
Delete the Service. Wait one reconcile cycle.
-
The A record remains in Route53 indefinitely; policy=sync cannot reap it because there is no TXT registry entry tying it back to the source. external-dns emits no further log lines about the record (the source is gone).
Anything else we need to know?:
Suggested fix
Environment:
- External-DNS version (use
external-dns --version): v0.20.0 (Helm chart external-dns-1.20.0). Code path identical on v0.21.0 and master.
- DNS provider: AWS Route53 (private hosted zones).
- Others:
- Process flags (subset relevant to the bug):
--provider=aws
--registry=txt
--source=ingress
--source=service
--policy=sync
--aws-zone-type=private
--log-level=warning
- Kubernetes: EKS, kubernetes 1.32.
Checklist
What happened:
When the TXT registry name exceeds the 63-character DNS label limit, the error is logged and the execution proceeds. So the parent A/AAAA endpoint is pushed to the provider with no ownership TXT companion. Once the source disappears, there is nothing in the TXT registry to match, so the parent record becomes an orphan.
Trigger conditions is when the source FQDN's leftmost label fits in 63 chars, but
<txt-prefix><recordType-prefix><leftmost-source-label>does not.What you expected to happen:
When the registry TXT cannot be created, the parent record should not be applied either.
How to reproduce it (as minimally and precisely as possible):
Validated against external-dns v0.20.0, provider=aws, in a private Route53 zone, using a single
Serviceobject so no ingress controller or load balancer is needed. Process flags:--source=service --source=ingress --registry=txt --policy=sync --provider=aws --aws-zone-type=private.a-<63chars>= 65 chars and fails.a-TXT companion exists.Delete the Service. Wait one reconcile cycle.
The A record remains in Route53 indefinitely;
policy=synccannot reap it because there is no TXT registry entry tying it back to the source. external-dns emits no further log lines about the record (the source is gone).Anything else we need to know?:
Suggested fix
Environment:
external-dns --version):v0.20.0(Helm chartexternal-dns-1.20.0). Code path identical onv0.21.0andmaster.Checklist
or have checked the staging image to confirm the bug is still reproducible
kubectl get <resource> -o yamloutput includingstatus