循环

源代码

loop 可检测到简单的转发循环并停止服务器。

描述

loop 插件会向我们自己发送一个随机探测查询,然后会跟踪我们看到它的次数。如果我们看到它的次数多于两次,我们便假定 CoreDNS 已经看到一个转发循环,然后我们就会停止该进程。

该插件会尝试发送查询,最长可达 30 秒。这样做是为了给 CoreDNS 足够的时间启动。在成功发送查询后,loop 会禁用自身,以防查询死循环。

请注意,loop 会发送服务器区块中给出的第一个区域的“循环查询”。

发送的查询为 <随机数>.<随机数>.zone,类型设置为 HINFO。

语法

loop

示例

在默认端口上启动一个服务器并加载 loopforward 插件。forward 插件转发到其自身。

. {
    loop
    forward . 127.0.0.1
}

CoreDNS 启动后,它在记录日志时停止进程

plugin/loop: Loop (127.0.0.1:55953 -> :1053) detected for zone ".", see https://coredns.golang.ac.cn/plugins/loop#troubleshooting. Query: "HINFO 4547991504243258144.3688648895315093531."

限制

此插件仅尝试在启动时查找简单的静态转发循环。若要检测循环,以下情况必须为真

  • 循环必须在启动时存在。

  • 对于 HINFO 查询类型,必须出现循环。

故障排除

当 CoreDNS 日志包含消息 Loop ... detected ... 时,这意味着 loop 检测插件已在其中一个上游 DNS 服务器中检测到无限转发循环。这是一个致命错误,因为使用无限循环会导致直至最终由主机耗尽内存而死亡的内存和 CPU 消耗。

转发循环通常是由以下原因引起的

  • 最常见的情况是,CoreDNS 直接向其自身转发请求。例如,通过回送地址,例如 127.0.0.1::1127.0.0.53
  • 较少见的情况是,CoreDNS 转发到上游服务器,而上游服务器又将请求转发回 CoreDNS。

若要对此问题进行故障排除,请在 Corefile 中查找任何对检测到循环所在的区域的 forward。确保它们没有转发到本地地址或转发请求回 CoreDNS 的另一个 DNS 服务器。如果 forward 正在使用文件(例如 /etc/resolv.conf),请确保该文件没有包含本地地址。

Kubernetes 集群中的循环故障排除

在 Kubernetes 中部署的 CoreDNS Pod 检测到循环时,CoreDNS Pod 将开始“CrashLoopBackOff”。这是因为每次 CoreDNS 检测到循环并退出时,Kubernetes 都会尝试重新启动 Pod。

在 Kubernetes 集群中造成转发循环的一个常见原因是在主机节点(例如 systemd-resolved)上与本地 DNS 缓存进行交互。例如,在特定配置中,systemd-resolved 会将环回地址 127.0.0.53 作为 DNS 服务器放入 /etc/resolv.conf 中。Kubernetes(通过 kubelet)默认会使用 default dnsPolicy 将此 /etc/resolv.conf 文件传递至所有 Pod,从而使它们无法进行 DNS 查找(包括 CoreDNS Pod)。CoreDNS 将此 /etc/resolv.conf 用作将请求转发到的上游列表。由于它包含环回地址,因此 CoreDNS 最终会将请求转发到它自己。

解决此问题的方法有很多,这里列出了一些

  • 将以下内容添加到 kubelet 配置 yaml:resolvConf: <path-to-your-real-resolv-conf-file>(或通过 1.10 中弃用的命令行标志 --resolv-conf)。您的“真实”resolv.conf是包含上游服务器实际 IP 且没有本地/环回地址的resolv.conf。此标志告诉 kubelet 将备用的 resolv.conf 传递给 Pod。对于使用 systemd-resolved 的系统,/run/systemd/resolve/resolv.conf 通常是“真实”resolv.conf的位置,尽管它可能因您的发行版而异。
  • 禁用主机节点上的本地 DNS 缓存,并将 /etc/resolv.conf 恢复为原始状态。
  • 一种快速且粗略的修复方法是编辑您的 Corefile,将 forward . /etc/resolv.conf 替换为上游 DNS 的 IP 地址,例如 forward . 8.8.8.8。但这仅适用于 CoreDNS,kubelet 将继续向所有 default dnsPolicy Pod 转发无效的 resolv.conf,导致它们无法解析 DNS。