为什么 dig 没有通过 dns 名称解析 K8s 服务,而 nslookup 没有问题?
Why dig does not resolve K8s service by dns name while nslookup has no problems with it?
重现步骤如下:
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
现在让我们尝试查询 kibe-dns 以获得 nginx
服务
与 nslookup
:
/ # 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
需要指出的几点:
- 始终使用 "nginx.default.svc.cluster.local",不要依赖工具为您完成。
- 运行
dig nginx.default.svc.cluster.local NS
您会看到它没有托管名称服务器。当至少存在一个时,您只能指定一个。
- 有趣的是,我发现
dig any
在 alpine 中并没有真正起作用,所以在这种情况下,恐怕您必须明确使用 A
或将其留空(A 是默认)
结论:
运行 dig nginx.default.svc.cluster.local
或 dig nginx.default.svc.cluster.local A
。
回答
Dig 默认不使用搜索路径完成查询。搜索路径设置在/etc/resolv.conf
中。 +search
标志启用搜索路径完成。
来自手册页
+[no]search
Use [do not use] the search list defined by the searchlist or domain directive in resolv.conf (if any). The search list is not used by default.
https://linux.die.net/man/1/dig
示范[=56=]
我为 katacoda 创建了一个场景,它以交互方式执行相同的示例 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 tutum/dnsutils -ti -- bash
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
方法的好处是查询将自动解析为同名资源 space。这对于将相同的配置应用于不同的环境(例如生产和开发)很有用。
与 resolv.conf
中的搜索条目以默认名称 space 完成查询的方式相同,它将从左到右完成 FQDN 的任何部分。所以在下面的例子中,它将解析到本地集群。
$ dig +short +search my-app.dev
10.43.52.98
重现步骤如下:
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
现在让我们尝试查询 kibe-dns 以获得 nginx
服务
与 nslookup
:
/ # 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
需要指出的几点:
- 始终使用 "nginx.default.svc.cluster.local",不要依赖工具为您完成。
- 运行
dig nginx.default.svc.cluster.local NS
您会看到它没有托管名称服务器。当至少存在一个时,您只能指定一个。 - 有趣的是,我发现
dig any
在 alpine 中并没有真正起作用,所以在这种情况下,恐怕您必须明确使用A
或将其留空(A 是默认)
结论:
运行 dig nginx.default.svc.cluster.local
或 dig nginx.default.svc.cluster.local A
。
回答
Dig 默认不使用搜索路径完成查询。搜索路径设置在/etc/resolv.conf
中。 +search
标志启用搜索路径完成。
来自手册页
+[no]search
Use [do not use] the search list defined by the searchlist or domain directive in resolv.conf (if any). The search list is not used by default.
https://linux.die.net/man/1/dig
示范[=56=]
我为 katacoda 创建了一个场景,它以交互方式执行相同的示例 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 tutum/dnsutils -ti -- bash
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
方法的好处是查询将自动解析为同名资源 space。这对于将相同的配置应用于不同的环境(例如生产和开发)很有用。
与 resolv.conf
中的搜索条目以默认名称 space 完成查询的方式相同,它将从左到右完成 FQDN 的任何部分。所以在下面的例子中,它将解析到本地集群。
$ dig +short +search my-app.dev
10.43.52.98