{"id":8245,"date":"2023-12-05T00:15:58","date_gmt":"2023-12-05T00:15:58","guid":{"rendered":"https:\/\/cheapwindowsvps.com\/blog\/exploring-the-coredns-feature-in-kubernetes\/"},"modified":"2025-01-16T11:22:27","modified_gmt":"2025-01-16T11:22:27","slug":"exploring-the-coredns-feature-in-kubernetes","status":"publish","type":"post","link":"https:\/\/cheapwindowsvps.com\/blog\/exploring-the-coredns-feature-in-kubernetes\/","title":{"rendered":"Exploring the CoreDNS Feature in Kubernetes"},"content":{"rendered":"<p><div>In a previous post in this <a href=\"https:\/\/4sysops.com\/archives\/create-a-kubernetes-pod\/\" rel=\"nofollow noopener\" target=\"_blank\">Kubernetes guide<\/a>, you learned about <a href=\"https:\/\/4sysops.com\/archives\/deploying-stateful-applications-with-kubernetes-statefulsets\/\" rel=\"nofollow noopener\" target=\"_blank\">deploying stateful applications with Kubernetes StatefulSets<\/a>. Today&#8217;s post will discuss Kubernetes CoreDNS. Earlier versions of Kubernetes used <em>kube-dns<\/em> to provide service discovery and name resolution within the cluster, which was based on <em>dnsmasq<\/em> and <em>SkyDNS<\/em>. The kube-dns had many problems, such as <a href=\"https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2020-8559\" rel=\"nofollow noopener\" target=\"_blank\">security<\/a> vulnerabilities, scalability concerns, and higher latency, so starting with Kubernetes version 1.13, CoreDNS became the default cluster DNS server.<\/div>\n<\/p>\n<p><h2>How CoreDNS works<\/h2>\n<\/p>\n<p><p>CoreDNS is a modern, flexible, extensible DNS server with a modular architecture. You can easily extend it with plugins, and it has no scalability concerns. The Kubernetes cluster configured with Kubeadm runs CoreDNS as a <a href=\"https:\/\/4sysops.com\/archives\/kubernetes-guide-create-a-kubernetes-deployment\/\" rel=\"nofollow noopener\" target=\"_blank\">Deployment<\/a> with two replicas and exposes it with a kube-dns service in the <em>kube-system<\/em> namespace. The service name <em>kube-dns<\/em> is intended to offer backward compatibility with the legacy DNS server.<\/p>\n<\/p>\n<p><pre>kubectl get deploy -n kube-system<\/p><p>kubectl get svc -n kube-system<\/p><p><\/pre>\n<\/p>\n<p><div><a href=\"https:\/\/4sysops.com\/wp-content\/uploads\/2023\/12\/View-CoreDNS-deployment-and-service-in-the-cluster.png\" rel=\"nofollow noopener\" target=\"_blank\">View CoreDNS deployment and service in the cluster<\/a><\/p>\n<p><p>View CoreDNS deployment and service in the cluster<\/p>\n<\/div>\n<p><p>The above hyperlink takes the reader to a screenshot showing the Deployment and service objects. The second command also indicates the Cluster-IP of the kube-dns service. The following commands will help you view the service endpoints and the IP address of the Pods.<\/p>\n<\/p>\n<p><pre>Kubectl describe svc kube-dns -n kube-system<\/p><p>kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide<\/p><p><\/pre>\n<\/p>\n<p><div><a href=\"https:\/\/4sysops.com\/wp-content\/uploads\/2023\/12\/View-kube-dns-service-endpoints-and-the-IP-addresses-of-the-CoreDNS-Pods.png\" rel=\"nofollow noopener\" target=\"_blank\">View kube dns service endpoints and the IP addresses of the CoreDNS Pods<\/a><\/p>\n<p><p>View kube dns service endpoints and the IP addresses of the CoreDNS Pods<\/p>\n<\/div>\n<p><p>The first command displays the IP address of the CoreDNS service, while the second command reveals the IP addresses of the Pods acting as service endpoints. The primary nameserver for the Kubernetes cluster is represented by the CoreDNS service IP address, which in our case is <em>10.96.0.10<\/em>.<\/p>\n<\/p>\n<p><h2>Corefile\u2014the CoreDNS configuration file<\/h2>\n<\/p>\n<p><p>The DNS server&#8217;s behaviour is defined by a configuration file used by CoreDNS called the Corefile. This file enables you to configure DNS zones, plugins, the rules for forwarding, and other settings that manage DNS requests. In a Kubernetes cluster, the Corefile is saved in a <a href=\"https:\/\/4sysops.com\/archives\/configmap-in-kubernetes\/\" rel=\"nofollow noopener\" target=\"_blank\">ConfigMap<\/a> resource named <em>coredns<\/em>. The following command can be utilized to view it:<\/p>\n<\/p>\n<p><pre>kubectl get configmap coredns -n kube-system -o yaml<\/pre>\n<\/p>\n<p><div><a href=\"https:\/\/4sysops.com\/wp-content\/uploads\/2023\/12\/Viewing-the-CoreDNS-Corefile-in-YAML-format.png\" rel=\"nofollow noopener\" target=\"_blank\">Viewing the CoreDNS Corefile in YAML format<\/a><\/div>\n<\/p>\n<p><p>Let&#8217;s break down the Corefile for better understanding. The Corefile begins with a DNS zone name. The .:53 indicates that the CoreDNS server should handle all possible queries and listen on the default Port 53. All the keywords in the Corefile (e.g., errors, log, health, ready, kubernetes, and forward) are plugins that perform a particular task. The plugins are configured using directives, and the options for each directive vary with the plugin. Some plugins have no directives; some have one or more (required and optional). Let&#8217;s discuss some of the most common plugins.<\/p>\n<\/p>\n<ol>\n<li><strong>kubernetes:<\/strong> This is an essential plugin for implementing DNS-based service discovery in the Kubernetes cluster. It supports many directives that are worth discussing.\n<div><a href=\"https:\/\/4sysops.com\/wp-content\/uploads\/2023\/12\/CoreDNS-Kubernetes-plugin-configuration.png\" rel=\"nofollow noopener\" target=\"_blank\">CoreDNS Kubernetes plugin configuration<\/a><\/div>\n<p>The plugin&#8217;s syntax follows the pattern <em>kubernetes [zones]{}<\/em>, where <em>zones<\/em> specify the DNS zones for which the kubernetes plugin is authoritative. As per the screenshot, the <em>cluster.local <\/em>zone is for the default cluster domain, while <em>in-addr.arpa <\/em>and<em> ip6.arpa<\/em> are the reverse DNS zones for the IPv4 and IPv6 addresses, respectively. The curly braces include various directives for adjusting the plugin&#8217;s behavior.<\/p>\n<ul>\n<li>The <em>pods<\/em> directive is used to set the mode for handling IP-based A records for the Pods. It can have three possible values:<\/li>\n<li>\n<p>disabled\u2014Setting this mode means that the <em>kubernetes<\/em> plugin does not process Pod requests and returns an NXDOMAIN as a response when you try to query a Pod name. This is the default mode.<\/p>\n<\/li>\n<li>verified\u2014Setting this mode means the <em>kubernetes<\/em> plugin will process Pod requests and return the Pod&#8217;s IP address only if it exists in the same namespace. This mode is more secure but also increases the memory footprint of CoreDNS, since it needs to watch all Pods.<\/li>\n<li>\n<p>insecure\u2014Setting this mode means the <em>kubernetes<\/em> plugin will process Pod requests and return the Pod&#8217;s IP address without verifying that the IP address belongs to a Pod in the specified namespace. This mode is not secure because it can expose Pods in other namespaces. It is only there for backward compatibility with the legacy kube-dns.- The <em>fallthrough<\/em> directive helps pass the unhandled queries to the next plugin in the chain (e.g., forward). It allows the <em>kubernetes<\/em> plugin to delegate the reverse DNS queries to another plugin so it can focus on handling the DNS queries for the cluster domain (e.g., <em>cluster.local<\/em>) itself.<\/p>\n<\/li>\n<li>The <em>ttl<\/em> option allows you to set a custom TTL for the responses. The default value is 5 seconds, but you can set it between 0 and 3600.<\/li>\n<\/ul>\n<\/li>\n<li><strong>log:<\/strong> The log plugin has no directives and writes logs to the STDOUT. If you omit it in the Corefile, you will see no logging except errors, which are suitable for large clusters with many DNS requests.<\/li>\n<li><strong>errors:<\/strong> The <em>errors<\/em> plugin writes the error logs to the STDOUT. If you omit it in the Corefile, you will see no error logs, which could make troubleshooting any issues harder.<\/li>\n<li><strong>health: <\/strong>The <em>health<\/em> plugin enables a health check endpoint for the DNS server, allowing you to monitor the server&#8217;s status. The <em>lameduck 5s, <\/em>which you can see in the screenshot, is the duration in seconds (5 seconds, by default), for which the server delays the shutdown after receiving a SIGTERM signal. This duration is handy for a graceful shutdown without causing abrupt disruptions.<\/li>\n<li><strong>ready: <\/strong>The <em>ready<\/em> plugin enables a readiness check HTTP endpoint for the DNS server, which allows you to monitor when the server and all its plugins are ready to serve DNS requests. The ready plugin does not return OK when the server is in <em>lameduck<\/em> mode.<\/li>\n<li><strong>prometheus: <\/strong>This plugin enables Prometheus metrics for the DNS server, which allow you to monitor the CoreDNS server and troubleshoot any issues.<\/li>\n<li><strong>forward: <\/strong>The <em>forward<\/em> plugin allows you to forward DNS queries to other DNS servers that can handle them. It supports the UDP, TCP, and DNS-over-TLS (DoT) protocols and uses in-band health checking to detect and avoid unhealthy upstream servers. The <em>forward . \/etc\/resolv.conf<\/em>, which you can see in the screenshot, instructs the CoreDNS server to forward the DNS queries that could not be resolved by the kubernetes plugin to the upstream resolvers specified in the <em>\/etc\/resolv.conf<\/em> file of the Kubernetes node. The <em>max<\/em>concurrent 1000<em> directive limits the number of concurrent queries to 1000, which means the new queries will result in a REFUSED response.<\/em><\/li>\n<li><strong>cache: <\/strong>The <em>cache<\/em> plugin enables a frontend cache for DNS queries for up to 3600 seconds (default). The <em>cache 30<\/em>, which you can see in the screenshot, sets the caching TTL at 30 seconds.<\/li>\n<li><strong>loop: <\/strong>This plugin detects simple forwarding loops and halts the CoreDNS server when a loop is detected to prevent it from consuming too many resources on the node.<\/li>\n<li><strong>reload: <\/strong>The <em>reload<\/em> plugin allows automatic reload of the Corefile once it is changed.<\/li>\n<li><strong>loadbalance: <\/strong>The <em>loadbalance<\/em> plugin acts as a DNS load balancer to randomize the order of A, AAAA, and MX records returned in the answer.<\/li>\n<\/ol>\n<p><p>Please note that covering all plugins and their options is beyond the scope of this post. To learn more about CoreDNS plugins, check out the <a href=\"https:\/\/coredns.io\/plugins\/\" rel=\"nofollow noopener\" target=\"_blank\">official docs<\/a>.<\/p>\n<\/p>\n<p><h2>Changing the Corefile<\/h2>\n<\/p>\n<p><p>As stated earlier, the CoreDNS runs as a Deployment object in the Kubernetes cluster, which runs two Pods for redundancy. The Corefile is passed to these Pods as a ConfigMap, making it easier to edit the Corefile when needed.<\/p>\n<\/p>\n<p><pre><\/p><p># Run this command to view all CoreDNS Pods <\/p><p>kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide<\/p><p># Run this command to describe a CoreDNS Pod<\/p><p>kubectl describe pod coredns-5d78c9869d-7hhb5 -n kube-system<\/p><p><\/pre>\n<\/p>\n<p><a href=\"https:\/\/4sysops.com\/wp-content\/uploads\/2023\/12\/Understanding-how-the-Corefile-is-passed-to-the-CoreDNS-Pods-in-Kubernetes.png\" rel=\"nofollow noopener\" target=\"_blank\">Understanding how the Corefile is passed to the CoreDNS Pods in Kubernetes<\/a><\/p>\n<p><p>The first command lists all the Pods managed by the CoreDNS Deployment, and the second command describes a CoreDNS Pod. Don&#8217;t forget to specify your actual Pod name with the second command. The paragraph describes that the <em>coredns<\/em> ConfigMap is defined as a volume in the Pod. The volume is then mounted in the <em>\/etc\/coredns<\/em> container path as read-only, and finally, the <em>\/etc\/coredns\/Corefile<\/em> is passed as an argument to the <em>coredns<\/em> container that runs in the Pod.<\/p>\n<\/p>\n<p><p>To make any changes to the Corefile, you can edit the ConfigMap with this command:<\/p>\n<\/p>\n<p><pre>kubectl edit configmap coredns -n kube-system<\/p><p><\/pre>\n<\/p>\n<p><a href=\"https:\/\/4sysops.com\/wp-content\/uploads\/2023\/12\/Changing-the-CoreDNS-configuration-file-Corefile.png\" rel=\"nofollow noopener\" target=\"_blank\">Changing the CoreDNS configuration file Corefile<\/a><\/p>\n<p><p>The above command opens the ConfigMap object for in-place editing. For the demo, I changed the <em>pods<\/em> mode from <em>insecure<\/em> to <em>disabled<\/em>. The reload plugin periodically (30 seconds, by default) checks the Corefile by calculating the SHA512 checksum. When the file is changed, the plugin gracefully reloads it without causing any service disruption.<\/p>\n<\/p>\n<p><p>If you make significant changes to the Corefile, the Pods might not automatically detect the changes. In this case, you can kill the Pods manually with this command, and ReplicaSet will create new Pods with an updated configuration file for you.<\/p>\n<\/p>\n<p><pre>kubectl delete pods -n kube-system -l k8s-app=kube-dns<\/p><p>kubectl get pods -n kube-system -l k8s-app=kube-dns<\/p><p><\/pre>\n<\/p>\n<p><p><a href=\"https:\/\/4sysops.com\/wp-content\/uploads\/2023\/12\/Forcing-the-recreation-of-CoreDNS-Pods-after-changing-the-Corefile.png\" rel=\"nofollow noopener\" target=\"_blank\">Forcing the recreation of CoreDNS Pods after changing the Corefile<\/a><\/p>\n<\/p>\n<p><p>The screenshot reveals that new Pods are automatically generated.<\/p>\n<\/p>\n<p><h2>How are Pods utilizing CoreDNS?<\/h2>\n<\/p>\n<p><p>Understanding the notions of CoreDNS and the Corefile may leave you pondering about how each Pod in the cluster utilizes CoreDNS. What configures them for CoreDNS usage?<\/p>\n<\/p>\n<p><p>It&#8217;s probably known to you that kubelet is the one in charge of executing Pods on Kubernetes nodes. The exposition of the CoreDNS Deployment through a kube-dns service was also discussed. The kubeadm tool is configured to make use of the kube-dns service IP address as the cluster DNS server on each node. Here is the command to view the kubelet configuration:<\/p>\n<\/p>\n<p><pre>cat \/var\/lib\/kubelet\/config.yaml<\/pre>\n<\/p>\n<p><a href=\"https:\/\/4sysops.com\/wp-content\/uploads\/2023\/12\/Viewing-the-cluster-DNS-IP-address-in-the-kubelet-configuration.png\" rel=\"nofollow noopener\" target=\"_blank\"><\/a><\/p>\n<p><p>Viewing the cluster DNS IP address in the kubelet configuration<\/p>\n<\/p>\n<p><p>The screenshot shows the <em>clusterDNS<\/em> and <em>clusterDomain<\/em> set in the kubelet configuration file. When the kubelet creates a Pod, it adds the clusterDNS IP address to the <em>\/etc\/resolv.conf<\/em> file of the Pod to help resolve internal service names within the cluster. The external names are resolved by the <em>forward<\/em> plugin specified in the Corefile. Remember the <em>forward . \/etc\/resolv.conf<\/em> line of the Corefile?<\/p>\n<\/p>\n<p><p>Let&#8217;s quickly run a temporary Pod and view its <em>\/etc\/resolv.conf<\/em> file.<\/p>\n<\/p>\n<p><pre>kubectl run test-pod -it --rm --restart=Never --image=tutum\/dnsutils -- \/bin\/bash<\/p><p><\/pre>\n<\/p>\n<p><a href=\"https:\/\/4sysops.com\/wp-content\/uploads\/2023\/12\/Run-a-test-Pod-and-view-its-resolv.conf-file.png\" rel=\"nofollow noopener\" target=\"_blank\">Run a test Pod and view its resolv.conf file<\/a><\/p>\n<p><p>You can see that the kube-dns service IP address is already configured as the nameserver in the Pod. Suppose you run the host command to resolve a nonfully qualified domain name (e.g., 4sysops.com), as shown in the screenshot. In that case, you will notice that all the search domains are appended to the keyword in the same order mentioned in the resolv.conf file. First, it tries 4sysops.com.default.svc.cluster.local, where default is the namespace and cluster.local is the cluster domain. This behavior allows Pods to discover internal services within the Kubernetes cluster.<\/p>\n<\/p>\n<p><p>To resolve a service name in the same namespace, you need to specify its name, and CoreDNS will do it for you. However, to access a service in a different namespace, you must use the service-name.namespace format. For example, if your Pod runs in the default namespace, you will run this command to get the IP address of the kube-dns service that runs in the kube-system namespace.<\/p>\n<\/p>\n<p><pre>host kube-dns.kube-system<\/pre>\n<\/p>\n<p><p><a href=\"https:\/\/4sysops.com\/wp-content\/uploads\/2023\/12\/Performing-a-DNS-lookup-in-a-Kubernetes-Pod.png\" rel=\"nofollow noopener\" target=\"_blank\">Performing a DNS lookup in a Kubernetes Pod<\/a><\/p>\n<\/p>\n<p><p>To view the DNS logs, run the kubectl logs command, as shown below:<\/p>\n<\/p>\n<p><pre>kubectl logs -f coredns-5d78c9869d-6fc7b -n kube-system<\/pre>\n<\/p>\n<p><div><a href=\"https:\/\/4sysops.com\/wp-content\/uploads\/2023\/12\/Viewing-CoreDNS-logs-in-Kubernetes.png\" rel=\"nofollow noopener\" target=\"_blank\">Viewing CoreDNS logs in Kubernetes<\/a><\/p>\n<p>Viewing CoreDNS logs in Kubernetes<\/p>\n<\/div>\n<p>Don&#8217;t forget to specify the correct CoreDNS Pod name with the <em>kubectl logs<\/em> command. The DNS queries are load balanced across both Pods, so you might need to view the logs of both Pods.<\/p>\n<div>\n<h2>Subscribe to 4sysops newsletter!<\/h2>\n<\/div>\n<h2>Conclusion<\/h2><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In a previous post in this Kubernetes guide, you learned about deploying stateful applications with Kubernetes StatefulSets. Today&#8217;s post will discuss Kubernetes CoreDNS. Earlier versions of Kubernetes used kube-dns to provide service discovery and name resolution within the cluster, which was based on dnsmasq and SkyDNS. The kube-dns had many problems, such as security vulnerabilities, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":8246,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[92,132,133],"tags":[],"class_list":["post-8245","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-articles","category-kubernetes","category-networking"],"_links":{"self":[{"href":"https:\/\/cheapwindowsvps.com\/blog\/wp-json\/wp\/v2\/posts\/8245","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cheapwindowsvps.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cheapwindowsvps.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cheapwindowsvps.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cheapwindowsvps.com\/blog\/wp-json\/wp\/v2\/comments?post=8245"}],"version-history":[{"count":1,"href":"https:\/\/cheapwindowsvps.com\/blog\/wp-json\/wp\/v2\/posts\/8245\/revisions"}],"predecessor-version":[{"id":10284,"href":"https:\/\/cheapwindowsvps.com\/blog\/wp-json\/wp\/v2\/posts\/8245\/revisions\/10284"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cheapwindowsvps.com\/blog\/wp-json\/wp\/v2\/media\/8246"}],"wp:attachment":[{"href":"https:\/\/cheapwindowsvps.com\/blog\/wp-json\/wp\/v2\/media?parent=8245"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cheapwindowsvps.com\/blog\/wp-json\/wp\/v2\/categories?post=8245"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cheapwindowsvps.com\/blog\/wp-json\/wp\/v2\/tags?post=8245"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}