Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce AWS Route53 API calls #2010

Merged

Conversation

tjamet
Copy link
Contributor

@tjamet tjamet commented Mar 12, 2021

Currently, planning instructs to create all records even
those which does not match any zone.
Later, those records will be checked towards the existing
records and filtered whether they match or not a hosted zone.

This causes a problem, at least in the specific case of the Route53
implementation as it always calls the ApplyChanges method, which in its
turn always retrieves all records in all zones.

This causes high pressure on Route53 APIs, for non-necessary actions.

By being able to filter all unmanaged records from the plan, we can
prevent from calling ApplyChanges when nothing has to be done and hence
prevent an unnecessary listing of records.

By doing so, the rate of API calls to AWS Route53 is expected to be
reduced by 2

To do this change, providers now export, through registries, a DomainFilter, empty by default, provided by the BaseProvider.
This caused some conflicts on dyn and rcode0 provider structures that have been adapted to be closer to other provider ones.

Any provider may now implement such a feature to restrict the planning output before it enters the registry.

Helps to improve #1293

With this change, in the case of a single instance of external-dns running for a single owner, we can expect no-op changes to reduce by 2 the number of calls to the AWS Route53 API while there are no changes to perform.

Checklist

  • Unit tests updated
  • End user documentation updated

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Mar 12, 2021
@k8s-ci-robot k8s-ci-robot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Mar 12, 2021
@tjamet tjamet force-pushed the limit-required-aws-calls-only branch from b10bf4b to 11e44d3 Compare March 12, 2021 14:26
@tjamet
Copy link
Contributor Author

tjamet commented Mar 12, 2021

/assign @njuettner

Copy link
Member

@njuettner njuettner left a comment

Choose a reason for hiding this comment

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

Hey thanks your awesome work, really appreciated. I added some comments.

I'm happy to merge it if we can address my comments 🙂

@@ -40,7 +43,7 @@ type Plan struct {
// Populated after calling Calculate()
Changes *Changes
// DomainFilter matches DNS names
DomainFilter endpoint.DomainFilter
DomainFilter endpoint.DomainFilterInterface
Copy link
Member

Choose a reason for hiding this comment

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

nit, I wouldn't name it Interface. Just change the description showing it's an interface

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about changing endpoints.DomainFilter to be an interface. The problem I face is that it is several providers like AlibabaCloud are relying on the internals ( mostly the Filters entry) I would like to keep the PR as small as possible even though it may lead to a need fo refactoring

@@ -192,3 +216,44 @@ func TestShouldRunOnce(t *testing.T) {
// But not two times
assert.False(t, ctrl.ShouldRunOnce(now))
}

func TestControllerSkipsEmptyChanges(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

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

Can you add tests for several domain filter and without a domain filter?

@@ -145,7 +154,14 @@ type ZonePublishResponse struct {
// NewDynProvider initializes a new Dyn Provider.
func NewDynProvider(config DynConfig) (provider.Provider, error) {
return &dynProviderState{
Copy link
Member

Choose a reason for hiding this comment

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

Please create a separate PR for dyn provider, I'd like to keep the PR as small as possible

@seanmalloy
Copy link
Member

/kind bug

@k8s-ci-robot k8s-ci-robot added the kind/bug Categorizes issue or PR as related to a bug. label Apr 13, 2021
@njuettner
Copy link
Member

@tjamet 👋🏻 any progress since my last my comment? anything we can help with? We'd really like to merge it ❤️ . Is it possible to split it into smaller PR's, so we can focus for now only on Route53 changes?

@tjamet
Copy link
Contributor Author

tjamet commented Apr 22, 2021

Hi @njuettner
Yes, I am working on making smaller PRs. I am slown down by some naming conflicts between field and function.
I keep you posted very soon

Currently, planning instructs to create all records even
those which does not match any zone.
Later, those records will be checked towards the existing
records and filtered whether they match or not a hosted zone.

This causes a problem, at least in the specific case of the Route53
implementation as it always calls the ApplyChanges method, which in its
turn always retrieves all records in all zones.

This causes high pressure on Route53 APIs, for non-necessary actions.

By being able to filter all unmanaged records from the plan, we can
prevent from calling ApplyChanges when nothing has to be done and hence
prevent an unnecessary listing of records.

By doing so, the rate of API calls to AWS Route53 is expected to be
reduced by 2
@tjamet tjamet force-pushed the limit-required-aws-calls-only branch from 5afaa9c to 17fb881 Compare April 25, 2021 16:10
@cmsmith7
Copy link

Hi .. please could you advise when you think this PR will be merged? Many thanks.

Copy link
Member

@njuettner njuettner left a comment

Choose a reason for hiding this comment

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

small nit

controller/controller.go Outdated Show resolved Hide resolved
Co-authored-by: Nick Jüttner <nick@juni.io>
@njuettner
Copy link
Member

@tjamet is this ready for another review? Will the DomainFilterInterface break anything for other providers? You mentioned it is used by different providers? Anything we need to test here as well?

@tjamet
Copy link
Contributor Author

tjamet commented May 27, 2021

I think it is ready for review yes.
I don't think, in the current implementation, the domain filter interface would break other providers, as it is added on top. The problem I have seen was with naming it a DomainFilter that conflicts with other providers internal implementations

@njuettner
Copy link
Member

I think it is ready for review yes.
I don't think, in the current implementation, the domain filter interface would break other providers, as it is added on top. The problem I have seen was with naming it a DomainFilter that conflicts with other providers internal implementations

Thanks again, as long we don't introduce a break and all providers keep running, I'm fine merging it 🙂

@tjamet
Copy link
Contributor Author

tjamet commented Jun 1, 2021

as long we don't introduce a break and all providers keep running

Indeed, I have been careful to do the smallest change possible and keep backward compatibility for this specific purpose.
Re-reading the change, I don't see a risk for any other provider. the added filter is indeed added as an and filter. The provided default DomainFilter that defaults to match all
hence the added and is equivalent to the previous DomainFilter.Match([...) && true

This makes me think this change should be safe for other providers

Copy link
Member

@njuettner njuettner left a comment

Choose a reason for hiding this comment

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

Ok @tjamet you wanted long enough, sorry about that. Once again thank you for your contribution and sorry about taking longer to merge this PR.

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 23, 2021
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: njuettner, tjamet

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

The pull request process is described 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 approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 23, 2021
@k8s-ci-robot k8s-ci-robot merged commit 55b7119 into kubernetes-sigs:master Jun 23, 2021
@tjamet
Copy link
Contributor Author

tjamet commented Jun 28, 2021

no worries @njuettner thanks for yout support

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/bug Categorizes issue or PR as related to a bug. lgtm "Looks good to me", indicates that a PR is ready to be merged. provider/aws size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants