Skip to content

Conversation

@u-kai
Copy link
Contributor

@u-kai u-kai commented Dec 7, 2025

What does it do ?

Fixes: #5815

This PR adds support for selective control over A and AAAA alias record creation in the AWS Route53 provider through two new ProviderSpecific annotations:

  • aws/alias-disable-a: "true" - prevents creation of A alias records
  • aws/alias-disable-aaaa: "true" - prevents creation of AAAA alias records

When a CNAME endpoint creates alias records, external-dns automatically creates both A and AAAA alias records by default. These new annotations allow users to disable specific record types on a per-endpoint basis, providing granular control without affecting other DNS records.

Motivation

Issue #5815 requested the ability to selectively disable AAAA alias records for specific use cases. Currently, the only option is the global --exclude-record-types=AAAA flag, which affects all records across all providers.

This feature is particularly important for same-zone alias records where CNAME endpoints point to other records within the same hosted zone. While AWS managed services (like ELBs, CloudFront) typically support both IPv4 and IPv6, custom applications and services within the same zone often have different connectivity requirements.

Unlike AWS managed resources which are generally dual-stack capable, user-managed records in the same zone frequently have single-stack limitations, making this granular control essential for proper DNS configuration.

This enhancement provides the targeted control needed for these scenarios while maintaining full backward compatibility.

More

  • Yes, this PR title follows Conventional Commits
  • Yes, I added unit tests
  • Yes, I updated end user documentation accordingly

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign raffo for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the provider Issues or PRs related to a provider label Dec 7, 2025
@k8s-ci-robot k8s-ci-robot requested a review from szuecs December 7, 2025 06:39
@k8s-ci-robot k8s-ci-robot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Dec 7, 2025
@k8s-ci-robot
Copy link
Contributor

Hi @u-kai. Thanks for your PR.

I'm waiting for a github.com member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-ci-robot k8s-ci-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Dec 7, 2025
@mloiseleur
Copy link
Collaborator

@u-kai thanks for this interesting PR.

Wdyt of re-use existing annotation, external-dns.alpha.kubernetes.io/alias, (doc here) instead of using a new one ?

It could be configurable like this :

  • external-dns.alpha.kubernetes.io/alias: false => no aliases
  • external-dns.alpha.kubernetes.io/alias: true => A & AAAA aliases
  • external-dns.alpha.kubernetes.io/alias: "A" => only A aliases
  • external-dns.alpha.kubernetes.io/alias: "AAAA" => only AAAA aliases

@u-kai
Copy link
Contributor Author

u-kai commented Dec 7, 2025

@mloiseleur
Thank you for the suggestion! I hadn’t thought about reusing the existing annotation at all — that’s a great idea. Your proposal looks much cleaner and more flexible, so I’ll switch to this approach.

@ivankatliarchuk
Copy link
Member

/ok-to-test

@k8s-ci-robot k8s-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Dec 8, 2025
@coveralls
Copy link

Pull Request Test Coverage Report for Build 20000357394

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • 51 unchanged lines in 2 files lost coverage.
  • Overall coverage increased (+0.02%) to 78.7%

Files with Coverage Reduction New Missed Lines %
openshift_route.go 1 79.49%
aws/aws.go 50 90.87%
Totals Coverage Status
Change from base Build 19973832146: 0.02%
Covered Lines: 16028
Relevant Lines: 20366

💛 - Coveralls

Copy link
Member

@ivankatliarchuk ivankatliarchuk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation with use cases for this properties is missing, and how it was tested on a real cluster

return endpoints, nil
}

func aliasDisableARecord(ep *endpoint.Endpoint) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My opinion, we will benefit to have a generic,centralised method on Endpoint object for all annotations that contains booleans like true/false

Copy link
Member

@ivankatliarchuk ivankatliarchuk Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something like

func (ep *endpoint.Endpoint) GetProviderSpecificBool(key string bool) bool {
	val, ok := ep.GetProviderSpecificProperty(key)
	if !ok {
		return false
	}
	// Normalize whitespace and case; accept common truthy values
	v := strings.TrimSpace(strings.ToLower(val))
	switch v {
	case "1", "t", "true", "yes", "y":
		return true
	case "0", "f", "false", "no", "n":
		return false
	default:		
		return false
	}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That does sound like a good idea.
However, in this change we’re going to use values other than just true/false, as @mloiseleur mentioned, and I’m a bit concerned that introducing a generic, centralized method here would make the scope of this PR too large.
I’d prefer to handle that refactor in a separate PR that can apply the change across the whole codebase. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

@u-kai
Copy link
Contributor Author

u-kai commented Dec 9, 2025

@mloiseleur @ivankatliarchuk

While creating comprehensive tests for supporting annotations like external-dns.alpha.kubernetes.io/alias: "AAAA", I encountered an inconsistent behavior in the existing code.

Should I include this fix in this PR, or would it be better to submit it as a separate PR?
In the latter case, I would work on this PR after the new PR is merged first.

Discovered Issue

When a ProviderSpecific property alias=true exists on record types that don't support alias records
(like MX records):

  1. Alias processing continues even after alias property deletion

    • The alias property is deleted at aws.go, but the alias variable remains true
    • This results in unnecessary evaluateTargetHealth=false being added
  2. TTL value gets unintentionally modified

    • When RecordTTL is configured, it gets fixed to 300

Reproduction

ep := &endpoint.Endpoint{
    RecordType: endpoint.RecordTypeMX,
    RecordTTL:  600,
    ProviderSpecific: endpoint.ProviderSpecific{
        {Name: "alias", Value: "true"},
    },
}
// Expected: TTL=600, ProviderSpecific=empty
// But result is: TTL=300, evaluateTargetHealth=false gets added

While this affects cases with incorrectly configured ProviderSpecific properties, I believe the behavior should be consistent.

@mloiseleur
Copy link
Collaborator

Should I include this fix in this PR, or would it be better to submit it as a separate PR?

It's better as a separate PR. It's easier to review & test this way.
It's also more clear for Changelog / Release notes.

@u-kai
Copy link
Contributor Author

u-kai commented Dec 12, 2025

@mloiseleur

I’ve submitted the fix in a separate PR here: #6017.
When you have a moment, I’d appreciate it if you could take a look.

@ivankatliarchuk
Copy link
Member

Refactoring, bug fixes, new features - all should be in they own PRs. We are trying to de-resk releases. Way too many issues opened ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. provider Issues or PRs related to a provider size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(aws): Add ProviderSpecific option to disable A/AAAA Alias record creation for Route53

5 participants