场景

在 Kubernetes 中,我们经常会有直接使用 Service 的名字访问对应 Service 地址的场景。

举个栗子,我们建一个 Service,名字叫 demo-svc ,对应的 ClusterIP10.0.171.239 ,端口为 80 。 那么,我们在访问同一个 Namespace 下的这个 Service 时,我们一般会通过一下几种方式之一访问:

  • 10.0.171.239:80
  • demo-svc:80
  • demo-svc.namespace-name.svc.cluster.local:80

注意:如果时要访问不同 Namespace 下,或者集群外部 Service,可以通过 ExternalName 类型的 Service 实现, 但是这是另一个话题,就不展开了。

通过 IP 地址访问的情况自然是不需要解释,通过 Service 名字访问的方式也很自然能想到时通过 DNS 解析实现。

但是, demo-svcdemo-svc.namespace-name.svc.cluster.local 之间的区别和关系是什么呢?

原理解析

DNS

查看 Pod 内的 /etc/resolve.conf ,能看到一下内容:

  nameserver 10.0.0.10
  search namespace-name.svc.cluster.local svc.cluster.local cluster.local
  options ndots:5

其中:

  • 10.0.0.10 时 CoreDNS 的 Service 的 IP 地址,我们的请求都会发送到 CoreDNS 解析。
  • search 时 Kubernetes 加上的,顾名思义,解析 DNS 的时候会 查找 后面对应的这几个后缀。
  • options ndots:5 这个有意思,当请求的域名里,显式出现少于 5 个 时,才补上 search 的后缀。

值得注意的时 options ndots:5 ,显式出现少于 5 个 是什么意思呢?

  • demo-svc.namespace-name.svc.cluster.local: 有 4 个点,会补全 search 中后缀解析
  • demo-svc.namespace-name.svc.cluster.local.: 有 5 个点,只会使用原域名解析

所以,我们在使用 demo-svc 访问 Service 的时候,DNS 解析时会自动加上 namespace-name.svc.cluster.local 进行解析,得到 demo-svc.namespace-name.svc.cluster.local. 的 IP 地址, 所以,我们在访问 Service 时,最终都是以 demo-svc.namespace-name.svc.cluster.local. 的地址访问的。

补全顺序

上文提到当少于 5 个 时,会补全域名再解析,那会按 search 配置中的顺序, 从前往后,依次尝试,还是刚刚的栗子:

demo-svc 在解析时,会尝试:

  • demo-svc.namespace-name.svc.cluster.local
  • demo-svc.svc.cluster.local
  • demo-svc.cluster.local

当然,在尝试 demo-svc.namespace-name.svc.cluster.local 时就已经匹配了,就不会继续尝试后续的了。

验证

怎么来验证上文内容呢,有两个方式:

  • 客户端
  • 服务端

客户端

上文内容也不外乎是 DNS 解析,既然时 DNS,那少不了的工具就是dig

dig 是 BIND9 套件中的域名解析工具,至于 BIND9 又是什么,那就可以再花一篇文章来讲了。

本文中,我们可以进到某一个容器中,用 dig 来验证我们的结果。

使用 dig 时, +showsearch 参数会打印出尝试结果:

4 个点,补全:

可以看到,我们访问 demo-svc.namespace-name.svc.cluster.local 时,由于上文提到的, 只有 4 个点,所以自动补全搜索了:

如果我们访问 demo-svc 也是一样的结果,只是第一次补全就会看到成功。

  # 进入容器
  kubectl exec -it pod-name bash
  # root@pod-name:/#

  # 使用 4 个点的域名,用于验证 4 个点的补全
  dig demo-svc.namespace-name.svc.cluster.local +showsearch

  # ; <<>> DiG 9.11.3-1ubuntu1.7-Ubuntu <<>> demo-svc.namespace-name.svc.cluster.local +showsearch
  # ;; global options: +cmd
  # ;; Got answer:
  # ;; WARNING: .local is reserved for Multicast DNS
  # ;; You are currently testing what happens when an mDNS query is leaked to DNS
  # ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 44747
  # ;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
  # ;; WARNING: recursion requested but not available
  #
  # ;; OPT PSEUDOSECTION:
  # ; EDNS: version: 0, flags:; udp: 4096
  # ; COOKIE: 0e9627a231a03702 (echoed)
  # ;; QUESTION SECTION:
  # ;demo-svc.namespace-name.svc.cluster.local.namespace-name.svc.cluster.local. IN A
  #
  # ;; AUTHORITY SECTION:
  # cluster.local.		5	IN	SOA	ns.dns.cluster.local. hostmaster.cluster.local. 1567162775 7200 1800 86400 5
  #
  # ;; Query time: 0 msec
  # ;; SERVER: 10.0.0.10#53(10.0.0.10)
  # ;; WHEN: Fri Aug 30 11:06:19 UTC 2019
  # ;; MSG SIZE  rcvd: 200
  #
  #
  # ; <<>> DiG 9.11.3-1ubuntu1.7-Ubuntu <<>> demo-svc.namespace-name.svc.cluster.local +showsearch
  # ;; global options: +cmd
  # ;; Got answer:
  # ;; WARNING: .local is reserved for Multicast DNS
  # ;; You are currently testing what happens when an mDNS query is leaked to DNS
  # ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 53786
  # ;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
  # ;; WARNING: recursion requested but not available
  #
  # ;; OPT PSEUDOSECTION:
  # ; EDNS: version: 0, flags:; udp: 4096
  # ; COOKIE: 0e9627a231a03702 (echoed)
  # ;; QUESTION SECTION:
  # ;demo-svc.namespace-name.svc.cluster.local.svc.cluster.local.	IN A
  #
  # ;; AUTHORITY SECTION:
  # cluster.local.		5	IN	SOA	ns.dns.cluster.local. hostmaster.cluster.local. 1567162775 7200 1800 86400 5
  #
  # ;; Query time: 0 msec
  # ;; SERVER: 10.0.0.10#53(10.0.0.10)
  # ;; WHEN: Fri Aug 30 11:06:19 UTC 2019
  # ;; MSG SIZE  rcvd: 188
  #
  #
  # ; <<>> DiG 9.11.3-1ubuntu1.7-Ubuntu <<>> demo-svc.namespace-name.svc.cluster.local +showsearch
  # ;; global options: +cmd
  # ;; Got answer:
  # ;; WARNING: .local is reserved for Multicast DNS
  # ;; You are currently testing what happens when an mDNS query is leaked to DNS
  # ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 1277
  # ;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
  # ;; WARNING: recursion requested but not available
  #
  # ;; OPT PSEUDOSECTION:
  # ; EDNS: version: 0, flags:; udp: 4096
  # ; COOKIE: 0e9627a231a03702 (echoed)
  # ;; QUESTION SECTION:
  # ;demo-svc.namespace-name.svc.cluster.local.cluster.local. IN A
  #
  # ;; AUTHORITY SECTION:
  # cluster.local.		5	IN	SOA	ns.dns.cluster.local. hostmaster.cluster.local. 1567162775 7200 1800 86400 5
  #
  # ;; Query time: 0 msec
  # ;; SERVER: 10.0.0.10#53(10.0.0.10)
  # ;; WHEN: Fri Aug 30 11:06:19 UTC 2019
  # ;; MSG SIZE  rcvd: 184
  #
  #
  # ; <<>> DiG 9.11.3-1ubuntu1.7-Ubuntu <<>> demo-svc.namespace-name.svc.cluster.local +showsearch
  # ;; global options: +cmd
  # ;; Got answer:
  # ;; WARNING: .local is reserved for Multicast DNS
  # ;; You are currently testing what happens when an mDNS query is leaked to DNS
  # ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8827
  # ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
  # ;; WARNING: recursion requested but not available
  #
  # ;; OPT PSEUDOSECTION:
  # ; EDNS: version: 0, flags:; udp: 4096
  # ; COOKIE: 0e9627a231a03702 (echoed)
  # ;; QUESTION SECTION:
  # ;demo-svc.namespace-name.svc.cluster.local. IN A
  #
  # ;; ANSWER SECTION:
  # demo-svc.namespace-name.svc.cluster.local. 5	IN A	10.102.159.83
  #
  # ;; Query time: 0 msec
  # ;; SERVER: 10.0.0.10#53(10.0.0.10)
  # ;; WHEN: Fri Aug 30 11:06:19 UTC 2019
  # ;; MSG SIZE  rcvd: 129

5 个点,不补全

当访问域名有 5 个点时,就不会尝试补全,如完整的 demo-svc.namespace-name.svc.cluster.local.:

  # 进入容器
  kubectl exec -it pod-name bash
  # root@pod-name:/#

  # 使用 5 个点的域名,用于验证 5 个点的不补全