它是用GO编写的一个高性能、高可扩展的DNS服务,旨在解决Kube-dns目前的一些问题,内部采用插件机制,所有功能都以插件的形式编写,用户也可以扩展自己的插件。
以下是部署时的默认配置
.:53 {
errors # 启用错误记录
health # 启用运行状况检查端点,8080/health
kubernetes cluster.local in-addr.arpa ip6.arpa { # 处理k8s 域名解析
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153 # 启用Prometheus指标。9153/metrics
forward . /etc/resolv.conf # 通过resolv.conf内的nameservers解析
cache 30 # 启用缓存,所有内容限制为30秒的TTL
loop # 检测简单的转发循环并停止服务器
reload # reload允许自动重新加载已更改的Corefile
loadbalance # 负载均衡,默认round_robin,
}
每个{}代表一个区域,格式为“区域:端口{}”,其中“.”代表默认区域,{}中的每个名称代表一个插件的名称。只有配置的插件才会启用。
在解析域名时,会先匹配区域(若匹配不到则执行默认区域),然后从上到下执行区域内的插件(这个顺序不是配置文件中谁在前的顺序,而是配置文件内部的顺序),匹配成功后就返回(执行过的插件会从下到上处理返回逻辑),不会再执行下一个插件。
插件文档请参考:.io/
表现
根据官方测试,单实例在2core 1g资源下可以达到30k qps。根据官方测试报告,在2k pod环境下,qps预计不会超过30k。配置是2core 1g(为了更稳定,我给了更高的估计)。
参考://dep…
源码分析
基于Caddy框架编写的,上图是大概的代码架构,简单解释如下(其实看图结合源码基本就能看懂):
首先main方法在.go中,因为这个文件导入了core/.go,而core/.go又导入了所有插件,所以所有插件的init方法都会被执行,每个插件的init方法作用都是一样的,就是把自己注册为“dns”到caddy中。
然后main方法里就只有一行,运行/run.go里的Run方法,因为这个文件导入了core//.go,所以会执行这个文件的init方法,这个方法通过caddy注册了“dns”类型的服务器,这里有两个参数,一个是包含所有插件名的列表,一个是初始化
/run.go 在Run方法中开始执行caddy,加载配置文件,然后执行caddy.start方法,该方法会进行一系列的初始化,主要处理1、2注册
根据第二步中的初始化,会执行caddy里面的方法,该方法主要作用是根据第二步注册的配置文件依次调用配置文件启用的各个插件的setup(),将启用的插件注册为。然后执行.()和.(),也就是//.go里面的两个方法,分别加载配置文件,注册并返回调用的lisen或方法,也就是core//.go里面的两个方法,启动TCP或UDP监听,调用core//.go或方法注册处理TCP或UDP请求,这两个方法会将方法注册为
执行caddy.Wait() 主进程进入等待状态,caddy开始处理请求,这里每个请求都会被发到core//.go去处理,下面是dns的整体逻辑
遍历 dns.(dns),找到匹配的 zone,如果没找到匹配的,则尝试默认的 zone(“.”),并调用 zone..() 进行处理,是一个链,链的顺序由 core//.go 定义,第一个先执行。
每个插件的()将进行如下处理
执行插件的一些自定义处理调用()来执行下一个插件的处理(当然也可以不调用,直接返回) 执行插件的一些自定义处理各插件结构
通过上面的分析,每个插件的结构基本上提供了以下方法
init() //模版代码,把自己注册为caddy中名为"dns",参数是setup方法
setup() //初始化一个实例,注册为dnsContext.Plugin
ServeDns() //每次请求时,会执行的代码,这里是插件的功能实现的地方
循环检查插件
这个插件是用来检查DNS循环的。就是我要检查一个域名,会代理到父DNS,但是父地址还在本地,还会再次查询,如此反复。这样会消耗大量的CPU进行无效查询,因为如果部署中的配置错误导致循环检查失败,就会报错。
plugin/loop: Loop (127.0.0.1:55953 -> :1053) detected for zone ".", see https://coredns.io/plugins/loop#troubleshooting. Query: "HINFO 4547991504243258144.3688648895315093531."
loop的实现源码在/loop目录下,逻辑如下:
在setup.go中的setup方法中,注册了一个hook,在启动serve的时候,会启动一个协程,会尝试执行loop.方法,如果成功,则执行loop.方法(效果是不再检查,也就是只检查一次)
如下图所示,loop.go中的逻辑是对自己执行一个新的DNS查询(地址设置可参考上图,就是本地电脑的地址),查询DNS为l.qname,l.qname是生成一个随机的DNS(因为第二步是给自己发送查询请求,所以请求解析完之后会执行loop.go中的方法,如果出现循环,请求会再次转发,这里会执行多次,这里的逻辑是如果已经出现过(检查成功后会标注),那么就跳过处理,如果name是我们发送的l.qname,那么count加1,如果count大于2(即查询出现循环),那么输出日志并退出程序
因此可以看出主要原因是域名解析出现环路,具体原因需要排查,可以参考:另外:如果是1.2.2版本,提示失败,也有可能是pod里面的网络没有通上游DNS,可以运行-i -t test- --image= --=Never ping 你的上游DNS地址
参考:
/-添加…
扫一扫在手机端查看
-
Tags : 域名解析源码_CoreDns 介绍和源码解析
我们凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求,请立即点击咨询我们或拨打咨询热线: 13761152229,我们会详细为你一一解答你心中的疑难。