了解开放式移位网络:Router vs Route
OpenShift群集要求至少在三个位置使用DNS。
首先,当Pod上的应用程序通过域名访问外联网时,需要DNS来解析外联网的域名。其次,在群集内(pod或宿主机器)通过服务的域名访问群集内的服务时,这通常称为服务发现功能。必须先通过服务域名搜索(获取IP地址),然后使用此服务。第三,如果在群集外部通过域名访问部署到OpenShift pod的服务,则需要DNS来解析服务的外部域名。本文介绍了OpenShift如何实现这三种DNS功能。
一、OpenShift 中的DNS 相关组件及其配置
1.1 Pod 中的 DNS 配置
在Linux 系统上,当一个应用通过域名连接远端主机时,DNS 解析会通过系统调用来进行,比如 getaddrinfo()。和任何Linux 操作系统一样,Pod 的 DNS 定义在 re 文件中,其示例如下:
$ cat /etc/re
nameserver 172.22.122.9search dev. clu exam
options ndots:5
其中,
- nameserver 字段是 pod 所在的宿主机的主网卡的IP 地址。也就是说 pod 中发起的所有DNS 查询请求都会被转发到运行在宿主机的 53 端口上的DNS服务器上。
- search 字段指定当解析一个非FQDN域名时被附加的搜索域(search domain)列表。其解释如下:
域名(Domain Name)分为两种,一种是绝对域名(Absolute Domain Name,也称为 Fully-Qualified Domain Name,简称 FQDN),另一种是相对域名(Relative Domain Name,也称为 Partially Qualified Domain Name,简称PQDN)。FQDN 是完整域名,它能够唯一地在DNS名字空间中确定一个记录。比如最高级别的域名A包括子域名B它又包括子域名C,那么FQDN 是 C.B.A.,比如cs.widge.。 有时候我们也会使用PQDN,它是不完全的、模糊的。
FQDN 能被直接到 DNS 名字服务器中查询;而 PQDN 需要先转化为FQDN 再进行查询。其做法是将 PQDN 附加一个搜索域名(search domain)来生成一个 FQDN。在域名系统中,域名结尾是否是『.』被用来区分 FQDN 和 PQDN。比如 a. 表示一个Apple公司的 FQDN,而 apple 则表示一个 PQDN,它的FQDN 可能是 apple.cs.widge.;a 仍然是一个 PQDN,它的FQDN 可能是 a.cs.widge.。
- 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 来解析。
因此,这某些场景中,pod 中的DNS 查询速度会降低应用的性能。解决方法主要有两种,要么直接使用 FQDN,要么减小 ndots 的值,具体请查看 Kubernetes 和 DNS 的有关文档。
1.2 Pod 所在宿主机上的 DNS 配置及服务
1.2.1 re 文件
[root@node2 cloud-user]# cat /etc/re
# nameserver updated by /etc/NetworkManager
# Generated by NetworkManager
search clu exam
nameserver 172.22.122.9
在部署环境时,会在每个节点上部署 /etc/NetworkManager 文件。每当节点上的 NetworkManager 服务启动时,该文件会被运行。它的任务包括:
- 创建 dnsmasq 配置文件 :
- node-dn (在我的 3.11 版本环境上没有创建该文件,见下文分析)
- origin-dns.conf
- origin-u
- 当 NetworkManager 服务启动时启动 dnsmasq 服务
- 设置宿主机的所有默认路由 IP 为 Dnsmasq 的侦听IP
- 修改 /etc/re,设置搜索域,以及将宿主机的默认 IP 作为 nameserver
- 创建 /etc/origin/node/re
也就是说,宿主机上的 DNS 请求也会转到本机上的 53 端口。
1.2.2 dnsmasq 及其配置
宿主机上的 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。其中有两个配置文件(具体含义请查阅有关文档):
[root@node2 dn]# cat origin-dns.conf
no-resolv
domain-needed
no-negcache
max-cache-ttl=1enable-dbus
dns-forward-max=10000cache-size=10000bind-dynamic
min-port=1024except-interface=lo
# End of config
文件 origin-u 中定义了上游(upstream) DNS 名字服务器:
[root@node2 dn]# cat origin-u
server=172.22.122.3server=172.22.122.2server=172.22.122.4
这些上游服务器的地址是从 DHCP 服务器中获取到的(我的OpenShift 环境搭建在OpenStack虚拟机中。前两个地址是OpenStack neutron 网络的 DNSmasq 地址,最后一个是单独搭建的 bind9 DNS 服务器地址)。
在早期版本中(我的OpenShift版本是 3.11),还有一个配置文件 node-dn :
server=/in-addr.arpa/127.0.0.1server=/clu/127.0.0.1
这意味着所有以 clu 和 in-addr.arpa 结尾的域名,都会被转到 127.0.0.1:53 上被解析。而其它的解析请求,会被转到在 origin-u 中定义的上游 DNS 服务器。
我的3.11版本环境中并没有生成该文件。
从代码 看,OpenShift 中的 dnsmasq 在启动时会自动添加这两条记录:
而 dnsIP 和 dnsDomain 应该是在 /etc/origin/node 中的如下配置:
dnsBindAddress: 127.0.0.1:53dnsDomain: clu
从 dnsmasq 日志中也能看到相关记录:
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 clu
从上面的分析可见,在 node 节点上的 dnsmasq,其实只是一个DNS 查询转发器(转到上游DNS 服务器或者本机上的 SkyDns)和结果缓存器,它本身并不保存域名的原始记录。
1.2.3 SkyDNS 及其配置
关于 SkyDNS:它是一个开源的构建在 etcd 之上的分布式服务宣告(announcement)和发现(discovery)服务。利用它,可以通过 DNS 查询来发现可用的服务。其开源社区的地址是 。社区版本的 SkyDns 将记录保存在 etcd 中,在做查询时从etcd 获取数据并封装成 DNS 结果格式给客户端。
SkyDNS 的 server 部分支持被作为库文件使用,此时可以为其实现其它后端。在OpenShift 中并没有采用默认的 etcd 后端,而是基于 OpenShift API 服务实现了新的后端,其代码在 。SkyDns 调用 OpenShift API 服务来获取主机名、IP地址等信息,然后封装成标准 DNS 记录并返回给查询客户端。
在 127.0.0.1:53 上,包装在 openshift 进程中的 SkyDNS 在侦听。
tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 17182/openshift
Node 节点上的 SkyDN 要么从cache 中直接回答 DNS 查询,要么调用 OpenShift API 服务来获取数据并返回。
1.3 Master 节点上的 DNS 服务
re 文件同Node 节点上的:
[root@master1 cloud-user]# cat /etc/re
# nameserver updated by /etc/NetworkManager
# Generated by NetworkManager
search clu exam
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 clu
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。
二、DNS 查询流程
2.1 pod 内的应用通过域名访问外网服务器的DNS查询流程
流程示意图如最上面图中的 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. from 172.22.122.13
Nov 21 11:03:49 dnsmasq[17788]: forwarded www. to 172.22.122.4
Nov 21 11:03:49 dnsmasq[17788]: forwarded www. to 172.22.122.2
Nov 21 11:03:49 dnsmasq[17788]: forwarded www. to 172.22.122.3
Nov 21 11:03:49 dnsmasq[17788]: reply is 124.228.42.248
能看到 node 上的 dnsmasq 直接将查询请求转发给上游 DNS 名字服务器。因为存在多个名字服务器,所以是依次查询,直到成功为止。从日志看,其查询顺序和配置文件中的顺序是相反的。
2.2 Pod 内应用通过服务域名查找其IP 地址
流程示意图如上图中的 1 + 2.2 + 3 部分所示。
日志实例:
(1)从一个 pod 中 ping registry-console服务的域名 registry-console.default.。
(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.
;; QUESTION SECTION:
;mybank.dev.. IN A
;; ANSWER SECTION:
mybank.dev.. 30 IN A 172.30.162.172;; Query time: 1 msec
;; SERVER: 172.22.122.9#53)
;; 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. from 10.128.2.128
Dec 3 14:19:44 dnsmasq[29595]: forwarded mybank.dev. to 127.0.0.1
Dec 3 14:19:44 dnsmasq[29595]: reply mybank.dev. is 172.30.162.172
(5)其它实验:查询服务的所有端点
查询结果:
[root@node2 cloud-user]# nsenter -t 4216 -n dig jenkins.dev.endpoints.clu
;; QUESTION SECTION:
;jenkins.dev.endpoints.clu. IN A
;; ANSWER SECTION:jenkins.dev.endpoints.clu. 30 IN A 10.128.2.81
jenkins.dev.endpoints.clu. 30 IN A 10.131.1.70
dnsmasq 日志:
Dec 3 14:20:48 dnsmasq[29595]: query[A] jenkins.dev.endpoints.clu from 10.128.2.128
Dec 3 14:20:48 dnsmasq[29595]: forwarded jenkins.dev.endpoints.clu to 127.0.0.1
Dec 3 14:20:48 dnsmasq[29595]: reply jenkins.dev.endpoints.clu is 10.128.2.81
Dec 3 14:20:48 dnsmasq[29595]: reply jenkins.dev.endpoints.clu 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.clu;; QUESTION SECTION:
;172-30-162-172.dev.pod.clu. IN A
;; ANSWER SECTION:
172-30-162-172.dev.pod.clu. 30 IN A 172.30.162.172;; Query time: 1 msec
;; SERVER: 172.22.122.9#53)
;; 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.clu from 10.128.2.128
Dec 3 14:22:24 dnsmasq[29595]: forwarded 172-30-162-172.dev.pod.clu to 127.0.0.1
Dec 3 14:22:24 dnsmasq[29595]: reply 172-30-162-172.dev.pod.clu 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. ) 56(84) bytes of data.
而这个 FQDN 被直接做DNS查询,结果查询失败,未能获取IP地址:
[root@node2 cloud-user]# nsenter -t 4216 -n ping mybank.dev.: mybank.dev.svc.: Name or service not known
2.3 从外网通过服务域名访问pod 中运行的服务
可以看出,该过程中只涉及到外部DNS将服务的公共域名解析为 OpenShift Router 所在节点的公网地址,后面 HAProxy 作为代理,直接通过 IP 访问pod,并将结果返回客户端。
参考文档:
作者:Sammy Liu
1.文章《域名服务器是什么、dns域名服务器的作用是什么》援引自互联网,为网友投稿收集整理,仅供学习和研究使用,内容仅代表作者本人观点,与本网站无关,侵删请点击页脚联系方式。
2.文章《域名服务器是什么、dns域名服务器的作用是什么》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
相关推荐
- . 现代买票为什么带上携程保险
- . 潮阳怎么去广州南站
- . 湖南马拉河怎么样
- . 烧纸为什么到三岔路口
- . 百色为什么这么热
- . 神州租车怎么样
- . 芜湖方特哪个适合儿童
- . 护肤品保养液是什么类目
- . 早晚的护肤保养有哪些项目
- . 女孩护肤品怎么保养的最好