原文链接:https://fuckcloudnative.io/posts/install-coredns-on-macos/
CoreDNS 是 Golang 编写的一个插件式 DNS 服务器,是 Kubernetes 1.13 后所内置的默认 DNS 服务器。CoreDNS 的指标是成为 cloud-native 环境下的 DNS 服务器和服务发现解决方案,即:
Our goal is to make CoreDNS the cloud-native DNS server and service discovery solution.
它有以下几个个性:
- 插件化(Plugins)
基于 Caddy 服务器框架,CoreDNS 实现了一个插件链的架构,将大量利用端的逻辑形象成 plugin 的模式(如 Kubernetes 的 DNS 服务发现,Prometheus 监控等)裸露给使用者。CoreDNS 以预配置的形式将不同的 plugin 串成一条链,按序执行 plugin 的逻辑。从编译层面,用户抉择所需的 plugin 编译到最终的可执行文件中,使得运行效率更高。CoreDNS 采纳 Go 编写,所以从具体代码层面来看,每个 plugin 其实都是实现了其定义的 interface 的组件而已。第三方只有依照 CoreDNS Plugin API 去编写自定义插件,就能够很不便地集成于 CoreDNS。
- 配置简单化
引入表达力更强的 DSL,即
Corefile
模式的配置文件(也是基于 Caddy 框架开发)。 - 一体化的解决方案
区别于
kube-dns
,CoreDNS 编译进去就是一个独自的二进制可执行文件,内置了 cache,backend storage,health check 等性能,无需第三方组件来辅助实现其余性能,从而使得部署更不便,内存治理更为平安。
其实从性能角度来看,CoreDNS 更像是一个通用 DNS 计划(相似于 BIND
),而后通过插件模式来极大地扩大本身性能,从而能够实用于不同的场景(比方 Kubernetes)。正如官网博客所说:
CoreDNS is powered by plugins.
<span id=”inline-toc”>1.</span> Corefile 介绍
Corefile
是 CoreDNS 的配置文件(源于 Caddy 框架的配置文件 Caddyfile),它定义了:
server
以什么协定监听在哪个端口(能够同时定义多个 server 监听不同端口)- server 负责哪个
zone
的权威(authoritative)DNS 解析 - server 将加载哪些插件
常见地,一个典型的 Corefile 格局如下所示:
ZONE:[PORT] {[PLUGIN] ...
}
- <span id=inline-purple>ZONE</span> : 定义 server 负责的 zone,
PORT
是可选项,默认为 53; - <span id=inline-purple>PLUGIN</span> : 定义 server 所要加载的 plugin。每个 plugin 能够有多个参数;
比方:
. {chaos CoreDNS-001}
上述配置文件表白的是:server 负责根域 .
的解析,其中 plugin 是 chaos
且没有参数。
定义 server
一个最简略的配置文件能够为:
.{}
即 server 监听 53 端口并不应用插件。 如果此时在定义其余 server,要保障监听端口不抵触;如果是在原来 server 减少 zone,则要保障 zone 之间不抵触, 如:
. {}
.:54 {}
另一个 server 运行于 54 端口并负责根域 .
的解析。
又如:
example.org {whoami}
org {whoami}
同一个 server 然而负责不同 zone 的解析,有不同插件链。
定义 Reverse Zone
跟其余 DNS 服务器相似,Corefile 也能够定义 Reverse Zone
(反向解析 IP 地址对应的域名):
0.0.10.in-addr.arpa {whoami}
或者简化版本:
10.0.0.0/24 {whoami}
能够通过 dig
进行反向查问:
$ dig -x 10.0.0.1
应用不同的通信协议
CoreDNS 除了反对 DNS 协定,也反对 TLS
和 gRPC
,即 DNS-over-TLS 和 DNS-over-gRPC 模式:
tls://example.org:1443 {#...}
<span id=”inline-toc”>2.</span> 插件的工作模式
当 CoreDNS 启动后,它将依据配置文件启动不同 server,每台 server 都领有本人的插件链。当有 DNS 申请时,它将顺次经验如下 3 步逻辑:
- 如果有以后申请的 server 有多个 zone,将采纳贪婪准则抉择最匹配的 zone;
- 一旦找到匹配的 server,依照 plugin.cfg 定义的程序执行插件链上的插件;
- 每个插件将判断以后申请是否应该解决,将有以下几种可能:
- 申请被以后插件解决
插件将生成对应的响应并回给客户端,此时申请完结,下一个插件将不会被调用,如 whoami 插件;
- 申请被以后插件以 Fallthrough 模式解决
如果申请在该插件处理过程中有可能将跳转至下一个插件,该过程称为 fallthrough,并以关键字
fallthrough
来决定是否容许此项操作,例如 host 插件,当查问域名未位于 /etc/hosts,则调用下一个插件; - 申请在处理过程被携带 Hint
申请被插件解决,并在其响应中增加了某些信息(hint)后持续交由下一个插件解决。这些额定的信息将组成对客户端的最终响应,如
metric
插件;
<span id=”inline-toc”>3.</span> CoreDNS 如何解决 DNS 申请
如果 Corefile 为:
coredns.io:5300 {file db.coredns.io}
example.io:53 {
log
errors
file db.example.io
}
example.net:53 {file db.example.net}
.:53 {
kubernetes
proxy . 8.8.8.8
log
health
errors
cache
}
从配置文件来看,咱们定义了两个 server(只管有 4 个区块),别离监听在 5300
和 53
端口。其逻辑图可如下所示:
每个进入到某个 server 的申请将依照 plugin.cfg
定义程序执行其曾经加载的插件。
从上图,咱们须要留神以下几点:
-
只管在
.:53
配置了health
插件,然而它并为在下面的逻辑图中呈现,起因是:该插件并未参加申请相干的逻辑(即并没有在插件链上),只是批改了 server 配置。更个别地,咱们能够将插件分为两种:- Normal 插件 :参加申请相干的逻辑,且插入到插件链中;
- 其余插件 :不参加申请相干的逻辑,也不呈现在插件链中,只是用于批改 server 的配置,如
health
,tls
等插件;
<span id=”inline-toc”>4.</span> 配置 CoreDNS
既然 CoreDNS 如此优良,我用它来抵挡平凡的防火长城岂不美哉?钻研了一圈,发现技术上还是可行的,惟一的一个毛病是不反对应用代理,不过你能够通过 proxychians-ng 或 proxifier 来强制应用代理。上面开始折腾。
具体的思路其实非常简单,就是将国内的域名查问申请转发到 114 等国内的公共 DNS 服务器,将国外的域名查问申请转发到 8.8.8.8 等国外的公共 DNS 服务器。然而 CoreDNS 的插件链有点反直觉,同一个插件链上的每一个插件只能呈现一次,如果只应用 forward
插件是满足不了需要的。
CoreDNS 原来还有个插件叫 proxy
,性能和 forward
相似,目测如同同时利用 proxy
和 forward
插件就能够实现咱的需要了。但现实与事实的差距总是很大,不晓得从什么时候开始,CoreDNS 官网编译的二进制文件曾经没有 proxy
插件了,真是气人。
dnsredir
偶然间发现了一个第三方插件 dnsredir,目测能够解决我的所有问题。该插件综合了 proxy
和 forward
插件的所有长处,反对 UDP、TCP、DNS-over-TLS 和 DNS-over-HTTPS,也反对多个后端,还具备健康检查和故障转移的性能,真是太香了!
它的语法是这样的:
dnsredir FROM... {to TO...}
-
FROM...
是一个文件列表,蕴含了匹配的域名和解析该域名的服务器,说白了就是 dnsmasq 所应用的格局,间接看例子:server=/0-100.com/114.114.114.114 server=/0-100.com/114.114.114.114
为什么要用这种格局呢?当然是为了不便啦。
为什么这样会不便呢?当然是为了能够间接用上 FelixOnMars 的大陆区域名列表了。。。FelixOnMars 同时还提供了
Google
和Apple
的域名列表,这在某些地区某些 ISP 能够失去国内镜像的 IP,从而减速拜访,想想就刺激。 - 当然,除了应用文件列表外,还能够应用
.
,相似于下面所说的根域。 这个插件最大的亮点是能够在插件链中重复使用 dnsredir 插件 ,只有FROM...
不反复就行。 -
to TO...
用来将 DNS 解析申请发给上游 DNS 服务器。反对简直所有 DNS 协定,例如:dns://1.1.1.1 8.8.8.8 tcp://9.9.9.9 udp://2606:4700:4700::1111 tls://1.1.1.1@one.one.one.one tls://8.8.8.8 tls://dns.quad9.net doh://cloudflare-dns.com/dns-query json-doh://1.1.1.1/dns-query json-doh://dns.google/resolve ietf-doh://dns.quad9.net/dns-query
增强版 CoreDNS
dnsredir 虽香,但大家别忘了,它是第三方插件,官网默认的二进制文件是不蕴含该插件的。你能够抉择本人编译,但如果常常须要降级怎么办?总不能每次都手动编译吧,也太累了。
好在有位大佬曾经通过 CI/CD
流程将所需的第三方插件都集成编译进去了,并定期更新,几乎就是我等的福音。大佬的我的项目地址为:
- https://github.com/missdeer/coredns_custom_build
当初只须要下载对应操作系统的二进制文件,到处拷贝,就能够运行了。
上面通通以 MacOS 为例作解说。Openwrt
的玩法也一样,参考本文的方法论即可,具体本文就不开展了。
间接下载二进制文件:
$ wget 'https://appveyorcidatav2.blob.core.windows.net/missdeer-15199/coredns-custom-build/1-7-1-514/idbodwxwywg1xgdg/distrib/coredns-linux-amd64.zip?sv=2015-12-11&sr=c&sig=BhMWcOVtDuaETyz2DcjpOr9GdvkpNVOqoIa7iWFpFNQ%3D&st=2020-12-23T15%3A26%3A19Z&se=2020-12-23T15%3A32%3A19Z&sp=r'
$ $ tar zxf coredns-linux-amd64.zip
$ mv coredns-linux-amd64/coredns /usr/local/bin/
配置
要深刻理解 CoreDNS,请查看其文档,及 plugins 的介绍。上面是我的配置文件:
cat > /usr/local/etc/Corefile <<EOF
# https://coredns.io/plugins/cache/
(global_cache) {
cache {# [5, 60]
success 65536 3600 300
# [1, 10]
denial 8192 600 60
prefetch 1 60m 10%
}
}
.:7913 {
ads {
default-lists
blacklist https://raw.githubusercontent.com/privacy-protection-tools/anti-AD/master/anti-ad-domains.txt
whitelist https://files.krnl.eu/whitelist.txt
log
auto-update-interval 24h
list-store ads-cache
}
errors
hosts {fallthrough}
health
prometheus :9153
import global_cache
template ANY AAAA {rcode NXDOMAIN}
dnsredir accelerated-domains.china.conf google.china.conf apple.china.conf mydns.conf {
expire 15s
max_fails 3
health_check 3s
policy round_robin
path_reload 2s
to 114.114.114.114 223.5.5.5 119.29.29.29
}
dnsredir . {
expire 60s
max_fails 5
health_check 5s
policy random
spray
to tls://8.8.8.8@dns.google tls://8.8.4.4@dns.google
to tls://1.1.1.1@1dot1dot1dot1.cloudflare-dns.com tls://1.0.0.1@1dot1dot1dot1.cloudflare-dns.com
# Global TLS server name
# tls_servername cloudflare-dns.com
}
log
loop
reload 6s
}
EOF
- hosts :
hosts
是 CoreDNS 的一个 plugin,这一节的意思是加载/etc/hosts
文件外面的解析信息。hosts 在最后面,则如果一个域名在 hosts 文件中存在,则优先应用这个信息返回; - fallthrough : 如果
hosts
中找不到,则进入下一个 plugin 持续。短少这一个指令,前面的 plugins 配置就无意义了; - cache : 溯源失去的后果,缓存指定工夫。相似 TTL 的概念;
- reload : 多久扫描配置文件一次。如有变更,主动加载;
- errors : 打印 / 存储谬误日志;
- dnsredir : 这是重点插件。第一段 dnsredir 配置应用了 4 个文件列表,均是 FelixOnMars 的大陆区域名列表,这里我还加了一个自定义的文件列表
mydns.conf
。第二段 dnsredir 配置示意默认的解析配置,能够了解为故障转移,如果某个域名没有匹配到任何一个文件列表,就应用第二段 dnsredir 的上游 DNS 服务器进行解析。通过这样的配置形式,就实现了将国内的域名查问申请转发到 114 等国内的公共 DNS 服务器,将国外的域名查问申请转发到 8.8.8.8 等国外的公共 DNS 服务器。
讲一下我本人的了解:
- 配置文件相似于 nginx 配置文件的格局;
- 最里面一级的大括号,对应『服务』的概念。多个服务能够共用一个端口;
- 往里面一级的大括号,对应 plugins 的概念,每一个大括号都是一个 plugin。这里能够看出,plugins 是 CoreDNS 的一等公民;
- 服务之间程序有无关联没有感觉,但 plugins 之间是重大程序相干的。某些 plugin 必须用
fallthrough
关键字流向下一个 plugin; - plugin 外部的配置选项是程序无关的;
- 从 plugins 页面的介绍看,CoreDNS 的性能还是很强的,既能轻松从 bind 迁徙,还能兼容 old-style dns server 的运维习惯;
- 从 CoreDNS 的性能指标看,适宜做大型服务。
留神:该计划的前提是可能强制让 CoreDNS 应用代理,或者更准确一点,让 8.8.8.8 和 8.8.4.4 应用代理。这里的办法比较复杂一点,本文就不介绍了。如果你切实不晓得怎么办,能够将 8.8.8.8 这一行删除,间接应用 Cloudflare 提供的 DNS 服务,尽管响应有点慢,但好在能够拜访。
如果你无法忍受 Cloudflare 的响应速度,能够思考应用国内的无污染 DNS:红鱼 DNS。而后间接一劳永逸:
cat > /usr/local/etc/Corefile <<EOF
# https://coredns.io/plugins/cache/
(global_cache) {
cache {# [5, 60]
success 65536 3600 300
# [1, 10]
denial 8192 600 60
prefetch 1 60m 10%
}
}
.:7913 {
ads {
default-lists
blacklist https://raw.githubusercontent.com/privacy-protection-tools/anti-AD/master/anti-ad-domains.txt
whitelist https://files.krnl.eu/whitelist.txt
log
auto-update-interval 24h
list-store ads-cache
}
errors
hosts {fallthrough}
health
prometheus :9153
import global_cache
template ANY AAAA {rcode NXDOMAIN}
dnsredir accelerated-domains.china.conf google.china.conf apple.china.conf mydns.conf {
expire 15s
max_fails 3
health_check 3s
policy round_robin
path_reload 2s
to 114.114.114.114 223.5.5.5 119.29.29.29
}
dnsredir . {
expire 60s
max_fails 5
health_check 5s
policy random
spray
to doh://13800000000.rubyfish.cn
}
log
loop
reload 6s
}
EOF
这样 CoreDNS 就不必放心走代理的问题了。
定时更新国内域名列表
大陆域名列表每天都会更新,所以还须要写个脚本来更新文件列表。不必查看文件是否存在了,间接简略粗犷无脑更新:
$ cat > /usr/local/bin/update_coredns.sh <<EOF
#!/bin/bash
rm accelerated-domains.china.conf
wget https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf -O /usr/local/etc/accelerated-domains.china.conf
rm apple.china.conf
wget https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf -O /usr/local/etc/apple.china.conf
rm google.china.conf
wget https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/google.china.conf -O /usr/local/etc/google.china.conf
EOF
$ sudo chmod +x /usr/local/bin/update_coredns.sh
先执行一遍该脚本,更新 Corefile 的配置:
$ /usr/local/bin/update_coredns.sh
而后通过 Crontab
制作定时工作,每隔两天下午两点更新域名列表:
$ crontab -l
0 14 */2 * * /usr/local/bin/update_coredns.sh
开机自启
MacOS 能够应用 launchctl 来治理服务,它能够管制启动计算机时须要开启的服务,也能够设置定时执行特定工作的脚本,就像 Linux crontab 一样, 通过加装 *.plist
文件执行相应命令。Launchd 脚本存储在以下地位, 默认须要本人创立集体的 LaunchAgents
目录:
~/Library/LaunchAgents
: 由用户本人定义的工作项/Library/LaunchAgents
: 由管理员为用户定义的工作项/Library/LaunchDaemons
: 由管理员定义的守护过程工作项/System/Library/LaunchAgents
: 由 MacOS 为用户定义的工作项/System/Library/LaunchDaemons
: 由 MacOS 定义的守护过程工作项
咱们抉择在 /Library/LaunchAgents/
目录下创立 coredns.plist
文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>coredns</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/coredns</string>
<string>-conf</string>
<string>/usr/local/etc/Corefile</string>
</array>
<key>StandardOutPath</key>
<string>/var/log/coredns.stdout.log</string>
<key>StandardErrorPath</key>
<string>/var/log/coredns.stderr.log</string>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
设置开机主动启动 coredns:
$ sudo launchctl load -w /Library/LaunchAgents/coredns.plist
查看服务:
$ sudo launchctl list|grep coredns
61676 0 coredns
$ sudo launchctl list coredns
{
"StandardOutPath" = "/var/log/coredns.stdout.log";
"LimitLoadToSessionType" = "System";
"StandardErrorPath" = "/var/log/coredns.stderr.log";
"Label" = "coredns";
"TimeOut" = 30;
"OnDemand" = false;
"LastExitStatus" = 0;
"PID" = 61676;
"Program" = "/usr/local/bin/coredns";
"ProgramArguments" = (
"/usr/local/bin/coredns";
"-conf";
"/usr/local/etc/Corefile";
);
};
查看端口号:
$ sudo ps -ef|egrep -v grep|grep coredns
0 81819 1 0 2:54 下午 ?? 0:04.70 /usr/local/bin/coredns -conf /usr/local/etc/Corefile
$ sudo lsof -P -p 81819|egrep "TCP|UDP"
coredns 81819 root 5u IPv6 0x1509853aadbdf853 0t0 TCP *:5302 (LISTEN)
coredns 81819 root 6u IPv6 0x1509853acd2f39ab 0t0 UDP *:5302
coredns 81819 root 7u IPv6 0x1509853aadbdc493 0t0 TCP *:53 (LISTEN)
coredns 81819 root 8u IPv6 0x1509853acd2f5a4b 0t0 UDP *:53
coredns 81819 root 9u IPv6 0x1509853ac63bfed3 0t0 TCP *:5301 (LISTEN)
coredns 81819 root 10u IPv6 0x1509853acd2f5d03 0t0 UDP *:5301
功败垂成,当初你只须要将零碎的 DNS IP 设置为 127.0.0.1
就能够了。
验证
$ doggo www.youtube.com @udp://127.0.0.1
NAME TYPE CLASS TTL ADDRESS NAMESERVER
www.youtube.com. CNAME IN 293s youtube-ui.l.google.com. 127.0.0.1:53
youtube-ui.l.google.com. A IN 293s 172.217.14.110 127.0.0.1:53
youtube-ui.l.google.com. A IN 293s 172.217.11.174 127.0.0.1:53
youtube-ui.l.google.com. A IN 293s 172.217.5.206 127.0.0.1:53
youtube-ui.l.google.com. A IN 293s 172.217.5.78 127.0.0.1:53
youtube-ui.l.google.com. A IN 293s 172.217.14.78 127.0.0.1:53
youtube-ui.l.google.com. A IN 293s 142.250.72.238 127.0.0.1:53
youtube-ui.l.google.com. A IN 293s 216.58.193.206 127.0.0.1:53
youtube-ui.l.google.com. A IN 293s 142.250.68.110 127.0.0.1:53
youtube-ui.l.google.com. A IN 293s 142.250.68.78 127.0.0.1:53
youtube-ui.l.google.com. A IN 293s 172.217.4.142 127.0.0.1:53
youtube-ui.l.google.com. A IN 293s 142.250.68.14 127.0.0.1:53
搞定。
什么?你问我 doggo
是个啥?扫描下方二维码关注公众号:
公众号后盾回复 doggo 即可获取你想要的货色????
<span id=”inline-toc”>5.</span> 参考资料
- CoreDNS 应用与架构剖析
- CoreDNS 搭建无污染 DNS
Kubernetes 1.18.2 1.17.5 1.16.9 1.15.12 离线安装包公布地址 http://store.lameleg.com,欢送体验。应用了最新的 sealos v3.3.6 版本。作了主机名解析配置优化,lvscare 挂载 /lib/module 解决开机启动 ipvs 加载问题,修复 lvscare 社区 netlink 与 3.10 内核不兼容问题,sealos 生成百年证书等个性。更多个性 https://github.com/fanux/sealos。欢送扫描下方的二维码退出钉钉群,钉钉群曾经集成 sealos 的机器人实时能够看到 sealos 的动静。