CoreDNS CrashLoopBackOff问题排查之loop detected

背景

今天遇到一个奇怪的问题,集群中有个节点在重启后,调度到该节点上的CoreDNS就一直处于CrashLoopBackOff状态

查看CoreDNS pod的日志有报错

bash 复制代码
CoreDNS-1.9.3
linux/amd64, go1.18.2, 45b0a11
[FATAL] plugin/loop: Loop (127.0.0.1:38718 -> :53) detected for zone ".", see https://coredns.io/plugins/loop#troubleshooting. Query: "HINFO 1602357022762538710.2777015015780658687."

排查流程

1、根据错误日志提供的文档描述,这个报错是在loop插件发现了循环解析的问题,意味着CoreDNS forward给上游的请求还是回到了自身。

2、查看CoreDNS的配置,找到forward的上游是来自/etc/resolv.conf

arduino 复制代码
    .:53 {
                errors
        health {
            lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . /etc/resolv.conf {
          prefer_udp
          max_concurrent 1000
        }
        cache 30

        loop
        reload
        loadbalance
    }

3、现在我们需要知道容器里面的文件内容/etc/resolv.conf,最简单的方式就是exec到容器里面,但这个pod启动就crash了,没法exec进入容器,那应该如何debug。

常见思路

a、调整容器的启动命令改成sleep 3600,让容器处于运行状态,但coredns是核心组件,这么改服务就烂了,不可取。

b、复制pod的内容,改启动命令,并指定启动节点,这个思路在当前场景下是可行的。

这里我提供另一个思路,因为resolv.conf配置内容是容器创建时生成好再挂载到容器里面,所以在异常节点上是能直接查找容器resolv.conf对应在宿主机上的路径。

查找流程

shell 复制代码
# 先找到异常节点上coredns对应pod的id
$ sudo crictl pods |grep coredns
a70dbd1526493       37 minutes ago      Ready               coredns-676c5c79f-k74zq                              kube-system         0                   (default)
# 解析出resolv.conf在主机上的路径
$ sudo crictl inspectp a70dbd1526493 | jq '.info.runtimeSpec.mounts[] | select(.destination == "/etc/resolv.conf") | .source'
"/var/lib/containerd/io.containerd.grpc.v1.cri/sandboxes/a70dbd15264930d9969a684dbcd0429a4846d747410726859052e710a2930611/resolv.conf"
# 查看内容
$ sudo cat /var/lib/containerd/io.containerd.grpc.v1.cri/sandboxes/a70dbd15264930d9969a684dbcd0429a4846d747410726859052e710a2930611/resolv.conf
search xxxx.com
nameserver 127.0.0.53  ## 这里证实coredns forward的地址确实是本地的
options edns0 trust-ad

对比正常运行的coredns容器, 发现正常节点会forward到其他地址

bash 复制代码
cat /var/lib/containerd/io.containerd.grpc.v1.cri/sandboxes/aef05855960d32e3bc2559cb93fe626a67a18e45b90a12bc19a15a70e6e810a6/resolv.conf
search xxxx.com
nameserver 169.254.25.10
nameserver 8.8.8.8

排查到这里,原因基本清晰了,因为而这个127.0.0.53是本地回环IP,所以coredns forward给这个地址的请求又会回到自身,从而导致循环。

答疑解惑

为什么会出现resolv.conf不一致的内容

对比排查后发现,异常CoreDNS的resolv.conf内容来源和宿主机/etc/resolv.conf内容是相同,而正常的CoreDNS的resolv.conf内容来源和宿主机/run/systemd/resolve/resolv.conf内容是相同。

而控制这个配置来源在kubelet/etc/kubernetes/kubelet-config.yaml配置文件里面

makefile 复制代码
# 异常节点上
clusterDNS:
- 169.254.25.10
resolvConf: "/etc/resolv.conf"
# 正常节点
clusterDNS:
- 169.254.25.10
resolvConf: "/run/systemd/resolve/resolv.conf"

为什么异常节点上的业务pod的dns解析是正常的

根据上面的结论,如果pod没有使用host网络,那dns请求到127.0.0.53会导致pod服务解析域名,但排查过程中发现异常节点上的业务pod是能正常进行域名解析的。 通过查看业务pod容器里面的resolv.conf, 配置内容如下

lua 复制代码
search monitoring.svc.cluster.local svc.cluster.local cluster.local xxxx.com
nameserver 169.254.25.10
options ndots:5

熟悉pod配置的小伙伴应该反应过来了,这是因为pod的dnsPolicy不一样.

CoreDNS配置的是dnsPolicy: Default, 使用的dns配置内容来自kubeletresolvConf

而业务pod的配置是dnsPolicy: ClusterFirst, 对应的配置dns配置内容来自kubeletclusterDNS

修复方案

如果宿主机使用systemd-resolved.service来管理节点的dns解析配置,那kubelet里面配置的resolvConf需要还原为/run/systemd/resolve/resolv.conf,然后delete掉异常的coredns pod后就恢复正常了。

为什么节点kubelet配置会被改错

因为k8s集群的管理是通过kubespray维护,所有节点的配置按说应该都一样,为什么有些节点的配置不对呢?

相关推荐
java_cj3 天前
深入kube-apiserver认证机制:从Bearer Token到mTLS的完整认证链解析
linux·运维·服务器·云原生·容器·kubernetes
qq_452396234 天前
第十三篇:《K8s 安全基础:RBAC、ServiceAccount、Pod Security》
java·安全·kubernetes
睡不醒男孩0308234 天前
云原生运维实战:高并发架构下的云原生可观测性、韧性降级与自动化干预体系
数据库·kubernetes·高并发·prometheus·devops·sre·缓存调优
qq_452396234 天前
第十四篇:《K8s 网络模型与 CNI 插件(Calico、Flannel、Cilium)》
网络·kubernetes·php
Hadoop_Liang4 天前
Kubernetes 应用 HTTPS 安全访问配置实践
https·kubernetes
java_cj4 天前
从0到1启动kube-apiserver:深入源码解析API Server启动全流程
docker·容器·kubernetes
Hadoop_Liang4 天前
使用Kubernetes Gateway API实现域名访问应用
容器·kubernetes·gateway
java_cj4 天前
深入kubectl create源码:从YAML到Pod的完整链路拆解
运维·云原生·容器·kubernetes
万能的知了5 天前
K8s到底需不需要GPU节点?集群资源分配的底层逻辑
云原生·容器·kubernetes
卧室小白5 天前
K8S基础-控制器&deploy&pod回滚更新&service
docker·容器·kubernetes