CoreDNS源码分析

CoreDNS源码分析CoreDNS源码基于1.3.1版本。 CoreDNS架构基于Caddy框架实现,整个项目大量使用了Caddy的插件功能,整体代码结构比较清晰,读起来也特别的舒服。 如图,可以看到,core/plugin/zplugin.go和core/dnsserver/zdirective…

CoreDNS源码基于1.3.1版本。

架构

CoreDNS架构基于Caddy框架实现,整个项目大量使用了Caddy的插件功能,整体代码结构比较清晰,读起来也特别的舒服。

Makefile

首先看CoreDNS的Makefile部分代码:

CoreDNS源码分析

如图,可以看到,
core/plugin/zplugin.go
core/dnsserver/zdirectives.go文件都是由
coredns.go通过
plugin.cfg生成的。其中,
coredns.go就是启动文件,
plugin.cfg是配置的插件列表,默认插件如下:

# Directives are registered in the order they should be
# executed.
#
# Ordering is VERY important. Every plugin will
# feel the effects of all other plugin below
# (after) them during a request, but they must not
# care what plugin above them are doing.

# How to rebuild with updated plugin configurations:
# Modify the list below and run `go gen && go build`

# The parser takes the input format of
# <plugin-name>:<package-name>
# Or
# <plugin-name>:<fully-qualified-package-name>
#
# External plugin example:
# log:github.com/coredns/coredns/plugin/log
# Local plugin example:
# log:log

metadata:metadata
tls:tls
reload:reload
nsid:nsid
root:root
bind:bind
debug:debug
trace:trace
health:health
pprof:pprof
prometheus:metrics
errors:errors
log:log
dnstap:dnstap
chaos:chaos
loadbalance:loadbalance
cache:cache
rewrite:rewrite
dnssec:dnssec
autopath:autopath
template:template
hosts:hosts
route53:route53
federation:federation
k8s_external:k8s_external
kubernetes:kubernetes
file:file
auto:auto
secondary:secondary
etcd:etcd
loop:loop
forward:forward
proxy:proxy
erratic:erratic
whoami:whoami
on:github.com/mholt/caddy/onevent

默认代码中包含的是现有的所有插件,类似于一种键值对的方式提供。
再来看启动文件coredns.go

CoreDNS源码分析

代码很简单,就是一个
Run方法,但是加载了
github.com/coredns/coredns/core/plugin包下的所有init方法。
github.com/coredns/coredns/core/plugin包下只有一个
zplugin.go文件,而这个文件就是Makefile生成的文件,如下:

// generated by directives_generate.go; DO NOT EDIT package plugin import ( // Include all plugins. _ "github.com/coredns/coredns/plugin/auto" _ "github.com/coredns/coredns/plugin/autopath" _ "github.com/coredns/coredns/plugin/bind" _ "github.com/coredns/coredns/plugin/cache" _ "github.com/coredns/coredns/plugin/chaos" _ "github.com/coredns/coredns/plugin/debug" _ "github.com/coredns/coredns/plugin/dnssec" _ "github.com/coredns/coredns/plugin/dnstap" _ "github.com/coredns/coredns/plugin/erratic" _ "github.com/coredns/coredns/plugin/errors" _ "github.com/coredns/coredns/plugin/etcd" _ "github.com/coredns/coredns/plugin/federation" _ "github.com/coredns/coredns/plugin/file" _ "github.com/coredns/coredns/plugin/forward" _ "github.com/coredns/coredns/plugin/health" _ "github.com/coredns/coredns/plugin/hosts" _ "github.com/coredns/coredns/plugin/k8s_external" _ "github.com/coredns/coredns/plugin/kubernetes" _ "github.com/coredns/coredns/plugin/loadbalance" _ "github.com/coredns/coredns/plugin/log" _ "github.com/coredns/coredns/plugin/loop" _ "github.com/coredns/coredns/plugin/metadata" _ "github.com/coredns/coredns/plugin/metrics" _ "github.com/coredns/coredns/plugin/nsid" _ "github.com/coredns/coredns/plugin/pprof" _ "github.com/coredns/coredns/plugin/proxy" _ "github.com/coredns/coredns/plugin/reload" _ "github.com/coredns/coredns/plugin/rewrite" _ "github.com/coredns/coredns/plugin/root" _ "github.com/coredns/coredns/plugin/route53" _ "github.com/coredns/coredns/plugin/secondary" _ "github.com/coredns/coredns/plugin/template" _ "github.com/coredns/coredns/plugin/tls" _ "github.com/coredns/coredns/plugin/trace" _ "github.com/coredns/coredns/plugin/whoami" _ "github.com/mholt/caddy/onevent" ) 

Makefile生成的另一文件zdirectives.go如下:

// generated by directives_generate.go; DO NOT EDIT

package dnsserver

// Directives are registered in the order they should be
// executed.
//
// Ordering is VERY important. Every plugin will
// feel the effects of all other plugin below
// (after) them during a request, but they must not
// care what plugin above them are doing.
var Directives = []string{
	"metadata",
	"tls",
	"reload",
	"nsid",
	"root",
	"bind",
	"debug",
	"trace",
	"health",
	"pprof",
	"prometheus",
	"errors",
	"log",
	"dnstap",
	"chaos",
	"loadbalance",
	"cache",
	"rewrite",
	"dnssec",
	"autopath",
	"template",
	"hosts",
	"route53",
	"federation",
	"k8s_external",
	"kubernetes",
	"file",
	"auto",
	"secondary",
	"etcd",
	"loop",
	"forward",
	"proxy",
	"erratic",
	"whoami",
	"on",
}

两个文件,一个是加载所有的插件模块,执行init方法;另一个就是配置了一个数组。
回到zplugin.go文件,以github.com/coredns/coredns/plugin/auto包为例,其相应的init方法如下:

CoreDNS源码分析

执行的主要动作就是将auto插件注册到caddy中去,然后添加一个setup方法,主要用来做一些初始化配置的操作。

所以,通过这种init的方式,将生成的插件依次注册到caddy中。

CoreDNS初始化

通过Run方法进入CoreDNS的初始化过程。Run方法主要就是对参数的验证,重点看其引入的包github.com/coredns/coredns/core/dnsserver,对应的init方法如下:

CoreDNS源码分析

通过caddy的
RegisterServerType方法完成插件的最终注册,其中,插件列表
Directives
core/dnsserver/zdirectives.go文件的内容,包含了一系列的插件信息(插件顺序是有严格要求的);而
newContext就是
dnsContext对象,实现了caddy的Context接口,

CoreDNS源码分析

通过
MakeServers完成dnsServer的创建。

DNSServer创建

CoreDNS有多种Server的创建,

CoreDNS源码分析

分别有DNS、TLS、GRPC以及HTTPS几种方式。以DNS方式为例,进入
NewServer方法,主要作用是添加
pluginChain链,该链对应的就是相应插件的
plugin.Handler方法,逆序遍历,

CoreDNS源码分析

假设加载的插件为errors、log、host,则逆序之后,由于从后往前添加插件
host-->log-->errors,最终实际加载的顺序则是
errors-->log-->host,和定义的顺序一致。

插件执行

所有的插件主要实现了Handler接口,

CoreDNS源码分析

Name方法就是插件的名称,重点看
ServeDNS方法。
ServeDNS有三个参数,
Context表示整个上下文,
ResponseWriter表示返回给客户端的报文,
dns.Msg为客户端的请求。

每个插件在处理请求时,调用
NextOrFailure方法调用下一个插件去处理相应的逻辑,即链式调用;调用
WriteMsg方法完成结束调用,将消息传递给客户端。

如果需要自定义插件的话,基本上实现了
Name
ServeDNS方法,并在
plugin.cfg合适的位置添加插件的信息,即可完成自定义插件的实现,非常方便。

Kubernetes插件

Kubernetes在CoreDNS中也是以插件的形式提供的,主要提供后端的资源作为域名解析的源。

启动

同其他的插件一致,Kubernetes也是先执行init将插件注册到caddy中,然后调用setup方法完成启动工作。看下setup主要做什么工作。

CoreDNS源码分析

首先调用
kubernetesParse解析Kubernetes插件相应的配置;接着调用
InitKubeCache初始化
kubeClient,同时调用
newdnsController初始化dnsController,通过dnsController与Kubernetes集群交互,获取集群内相应的数据;最后调用
AddPlugin将插件以链表的形式添加到配置内,完成初始化工作。

运行

运行以实现了ServeDNS方法开始。主要就是通过解析不同的请求类型进入不同的处理逻辑。

CoreDNS源码分析

通过实现
ServiceBackend完成域名的解析工作。

CoreDNS源码分析

Services主要根据特定的请求类型,获取其相应的所有的Services;


Reverse主要做域名反向解析的动作,即通过IP获取相对应的域名;


Lookup主要用来做上游DNSServer的查找工作;


Records主要做域名解析的工作,返回特定的记录。

总结

CoreDNS代码的结构非常清晰,通过初始化时加载自定义的插件顺序,依次注入到caddy中去,并在执行的时候,按照定义的插件顺序依次执行,形成一个链式的调用结构。通过DNSServer的创建和多个插件的个性化实现构成整个统一的代码结构。

今天的文章CoreDNS源码分析分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18802.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注