Redundant DNS lookups
Some applications that need to resolve external DNS domains, when running in a container, if we catch packets in the container’s network namespace for dns messages (udp port 53), we may find that several redundant attempts are made before they resolve correctly.
Here are the packets I grabbed while ping google.com
in the container’s network namespace.
|
|
It can be seen that the following domains were queried in turn before the final (penultimate lines 3 and 4) correct resolution, and both IPv4 and IPv6 were queried.
google.com.default.svc.cluster.local.
google.com.svc.cluster.local.
google.com.cluster.local.
google.com.lan.
But all 8 of these queries failed because no such domain exists.
kubernetes container domain name resolution
To explain the above phenomenon, we need to start with kubernetes container domain name resolution.
The domain name resolution of containers running on kubernetes is based on the /etc/resolv.conf
file, just like Linux in general. Here are the contents of this file in the container.
The nameserver is the svc IP of kube-dns in the kubernetes cluster, and the nameserver of all containers in the cluster is set to kube-dns.
So what do search
and ndots
do?
search and ndots
Before explaining search and ndots, there is a concept that needs to be understood: FQDN (Fully qualified domain name).
FQDN is the full domain name, generally speaking, the domain name ends up with .
ends in FQDN, for example, google.com.
is FQDN, but google.com
is not.
For FQDN, the OS will query the DNS server directly. what about non-FQDN? Here is where search and ndots come into play.
ndots
indicates the number of .
, if the number of .
in the domain name is not less than ndots
, then the domain name is an FQDN and the operating system will query directly; if the number of .
in the domain name is less than ndots
, the operating system will query in the search
search domain.
For example, in the above example, ndots
is 5, the domain name google.com
does not end with .
, and the number of .
is less than 5, so the OS will search in default.svc.cluster.local svc.cluster.local cluster.local lan
, where the first 3 search domains are injected by kubernetes, and the last lan
is the OS default search domain.
The default value of ndots
is 1, which means that as long as the domain has a .
, the OS will assume it is an absolute domain and query it directly.
The upper limit of ndots
is 15.
|
|
Why kubernetes uses search domains
Why? Let’s look at the code first.
|
|
|
|
kubernetes search domains
As seen in the function generateSearchesForDNSClusterFirst
, there are three search domains: nsSvcDomain, svcDomain, and clusterDomain.
The reason why kubernetes sets up search domains is to facilitate user access to services.
For example, Pod a under default namespace, if you access service b under the same namespace, you can access it directly by using b. This is done by using the nsSvcDomain search domain default.svc.cluster.local
.
Similarly, for services under different namespace, you can use ${service name}. ${namespace name}
to access it, which is done by svcDomain search domain.
The clusterDomain is designed to facilitate access to non-kubernetes domains in the same domain, for example, if you set the domain of kubernetes to ieevee.com
, then for the s.ieevee.com
domain, you can access it directly using s
, provided of course that the current (Yes. The search domain has priority)
ndots default value
The default value of ndots
is written dead, 5.
Why is it 5?
This is explained by thockin in issue 33554 and is summarized as follows.
- kubernetes needs to support fast access to services under the same namespace, e.g.
name
, so ndots>=1, corresponding to the search domain$namespace.svc.$zone
- kubernetes needs to support fast access to services across namespaces, e.g.
kubernetes.default
, so ndots>=2, which corresponds to the search domainsvc.$zone
- kubernetes needs to support fast access to non-service names under the same namespace and across namespaces, e.g.
name.namespace.svc
, so ndots>=3, corresponding to the search domain$zone
- kubernetes needs to support access to each pod in a statefulset, e.g.
mysql-0.mysql.default.svc
, so ndots>=4 - kubernetes needs to support SRV records (
_$port._$proto.$service.$namespace.svc.$zone
), so ndots>=5