环境:

  • OS:Ubuntu 18.04.5 LTS
  • Kubernetes:v1.20.7
  • CoreDNS:1.6.7

背景:

在以二进制方式部署的Kubernetes集群中部署CoreDNS组件的时候,对应的pod一直处于CrashLoopBackOff状态,其错误日志如下:

# kubectl logs -f coredns-6cc56c94bd-nlnzm -n kube-system
.:53
[INFO] plugin/reload: Running configuration MD5 = a4809ab99f6713c362194263016e6fac
CoreDNS-1.6.7
linux/amd64, go1.13.6, da7f65b
[FATAL] plugin/loop: Loop (127.0.0.1:48691 -> :53) detected for zone ".", see https://coredns.io/plugins/loop#troubleshooting. Query: "HINFO 1853319330074714968.7855677413137606265."

问题分析:

从日志中来看,已经提示我们去查看https://coredns.io/plugins/loop#troubleshooting,在该文档中,可以找到这个问题的原因,如下图所示:

翻译成中文,大致意思如下:

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

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

问题解决:

解决该问题的方法,亲测有效的有两种,分别为:

(推荐)方法一:将/run/systemd/resolve/resolv.conf添加到kubelet的yml文件中,格式如下:
resolvConf: <path-to-your-real-resolv-conf-file>

操作步骤:

1、添加内容到kubelet的yml文件中

vim .../kubelet-config.yml

resolvConf: "/run/systemd/resolve/resolv.conf"

2、重启kubelet服务

systemctl restart kubelet

3、重新部署CoreDNS组件

先删除

kubectl delete -f coredns.yaml

再创建

kubectl apply -f coredns.yaml
方法二:编辑名为coredns的configmap,删除Corefile中的loop

执行以下命令:

kubectl -n kube-system edit configmap coredns

然后删除显示loop的行,并且保存配置。当部署coredns组件的对应pod在下次重启时,将会应用名为coredns的configmap的内容,它将会运行为running状态,并且准备就绪。

参考资料:

https://coredns.io/plugins/loop/#troubleshooting

https://github.com/coredns/coredns/issues/2087