11. DNS是怎么实现的
introduction
并不详细的分析, 就简单说说几种常见的 dns 玩法, 我们在上一节里说了为什么会有 dns 以及 pod是如何利用上 dns服务来解析地址的, 这一节来说说 dns 是如何提供服务的. 分成两类, 一种是经典玩法 sky-dns, 另一种是比较新的玩法 core-dns.
sky玩法
etcd + kube2sky + skyDNS 是比较经典(古老)的玩法, 相对来说比较好理解一点, 分成三个组件:
Kube2sky: 使用一种叫 watch 的手段监视 api-server, 这种监视手法能使得每次 service/endpoint 产生变动(出现了新的service, 或者旧的被删除了)的时候, 及时获取最新消息, 然后更新自己已知的情报
etcd: 同步到的所有情报都会存在这里
skyDNS: 监听在53(dns协议默认)端口, 别人来问的时候就去etcd了查询他想要的信息
# 我们进入etcd容器, 然后使用etcd工具. 查一下这个service是怎么被解析的
# skydns将所有情报存在 etcd 里, 因此你可以看到这个存储的key是以skydns开头的
$ docker exec -it etcd-contaniner \
etcdctl get /skydns/local/kube/svc/default/mysql-service
# 从这里我们知道了mysql服务的ip是多少, 等别人来问的时候就把这个告诉别人
{"host":"10.254.162.44","ttl":30 ...}
kubedns + dnsmasq + exechealthz 是换汤不换药的另一种sky玩法:
Kubedns: 负责监视, 并在内存里维护了一个 DNS 记录, 换句话说, 这回咱们不落盘了, 直接内存里整起来, 这样至少是不需要etcd容器参与其中了
Dnsmasq: 它负责监听53端口, 任何请求都会先经过 dnsmasq , 它维护一个查询缓存, 在缓存没有命中的情况下, 就会去 kubedns 查(因为他存的是全量). 这么做是可以减轻 kubedns 的压力
exechealthz: 负责上面两个组件的健康检查问题
这种玩法的确是没有直接部署 skydns, 但是问题在于, kubedns 如何做到维护dns记录的? 还是通过调用 skydns 库函数做到的, 因此我们说换汤不换药, 本质上还是一个 api-server 监视器 + skydns 的组合, 区别只是在于: 搂到的数据不落etcd, 而是维护在缓存里 , 还有你设置了一个二级缓存
core-dns 玩法
core我的一个感觉, 就是一个花样极多的 dns 解析器, 很多功能靠插件实现, 你需要先编写你的 corefile (coredns配置文件), 去配置core使用那些插件, 然后指定怎么解析域名访问请求. (就我观察这些年分布式App特别喜欢搞插件化, 之前看了个fluentd也这么玩, 仔细想想还是挺好的, 我们维护核心, 社区提供插件, 你按需使用, 除了比较零散琐碎好像也没什么毛病), 我们通过一个例子来说说core是怎么用的:
coredns.io:5300 {
file /etc/coredns/zones/coredns.io.db
}
example.io:53 {
errors
log
file /etc/coredns/zones/example.io.db
}
example.net:53 {
file /etc/coredns/zones/example.net.db
}
.:53 {
errors
log
health
rewrite name foo.example.com
}
我们监听两个端口(53, 5300)并提供四种解析方式, 5300端口, 仅仅负责解析以coredns.io
结尾的域名, 53端口同时解析 example.io / example.net / root
三种域名, 三者各自定义了自己需要使用的插件, 比如, 如果访问53, 想要解析example.io
, 那么会先使用errors插件, log插件, 最后前往 example.io.db 去查询对应的IP地址
上面一个方块, 我们叫它一个zone, 我们在上面的配置文件中就定义了四个zone, 一旦匹配上某个zone, 我们就按顺序执行zone里的插件, 每个插件可以决定怎么做, 做法分成以下几种:
响应: 如果插件决定接受这个请求, 就生成响应返回给客户端
不处理: 相当于无视, 直接进入下一个插件
处理: 这种做一下处理, 然后进入下一个流程, 比如host插件的处理方法就是查询/etc/hosts
Last updated
Was this helpful?