概述
DNS 是网络中非常重要的一个服务和话题,在平时工作中使用的也非常多,之前我也写过一篇介绍 DNS 以及系统设置的文章:DNS 以及 Linux 下的相关配置文件,但是今天我要聊一聊的是自己部署一个 DNS 服务器。
在之前我也写过自建 DNS 服务器的教程:Mac 搭建本地 DNS 服务器,但是这篇文章中用的是 DNSMasq,其实我之前的工作中也用的是这个,因为之前的产品是偏 IaaS,所以选型是相对比较偏传统的。但是,最近因为产品更倾向于云原生,所以换成了 CoreDNS,于是这里就简单做下总结。
CoreDNS 概念
CoreDNS 的实现有别于其他的 DNS 服务器(我从文档里面抄的,实际上其他服务器的实现有何特别之处我没有去了解过😂),CoreDNS 的特点就是非常的灵活,它的灵活来自于插件系统,也就是说,CoreDNS 将大部分的功能够交给一个个插件来完成,然后通过配置来组合插件从而实现我们需要的功能。
在 CoreDNS 中,有两个关于插件的配置非常重要,分别是:
plugin.cfg:这个是编译时使用的配置文件,用于决定需要使用 CoreDNS 的哪些插件;Corefile:这个是运行时配置,用于决定 CoreDNS 如何响应 DNS 查询请求;
插件
插件是 CoreDNS 的核心概念,它实际上就是一个实现了特定接口的代码,每当有一个 DNS 查询进来时,被配置的插件都将被调用,并传递给它三个参数:
context.Contextdns.ResponseWriter:用于写入响应数据;*dns.Msg:DNS 请求的 Client 信息;
需要哪些插件是通过编译时的 plugin.cfg 来配置的,并且需要注意的是,这个配置文件里面的顺序很重要,因为这也是插件在实际运行中的顺序,所以在 Corefile 中也有插件的定义顺序,但是那个顺序是没意义的,真正地顺序是 plugin.cfg 中配置的,例如这是一个官方的配置:
[root@liqiang.io]# cat plugin.cfgroot:rootmetadata:metadatageoip:geoipcancel:canceltls:tlstimeouts:timeoutsreload:reloadnsid:nsidbufsize:bufsizebind:binddebug:debugtrace:traceready:readyhealth:healthpprof:pprofprometheus:metricserrors:errorslog:logdnstap:dnstaplocal:localdns64:dns64acl:aclany:anychaos:chaosloadbalance:loadbalancetsig:tsigcache:cacherewrite:rewriteheader:headerdnssec:dnssecautopath:autopathminimal:minimaltemplate:templatetransfer:transferhosts:hostsroute53:route53azure:azureclouddns:clouddnsk8s_external:k8s_externalkubernetes:kubernetesfile:fileauto:autosecondary:secondaryetcd:etcdloop:loopforward:forwardgrpc:grpcerratic:erraticwhoami:whoamion:github.com/coredns/caddy/oneventsign:signview:view
配置
CoreDNS 在默认的情况下会在运行目录中寻找 Corefile 作为启动配置,但是你可以通过 -conf 指定启动配置。Corefile 配置也很简单,它由很多的 Server Blocks 组成(当然,你不指定或者只指定一个也是可以),每个 Server Block 的模式为:
<zones> {# Plugins defined here.}
可以看到,Server Block 包含两个部分,分别是 zone 和 plugins:
zone:监听的域名类型,协议和端口- 例如你想监听所有的域名,那么可以用一个
. - 你只关注 google 这个域名,那么可以用
google.com - 如果只关注 https 的 dns 查询(HoD):
https://google.com
- 例如你想监听所有的域名,那么可以用一个
plugin:- 对于满足
zone条件的域名,你希望用哪些插件来响应这个域名,下面可以加入插件的列表,但是,需要注意的是,你可以随便安排这个插件的列表,但是实际的执行顺序并不是按照你安排的顺序,而是在plugin.cfg中的顺序;
- 对于满足
一个配置的示例:
[root@liqiang.io]# cat Corefiledns://google.com:53 {errorsforward . 8.8.8.8}# 兜底配置,前面没有满足的都会使用这个配置dns://.:53 {errorsforward . 223.5.5.5:53}
实践
安装
CoreDNS 的安装支持多种方式,但是一般来说可以分为预编译程序和容器两种方式,一般来说我们都是在 K8S 环境下运行的,所以用容器的情况比较多,并且可能平时我们需要在本地运行来调试一下问题,所以这里给一个简单的使用 Docker 运行的示例:
[root@liqiang.io]# docker run -d --rm --name coredns \--volume=/tmp/coredns:/root/ \-p 53:53/udp \coredns/coredns \-conf /root/Corefile
这样,我们就跑起来一个 CoreDNS 实例了,因为 CoreDNS 是一个无状态的服务,所以,我们可以快速地进行横向扩展,而无需考虑其他额外的配置。
验证
当我们跑起来之后,可以通过 DNS 相关的命令指定 DNS 服务器进行验证,例如我这里用 dig:
[root@liqiang.io]# dig @127.0.0.1 google.com; <<>> DiG xxxxxx <<>> @127.0.0.1 google.com; (1 server found);; global options: +cmd;; Got answer:;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30520;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1;; OPT PSEUDOSECTION:; EDNS: version: 0, flags:; udp: 1232; COOKIE: 754b24dbebe1a964 (echoed);; QUESTION SECTION:;google.com. IN A;; ANSWER SECTION:google.com. 30 IN A 142.251.175.113google.com. 30 IN A 142.251.175.102google.com. 30 IN A 142.251.175.101google.com. 30 IN A 142.251.175.138google.com. 30 IN A 142.251.175.139google.com. 30 IN A 142.251.175.100;; Query time: 11 msec;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP);; WHEN: Mon Jul 22 00:20:15 UTC 2024;; MSG SIZE rcvd: 207