为什么 dig 不能通过 dns 名称解析 K8s 服务,而 nslookup 却没有问题?

Kir*_*ill 14 nslookup dig kubernetes kube-dns kubernetes-service

以下是重现步骤:

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
Run Code Online (Sandbox Code Playgroud)

现在让我们尝试查询 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

nginx.default如果我仅将 name 替换为 ,则不会发生任何变化nginx

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

The*_*ool 17

回答

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

来自手册页

+[no]search
使用[不使用]resolv.conf 中的 searchlist 或域指令(如果有)定义的搜索列表。默认情况下不使用搜索列表。

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

示范

我为 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=bluebrown/netutils --rm -ti
Run Code Online (Sandbox Code Playgroud)

nslookup解析服务OK

$ nslookup my-app
...
Name:   my-app.dev.svc.cluster.local
Address: 10.43.52.98
Run Code Online (Sandbox Code Playgroud)

但dig没有得到答案,为什么呢?

$ dig my-app
...
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
...
Run Code Online (Sandbox Code Playgroud)

为了理解为什么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
Run Code Online (Sandbox Code Playgroud)

该文件包含具有以下格式的行。

search <namespace>.svc.cluster.local svc.cluster.local cluster.local
Run Code Online (Sandbox Code Playgroud)

这意味着,当提供完全限定域名 (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
Run Code Online (Sandbox Code Playgroud)

现在服务名称已被正确解析。您还可以通过将此命令的问题部分与前一个不带标志的命令部分进行比较,了解如何使用搜索路径完成查询+search

+search使用 FQDN 时,我们可以获得相同的服务而无需标记。该+short标志不是必需的,但它会将输出减少为仅 IP 地址。

$ dig +short my-app.dev.svc.cluster.local
10.43.52.98
Run Code Online (Sandbox Code Playgroud)

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

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

$ dig +short +search my-app.dev
10.43.52.98
Run Code Online (Sandbox Code Playgroud)


小智 5

有几点需要指出:

  1. 始终使用“nginx.default.svc.cluster.local”,并且不要依赖该工具为您完成它。
  2. 运行dig nginx.default.svc.cluster.local NS你会看到没有托管名称服务器。当至少存在一个时,您只能指定一个。
  3. 有趣的是,我发现dig any在高山中并没有真正起作用,所以在这种情况下,恐怕你必须明确使用A或将其留空(A是默认值)

结论:

运行dig nginx.default.svc.cluster.localdig nginx.default.svc.cluster.local A代替。

  • dig 默认情况下不使用搜索路径。尝试挖掘 + 搜索简称。参考:https://github.com/kubernetes/kubernetes/issues/16744 (5认同)