external-dns: AWS R53 "A" alias record incorrectly uses TXT record with "cname-" prefix
What happened:
When A alias record is created by external-dns, it also creates two TXT records, one of which contains “cname-” prefix, despite documentation on new registry format stating that it should be based on record type, and TXT records related to A records should have “a-” prefix.
What you expected to happen:
TXT record having “a-” prefix.
How to reproduce it (as minimally and precisely as possible):
- Run external-dns in the cluster with options:
- --source=service
- --registry=txt
- --txt-owner-id=some-owner-id
- --txt-prefix=myprefix-
- --provider=aws
- --aws-zone-type=public
- Deploy ExternalName Service pointing to the hostname of an existing AWS Load Balancer (required to create A alias, otherwise CNAME will be created):
apiVersion: v1
kind: Service
metadata:
name: my-svc
annotations:
external-dns.alpha.kubernetes.io/hostname: foo.bar.com
spec:
type: ExternalName
externalName: foo-bar-00000000.us-west-2.elb.amazonaws.com # Hostname of ALB
Anything else we need to know?:
Logs from the creation process look like this:
level=info msg="Desired change: CREATE foo.bar.com A [Id: /hostedzone/<redacted>]"
level=info msg="Desired change: CREATE myprefix-foo.bar.com TXT [Id: /hostedzone/<redacted>]"
level=info msg="Desired change: CREATE myprefix-cname-foo.bar.com TXT [Id: /hostedzone/<redacted>]"
Environment:
- External-DNS version: v0.12.2
- DNS provider: AWS Route53
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 4
- Comments: 16 (2 by maintainers)
Unfortunately, I think this problem is caused by poor modularisation of the
external-dns
internals.The program main loop consists of repetitions of controller.Controller.RunOnce. This uses the source subpackage to gather what rules are desired, and uses the TXT subclass of the registry subpackage to ascertain what rules already exist on the DNS server and which ones
external-dns
has responsibility for managing. (To accomplish this, the registry wraps the provider interface.) The controller then uses the plan subpackage to compare these two lists to decide what updates to perform, and has the registry action the result.The problem is that the source object is (inappropriately) opinionated about what types of DNS records should be used to represent each desired rule. So type CNAME is already specified (solely based on the target not resembling an IP address) before the rule even gets suggested to the controller or registry. This is why, when TXTRegistry injects its TXT records, it labels them “CNAME”.
Alias records are supported by multiple cloud providers (as they make the DNS system more efficient), but unfortunately the aliasing logic in
external-dns
is applied transparently at the last moment by the AWS provider. (The conversion is applied in AWSProvider.ApplyChanges and removed again in AWSProvider.Records.) Not only does it swap CNAME records for A records (depending on whether the target is something AWS supports DNS aliasing for) but it may additionally create AAAA records (for IPv6 support). The registry has no knowledge that this transformation has occurred, and the AWSProvider has no knowledge that the registry subclass may have intended the TXT records to have a relationship to those modified records.To properly solve this problem, I think a major refactor of
external-dns
is appropriate (bringing aliasing logic outside of the provider subpackage, possibly leading to changes in how the controller interacts with registries), which is difficult because there are so many different providers and components at risk of being impacted. You could just do a bandaid fix (like duplicating some of the TXTRegistry logic inside of the AWSProvider), but I think this is a bad idea (making the entire codebase more spaghetti complicated and harder to refactor in the future), although there already appears to be a history of such bandaids (for example some of the TXTRegistry logic has leaked into the main controller loop and hence also into the interface for other kinds of registry, namely the missing records interface which is solely for upgrades/downgrades of the format used by TXTRegistry and is handled separately from all other kinds of missing DNS records, aside from that it misleadingly pretends to be an independent method call rather than an extra return value…).Incidentally, when (A and/or AAAA) aliasing is in use, it might also be possible for MX and SRV records to exist for the same hostname (unlike if a CNAME record were used), which could further interfere with the ability of the TXTRegistry to judge which records
external-dns
can safely manage at present.@benjimin Yes, it creates A “alias” record. That part is normal and working as expected. The problem is that it appends “cname” to TXT record, despite alias actually being A record type.