为什么dig无法通过DNS名称解析K8s服务,而nslookup却没有问题?

14

以下是复现步骤:

minikube start
kubectl run nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=ClusterIP

kubectl run -i --tty --rm alpine --image=alpine --restart=Never -- sh
apk add --no-cache bind-tools

现在让我们尝试使用nslookup查询kibe-dns中的nginx服务。

/ # nslookup nginx.default 10.96.0.10
Server:     10.96.0.10
Address:    10.96.0.10#53

Name:   nginx.default.svc.cluster.local
Address: 10.97.239.175

并且使用 dig 命令:

dig nginx.default @10.96.0.10 any

; <<>> DiG 9.11.3 <<>> nginx.default @10.96.0.10 any
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46414
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;nginx.default.         IN  ANY

;; Query time: 279 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Sun Jun 03 15:31:15 UTC 2018
;; MSG SIZE  rcvd: 42

如果我将名称nginx.default替换为nginx,则不会发生任何更改。

minikube 版本: v0.27.0, k8s 版本: 1.10.0

2个回答

17

答案

Dig默认情况下不使用搜索路径完成查询。搜索路径在/etc/resolv.conf中设置。+search标志启用搜索路径完成。

来自Man Pages

+[no]search
使用[不使用]由resolv.conf中的searchlist或domain指令定义的搜索列表。默认情况下不使用搜索列表。

https://linux.die.net/man/1/dig

演示

我创建了一个场景,可以互动地通过相同的示例进行演示https://www.katacoda.com/bluebrown/scenarios/kubernetes-dns

首先创建并暴露一个Pod,然后以dnsutils安装的交互方式启动另一个Pod,可以从中进行DNS查询。

kubectl create namespace dev
kubectl run my-app --image nginx --namespace dev --port 80
kubectl expose pod my-app --namespace dev
kubectl run dnsutils --namespace dev --image=bluebrown/netutils --rm -ti

Nslookup 可以成功解析该服务。

$ nslookup my-app
...
Name:   my-app.dev.svc.cluster.local
Address: 10.43.52.98

但是dig没有得到一个答案,为什么?

$ dig my-app
...
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
...
为了理解为什么dig找不到该服务,请查看/etc/resolv.conf。
$ cat /etc/resolv.conf
search dev.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.43.0.10
options ndots:5

这个文件包含一个遵循以下格式的行。

search <namespace>.svc.cluster.local svc.cluster.local cluster.local

这意味着,当提供完全限定域名(FQDN)的不完整部分时,可以使用该文件来完成查询。但是,默认情况下dig不会这样做。我们可以使用+search标志来启用它。

dig +search my-app
...
;; QUESTION SECTION:
;my-app.dev.svc.cluster.local.  IN      A

;; ANSWER SECTION:
my-app.dev.svc.cluster.local. 5 IN      A       10.43.52.98

现在服务名称已经正确解析。您可以通过将此命令的问题部分与没有+search标志的先前命令进行比较,来查看查询是如何使用搜索路径完成的。

当使用FQDN时,我们可以不使用+search标志获取相同的服务。 +short标志不是必需的,但它将仅缩小输出到IP地址。

$ dig +short my-app.dev.svc.cluster.local
10.43.52.98

然而,使用search方法的好处在于查询将自动解析到相同命名空间内的资源。这对于将相同配置应用于不同环境(例如生产和开发)非常有用。

resolv.conf中的搜索条目完成默认名称空间的查询方式相同,它将从左到右地完成FQDN的任何部分。因此,在下面的示例中,它将解析为本地集群。

$ dig +short +search my-app.dev
10.43.52.98

5

需要指出的几件事情:

  1. 始终使用 "nginx.default.svc.cluster.local",不要依赖工具来为您完成。
  2. 运行 dig nginx.default.svc.cluster.local NS,您会发现没有任何托管名称服务器。只有至少存在一个名称服务器时,您才能指定一个名称服务器。
  3. 有趣的是,我发现 alpine 中的 dig any 并不能很好地工作,因此在这种情况下,恐怕您必须明确使用 A 或将其留空(A 是默认值)。

结论:

请使用 dig nginx.default.svc.cluster.localdig nginx.default.svc.cluster.local A 进行查询。


1
谢谢。您提供的两个选项都可以使用dig进行DNS解析。这个问题实际上是在使用HaProxy后出现的。我有一个resolvers部分和一个带有DNS名称而不是网络地址的后端服务器。我试图检查当DNS名称首次停止解析并在一段时间后继续解析时,HaProxy是否继续代理。有趣的是,nginx在启动时被正确解析。但是每30秒钟它都无法通过这个“短”名称检查服务器后端。HaProxy解析器也更喜欢nginx.default.svc.cluster.local,即使它在启动时只能处理nginx - Kirill
5
默认情况下,dig 不使用搜索路径。请尝试使用 dig +search shortname 命令。参考资料:https://github.com/kubernetes/kubernetes/issues/16744 - mellow-yellow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接