Skip to content

DNS support for Windows#1412

Merged
mavenugo merged 2 commits intomoby:masterfrom
msabansal:dnsv2
Sep 21, 2016
Merged

DNS support for Windows#1412
mavenugo merged 2 commits intomoby:masterfrom
msabansal:dnsv2

Conversation

@msabansal
Copy link
Contributor

This PR adds support for DNS for windows. In Windows the DNS resolver will listen on the gateway for the network which is routable from each container. If the name can be resolved we reply back with a positive answer. If the name can't be resolved we reply with a negative answer and the dns client in the container takes care of forwarding the queries to other DNS servers

Signed-off-by: msabansal [email protected]

}

n.startResolver()

Copy link

Choose a reason for hiding this comment

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

@msabansal Can a container be connected to only one network in Windows ? Even if that is the case today for nat networks I think we should consider the possibility in future a container can be connected to multiple networks. Hence the resolver instance should be associated with the sandbox and not per network. We already have platform specific files, sandbox_dns_unix.go and sandbox_dns_windows.go to abstract out the implementation details of startResolver.

The name/ip lookup functions are not platform specific and the service DB svcRecords is already keyed by the network ID. So the lookup functions ResolveName etc. can remain in sandbox.go and doesn't have to be refactored.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reason we have the resolver associated with the network is we can't distinguish a sandbox based on the request. There is a single resolver listening on the gateway IP of the network. The IP is routable from the container. In windows DNS servers are associated with a network adapter (endpoint). If there are multiple networks we will have multiple endpoints each with it's own list of dns servers (which will be the gateway IP plus any other user supplied dns servers).

Copy link

Choose a reason for hiding this comment

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

A container connected to multiple networks should be able to resolve the service names in any network its connected to. This is done by walking through all the end-points in resolveName and lookup the service DB of the network to which the EP belongs.

For Windows containers if the query from the container can be associated with only one of the networks (depending on which interface the client sends the query on) is there any way to search the other networks as well ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. Windows DNS resolver inside the container would send out a new query for every endpoint the container is connected to so this should not be an issue. Every network connected to the container will get a query and will be able to resolve the name.

@sanimej
Copy link

sanimej commented Aug 29, 2016

docker run has the following dns specific config options; --dns, --dns-opt and --dns-search. Will any of this be used for Windows containers ? If they are not relevant will the config be blocked ?

ep.generic[netlabel.DNSServers] = dns
}
}

Copy link

Choose a reason for hiding this comment

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

External nameservers are not a property of the endpoints. Since the windows DNS server will only try to resolve the container names and not doing the proxying (ie: forwarding queries to external servers) why is this necessary ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have added this to support the --dns server options. These servers will be passed on to HNS for configuring the container. In windows dns servers are specific to network adapters and are not universal as in linux

Copy link
Contributor

Choose a reason for hiding this comment

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

@msabansal its fine to have windows network adapters to have specific dns servers. But from Docker POV, the configuration is per container and this configuration is passed to libnetwork when the sandbox is created. Shouldn't we reuse that and use it per-endpoint instead of adding a new option per endpoint ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mavenugo With the current libnetwork model you can have an endpoint created before the sandbox is created. We don't allow updating endpoints after they have been created. We need the DNS information before endpoint creation and the current model doesn't guarantee it.

@sanimej
Copy link

sanimej commented Aug 29, 2016

One of the use cases we have had is to be able to run a DNS server in a container and use that as the resolver for other containers. Can you confirm that it will work for Windows as well ?

@sanimej
Copy link

sanimej commented Aug 29, 2016

In Windows the DNS resolver will listen on the gateway for the network which is routable from each container.

If the host is already running a DNS server and using the default config it will bind port 53 on all IPs. In that case setting up the internal DNS on the gateway IP will fail. Will this be a limitation or are there any alternatives ? In Linux we explicitly setup the listener in the container namespace on a random port and do the port translation from port 53 to this random port to not break this use case.

@msabansal
Copy link
Contributor Author

One of the use cases we have had is to be able to run a DNS server in a container and use that as the resolver for other containers. Can you confirm that it will work for Windows as well ?
This cannot be supported with our current implementation. There is no way for us to execute a query in the context of another container (particularly for Hyperv containers which are default on developer machines)

If the host is already running a DNS server and using the default config it will bind port 53 on all IPs. In that case setting up the internal DNS on the gateway IP will fail. Will this be a limitation or are there any alternatives ? In Linux we explicitly setup the listener in the container namespace on a random port and do the port translation from port 53 to this random port to not break this use case.

Yes that is a limitation which can't be avoided. We have no port translation facility available on windows to enable this.

@sanimej
Copy link

sanimej commented Aug 30, 2016

We currently support the concept of container scoped aliases; ie: one container can add an alias for another container's name using --link option. In the example below only for c2, web is an alias for c1.

vagrant@net-1:~$ docker run -d --net docker --name c1 busybox top
83006320f67d176ff29a9d07405e2433c759a45149650039bb8930dcae915f73
vagrant@net-1:~$ docker run -d --net docker --name c2 --link c1:web busybox top
09156b7efd49196048fd5b9093107d3da4b0c58edd4a8157a2513d0f7a2cdc24
vagrant@net-1:~$ docker exec -it c2 sh
/ # nslookup c1
Server:    127.0.0.11
Address 1: 127.0.0.11

Name:      c1
Address 1: 172.18.0.2 c1.docker
/ # nslookup web
Server:    127.0.0.11
Address 1: 127.0.0.11

Name:      web
Address 1: 172.18.0.2 c1.docker
/ # 

I think this can't be supported in Windows because of resolver being at the network level and not per container. This should also be mentioned in the caveats with other limitations we have identified.

@msabansal
Copy link
Contributor Author

@sanimej Incorporated the changes.

Not sure why this test is failing:
--- FAIL: TestNetworkRequest (0.02s)
utils_test.go:226: exected 172.17.0.0/16. got 172.18.0.0/16

Don't think I have any changes that should impact this. I am trying to figure it out

@sanimej
Copy link

sanimej commented Sep 2, 2016

--- FAIL: TestNetworkRequest (0.02s)

Yes, this failure is not related to your changes. This has been fixed in the master. If you rebase to the latest master it should pass.

Copy link
Contributor

@mavenugo mavenugo left a comment

Choose a reason for hiding this comment

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

Overall the code looks simple & clean. 1 minor comment regarding a change to public endpoint API which I think we can avoid.

@mavenugo
Copy link
Contributor

@msabansal can you please rebase & resolve the conflicts ?

@msabansal
Copy link
Contributor Author

@mavenugo Working on it. Getting it done by EOD

network.go Outdated
// ResolveService returns all the backend details about the containers or hosts
// backing a service. Its purpose is to satisfy an SRV query
ResolveService(name string) ([]*net.SRV, []net.IP)

Copy link

Choose a reason for hiding this comment

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

These Resolve methods are defined in the DNSBackend interface. Please remove it from the Network interface.

Its not necessary in the Sandbox interface either where its currently defined. That can be removed as well.

@msabansal
Copy link
Contributor Author

@mavenugo Done. There is one test failing but I don't think its related. I will take a look at the test soon.


func (n *network) startResolver() {
n.resolverOnce.Do(func() {
log.Warnf("Launching DNS server for network", n.Name())
Copy link

Choose a reason for hiding this comment

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

This should be log.Debugf

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Accepted. Will fix all the logging related stuff asap.

for _, subnet := range hnsresponse.Subnets {
if subnet.GatewayAddress != "" {
resolver := NewResolver(subnet.GatewayAddress, false, "", n)
log.Warnf("Binding a resolver on network %s gateway %s", n.Name(), subnet.GatewayAddress)
Copy link

Choose a reason for hiding this comment

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

This should be log.Debugf

@sanimej
Copy link

sanimej commented Sep 20, 2016

@msabansal Other than couple of nits the changes LGTM. I will try with the changes to confirm there is no collateral for Linux. Will update by tomorrow morning.

@mavenugo
Copy link
Contributor

Thanks @msabansal

LGTM

@sanimej
Copy link

sanimej commented Sep 20, 2016

Verified on docker master with these changes. Looks ok for the linux name resolution. I think we are good to merge if you can address couple of comments on changing Warn messages to Debug.

Signed-off-by: msabansal <[email protected]>
Signed-off-by: msabansal <[email protected]>
@mavenugo
Copy link
Contributor

LGTM

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.

4 participants