目前宿主机上全部采用的 dnsmasq 作为 DNS 管理,其中有一个很大的问题是需要进行 DNS 冗余,dnsmasq 每次修改都要多台机器同步,所以自己写了一个插件配合 CoreDNS 实现分布式部署,如果想了解插件编写方式请参考 Writing Plugin for Coredns 。
一、etcdhosts 插件简介 etcdhosts 顾名思义,就是将 hosts 文件存储在 Etcd 中,然后多个 CoreDNS 共享一份 hosts 文件;得益于 Etcd 提供的 watch 功能,当 Etcd 中的 hosts 文件更新时,每台 CoreDNS 服务器都会接到推送,同时完成热重载;etcdhosts 基本架构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 +-----------------------------------------------------------------------------+ | | | +-----------+ | | | | | | | CoreDNS +---------------------+ | | | | | | | +-----------+ | +------------------+ | | | | | | | +--------v---------+ | | | | +-----------+ | | | | | | | | | | | dnsctl or | | | | CoreDNS +------------> Etcd Cluster <------+ other etcd tool | | | | | | | | | | | +-----------+ | | | | | | +---------^--------+ | | | | | | | | | +-----------+ | +------------------+ | | | | | | | | CoreDNS +----------------------+ | | | | | | +-----------+ | | | | | +-----------------------------------------------------------------------------+
二、编译 CoreDNS etcdhosts release 页已经提供部分版本的预编译文件,可以直接下载使用。
etcdhosts 作为一个 CoreDNS 扩展插件采用直接偶合的方式编写(未采用 gRPC 是因为考虑性能影响),这意味着需要重新编译 CoreDNS 来集成插件,以下为 CoreDNS 编译过程(使用 docker):
1 2 3 4 git clone https://github.com/ytpay/etcdhosts.gitcd etcdhosts && ./build v1.8.0
编译完成后将在 build
目录下生成各个平台的二进制文件压缩包。
三、搭建 Etcd 集群 Etcd 集群搭建将直接采用 deb 安装包,具体细节这里不再阐述,本次搭建系统为 Ubuntu 20,以下为搭建步骤。
2.1、安装软件包 1 2 3 4 5 6 wget https://github.com/mritd/etcd-deb/releases/download/v3.4.13/cfssl_1.4.1_amd64.deb wget https://github.com/mritd/etcd-deb/releases/download/v3.4.13/etcd_3.4.13_amd64.deb dpkg -i cfssl_1.4.1_amd64.deb etcd_3.4.13_amd64.deb
2.2、创建证书 创建证书需要先修改证书配置文件(etcd-csr.json
)然后借助 cfssl 工具来创建证书
/etc/etcd/cfssl/etcd-csr.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 { "key": { "algo": "rsa", "size": 2048 }, "names": [ { "O": "etcd", "OU": "etcd Security", "L": "Beijing", "ST": "Beijing", "C": "CN" } ], "CN": "etcd", "hosts": [ "127.0.0.1", "localhost", "*.etcd.node", "*.kubernetes.node",+ "172.16.11.71", + "172.16.11.72", + "172.16.11.73" ] }
通过脚本创建证书
1 2 3 cd /etc/etcd/cfssl ./create.shcp *.pem /etc/etcd/ssl
证书创建完成后需要分发到其他两台机器上,保证三台节点的 /etc/etcd/ssl
目录证书相同。
1 2 3 4 5 scp /etc/etcd/ssl/*.pem root@NODE2:/etc/etcd/ssl scp /etc/etcd/ssl/*.pem root@NODE3:/etc/etcd/sslchown -R etcd:etcd /etc/etcd/
2.3、调整集群配置 证书签署完成后,简单的调整每台机器上的集群节点配置即可
/etc/etcd/etcd.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 # [member]+ # 节点号自行修改,推荐格式: etcd+节点IP,例如 etcd21 + ETCD_NAME=etcd1 ETCD_DATA_DIR="/var/lib/etcd/data" ETCD_WAL_DIR="/var/lib/etcd/wal" ETCD_SNAPSHOT_COUNT="100"+ # 修改为当前机器 IP + ETCD_LISTEN_PEER_URLS="https://172.16.11.71:2380" + # 修改为当前机器 IP + ETCD_LISTEN_CLIENT_URLS="https://172.16.11.71:2379,http://127.0.0.1:2379" ETCD_QUOTA_BACKEND_BYTES="8589934592" ETCD_MAX_REQUEST_BYTES="10485760" # [cluster]+ # 修改为当前机器 IP + ETCD_INITIAL_ADVERTISE_PEER_URLS="https://172.16.11.71:2380" # if you use different ETCD_NAME (e.g. test), set ETCD_INITIAL_CLUSTER value for this name, i.e. "test=http://..."+ # 三台机器都要按照格式写好 + ETCD_INITIAL_CLUSTER="etcd1=https://172.16.11.71:2380,etcd2=https://172.16.11.72:2380,etcd3=https://172.16.11.73:2380" ETCD_INITIAL_CLUSTER_STATE="new" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"+ # 修改为当前机器 IP + ETCD_ADVERTISE_CLIENT_URLS="https://172.16.11.71:2379" ETCD_AUTO_COMPACTION_MODE="revision" ETCD_AUTO_COMPACTION_RETENTION="16" ETCD_QUOTA_BACKEND_BYTES="5368709120" # [security] ETCD_CERT_FILE="/etc/etcd/ssl/etcd.pem" ETCD_KEY_FILE="/etc/etcd/ssl/etcd-key.pem" ETCD_TRUSTED_CA_FILE="/etc/etcd/ssl/etcd-root-ca.pem" ETCD_CLIENT_CERT_AUTH="true" ETCD_AUTO_TLS="true" ETCD_PEER_CERT_FILE="/etc/etcd/ssl/etcd.pem" ETCD_PEER_KEY_FILE="/etc/etcd/ssl/etcd-key.pem" ETCD_PEER_CLIENT_CERT_AUTH="true" ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/ssl/etcd-root-ca.pem" ETCD_PEER_AUTO_TLS="true"
最后每台机器执行 systemctl start etcd
启动即可,验证集群是否健康可以使用如下命令测试:
1 2 3 4 5 etcdctl endpoint health --cert /etc/etcd/ssl/etcd.pem --key /etc/etcd/ssl/etcd-key.pem --cacert /etc/etcd/ssl/etcd-root-ca.pem --endpoints https://172.16.11.71:2379,https://172.16.11.72:2379,https://172.16.11.73:2379 https://172.16.11.71:2379 is healthy: successfully committed proposal: took = 33.07493ms https://172.16.11.72:2379 is healthy: successfully committed proposal: took = 32.132266ms https://172.16.11.73:2379 is healthy: successfully committed proposal: took = 40.745291ms
三、搭建 CoreDNS 集群 3.1、CoreDNS 安装 系统级 CoreDNS 安装推荐直接使用 systemd 管理,官方目前提供了 systemd 相关配置文件: https://github.com/coredns/deployment/tree/master/systemd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 tar -zxvf coredns_1.8.0_linux_amd64.tgzmv coredns /usr/bin/coredns wget https://raw.githubusercontent.com/coredns/deployment/master/systemd/coredns-sysusers.conf -O /usr/lib/sysusers.d/coredns-sysusers.conf wget https://raw.githubusercontent.com/coredns/deployment/master/systemd/coredns-tmpfiles.conf -O /usr/lib/tmpfiles.d/coredns-tmpfiles.conf wget https://raw.githubusercontent.com/coredns/deployment/master/systemd/coredns.service -O /usr/lib/systemd/system/coredns.service systemctl daemon-reload systemd-sysusers systemd-tmpfiles --createmkdir -p /etc/coredns/ssl
3.2、etcdhosts 配置 etcdhosts 的配置类似官方的 etcd 插件,其配置格式如下:
1 2 3 4 5 6 7 8 9 10 11 etcdhosts [ZONES...] { [INLINE] ttl SECONDS no_reverse fallthrough [ZONES...] key ETCD_KEY endpoint ETCD_ENDPOINT... credentials ETCD_USERNAME ETCD_PASSWORD tls ETCD_CERT ETCD_KEY ETCD_CACERT timeout ETCD_TIMEOUT }
以下是一个简单的可启动的样例配置:
/etc/coredns/Corefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 . { bind 172.16.11.71 cache 30 . { success 4096 } etcdhosts . { fallthrough . key /etcdhosts timeout 5s tls /etc/coredns/ssl/etcd.pem /etc/coredns/ssl/etcd-key.pem /etc/coredns/ssl/etcd-root-ca.pem endpoint https://172.16.11.71:2379 https://172.16.11.72:2379 https://172.16.11.73:2379 } forward . 114.114.114.114:53 { max_fails 2 expire 20s policy random health_check 0.2s } errors log . "{remote}:{port} - {>id} \"{type} {class} {name} {proto} {size} {>do} {>bufsize}\" {rcode} {>rflags} {rsize} {duration}" }
由于 etcdhosts 插件需要连接 etcd 集群,所以需要将证书复制到 Corefile
指定的位置:
1 2 3 4 cp /etc/etcd/ssl/*.pem /etc/coredns/sslchown -R coredns:coredns /etc/coredns
最后直接启动即可(首次启动会出现 [ERROR] plugin/etcdhosts: invalid etcd response: 0
错误,属于正常情况):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 systemctl start coredns dig @172.16.11.71 baidu.com ; <<>> DiG 9.16.1-Ubuntu <<>> @172.16.11.71 baidu.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35323 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: 8e3137531ed0b57a (echoed) ;; QUESTION SECTION: ;baidu.com. IN A ;; ANSWER SECTION: baidu.com. 30 IN A 220.181.38.148 baidu.com. 30 IN A 39.156.69.79 ;; Query time: 8 msec ;; SERVER: 172.16.11.71#53(172.16.11.71) ;; WHEN: Mon Nov 16 20:18:25 CST 2020 ;; MSG SIZE rcvd: 100
最后在多台机器上通过同样的配置启动 CoreDNS 即可,此时所有 CoreDNS 服务器通过 Etcd 提供一致性的记录解析。
四、记录调整 所有 CoreDNS 启动成功后,默认 etcdhosts 插件将会读取 Etcd 中的 /etcdhosts
key 作为 hosts 文件载入;载入成功后将会在内存级进行 Cache,多次查询不会造成疯狂的 Etcd 请求,只有当触发 reload 时(包括 Etcd 更新)才会重新查询 Etcd。 所以此时只需要向 Etcd 的 /etcdhosts
key 写入一个 hosts 文件即可;写入 Etcd 可以使用 etcdctl 以及其他的开源工具,甚至自己开发都可以,记录更改只需要跟 Etcd 打交道,不需要理会 CoreDNS; 由于本人实在是比较菜,前端页面写不出来,所以弄了一个命令行版本的工具: dnsctl
dnsctl 只有一个可执行文件,默认情况下 dnsctl 读取 $HOME/.dnsctl.yaml
配置文件来沟通 Etcd, 配置文件格式如下:
1 2 3 4 5 6 7 8 9 10 11 dnskey: /etcdhosts etcd: cert: /etc/etcd/ssl/etcd.pem key: /etc/etcd/ssl/etcd-key.pem ca: /etc/etcd/ssl/etcd-root-ca.pem endpoints: - https://172.16.11.71:2379 - https://172.16.11.72:2379 - https://172.16.11.73:2379
dnsctl 提供如下命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 dnsctl for etcdhosts plugin Usage: dnsctl [flags] dnsctl [command ] Available Commands: config show example config dump dump hosts edit edit hosts help Help about any command upload upload hosts from file version show hosts version Flags: --config string config file (default is $HOME /.dnsctl.yaml) -h, --help help for dnsctl -v, --version version for dnsctl Use "dnsctl [command] --help" for more information about a command .
其中 edit
命令将会打开系统默认编辑器(例如 vim),然后编辑完保存后会自动上传到 Etcd 中,此后 CoreDNS 的 etcdhosts 插件将会立即重载;**dump
命令用于将 Etcd 中的 hosts 文件保存到本地用于备份,upload
命令可以将已有的 hosts 文件上传到 Etcd 用于恢复。**