CoreDNS简介
CoreDNS是一个使用Go编写的DNS服务器。不同于其他DNS服务器,CoreDNS的所有功能都外包到了“插件”中,因此可以说:
CoreDNS is powered by plugins.
通常,使用Corefile来配置CoreDNS,在CoreDNS的启动参数中使用 -conf指定,当CoreDNS启动并且没有给出-conf标志时,它将在当前目录中查找一个名为Corefile的文件。
Corefile是CoreDNS的配置文件,由一个或多个服务器块 Server Blocks组成;每个服务器块列出一个或多个插件Plugins;这些插件可以进一步配置一些参数。
Corefile配置
服务器块 Server Blocks
每一个服务器块都由区域名称以及一组由大括号包围的插件构成,下方的Corefile配置表示该CoreDNS会处理所有DNS请求。
. {
# 此处配置插件
}
区域名称的规则是 <域名>:<端口>,其中.代表匹配所有域名,端口即CoreDNS会监听的端口,默认是53。下方的Corefile配置表示CoreDNS会监听53端口,所有后缀是tg.example.com的域名解析请求都会由该服务器块中的插件进行处理,其余请求不处理。
tg.example.com {
# 此处配置插件
}
特别注意:所有区域名称和大括号之间都必须有一个空格
一个Corefile可以配置多个服务器块分别处理不同的域名解析请求。下方的Corefile配置表示CoreDNS会监听53端口和1053端口:其中所有来自1053端口的请求由服务器块B中的插件进行处理;来自53端口的请求,如果是以tg.example.com或example.com结尾,则由服务器块C或D中的插件处理,否则交给服务器块A。
# 服务器块A
. {
# 此处配置插件
}
# 服务器块B
.:1053 {
# 此处配置插件
}
# 服务器块C
tg.example.com:53 { # 此处可以省略:53
# 此处配置插件
}
# 服务器块D
example.com { # 此处可以省略了:53
# 此处配置插件
}
特别地,两个服务器块的区域名称中域名的后缀均匹配上了请求,则由更长的(或者说
.更多的)那个服务器块处理上边的配置中,xxx.tg.example.com由C处理,因为 tg.example.com 相比 example.com 更长
同理,如果两个服务器块配置了相同的区域名称,CoreDNS将会在启动时报错退出。
插件 Plugins
对于每个服务器块,可以通过配置各类插件来处理DNS请求。一个最简单的配置形式是将插件名称填在大括号内即可
. {
whoami
}
上方示例使用了一个名为 whoami的插件,该插件的作用是无论请求任何域名,都返回请求者的ip作为域名解析的结果。当请求域名example.org 的A记录解析时,服务器返回的结果为:
;; QUESTION SECTION:
;example.org. IN A
;; ADDITIONAL SECTION:
example.org. 0 IN A 192.168.0.111
_udp.example.org. 0 IN SRV 0 0 40212
并非所有的插件都是用来进行域名解析,它们也可能提供一些额外能力。例如log插件可以将所有查询(以及回复的部分)输出到标准输出上供日志查询。
一些插件可以配置额外的参数,配置方法可以查看对应插件的说明文档,一些插件可以将配置项紧跟插件名写在后方,其他具有更多配置选项的插件有一个插件块,它就像一个服务器块一样,包含在大括号中。
一个服务器块中存在多个插件的情况下,将按照文件plugin.cfg中的顺序依次处理,而非按照服务器块中填写的顺序处理。
访问coredns.io/plugins 查看每个插件的功能和使用说明
也可以自行研发各类插件,与现有插件协作满足自定义需求,不在本文介绍范围内
CoreDNS工作流程
当CoreDNS启动并成功加载了Corefile配置后,就会作为服务器开始运行,包含若干个服务器块。每个服务器块都由它服务的区域和端口定义;每个服务器块也都有自己的插件链。
当CoreDNS接收到DNS请求时:
- 如果配置了多个服务器块来侦听查询的端口,它将检查哪一个具有该查询的最特定区域(最长后缀匹配)。例如,如果有两个服务器块,一个用于example.org,一个用于a.example.org,当请求是www.a.example.org时,它将被路由到后者。
- 一旦找到服务器,它将通过为此服务器配置的插件链进行路由,这个顺序是固定的,在
plugin.cfg中定义。 - 每个插件都将检查这个请求并确定自己是否应该进行操作处理它,此时可能会发生几件事:
- 这个插件处理这个请求并返回解析结果,插件链中后方的插件将不再工作
- 这个插件不处理这个请求并将请求传递给下一个插件,如果链中的最后一个插件决定不处理该请求,CoreDNS将返回SERVFAIL
- 这个插件本该处理这个请求,但发生某些情况(如处理失败等)让它决定传给下一个插件。通常有此功能的插件大多需要配置
fallthrough参数,如hosts插件,具体以插件文档为准 - 这个插件处理这个请求,但仅将请求进行处理加工后传给下一个插件
- 一类特殊的插件,根本不处理任何DNS数据,但会影响CoreDNS在其他方面的行为方式,如添加健康检查和就绪检查端点等。
附件
配置示例
.:53 {
errors
health :18080 {
lameduck 5s
}
ready :18181
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
loadbalance
}
example.com:53 {
errors
cache 30
forward . 1.1.1.1 2.2.2.2
}
每个插件的功能可以通过coredns.io/plugins/查看
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 generate && 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
root:root
metadata:metadata
geoip:geoip
cancel:cancel
tls:tls
timeouts:timeouts
reload:reload
nsid:nsid
bufsize:bufsize
bind:bind
debug:debug
trace:trace
ready:ready
health:health
pprof:pprof
prometheus:metrics
errors:errors
log:log
dnstap:dnstap
local:local
dns64:dns64
acl:acl
any:any
chaos:chaos
loadbalance:loadbalance
tsig:tsig
cache:cache
rewrite:rewrite
header:header
dnssec:dnssec
autopath:autopath
minimal:minimal
template:template
transfer:transfer
hosts:hosts
route53:route53
azure:azure
clouddns:clouddns
k8s_external:k8s_external
kubernetes:kubernetes
file:file
auto:auto
secondary:secondary
etcd:etcd
loop:loop
forward:forward
grpc:grpc
erratic:erratic
whoami:whoami
on:github.com/coredns/caddy/onevent
sign:sign
view:view