curl 和 wget 无法解析 aks 集群内的内部 dns 名称,但 nslookup、host、dig 工作正常

curl 和 wget 无法解析 aks 集群内的内部 dns 名称,但 nslookup、host、dig 工作正常

我在 Azure 上有一个托管的 kubernetes 实例。我非常确定核心 DNS 正在运行,并且 DNS Pod 运行正常。

我有几个服务

  1. 带有一个 pod 的前端服务 - 具有静态前端文件的图像[nginx-alpine]。

  2. backend-service ,带有一个 pod - 包含 nodejs 代码的镜像 [ubuntu:20.04]。

我无法从后端的 pod 解析内部 dns 服务名称(如 frontend-service 或 frontend-service.default.svc.cluster.local),但内部 dns 名称的 nslookup 、 host 、 dig 可以解析到正确的地址。后端 pod 还能够解析外部 dns 名称(如 google.com)。

curl http://frontend-service
curl: (6) Could not resolve host: frontend-service

curl http://frontend-service.default.svc.cluster.local
curl: (6) Could not resolve host: frontend-service.default.svc.cluster.local
wget frontend-service
--2020-08-31 23:36:43--  http://frontend-service
Resolving frontend-service (frontend-service)... failed: Name or service not known.
wget: unable to resolve host address 'frontend-service'
/etc/nsswitch.conf shows the below :

passwd:         files
group:          files
shadow:         files
gshadow:        files

hosts:          files dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

尝试从前端服务的 pod 解析后端服务内部 DNS 名称时,一切正常。

经过一些调试并查看 coredns 和 strace 的日志后,我发现在执行 curl 时没有对 coredns pod 进行任何调用,但在执行 nslookup 时我可以看到该条目。

我还验证了 /etc/resolv.conf 是否具有正确的配置。

nameserver 10.3.0.10
search default.svc.cluster.local svc.cluster.local cluster.local tdghymxumodutbxfnz5m2elcog.bx.internal.cloudapp.net
options ndots:5

strace 没有显示任何用于搜索 /etc/resolv.conf 的条目,因此 curl 没有检查 /etc/resolv.conf。

编辑1

From the backend service pod :
dig frontend-service [It is able to resolve to the correct name server.]


; <<>> DiG 9.16.1-Ubuntu <<>> frontend-service
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 13441
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; OPT=65436: 87 a1 ee 81 04 d8 5a 49 be 0e c4 ed 1d d8 27 41 ("......ZI......'A")
;; QUESTION SECTION:
;frontend-service.            IN      A

;; AUTHORITY SECTION:
.                       30      IN      SOA     a.root-servers.net. nstld.verisign-grs.com. 2020083101 1800 900 604800 86400

;; Query time: 20 msec
;; SERVER: 10.3.0.10#53(10.3.0.10)
;; WHEN: Tue Sep 01 10:48:00 IST 2020
;; MSG SIZE  rcvd: 142

nslookup frontend-service

Server:         10.3.0.10
Address:        10.3.0.10#53

Name:   frontend-service.default.svc.cluster.local
Address: 10.3.0.30
host frontend-service     
frontend-service.default.svc.cluster.local has address 10.3.0.30

编辑2

我想使用相同的 ubuntu:20.04 映像逐步测试部署,因此我执行了以下步骤。

方法 1

我在集群中创建了一个临时 pod,如下所示。

kubectl run -it --rm test-ubuntu --image=ubuntu:20.04 --restart=Never

Installed curl (7.68) and ran the curl http://frontend-service – This is successful.

这让我很困惑,所以我从 Dockerfile 中删除了所有的构建步骤,只使用了以下命令。

方法 2

Dockerfile

FROM ubuntu:20.04
 
EXPOSE 3688
CMD [ "sleep", "infinity" ]

将图像推送到 acr 并再次部署后端 pod。

kubectl exec -it <pod-name> /bin/bash

I installed curl (7.68) and ran the curl http://frontend-service – Same error – unable to resolve host.

令人惊讶的是,具有相同内容的相同图像 - 通过 kubectl run 运行并通过 Dockerfile 部署,在运行相同版本(7.68)的 curl 时却有不同的行为。

我想查看这两个方法中的 strace 流程。请找到 RUN 和 EXEC 中的 strace 链接

从临时 pod 中运行 curl 进行 strace 操作。 https://pastebin.com/NthHQacW

通过 Dockerfile 部署的 pod 运行 curl 进行 strace https://pastebin.com/6LCE5NXu

通过运行分析探测路径后

cat strace-log | grep open

我发现方法 2 的 strace 日志缺少以下几行。


2844  openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 7
2844  openat(AT_FDCWD, "/etc/host.conf", O_RDONLY|O_CLOEXEC <unfinished...>
2844  <... openat resumed>)             = 7
2844  openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 7
2844  openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 7
2844  openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 7
2844  openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 7
2844  openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC <unfinished ...>
2844  <... openat resumed>)             = 7
2844  openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_dns.so.2", O_RDONLY|O_CLOEXEC) = 7

因此 pod 内的 curl 命令不会查看 /etc/resolv.conf 或 /etc/nsswitch.conf。

我很困惑为什么同一个集群中具有相同图像和相同 curl 版本的两个 pod 中的 curl 行为会有所不同。

答案1

尝试了很多选项后,我尝试调试用于将 pod 部署到 AKS 集群的部署配置文件。我有一个基于主机挂载的卷,指向路径“/var/run”。

一旦我删除了主机挂载,curl 和 wget 就可以按预期工作。

在与 MS 支持人员讨论了此行为之后,他们确认如果您有一个指向路径“/var/run”的主机挂载,curl 和 wget 不会回退到 /etc/resolv.conf 文件进行 DNS 解析,这可能是由于 DNS 探测在 curl 和 wget 中的实现方式所致。

相关内容