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

Only allow 1 CNAME when querying for a service. #4328

Merged
merged 5 commits into from
Jul 10, 2018
Merged

Conversation

mkeeler
Copy link
Member

@mkeeler mkeeler commented Jul 2, 2018

This just makes sure that if multiple services are registered with unique service addresses that we don’t blast back multiple CNAMEs for the same service DNS name and keeps us within the DNS specs.

The general rule in place now:

  1. If any service node has an addr that is an IP then no CNAMEs will be returned (according to the spec if a name resolves to a CNAME no other data should be returned for that name including other A records).
  2. If all service nodes have addrs that are CNAMES only 1 is returned.

This just makes sure that if multiple services are registered with unique service addresses that we don’t blast back multiple CNAMEs for the same service DNS name and keeps us within the DNS specs.
@pearkes pearkes added this to the 1.2.1 milestone Jul 2, 2018
agent/dns.go Outdated
// only allow at most 1 CNAME record
switch records[0].(type) {
case *dns.CNAME:
if haveCNAME || !allowCNAME {
Copy link
Contributor

Choose a reason for hiding this comment

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

My recommendation would be to add some detailed comments here. It took me awhile reading the code to figure out what was going on and I'm questioning whether I even understood it correctly. It'd help to have a 2nd source helping me here.

Copy link
Member Author

@mkeeler mkeeler Jul 3, 2018

Choose a reason for hiding this comment

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

I just refactored it a lot and it should be much more straight forward. I also added a comment but hopefully this is much easier to follow.

Now we hold onto the first CNAME RR (+ associated RRs) until the end of the loop. If we have nothing in the Answer section then we add the CNAME answer.

@mkeeler mkeeler requested a review from banks July 9, 2018 16:17
Copy link
Member

@banks banks left a comment

Choose a reason for hiding this comment

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

Seems good. My question might be invalid and due to bad understanding of the context this is using in which case I'll accept...

agent/dns.go Outdated
switch records[0].(type) {
case *dns.CNAME:
// keep track of the first CNAME + associated RRs but don't add to the resp.Answer yet
// this will only be added if no non-CNAME RRs are found
Copy link
Member

Choose a reason for hiding this comment

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

Is the first one always correct? For example could this result in CNAMEs always resolving to a single instance of a service and so sending all load there versus the expected random order to spread the load?

Copy link
Member Author

Choose a reason for hiding this comment

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

The node list gets shuffled in the serviceLookup function prior to actually formatting so it will be randomized which CNAME gets used.

This is kind of the best we can always do when mapping a single service name with fqdns for the service address.

One other approach I thought of would be to check if we knew the A/AAAA RR for the name pointed to by the CNAME and instead propagate those records up and hide the CNAME all together. This would work when the service address is a name known to Consul (either it is authoritative for it like with being a node name or Consul has recursors configured and can lookup the name that way).

However because this wouldn't work in a general case like the one that prompted this change I didn't think that was the route we should go.

Copy link
Member

Choose a reason for hiding this comment

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

Shuffling done higher up is 👍

@mkeeler mkeeler merged commit ad3d5e3 into master Jul 10, 2018
@mkeeler mkeeler deleted the bugfix/prevent-multi-c branch July 10, 2018 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants