书籍来源:《Kubernetes网络权威指南:基础、原理与实践》
一边学习一边整理读书笔记,并与大家分享,侵权即删,谢谢支持!
附上汇总贴:《Kubernetes网络权威指南》读书笔记 | 汇总_COCOgsta的博客-CSDN博客
Kubernetes DNS服务目前有两个实现,分别是Kube-dns和CoreDNS。
Kube-dns架构历经两个较大的变化。Kubernetes 1.3之前使用etcd+kube2sky+SkyDNS的架构,Kubernetes 1.3之后使用kubedns+dnsmasq+exechealthz的架构,这两种架构都利用了SkyDNS的能力。下面将分别详解Kube-dns的这两种架构。
etcd+kube2sky+SkyDNS属于第一个版本的Kube-dns架构,包含三个重要的组件,分别是:
图4-13 etcd+kube2sky+SkyDNS版本的Kube-dns架构
SkyDNS配置etcd作为后端数据储存,当Kubernetes cluster中的DNS请求被SkyDNS接受时,SkyDNS从etcd中读取数据,然后封装数据并返回,完成DNS请求响应。Kube2Sky通过watch Service和Endpoints更新etcd中的数据。
假设etcd容器ID为0fb60dcfb8b4,下面让我们一窥Service的Cluster IP在etcd中的数据存储:
如上所示,位于default namespace的服务mysql-service的Cluster IP为10.254.162.44。SkyDNS的基本配置信息也存在etcd中,例如Kube-dns IP地址、域名后缀等。如下所示:
不难看出,SkyDNS是真正对外提供DNS查询服务的组件,kube2sky是Kubernetes到SkyDNS之间的“桥梁”,而etcd则存储Kubernetes只涉及域名解析部分的API对象。这个版本的Kube-dns选择直接部署SkyDNS进程来提供域名解析服务。
新演进的Kube-dns架构如图4-14所示。
图4-14 新演进的Kube-dns架构
Kube-dns包含以下三个核心组件:
这个版本的Kube-dns和之前版本的区别在于:
运行过程中,dnsmasq在内存中预留一个缓冲区(默认是1GB),保存最近使用到的DNS查询记录。如果缓存中没有要查找的记录,dnsmasq会去kubeDNS中查询,同时把结果缓存起来。
需要注意的是,dnsmasq是一个C++写的小程序,有内存泄漏的“小毛病”。
综上所述,无论是哪个版本的架构,Kube-dns的本质就是一个Kubernetes API对象的监视器+SkyDNS。
CoreDNS作为CNCF中托管的一个域名发现的项目,原生集成Kubernetes,它的目标是成为云原生的DNS服务器和服务发现的参考解决方案。所以,CoreDNS走的也是Traefik的路子,降维打击SkyDNS。
从Kubernetes 1.12开始,CoreDNS就成了Kubernetes的默认DNS服务器,但kubeadm默认安装CoreDNS的时间要更早。在Kuberentes 1.9版本中,使用kubeadm方式安装的集群可以通过以下命令直接安装CoreDNS。
下面,我们将详细解释CoreDNS的架构设计和基本用法。
从功能角度看,CoreDNS更像是一个通用的DNS方案,通过插件模式极大地扩展自身功能,从而适用于不同的场景。正如CoreDNS官方博客描述的那样:
CoreDNS is powered by plugins.
CoreDNS有以下3个特点。
(1)插件化(Plugins)。基于Caddy服务器框架,CoreDNS实现了一个插件链的架
构,将大量应用端的逻辑抽象成插件的形式(例如,Kubernetes 的DNS服务发现、Prometheus监控等)暴露给使用者。CoreDNS以预配置的方式将不同的插件串成一条链,按序执行插件链上的逻辑。在编译层面,用户选择需要的插件编译到最终的可执行文件中,使得运行效率更高。CoreDNS采用Go语音编写,所以从代码层面来看,每个插件其实都只实现了CoreDNS定义的接口的组件而已。第三方开发者只要按照CoreDNS Plugin API编写自定义插件,就可以很方便地集成到CoreDNS中。
(2)配置简单化。引入表达力更强的DSL,即Corefile形式的配置文件(也是基于Caddy框架开发的)。
(3)一体化的解决方案。区别于Kube-dns“三合一”的架构,CoreDNS编译出来就是一个单独的可执行文件,内置了缓存、后端存储管理和健康检查等功能,无须第三方组件辅助实现其他功能,从而使部署更方便,内存管理更安全。
Corefile是CoreDNS的配置文件(源于Caddy框架的配置文件Caddyfile),它定义了:
通常,一个典型的Corefile格式如下:
上述配置文件表达的是:DNS server负责根域.的解析,其中插件是chaos且没有参数。
1)定义DNS server
一个最简单的DNS server配置文件如下:
即DNS server监听53端口并且不使用任何插件。如果此时定义其他DNS server,需要保证监听端口不冲突。如果是在原来DNS server的基础上增加zone,则要保证zone之间不冲突。例如:
如上所示,另一个DNS server监听在54端口并负责根域.的解析。
又如:
这是同一个DNS server但是负责不同zone的解析,而且有不同的插件链。
2)定义Reverse Zone
跟其他DNS服务器类似,Corefile也可以定义Reverse Zone:
或者简化版本:
3)使用不同的通信协议
CoreDNS除了支持DNS协议,也支持TLS和gRPC,即DNS-over-TLS和DNS-overgRPC模式。例如:
当CoreDNS启动后,它将根据配置文件启动不同的DNS server,每个DNS server都拥有自己的插件链。当新来一个DNS请求时,它将依次经历以下3步逻辑:
(1)如果当前请求的DNS server有多个zone,则将采用贪心原则选择最匹配的zone。
(2)一旦找到匹配的DNS server,按照plugin.cfg定义的顺序遍历执行插件链上的插件。
(3)每个插件将判断当前请求是否应该处理,将有以下几种可能的情况:
下面将以一个实际的Corefile为例,详解CoreDNS处理DNS请求的工作流。Corefile如下所示:
通过配置文件不难看出,我们定义了两个DNS server(尽管有4个配置块),分别监听5300和53端口。将以上Corefile翻译成处理逻辑图,如图4-15所示。
图4-15 CoreDNS请求处理流程
每个进入某个DNS server的请求将按照plugin.cfg的定义顺序执行其已经加载的插件。
需要注意的是,尽管在.:53配置了health插件,但是它并未在上面的逻辑图中出现,原因是该插件并未参与请求相关的逻辑(即并没有在插件链上),只是修改了DNS server的配置。通常,我们可以将插件分为两种:
表4-4 CoreDNS的域名解析性能和资源消耗情况
值得一提的是,以上性能测试数据是在不带cache的情况下取得的,一般情况下要高于Kube-dns,具体的CoreDNS与Kube-dns的性能对比数据请看下文。
虽然Kube-dns血统纯正,而且早早地进入Kubernetes的“后宫”,也早有“名分”,但近来CoreDNS却独得Kubernetes Network工作小组核心成员“圣宠”,它不仅早早地进入CNCF,就连其中一位创始人也被挖到谷歌的Kubernetes核心团队担任资深工程师(senior staff engineer)。
与Kube-dns的三进程架构不同,CoreDNS就一个进程,运维起来更加简单。而且采用Go语言编写,内存安全,高性能。值得称道的是,CoreDNS采用的是“插件链”架构,每个插件挂载一个DNS功能,保证了功能的灵活、易扩展。尽管资历不深,却“集万千宠爱于一身”,自然是有绝技的。
下面我们从性能和功能两个维度全面对比Kube-dns和CoreDNS。
下面从内存、CPU、QPS和时延这4个维度对比Kube-dns和CoreDNS的性能和资源消耗。内存和CPU消耗
CoreDNS和Kube-dns都维护集群中所有服务和端点的本地缓存。因此,随着服务和端点数量的增加,每个DNS Pod的内存要求也会增加。在默认设置下,CoreDNS应该比Kube-dns使用更少的内存,这是由于部署Kube-dns需要使用三个容器,而CoreDNS只要一个容器便足够。
图4-16对比了随着集群内服务和Pod数量的增加,CoreDNS和Kube-dns消耗的内存。
图4-16 CoreDNS和Kube-dns内存消耗对比
当Kube-dns 和CoreDNS分别达到最大QPS负载时,观测CPU的使用量分别是58Mi(Kube-dns)和5Mi(CoreDNS)。
注:Mi是CPU核心数的度量单位,代表千分之一核,因此58Mi即0.058核,5Mi即0.005核。
QPS和时延
从表4-5所示的数据中可以看出:
表4-5 Kube-dns和CoreDNS的QPS和时延对比
表4-6 Kube-dns在缓存中存储了负面响应时响应内/外部域名请求的QPS与时延
为什么建议使用CoreDNS呢?Kubernetes官方已经将CoreDNS“扶正”,成为了默认模式,除了性能好,还有什么其他优势吗?Core DNS修复了Kube-dns的一些“令人讨厌”的的问题:
同时,还有一些吸引人的特性:
其中,原生支持基于namespace和labels隔离及过滤Service和Pod的DNS记录这一特性,在多租户场景下格外有用。
无论是Kube-dns还是CoreDNS,基本原理都是利用watch Kubernetes的Service和Pod,生成DNS记录,然后通过重新配置Kubelet的DNS选项让新启动的Pod使用Kube-dns或CoreDNS提供的Kubernetes集群内域名解析服务。