问题描述
# 04/16/2019
主机 centos 4.18.12-1.el7.elrepo.x86_64 系统,镜像 apline 系统。在容器里 PING 某个域名,在进行 DNS 解析时会有一段时间的延迟。
使用tcpdump抓包,发现:在容器中,当 PING 某个域名时,发出两次 DNS 查询,一个 IPv4 的 A 记录,一个 IPv6 的 AAAA 记录。当 DNS 查询记录为 A 类型时,是整正常的。当 DNS 查询类型为 AAAA 时,返回的 DNS 状态码是 SERVFAIL(RCODE=2)。当然,我们的 DNS 服务器中并没有 IPv6 的记录,但是返回 SERVFAIL 是不正常的(我查了返回 SERVFAIL 的原因)。但是,在容器中 PING 百度时是正常的。因为 BAIDU 的 IPv6 返回的不是 ServFail 状态,而是 IPv6 地址。
使用 PING -4 时,马上返回结果,因为值进行了 IPv4 的 A 记录解析。然后,结合 DNS Issue #255 中的描述,我们将问题的焦点放在了 DNS 上,DNS 服务器是 BIND,使用它的了 DLZ 技术。
这里面有很多猜疑的成分,由于不具备某些方面的知识,正确的思路是:在 PING 出现问题的时候,进行调试,堆栈追踪,找到程序的行为,然后确定是 DNS 返回的 SERVFAIL 导致程序的延迟,然后了解 SERFFAIL 的状态值、含义、返回原因,然后综合处理问题。
原因分析
问题是 DNS 服务器返回 SERVFAIL 状态导致的。该状态导致了 PING 命令延迟。(这里面存在猜疑的成分,但是结论的可信度还是很高的)
还有一方面,好多程序开始尝试同时进行 IPv4 的 A 记录和 IPv4 之上的 AAAA 记录的解析。在 PHP 的 CURL 中,也出现了类似的现象,但是我没有进行验证,只是相信是同样的原因。时间成本太高了,还有很多其他的事情要做,又不是只解决这个一个问题。
解决方法
解决方法由以下几个:
1)从根本上解决 DNS 服务器返回 SERVFAIL 状态的。(我们采用的方案)
2)更换镜像或者依赖程序类库,来使得解析的时候只进行 IPv4 的 A 记录解析。(不根本,影响后期 IPv4 切换)
3)调整容器,修改 /etc/resov.conf 配置,设置 timeout 和 attempts 选项,减少重试和超时。(不根本,时间粒度大,影响体验,最多就是暂缓问题)
4)调整容器,在 /etc/hosts 手动绑定。(此方案最多就是暂缓了问题,依旧没有解决问题)
5)还有一些其他的办法,最后都被过滤掉了。技术不可行,或者工作量太大。
该问题特定于 BIND 的 DLZ 技术,问题已经记录在 BIND DLZ 笔记中。
# 04/02/2021 今天,在 Ubuntu 18.04 中,我们再次遇见该问题,在 tcpdump 后,我们发现相同的原因导致该问题。解决方案有以下几种:
参考文献
DNS Issue #255
DNS/IPV6 Problem #153
What does it mean when I get a server failure when connecting to a router with DNS protocol