SkyDNS是kubernetes用于服务发现的默认的开源DNS服务。本文将抛开kubernetes单独体验SkyDNS。其开源在github。依赖与etcd作为数据存储。
其官方介绍如下:
Version 2.5.2c
SkyDNS is a distributed service for announcement and discovery of services built on top of etcd. It utilizes DNS queries to discover available services. This is done by leveraging SRV records in DNS, with special meaning given to subdomains, priorities and weights.
This is the original announcement blog post for version 1. Since then, SkyDNS has seen some changes, most notably the ability to use etcd as a backend. Here you can find the SkyDNS2 announcement.
本文中将使用单机版etcd作为其服务。etcd发布版本下载可能需要翻墙。
下载完成后解压,在解压目录中执行./etcd即可运行服务。
使用go get -u github.com/skynetservices/skydns
即可将SkyDNS所需的文件从源码中下载并编译完成,位置位于$GOPATH/bin
。
如果$GOPATH/bin
在系统环境变量PATH
中,则可以直接在终端模拟器(命令行)中执行skydns
,如在我测试机上执行查看帮助如下:
sope:~ goyoo$ skydns --help Usage of skydns: -addr string ip:port to bind to (SKYDNS_ADDR) (default "127.0.0.1:53") -ca-cert string CA Certificate -discover discover new machines by watching /v2/_etcd/machines -dnssec string basename of DNSSEC key file e.q. Kskydns.local.+005+38250 -domain string domain to anchor requests to (SKYDNS_DOMAIN) (default "skydns.local.") -hostmaster string hostmaster email address to use (default "hostmaster@skydns.local.") -local string optional unique value for this skydns instance -machines string machine address(es) running etcd -nameservers string nameserver address(es) to forward (non-local) queries to e.g. 8.8.8.8:53,8.8.4.4:53 -no-rec do not provide a recursive service -path-prefix string backend(etcd) path prefix, default: skydns (default "skydns") -rcache int capacity of the response cache -rcache-ttl int TTL of the response cache (default 60) -round-robin round robin A/AAAA replies (default true) -rtimeout duration read timeout (default 2s) -scache int capacity of the signature cache (default 10000) -stubzones support stub zones -systemd bind to socket(s) activated by systemd (ignore -addr) -tls-key string TLS Private Key path -tls-pem string X509 Certificate -verbose log queries
设置etcd的环境变量ETCD_MACHINES
,如果未设置SkyDNS将使用默认的http://127.0.0.1:4001
来连接etcd,或者使用-machines
选项。可以通过设置-discover
来启用自动发现新添加到网络中的机器。因启动时需要占用53端口,需要使用sudo执行。
export ETCD_MACHINES='http://192.168.0.1:4001,http://192.168.0.2:4001' skydns
推荐方式设置nameserver
:
curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/local/skydns/dns/ns/ns1 \ -d value='{"host":"192.168.0.1"}'
SkyDNS的配置文件都是作为JSON对象存储在etcd的key/skydns/config
下。以下是可能需要设置的参数:
dns_addr
: SkyDNS需要监听的IP:port,默认127.0.0.1:53
domain
: SkyDNS 专属域名,默认skydns.local.
dnssec
:开启DNSSEC hostmaster
:主机管理者邮件地址local
:可选的SkyDNS实体的唯一值,默认为空。当查询local.dns.skydns.local
时返回这个值round_robin
:开启A的AAAA响应的round-robin功能,默认true。注意包中包含不止一个CNAME被免除nameservers
:当不属于当前DNS中记录时,转发(递归)DNS请求至nameservers(IP:port的数组),默认转到/etc/resolv.conf
中的服务列表no_rec
:不提供递归服务(如:转发至在-nameservers
)提供的服务列表read_timeout
:DNS与etcd的网络通讯超时ttl
:当etcd中未设置时,默认以秒为单位来作为应答时间,默认时间为3600min_ttl
: 使用NXDOMAIN的最小ttl时间设置,默认为30scache
: DNSSEC签名的容量,默认10000条记录rcache
: 响应缓存,默认为0条消息rcache_ttl
: 缓存响应ttl,默认为60systemd
: 绑定到由systemd激活的socket,将会忽略-addr
path-prefix
: 后台(etcd)路径前缀,默认为skydns(例如:如果设置为mydns
,SkyDNS的配置对象将存储在key为/mydns/config
路径下)在未初始化时进行以下测试,从结果中可以看出,当前DNS服务继承了宿主机上的DNS,当当前记录在SkyDNS中未找到时,会轮训宿主机上配置的DNS
sope:~ goyoo$ dig @localhost baidu.com
; <<>> DiG 9.8.3-P1 <<>> @localhost baidu.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56201
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 5, ADDITIONAL: 5
;; QUESTION SECTION:
;baidu.com. IN A
;; ANSWER SECTION:
baidu.com. 600 IN A 123.125.114.144
baidu.com. 600 IN A 111.13.101.208
baidu.com. 600 IN A 220.181.57.217
baidu.com. 600 IN A 180.149.132.47
;; AUTHORITY SECTION:
baidu.com. 10940 IN NS ns2.baidu.com.
baidu.com. 10940 IN NS ns4.baidu.com.
baidu.com. 10940 IN NS dns.baidu.com.
baidu.com. 10940 IN NS ns3.baidu.com.
baidu.com. 10940 IN NS ns7.baidu.com.
;; ADDITIONAL SECTION:
dns.baidu.com. 168235 IN A 202.108.22.220
ns2.baidu.com. 172699 IN A 61.135.165.235
ns3.baidu.com. 13330 IN A 220.181.37.10
ns4.baidu.com. 11265 IN A 220.181.38.10
ns7.baidu.com. 6547 IN A 119.75.219.82
;; Query time: 2005 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat Oct 10 13:39:03 2015
;; MSG SIZE rcvd: 261
从上面的结果可以看出,没有在etcd中初始化也是可以解析的
初始化etcd数据,当设置初始化数据之后SkyDNS服务需要重启才能生效,此时继承的dns为谷歌的DNS。
sope:~ goyoo$ etcdctl set /skydns/config '{"dns_addr":"127.0.0.1:53","ttl":3600,"nameservers": ["8.8.8.8:53","8.8.4.4:53"]}'
先测试一个不存在的域名test1.shenshouer.skydns.local
,从下列结果中可以看出当前域名的应答数为0,说明不存在。
sope:~ goyoo$ dig @localhost test1.shenshouer.skydns.local
; <<>> DiG 9.8.3-P1 <<>> @localhost test1.shenshouer.skydns.local
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 29867
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0
;; QUESTION SECTION:
;test1.shenshouer.skydns.local. IN A
;; AUTHORITY SECTION:
com. 899 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1444455889 1800 900 604800 86400
;; Query time: 125 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat Oct 10 13:44:55 2015
;; MSG SIZE rcvd: 105
添加不存在的域名test1.shenshouer.skydns.local
,并进行检查发现有一个应答,并将此域名映射到localhost
上,注意是映射到localhost
或者127.0.0.1
上,如果是指定的其他域名,如test1.skydns.local
的话,则必须去指定test1.skydns.local
域名的CNAME
记录:
sope:~ goyoo$ etcdctl set /skydns/local/skydns/shenshouer/test1. ‘{“host”:“localhost”}’
{“host”:”localhost”,”port”:8080}
sope:~ goyoo$ dig @localhost SRV test1.shenshouer.skydns.local
; <<>> DiG 9.8.3-P1 <<>> @localhost SRV test1.shenshouer.skydns.local
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43169
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;test1.shenshouer.skydns.local. IN SRV
;; ANSWER SECTION:
test1.shenshouer.skydns.local. 3600 IN SRV 10 100 8080 localhost.
;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat Oct 10 14:01:34 2015
;; MSG SIZE rcvd: 70
解析测试OK。
将本机的配置的其他DNS服务IP地址全部删除,只配置一个127.0.0.1。此时,在访问域名的时候如果记录不存在SkyDNS中,访问不到,则SkyDNS将轮询谷歌DNS服务。此时再在本地开启一个端口为30001的web服务,当访问此服务时会返回请求端的IP地址,用于测试。
使用nslookup测试,从结果中可以看到已经能够正常解析了:
sope:~ goyoo$ nslookup test1.shenshouer.skydns.local Server: 127.0.0.1 Address: 127.0.0.1#53 Name: test1.shenshouer.skydns.local Address: 127.0.0.1
再试试使用curl是否能够基于域名能够访问本地服务:
sope:~ goyoo$ curl test1.shenshouer.skydns.local curl: (7) Failed to connect to test1.shenshouer.skydns.local port 80: Connection refused
从以上结果中可以看出域名已经访问当了localhost,但请求的为默认的80端口。在请求的域名后面新增30001端口试试:
sope:~ goyoo$ curl test1.shenshouer.skydns.local:30001 127.0.0.1:60358 sope:~ goyoo$
从以上结果中可以看出添加端口后服务访问正常。
但此时只增加了SRV记录,如果test1.shenshouer.skydns.local
映射到的不是localhost
而是test1.skydns.local
,则使用nslookup测试会出现不能解析域名的问题,此时需要给域名test1.skydns.local
再新增一条SRV记录,且必须映射到具体的IP地址或可访问的域名,此时叫做新增CNAME记录。
为test1.shenshouer.skydns.local
新增CNAME记录,具体操作如下:
// 先清理掉已经添加的任何域名信息 sope:~ goyoo$ etcdctl rm --recursive /skydns/local // 新增test1.shenshouer.skydns.local sope:~ goyoo$ etcdctl set /skydns/local/skydns/shenshouer/test1. '{"host":"test1.skydns.local","port":8080}' // 新增test1.skydns.local etcdctl set /skydns/local/skydns/test1 '{"host":"127.0.0.1","port":30001}'
此时CNAME记录新增完成。
SkyDNS还有子域名、MX记录、TXT记录、NS记录、PTR记录(域名反转地址)等系列功能,本文中不做尝试。