「DNS」- 请求响应慢、延迟约 5 秒钟

  CREATED BY JENKINSBOT

问题描述

# 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 后,我们发现相同的原因导致该问题。解决方案有以下几种:

1)修改 /etc/resolv.conf 文件,添加 options single-request 选项(因为从 glibc 2.9 开始,将并行执行 A 与 AAAA 查询,而部分服务端不响应而导致客户端等待,参考 man 5 resolv.conf 对 single-request 的说明)。
但是,在 Ubuntu 18.04 中,默认使用 Netplan 管理网络,暂不支持设置 single-request 选项。

2)禁用 Linux IPv6 协议栈,参考
Disable IPv6 on Linux 笔记。

参考文献

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