描述
loop 插件会向我们自己发送一个随机探测查询,然后会跟踪我们看到它的次数。如果我们看到它的次数多于两次,我们便假定 CoreDNS 已经看到一个转发循环,然后我们就会停止该进程。
该插件会尝试发送查询,最长可达 30 秒。这样做是为了给 CoreDNS 足够的时间启动。在成功发送查询后,loop 会禁用自身,以防查询死循环。
请注意,loop 仅会发送服务器区块中给出的第一个区域的“循环查询”。
发送的查询为 <随机数>.<随机数>.zone
,类型设置为 HINFO。
语法
loop
示例
在默认端口上启动一个服务器并加载 loop 和 forward 插件。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
、::1
或127.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。