📜 ⬆️ ⬇️

CoreDNS - DNS server for the cloud native world and Service Discovery for Kubernetes



Two weeks ago, the Open Source-project CoreDNS was marked with its next release - 008 . The authors call their product “a DNS server consisting of a chain of intermediate components (middleware), each of which implements some kind of DNS capability.” Remarkably, they have already managed to achieve the inclusion of CoreDNS in the list of official projects of the CNC organization (Cloud Native Computing Foundation), adding to the ranks of Kubernetes, Prometheus, CNI , containerd , rkt and other developments actively used in the world of containers, microservices and native cloud applications. ( cloud native ).

How did CoreDNS appear, what is it intended for and how can it be used?
')

Meet CoreDNS


CoreDNS is a DNS server that appeared in early 2016 (under the free Apache License v2 license) as a fork of the fast Caddy web server written in the Go language. The HTTP server in Caddy is implemented by the httpserver package, the two most important types in which are Handler (the HTTP request processing function) and Middleware (the intermediate layer hooking one Handler to another, thus forming a chain of handlers). This approach with a chain of functions was adopted in CoreDNS, which allowed developers to describe their solution very succinctly: “CoreDNS is a DNS server concatenating middleware”.

The second fundamental part of the CoreDNS project is its succession from SkyDNS - service discovery, built on top of NoSQL-storage etcd and using DNS queries (specially created SRV-records) to detect available services. In fact, SkyDNS was an easy layer between etcd, where information about services was actually stored, and the DNS server through which this information became “publicly” accessible. Apparently, the active development of SkyDNS stopped about 7 months ago (with the addition of support for etcd 3), while commits in the CoreDNS codebase can be observed almost daily.

In CoreDNS, etcd was not limited to the only backend for the data displayed in the DNS records. At the moment, Kubernetes is also supported (which, however, as is well known, also uses etcd ...) , which allows authors to officially position CoreDNS as a replacement for kube-dns . (For details on how to try this replacement in action, read below.)

Note : The full history of the relationship of the mentioned DNS solutions: SkyDNS, CoreDNS, kube-dns - is intertwined even more closely than it seemed. The fact is that, firstly, kube-dns uses SkyDNS libraries to handle DNS queries coming into the hearth and Kubernetes services. And secondly, the main CoreDNS developer is SkyDNS original author - Miek Gieben - SRE from Google, who is also known in the Go community thanks to its DNS library . All this allows you to see in CoreDNS not the "competitor" kube-dns, but rather its evolution.

CoreDNS features


This server allows you to receive requests over UDP / TCP, TLS (RFC 7858) and gRPC. And it functions as:


Among other significant features of CoreDNS:


All of these functions (including even the primary and secondary server modes) are implemented by various modules, more precisely (in Caddy / CoreDNS terminology) middleware. Obviously, the ability to easily expand the creation of new middleware.


CoreDNS architecture, where the middleware is responsible for each function

John Belamaric, an architect at Infoblox and one of the leading CoreDNS developers, considers this feature to be the main one in the project:
There are many different DNS servers, there are even other solutions for discovering services based on DNS. But one of the main advantages of CoreDNS is how expandable and flexible this solution is. This makes it easy to adapt it to the dynamic, often changing world of cloud-native.

Why did CoreDNS take care of CNCF?


Here is how this event is explained on the project website:
Our goal is to make CoreDNS a DNS server and service discovery solution for cloud-native. CNCF, as an organization, is focused on improving cloud-native architectures. Thus, for us, this is a wonderful coincidence. Service discovery is a key component in CNCF's native cloud space, and CoreDNS excels in this role.

In a statement on behalf of CNCF itself, Chris Aniszczyk (COO at CNCF) made a comment that “CoreDNS provides important services for naming and effectively integrates with many other projects in the cloud-native category at CNCF”, as well as “CoreDNS is an attractive option for detecting Kubernetes services.

Note : At the moment, CoreDNS has an initial status (inception) among CNCF projects, which means that the technical committee must review this status in a year and decide on its future: remove, extend, upgrade to incubating or graduated.

Let's move from theory to practice.

CoreDNS as a Service Discovery for Kubernetes


As already stated in the note above, CoreDNS developers do not just offer an alternative to kube-dns - they interact with the Kubernetes community so that the result of their work will be useful for everyone. A good example is their initiative to create a specification describing DNS-based Service Discovery for Kubernetes. It appeared in order to “ensure the compatibility of the existing implementation in Kube-DNS and the new in CoreDNS”. Version 1.0.0 of this specification basically copies the behavior of kube-dns - it corresponds to releases of CoreDNS 005 and higher (offering, in addition to this, additional features when compared with kube-dns).

To start using CoreDNS as a Service Discovery in Kubernetes, developers have prepared a configuration ( ConfigMap and Deployment ) and even the deploy.sh Bash script for quick deployment. They took care of an example of how to use it (all further listings are taken from it) :

 $ ./deploy.sh 10.3.0.0/24 cluster.local 


The result of the script will be the following manifest:

 apiVersion: v1 kind: ConfigMap metadata: name: coredns namespace: kube-system data: Corefile: | .:53 { errors log stdout health kubernetes cluster.local { cidrs 10.3.0.0/24 } proxy . /etc/resolv.conf cache 30 } --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: coredns namespace: kube-system labels: k8s-app: coredns kubernetes.io/cluster-service: "true" kubernetes.io/name: "CoreDNS" spec: replicas: 1 selector: matchLabels: k8s-app: coredns template: metadata: labels: k8s-app: coredns annotations: scheduler.alpha.kubernetes.io/critical-pod: '' scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]' spec: containers: - name: coredns image: coredns/coredns:latest imagePullPolicy: Always args: [ "-conf", "/etc/coredns/Corefile" ] volumeMounts: - name: config-volume mountPath: /etc/coredns ports: - containerPort: 53 name: dns protocol: UDP - containerPort: 53 name: dns-tcp protocol: TCP livenessProbe: httpGet: path: /health port: 8080 scheme: HTTP initialDelaySeconds: 60 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 dnsPolicy: Default volumes: - name: config-volume configMap: name: coredns items: - key: Corefile path: Corefile --- apiVersion: v1 kind: Service metadata: name: kube-dns namespace: kube-system labels: k8s-app: coredns kubernetes.io/cluster-service: "true" kubernetes.io/name: "CoreDNS" spec: selector: k8s-app: coredns clusterIP: 10.3.0.10 ports: - name: dns port: 53 protocol: UDP - name: dns-tcp port: 53 protocol: TCP 

The Corefile directive indicated here (in Corefile ) tells Kubernetes middleware from CoreDNS that it is necessary to service PTR requests for the reverse zone 0.3.10.in-addr.arpa .

It remains to transmit the result to Kubernetes for execution:

 $ ./deploy.sh 10.3.0.0/24 | kubectl apply -f - configmap "coredns" created deployment "coredns" created service "kube-dns" configured 

... and make sure that the new DNS server really worked:

 $ kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools Waiting for pod default/dnstools to be running, status is Pending, pod ready: false If you don't see a command prompt, try pressing enter. # host kubernetes kubernetes.default.svc.cluster.local has address 10.3.0.1 # host kube-dns.kube-system kube-dns.kube-system.svc.cluster.local has address 10.3.0.10 # host 10.3.0.1 1.0.3.10.in-addr.arpa domain name pointer kubernetes.default.svc.cluster.local. # host 10.3.0.10 10.0.3.10.in-addr.arpa domain name pointer kube-dns.kube-system.svc.cluster.local. 

How does this look on the side of CoreDNS itself? Here is an example for the case of a cluster of two CoreDNS replicas, between which DNS query balancing is done:
 #     CoreDNS $ kubectl get --namespace kube-system pods NAME READY STATUS RESTARTS AGE coredns-3558181428-0zhnh 1/1 Running 0 2m coredns-3558181428-xri9i 1/1 Running 0 2m heapster-v1.2.0-4088228293-a8gkc 2/2 Running 0 126d kube-apiserver-10.222.243.77 1/1 Running 2 126d kube-controller-manager-10.222.243.77 1/1 Running 2 126d kube-proxy-10.222.243.77 1/1 Running 2 126d kube-proxy-10.222.243.78 1/1 Running 0 126d kube-scheduler-10.222.243.77 1/1 Running 2 126d kubernetes-dashboard-v1.4.1-gi2xr 1/1 Running 0 24d tiller-deploy-3299276078-e8phb 1/1 Running 0 24d #     $ kubectl logs --namespace kube-system coredns-3558181428-0zhnh 2017/02/23 14:48:29 [INFO] Kubernetes middleware configured without a label selector. No label-based filtering will be performed. .:53 2017/02/23 14:48:29 [INFO] CoreDNS-005 CoreDNS-005 10.2.6.127 - [23/Feb/2017:14:49:44 +0000] "AAAA IN kubernetes.default.svc.cluster.local. udp 54 false 512" NOERROR 107 544.128µs 10.2.6.127 - [23/Feb/2017:14:49:44 +0000] "MX IN kubernetes.default.svc.cluster.local. udp 54 false 512" NOERROR 107 7.576897ms 10.2.6.127 - [23/Feb/2017:14:49:52 +0000] "A IN kube-dns.kube-system.default.svc.cluster.local. udp 64 false 512" NXDOMAIN 117 471.176µs 23/Feb/2017:14:49:52 +0000 [ERROR 0 kube-dns.kube-system.default.svc.cluster.local. A] no items found 10.2.6.127 - [23/Feb/2017:14:50:00 +0000] "PTR IN 10.0.3.10.in-addr.arpa. udp 40 false 512" NOERROR 92 752.956µs #     $ kubectl logs --namespace kube-system coredns-3558181428-xri9i 2017/02/23 14:48:29 [INFO] Kubernetes middleware configured without a label selector. No label-based filtering will be performed. .:53 2017/02/23 14:48:29 [INFO] CoreDNS-005 CoreDNS-005 10.2.6.127 - [23/Feb/2017:14:49:44 +0000] "A IN kubernetes.default.svc.cluster.local. udp 54 false 512" NOERROR 70 1.10732ms 10.2.6.127 - [23/Feb/2017:14:49:52 +0000] "A IN kube-dns.kube-system.svc.cluster.local. udp 56 false 512" NOERROR 72 409.74µs 10.2.6.127 - [23/Feb/2017:14:49:52 +0000] "AAAA IN kube-dns.kube-system.svc.cluster.local. udp 56 false 512" NOERROR 109 210.817µs 10.2.6.127 - [23/Feb/2017:14:49:52 +0000] "MX IN kube-dns.kube-system.svc.cluster.local. udp 56 false 512" NOERROR 109 796.703µs 10.2.6.127 - [23/Feb/2017:14:49:56 +0000] "PTR IN 1.0.3.10.in-addr.arpa. udp 39 false 512" NOERROR 89 694.649µs 

To disable logging of all DNS queries (a large load on the disk for real use), it is enough to remove the log stdout line from the Corefile .

Important : the authors warn that in the case of using the Google Container Engine (GKE) the described example will not work due to additional processes that do not allow replacing the standard kube-dns. There is a way to solve this problem, but officially it has not yet been documented / announced by them.

CoreDNS for Minikube


In the case of local launch of Kubernetes with Minikube, there is a similar problem: the addon manager used in it periodically checks (and maintains) the state of the configurations of all installed add-ons, one of which is kube-dns. To prevent this manager from interfering with the work of CoreDNS, there is a simple solution .

It consists in changing the list of installed add-ons for minikube:

 $ minikube addons list - dashboard: enabled - default-storageclass: enabled - kube-dns: enabled - heapster: disabled - ingress: disabled - registry-creds: disabled - addon-manager: enabled $ minikube addons disable kube-dns kube-dns was successfully disabled $ minikube addons list - heapster: disabled - ingress: disabled - registry-creds: disabled - addon-manager: enabled - dashboard: enabled - default-storageclass: enabled - kube-dns: disabled 

This setting must be done before applying the CoreDNS configuration in Kubernetes (that is, before running kubectl apply -f from the example above). And after applying this configuration, you will still need to remove ReplicationController from kube-dns, since disabling the add-on does not automatically do this:

 $ kubectl get -n kube-system pods NAME READY STATUS RESTARTS AGE coredns-980047985-g2748 1/1 Running 1 36m kube-addon-manager-minikube 1/1 Running 0 9d kube-dns-v20-qzvr2 3/3 Running 0 1m kubernetes-dashboard-ks1jp 1/1 Running 0 9d $ kubectl delete -n kube-system rc kube-dns-v20 replicationcontroller "kube-dns-v20" deleted 

Conclusion


CoreDNS is an interesting project, with real perspectives given by its convincing legacy (experience from the time of SkyDNS), close cooperation with the core community (Kubernetes and Go), recognition at the CNCF and, of course, a modern approach to implementation.

Read also in our blog on related topics:

Source: https://habr.com/ru/post/331872/


All Articles