coredns 排查之 IPV6 解析异常导致镜像 pull 失败

150 阅读2分钟

表现

在机器上,curl harbor 域名返回状态码 200,但执行 crictl pull rancher/rancher-agent:v2.6.8 时出现异常:dial tcp: lookup <domain>: try again

# crictl pull rancher/rancher-agent:v2.6.8
FATA[2023-05-10T22:23:36.325976772+08:00]pulling image: rpc error: code = Unknown desc = failed to pull and unpack image "rancher/rancher-agent:v2.6.8": failed to copy: httpReaderSeeker: failed open: failed to do request: Get "..."
... : dial tcp: lookup <domain>: try again 

排查

  1. 通过 PINGcurl https://<domain> 两者验证 OK。
  2. 通过配置 /etc/hosts 后执行后重新 pull 成功。

怀疑是 crictl 命令执行时 dns 返回的解析参数问题。通过 tcpdump 抓取 DNS 包分析。从包中发现,镜像域名的 A 记录解析正常,但 AAAA 记录返回的状态是 Server Failure,而不是预期的 NOERROR 状态。

image.png

结合上面 curl 操作正常,我们将问题范围缩小到 golang net 库对于 DNS 解析的实现上(crictl 是 golang 实现的工具)。

查看 go net 的源码,在 src/net/dnsclient_unix 解析时,会同时进行 A 和 AAAA 记录的解析:

image.png

在对解析结果的处理上,在 dns response 处理 时,AAAA 解析返回 Server Failure 导致返回的 addr = nil:

image.png

从而导致后续在 crictl pull 时出现异常:dial tcp : lookup 异常。

补充:什么样的异常会中断 DNS 解析呢?哪些异常是 strictErrors() 呢?

StrictErrors 控制使用 Go 内置解析器时的临时错误(包括超时、套接字错误和 SERVFAIL)的行为。对于由多个子查询组成的查询(例如 A+AAAA 地址查找或遍历 DNS 搜索列表),此选项会导致此类错误中止整个查询而不是返回部分结果。默认情况下未启用,因为它可能会影响与错误处理 AAAA 查询的解析器的兼容性

按照 RFC 1035 中的定义了 DNS 返回异常的 RCODE,从而中断了 DNS 解析。

措施

  1. 检查运行环境对 AAAA 进行拦截,放行
  2. 配置 /etc/hosts (优先级更高)