1. About DNS
1.1 What the DNS Service Is For
DNS provides a mapping service from domain names to IPs. For example, you type https://www.chenshaowen.com into a browser to open a page, but the data link communicates over IP and cannot recognize www.chenshaowen.com. This is where a DNS lookup comes in: the input is www.chenshaowen.com and the result is an IP address.
As you can see, DNS provides a mnemonic: we do not have to care about IP addresses and how they change, and only need to remember a string of English characters to find a service.
One common service discovery mechanism is a configuration management center that stores Key/Value pairs, such as Consul, ZooKeeper, and Etcd. The functionality DNS provides can also meet the service discovery needs of a microservice architecture, and Kubernetes takes exactly this approach.
Starting with version 1.11, Kubernetes uses CoreDNS in place of KubeDNS as its built-in DNS service.
1.2 resolv.conf
/etc/resolv.conf is the configuration file of the DNS client, and it has four main parts:
- nameserver, the IP address of the DNS server
- domain, the suffix of the local domain name
- search, the domain suffixes to search
- sortlist, which sorts query results in a specific order
The resolver only uses domain and search when it hits a domain name it cannot resolve. For example, when accessing http://abc/index.html, the resolver cannot resolve abc, so it appends the domain or search configuration as a suffix and keeps resolving. When search is configured, domain is ignored.
2. CoreDNS
2.1 Introduction
CoreDNS is a CNCF graduated project. It is a modular, pluggable DNS server built on top of Caddy.
Every plugin follows a specific interface contract. The Corefile uses a DSL to define the DNS service, which makes it easy to enable various plugins and customize the DNS service. Here is an example:
| |
This configuration exposes a DNS server listening on port 8000, matching different handling logic per domain name. Each piece of logic loads the specified plugins to handle requests.
2.2 Related Plugins
Commonly used plugins include:
- hosts, configures hosts resolvable across the whole cluster; note that the domain suffix must match search, for example cluster.local, otherwise nodelocaldns cannot report resolutions to coredns
- errors, logs errors to stdout
- health, provides a health report endpoint
- kubernetes, resolves to the IP addresses of Kubernetes cluster services
- prometheus, provides a Prometheus metrics endpoint
- proxy, forwards queries outside the cluster domain to a designated resolver
- cache, enables caching
- loop, detects infinite loops and breaks them
- reload, automatically reloads the Corefile for hot updates
- loadbalance, a DNS load balancer
2.3 Cluster ConfigMap Configuration
- View the CoreDNS service:
| |
- View the CoreDNS configuration
| |
The default DNS port is 53. Domain names in the cluster.local, in-addr.arpa, and ip6.arpa formats are resolved to the internal IP addresses of Kubernetes.
The fallthrough setting in hosts is very important: unmatched domain names continue on to the next match.
2.4 Operations Recommendations
If you are updating in a production environment, it is recommended to do a canary update at the container level only, rather than letting CoreDNS change nodes.
This is because /etc/resolv.conf may differ between nodes, which would make it impossible to roll the configuration back.
3. NodelocalDNS
3.1 Introduction
To avoid frequent queries to CoreDNS when Pods resolve DNS, NodelocalDNS runs a DNS cache as a DaemonSet on every node to improve cluster performance.
The principle behind NodelocalDNS is to run a Pod in hostNetwork mode and create a network interface bound to the local DNS IP address. When a Pod on a node requests DNS resolution, it is intercepted by NodelocalDNS. NodelocalDNS completes the resolution by reading the cache or requesting DNS from upstream.
3.2 Cluster ConfigMap Configuration
- View the NodelocalDNS service
| |
- View the NodelocalDNS configuration
| |
It also serves DNS on port 53, but NodelocalDNS applies different resolution strategies depending on the domain name. Domain names in the cluster.local, in-addr.arpa, and ip6.arpa formats are resolved by CoreDNS and then cached locally, while everything else is resolved by the node’s DNS and then cached.
3.3 Pointing a Node’s DNS at NodelocalDNS
- Edit the parameters
| |
Change the setting that points at CoreDNS
| |
to point at the NodelocalDNS IP address
| |
- Restart Kubelet
| |
Pods newly created on this node will then use NodelocalDNS for DNS resolution.
3.4 Operations Recommendations
In production, NodeLocalDNS is sometimes not deployed and CoreDNS is used directly instead.
This is not a good choice, mainly because: if you want to switch DNS services, changing the CoreDNS configuration affects the entire cluster, and you cannot modify only a designated node for a canary test.
For production environments it is strongly recommended to deploy NodeLocalDNS, which guarantees cluster stability.
4. DNS Resolution in a Kubernetes Pod
- Create a Pod for testing
| |
| |
- View the DNS resolution configuration
| |
- Resolving a normal internal service
| |
Resolution path: nodelocaldns -> cache -> coredns -> return IP
This involves the logic of search adding a domain suffix, which is not covered here.
- Resolving a non-existent service
| |
Resolution path: nodelocaldns -> the node’s configured DNS -> not found
- Resolving a normal external service
| |
Resolution logic: nodelocaldns -> the node’s configured DNS -> return IP
5. ExternalName - CNAME Resolution
An ExternalName Service is a special case of Service. It has no selector and can be used to give an external service an internal alias.
- Create an ExternalName Service
| |
| |
- Test access to the internal service
| |
chenshaowen.default will be mapped to www.chenshaowen.com, which is achieved through a DNS CNAME record.
