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

Source external DNS queries from container namespace #895

Merged
merged 1 commit into from
Mar 4, 2016

Conversation

sanimej
Copy link

@sanimej sanimej commented Jan 24, 2016

Signed-off-by: Santhosh Manohar [email protected]

@mavenugo mavenugo changed the title Retain 1.9 behavior when --dns IP is container's loopback Enhance DNS resolution using self DNS server Jan 25, 2016
@mavenugo
Copy link
Contributor

this enhancement must work for both loopback IPs and Self-IP address.
Given the fact that 1.10 supports --ip, it is something to be considered as well.

@dvavili
Copy link

dvavili commented Feb 16, 2016

@sanimej @mavenugo
I am working in the Contiv team and tried this patch with docker1.10 to see if there are any issues with the co-existence of embedded DNS and external DNS server(s) provided by Contiv plugin. As mentioned by @jainvipin in moby/moby#19474 (comment), we were hitting issues in a multi-tenant environment as Contiv plugin launches a DNS server per tenant.

With the following fix, we see that the multi-tenant DNS servers are being honored and handled as expected:
https://gist.github.com/DivyaVavili/cae8636554985093c33f

PTAL and incorporate as necessary. I can open a PR for this if required.

@sanimej
Copy link
Author

sanimej commented Feb 16, 2016

@DivyaVavili The implementation in this PR to generate the queries from the container namespace might have some changes. We are also considering the option of generating all external queries from the container namespace by default. I will ping you when the updated changes are available for you to try it out.

@dvavili
Copy link

dvavili commented Feb 16, 2016

Sure @sanimej... Thanks for the update... Will wait for the changes...

@sanimej sanimej changed the title Enhance DNS resolution using self DNS server Source external DNS queries from container namespace Mar 2, 2016
@mavenugo
Copy link
Contributor

mavenugo commented Mar 2, 2016

LGTM

@mavenugo
Copy link
Contributor

mavenugo commented Mar 2, 2016

btw, I tried the patch to confirm if the DNS query is originated from the container namespace and the following capture (in a fake external DNS in the same network confirmed it).

$ sudo docker run -itd --net=demo1 --dns=172.18.0.2 --name=c1dns3 sanimej/ubuntu sh
1d855ceb9c44d0348c6870cdf6e75161c885d0cb56a3011ba5f7082bc5d42707

$ sudo docker exec c1dns3 dig www.google.com

# from inside 172.18.0.2 container

$ tcpdump -nnvvXSs 1514 -i eth0
03:10:28.697911 IP (tos 0x0, ttl 64, id 27702, offset 0, flags [DF], proto UDP (17), length 71)
    172.18.0.4.57490 > 172.18.0.2.53: [bad udp cksum 0x586f -> 0xee9b!] 8225+ [1au] A? www.google.com. ar: . OPT UDPsize=4096 (43)
    0x0000:  4500 0047 6c36 4000 4011 7645 ac12 0004  E..Gl6@[email protected]....
    0x0010:  ac12 0002 e092 0035 0033 586f 2021 0120  .......5.3Xo.!..
    0x0020:  0001 0000 0000 0001 0377 7777 0667 6f6f  .........www.goo
    0x0030:  676c 6503 636f 6d00 0001 0001 0000 2910  gle.com.......).
    0x0040:  0000 0000 0000 00

Yes. it works as advertised. now the behavior is identical to 1.9.x and before.

LGTM.

c := &dns.Client{Net: w.LocalAddr().Network()}
addr := fmt.Sprintf("%s:%d", r.extDNS[i], 53)
var extConn net.Conn
r.sb.execFunc(func() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's not get into the container namespace every time in the critical path when we need to make an external query. Let's create these connections during sandbox creation time and then just it here when we need to do external query.

Copy link
Author

Choose a reason for hiding this comment

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

@mrjana Yes, creating the connection during the query is sub-optimal. First I tried creating the connection as part of the SetupFunc. But the Dial fails; probably because the external connectivity is not fully setup yet.. The error I was getting was "dial udp 8.8.8.8:53: connect: network is unreachable".

Can we do this instead; on a first external query lets create the connection and let it persist after that ?

Copy link
Contributor

Choose a reason for hiding this comment

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

@sanimej Yes I am fine with lazy init but initializing once.

err = co.WriteMsg(query)
if err != nil {
log.Debugf("Send to DNS server failed, %s", err)
if proto == "tcp" {
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we do this in a defer? So that we will know we always cleanup now and in future if more error conditions or other paths are introduced in the code path.

Copy link
Author

Choose a reason for hiding this comment

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

Since we are looping through all the external servers if the read or write fails for the first one the other servers have to be tried.. To handle it in a defer a list of connections have to be maintained making it a bit kludgy. This looked cleaner. wdyt ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah but you don't need to maintain a list. defer is like a closure and will do variable capture of the co at that iteration to create the closure defer function and push it into a stack and it will execute all of those defer functions in that stack when we exit the function. All take care automatically. No need for us to maintain any list of connections.

@sanimej
Copy link
Author

sanimej commented Mar 3, 2016

@mrjana Addressed the comments.. PTAL

extConn.SetDeadline(time.Now().Add(extIOTimeout))
co := &dns.Conn{Conn: extConn}

cleanup := func() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not what I meant :-)

Just do this instead of defining a cleanup func like this:

defer func() {
     if proto == "tcp" {
         co.Close()
     }
}

and remove the defers that you added in all the error paths. That way it will always be closed at the end of the function and you don't need to remember to add them in all error paths. That is what the main benefit I was trying to get from the change.

@mrjana
Copy link
Contributor

mrjana commented Mar 3, 2016

Thanks @sanimej for taking care of all the comments.

LGTM. Will merge when CI is green.

mavenugo added a commit that referenced this pull request Mar 4, 2016
Source external DNS queries from container namespace
@mavenugo mavenugo merged commit 5718b0b into moby:master Mar 4, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants