DigitalOcean: support multiple targets per endpoint#1595
DigitalOcean: support multiple targets per endpoint#1595k8s-ci-robot merged 6 commits intokubernetes-sigs:masterfrom
Conversation
|
Thanks for your pull request. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please follow instructions at https://git.k8s.io/community/CLA.md#the-contributor-license-agreement to sign the CLA. It may take a couple minutes for the CLA signature to be fully registered; after that, please reply here with a new comment and we'll verify. Thanks.
DetailsInstructions 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/test-infra repository. I understand the commands that are listed here. |
|
Welcome @tdyas! |
|
/assign @hjacobs |
7a34cd0 to
f19d0bc
Compare
|
/assign @Raffo |
|
cc @andrewsomething: Just a heads up in case anyone at DigitalOcean has an interest in external-dns or Kubernetes stuff. |
d0af711 to
ba05243
Compare
There was a problem hiding this comment.
Should we have this done before merging this PR or do you want to keep it like this? What are the consequences?
There was a problem hiding this comment.
Not implementing this TODO would leave the status quo in place which is that we would just retrieve all of the records that Records retrieves, just as the existing version of the provider does. (--domain-filter would still be applied to limit the provider to only those zones where external-dns is managing records.)
My concern here was for avoiding having to retrieve all of the records if the zone had potentially many records. #1429 was on my mind as it flagged too many API calls as a potential hazard in such cases.
This TODO is a nice to have but should not block landing this PR.
|
@andrewsomething should you be willing to maintain the DO provider, feel free to ping me here or on slack, we are trying to scale how we maintain providers and we would definitely be happy to have someone from DO maintain the DO provider 😄 |
7174db3 to
84e514b
Compare
|
/approve |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: Raffo, tdyas The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
map multiple DNS records with the same name/type into the external-dns which models such records as a single Endpoint with multiple entries in the Targets attribute. Solution: Generalize the solution introduced to the DigitalOcean provider by kubernetes-sigs#1595 by refactoring the mergeEndpointsByNameType function into the endpoint module. Then use that function in the RFC2136 provider. Authored-by: Tom Dyas <tom.dyas@gmail.com> Signed-off-by: Bogdan Dobrelya <bogdando@yahoo.com>
This PR teaches the DigialOcean provider how to support multiple targets per endpoint. (The DigitalOcean provider currently only supports one endpoint per target which other providers do support.)
The Problem
I am running nginx-ingress in DaemonSet mode with host networking enabled on my Kubernetes cluster. I want the IPs for every node running nginx-ingress to appear as
Arecords in DNS. First, because the DigitalOcean provider only supports one endpoint per ingress currently, only one of the A records is created which means the additional nginx-ingress pods will not receive traffic.Moreover, because
external-dnsbelieves that there should be multiple A records for the endpoint in question, the reconciliation loop never converges and external-dns continually sends update API calls every minute. This is not how external-dns seems intended to operate. (Indeed, with this PR, the reconciliation loop does converge and avoids sending an update every minute.)Solution
If the DigitalOcean API were like the AWS or GCP APIs, then the API representation of a DNS record would have an attribute that is a list of RR datas, and supporting multiple targets per endpoint would be as simple as setting that attribute to the list of targets. The DigitalOcean API is not like that though because it represents multiple A records as multiple "domain record" instances.
This representation is actually quite similar to the Linode API. The Linode provider models updates by expanding an endpoint with multiple targets into multiple domain records to be sent to the Linode API. I have taken that approach with this PR: The DigitalOcean provider now expands an endpoint with multiple targets into multiple
godo.DomainRecordinstances.Overview of the changes:
The provider's
Recordsmethod uses the newmergeEndpointsByNameTypefunction to combine multiplegodo.DomainRecords for the same DNS name into a singleendpoint.Endpointwith multiple targets. This maps the DigitalOcean representation to theexternal-dnsdata modelThe provider's
ApplyChangesmethod has been rewritten to compute a set ofdigitalOceanChangeCreate,digitalOceanChangeUpdate, anddigitalOceanChangeDeleteinstances representing how to modify thegodo.DomainRecordinstances associated with agodo.Domain. Computation of each type of change has been put into theprocessCreateActions,processUpdateActions, andprocessDeleteActionsfunctions.Tests: Lots more testing of individual functions. I added go-cmp to the project so I could use its Equal and Diff functions. These handle structs with nested pointers to other structs much better than the testify package. I did that so I could actually compare the *godo.DomainRecordEditRequest struct contained in the change structs. (Added a TODO to try and see if testify would be willing to allow custom matching functions.)
Upgraded godo to the latest just to keep it current.
gobumped the version of two other packages in the go.mod as well, not sure why it did that.This is currently in production for my cluster. Seems to be working nicely. I did some basic tests against production by deleting and adding some records and external-dns figures out what changed and fixes it. And the reconciliation loop actually converges.