理解OpenShift(1):网络之 Router 和 Routehtml
理解OpenShift(2):网络之 DNS(域名服务)node
理解OpenShift(4):用户及权限管理github
理解OpenShift(5):从 Docker Volume 到 OpenShift Persistent Volumedocker
** 本文基于 OpenShift 3.11,Kubernetes 1.11 进行测试 ***后端
OpenShift 集群中,至少有三个地方须要用到 DNS:api
本文就从这三点出发,解释 OpenShift 是如何实现这三种DNS功能的。缓存
在Linux 系统上,当一个应用经过域名链接远端主机时,DNS 解析会经过系统调用来进行,好比 getaddrinfo()。
和任何Linux 操做系统同样,Pod 的 DNS 定义在 resolv.conf 文件中,其示例以下:服务器
sh-4.2$ cat /etc/resolv.conf nameserver 172.22.122.9 search dev.svc.cluster.local svc.cluster.local cluster.local exampleos.com options ndots:5
其中,微信
默认地,许多DNS 解析器若是发现被解析的域名中有任何的点(.)就把它当作一个 FQDN 来解析;若是域名中没有任何点,就把它当作 PQDN 来处理,而且会加上系统的默认domain name 和最后的点,来组成 FQDN。若是没有指定默认的 domain name (经过 domain 字段)或查询失败,则会将 search 字段的第一个值当作默认domain name,若是解析不成功,则依次往下试,直到有一个成功或者所有失败为止。
这个行为是经过 options ndots 来指定的,其默认值为1,这意味着只要被解析域名中有任何一个点(.),那么它就会被当作 FQDN,而不会附加任何 search domain,直接用来查询。OpenShift 环境中,这个值被设置为 5。这意味着,只要被解析域名中包含不超过五个点,该域名就会被当作PQDN,而后挨个使用 search domain,来组装成 FQDN 来作DNS查询。若是所有不成功过,则会尝试将它直接做为 FQDN 来解析。
[root@node2 cloud-user]# cat /etc/resolv.conf # nameserver updated by /etc/NetworkManager/dispatcher.d/99-origin-dns.sh # Generated by NetworkManager search cluster.local exampleos.com nameserver 172.22.122.9
在部署环境时,会在每一个节点上部署 /etc/NetworkManager/dispatcher.d/99-origin-dns.sh 文件。每当节点上的 NetworkManager 服务启动时,该文件会被运行。它的任务包括:
也就是说,宿主机上的 DNS 请求也会转到本机上的 53 端口。
宿主机上的 53 端口上,dnsmasq 服务在route 默认路由的全部IP的53端口上侦听。其中一个负责接受并处理宿主机上全部pod 中以及宿主机上的全部DNS查询服务。
tcp 0 0 10.128.2.1:53 0.0.0.0:* LISTEN 906/dnsmasq
tcp 0 0 172.17.0.1:53 0.0.0.0:* LISTEN 906/dnsmasq
tcp 0 0 172.22.122.9:53 0.0.0.0:* LISTEN 906/dnsmasq
这些 IP 地址和默认路由IP 地址是符合的:
10.128.0.0 0.0.0.0 255.252.0.0 U 0 0 0 tun0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0 172.22.122.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0 172.30.0.0 0.0.0.0 255.255.0.0 U 0 0 0 tun0
dnsmasq 服务的配置目录为 /etc/dnsmasq.d。其中有两个配置文件(具体含义请查阅有关文档):
[root@node2 dnsmasq.d]# cat origin-dns.conf no-resolv domain-needed no-negcache max-cache-ttl=1 enable-dbus dns-forward-max=10000 cache-size=10000 bind-dynamic min-port=1024 except-interface=lo # End of config
文件 origin-upstream-dns.conf 中定义了上游(upstream) DNS 名字服务器:
[root@node2 dnsmasq.d]# cat origin-upstream-dns.conf server=172.22.122.3 server=172.22.122.2 server=172.22.122.4
这些上游服务器的地址是从 DHCP 服务器中获取到的(个人OpenShift 环境搭建在OpenStack虚拟机中。前两个地址是OpenStack neutron 网络的 DNSmasq 地址,最后一个是单独搭建的 bind9 DNS 服务器地址)。
在早期版本中(个人OpenShift版本是 3.11),还有一个配置文件 node-dnsmasq.conf :
server=/in-addr.arpa/127.0.0.1 server=/cluster.local/127.0.0.1
这意味着全部以 cluster.local 和 in-addr.arpa 结尾的域名,都会被转到 127.0.0.1:53 上被解析。而其它的解析请求,会被转到在 origin-upstream-dns.conf 中定义的上游 DNS 服务器。
个人3.11版本环境中并无生成该文件。从代码 https://github.com/openshift/origin/blob/master/pkg/dns/dnsmasq.go 看,OpenShift 中的 dnsmasq 在启动时会自动添加这两条记录:
而 dnsIP 和 dnsDomain 应该是在 /etc/origin/node/node-config.yaml 中的以下配置:
dnsBindAddress: 127.0.0.1:53 dnsDomain: cluster.local
Dec 3 14:10:57 dnsmasq[29595]: using nameserver 127.0.0.1#53 for domain in-addr.arpa Dec 3 14:10:57 dnsmasq[29595]: using nameserver 127.0.0.1#53 for domain cluster.local
从上面的分析可见,在 node 节点上的 dnsmasq,其实只是一个DNS 查询转发器(转到上游DNS 服务器或者本机上的 SkyDns)和结果缓存器,它自己并不保存域名的原始记录。
关于 SkyDNS:它是一个开源的构建在 etcd 之上的分布式服务宣告(announcement)和发现(discovery)服务。利用它,能够经过 DNS 查询来发现可用的服务。其开源社区的地址是 https://github.com/skynetservices/skydns。社区版本的 SkyDns 将记录保存在 etcd 中,在作查询时从etcd 获取数据并封装成 DNS 结果格式给客户端。
SkyDNS 的 server 部分支持被做为库文件使用,此时能够为其实现其它后端。在OpenShift 中并无采用默认的 etcd 后端,而是基于 OpenShift API 服务实现了新的后端,其代码在https://github.com/openshift/origin/blob/master/pkg/dns/ 。SkyDns 调用 OpenShift API 服务来获取主机名、IP地址等信息,而后封装成标准 DNS 记录并返回给查询客户端。
tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 17182/openshift
Node 节点上的 SkyDN 要么从cache 中直接回答 DNS 查询,要么调用 OpenShift API 服务来获取数据再返回。
resolv.conf 文件同Node 节点上的:
[root@master1 cloud-user]# cat /etc/resolv.conf # nameserver updated by /etc/NetworkManager/dispatcher.d/99-origin-dns.sh # Generated by NetworkManager search cluster.local haihangyun.cn exampleos.com nameserver 172.22.122.5
dnsmasq 在多个IP 地址的 53 端口上侦听,为本机上的以及本机上Pod 中的DNS查询服务:
udp 0 0 10.128.0.1:53 0.0.0.0:* 866/dnsmasq udp 0 0 172.17.0.1:53 0.0.0.0:* 866/dnsmasq udp 0 0 172.22.122.5:53 0.0.0.0:* 866/dnsmasq
和 Node 节点不一样,Master 节点上有两个SkyDns 进程。一个在 127.0.0.1:53 侦听,负责本机上的集群内服务的DNS查询,由于 Master 节点同时承担 node 节点的角色:
udp 0 0 127.0.0.1:53 0.0.0.0:* 11700/openshift
Dec 3 14:50:41 dnsmasq[10607]: using nameserver 127.0.0.1#53 for domain cluster.local Dec 3 14:50:41 dnsmasq[10607]: using nameserver 127.0.0.1#53 for domain in-addr.arpa
另外一个是在全部网卡的 8053 端口上侦听,这是由于Master 还具备 master api 角色:
udp 0 0 0.0.0.0:8053 0.0.0.0:* 15096/openshift
对于这个 SkyDns 进程的做用尚不清楚,还需进一步研究。从已有资料上看看,全部节点上都须要安装 SkyDns,并组成一个分布式集群。由于 Master 节点上的 53 端口被另外一个 SkyDns 进程占用,所以换到了端口8053。
流程示意图如最上面图中的 1 和 2.1 部分所示。
dnsmasq 日志:
Nov 21 11:03:44 dnsmasq[17788]: using nameserver 172.22.122.3#53 Nov 21 11:03:44 dnsmasq[17788]: using nameserver 172.22.122.2#53 Nov 21 11:03:44 dnsmasq[17788]: using nameserver 172.22.122.4#53 Nov 21 11:03:49 dnsmasq[17788]: query[A] www.sina.com from 172.22.122.13 Nov 21 11:03:49 dnsmasq[17788]: forwarded www.sina.com to 172.22.122.4 Nov 21 11:03:49 dnsmasq[17788]: forwarded www.sina.com to 172.22.122.2 Nov 21 11:03:49 dnsmasq[17788]: forwarded www.sina.com to 172.22.122.3 Nov 21 11:03:49 dnsmasq[17788]: reply spool.grid.sinaedge.com is 124.228.42.248
能看到 node 上的 dnsmasq 直接将查询请求转发给上游 DNS 名字服务器。由于存在多个名字服务器,因此是依次查询,直到成功为止。从日志看,其查询顺序和配置文件中的顺序是相反的。
流程示意图如上图中的 1 + 2.2 + 3 部分所示。
日志实例:
(1)从一个 pod 中 ping registry-console服务的域名 registry-console.default.svc.cluster.local。
(2)Node宿主机(IP 地址为 172.22.122.13)上的 dnsmasq 收到该查询。
(3)dnsmasq 将查询转到 127.0.0.1:53 上的 SkyDns 服务。
(4)SkyDNS 作查询。SkyDNS 能接收的域名格式:<prefix>.<service_name>.<namespace>.(svc|endpoints|pod).<base>,这意味着它支持查询服务(svc)、端点(endpoints)和 pod 的 DNS信息。
查询结果:
[root@node2 cloud-user]# nsenter -t 4216 -n dig mybank.dev.svc.cluster.local ;; QUESTION SECTION: ;mybank.dev.svc.cluster.local. IN A ;; ANSWER SECTION: mybank.dev.svc.cluster.local. 30 IN A 172.30.162.172 ;; Query time: 1 msec ;; SERVER: 172.22.122.9#53(172.22.122.9) ;; WHEN: Mon Dec 03 11:43:01 CST 2018 ;; MSG SIZE rcvd: 62
dnsmasq 日志:
Dec 3 14:19:44 dnsmasq[29595]: query[A] mybank.dev.svc.cluster.local from 10.128.2.128 Dec 3 14:19:44 dnsmasq[29595]: forwarded mybank.dev.svc.cluster.local to 127.0.0.1 Dec 3 14:19:44 dnsmasq[29595]: reply mybank.dev.svc.cluster.local is 172.30.162.172
(5)其它实验:查询服务的全部端点
查询结果:
[root@node2 cloud-user]# nsenter -t 4216 -n dig jenkins.dev.endpoints.cluster.local ;; QUESTION SECTION: ;jenkins.dev.endpoints.cluster.local. IN A ;; ANSWER SECTION: jenkins.dev.endpoints.cluster.local. 30 IN A 10.128.2.81 jenkins.dev.endpoints.cluster.local. 30 IN A 10.131.1.70
dnsmasq 日志:
Dec 3 14:20:48 dnsmasq[29595]: query[A] jenkins.dev.endpoints.cluster.local from 10.128.2.128 Dec 3 14:20:48 dnsmasq[29595]: forwarded jenkins.dev.endpoints.cluster.local to 127.0.0.1 Dec 3 14:20:48 dnsmasq[29595]: reply jenkins.dev.endpoints.cluster.local is 10.128.2.81 Dec 3 14:20:48 dnsmasq[29595]: reply jenkins.dev.endpoints.cluster.local is 10.131.1.70
(6)查询 pod
待查询的pod域名的格式为 <IP_with_dashes>.<namespace>.pod.<base>,SkyDns 会返回其IP 地址,但我没明白这么作的场景和价值,也许是确认pod是否存在?
查询结果:
[root@node2 cloud-user]# nsenter -t 4216 -n dig 172-30-162-172.dev.pod.cluster.local ;; QUESTION SECTION: ;172-30-162-172.dev.pod.cluster.local. IN A ;; ANSWER SECTION: 172-30-162-172.dev.pod.cluster.local. 30 IN A 172.30.162.172 ;; Query time: 1 msec ;; SERVER: 172.22.122.9#53(172.22.122.9) ;; WHEN: Mon Dec 03 13:32:05 CST 2018 ;; MSG SIZE rcvd: 70
dnsmasq 日志:
Dec 3 14:22:24 dnsmasq[29595]: query[A] 172-30-162-172.dev.pod.cluster.local from 10.128.2.128 Dec 3 14:22:24 dnsmasq[29595]: forwarded 172-30-162-172.dev.pod.cluster.local to 127.0.0.1 Dec 3 14:22:24 dnsmasq[29595]: reply 172-30-162-172.dev.pod.cluster.local is 172.30.162.172
(7)对比 FQDN 和 PQDN
这个 PQDN 被加上了搜索域名再进行查询,能返回正确的IP地址:
[root@node2 cloud-user]# nsenter -t 4216 -n ping mybank.dev.svc PING mybank.dev.svc.cluster.local (172.30.162.172) 56(84) bytes of data.
而这个 FQDN 被直接作DNS查询,结果查询失败,未能获取IP地址:
[root@node2 cloud-user]# nsenter -t 4216 -n ping mybank.dev.svc. ping: mybank.dev.svc.: Name or service not known
能够看出,该过程当中只涉及到外部DNS将服务的公共域名解析为 OpenShift Router 所在节点的公网地址,后面 HAProxy 做为代理,直接经过 IP 访问pod,并将结果返回客户端。
参考文档:
感谢您的阅读,欢迎关注个人微信公众号: