K8s集群DNS解析失败怎么排查:从Pod到CoreDNS完整步骤
K8s集群DNS解析失败怎么排查:从Pod到CoreDNS完整步骤
K8s集群里Pod访问Service或外部域名失败,先别急着重启CoreDNS。关键第一步是判断故障范围:是所有Pod都解析不了,还是只有某个Pod或某个命名空间有问题。
范围不同,排查路径完全不一样。
下面按“先定位范围、再逐层检查”的顺序展开,覆盖从Pod内DNS配置到CoreDNS本身、再到网络策略的完整链路。
先确认故障范围
在一个正常Pod里执行:
kubectl run dnstest --image=busybox:1.28 --restart=Never -- sleep 3600
kubectl exec -it dnstest -- nslookup kubernetes.default
如果这条能解析,说明集群DNS基础链路是通的,问题可能出在特定Pod的dnsPolicy、dnsConfig或所在节点的网络。
如果这条也失败,继续往下查。
注意:busybox镜像版本会影响nslookup行为,1.28是K8s官方文档常用的调试镜像,建议固定使用。
检查Pod内的DNS配置
进入故障Pod,查看/etc/resolv.conf:
kubectl exec -it -n -- cat /etc/resolv.conf
正常输出应包含:
nameserver 10.96.0.10
search .svc.cluster.local svc.cluster.local cluster.local
options ndots:5
需要核对的点:
nameserver的IP是否等于kubectl get svc -n kube-system kube-dns的ClusterIP。不一致说明kubelet配置或dnsPolicy有问题。- Pod的
dnsPolicy如果是None,必须手动配dnsConfig,否则不会有默认DNS。 ndots:5会影响短域名的解析顺序,如果访问外部域名慢,可以考虑调低,但不要随意改。
检查CoreDNS Pod和Service
确认CoreDNS处于Running状态:
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl get svc -n kube-system kube-dns
再看Endpoints是否正常:
kubectl get endpoints -n kube-system kube-dns
如果Endpoints为空,
说明Service没有关联到任何CoreDNS Pod,
常见原因是CoreDNS Pod的label与Service selector不匹配,
或者Pod一直没就绪。
查看CoreDNS日志:
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=100
日志里可以重点关注:
SERVFAIL或REFUSED:可能是上游DNS不可达或Corefile配置错误。plugin/forward相关报错:指向上游DNS的转发有问题。no such host:说明查询本身能到达CoreDNS,但记录不存在,问题可能在Service名称或命名空间。
核对CoreDNS的Corefile配置
查看当前配置:
kubectl get configmap coredns -n kube-system -o yaml
典型的Corefile片段:
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
容易出问题的地方:
forward后面的上游DNS不可达。可以进入CoreDNS Pod测试:kubectl exec -it。-n kube-system -- nslookup baidu.com 114.114.114.114 loop插件检测到转发循环时会触发CrashLoopBackOff,日志里会明确提示。- 修改ConfigMap后需要重启CoreDNS Pod或等待
reload生效,建议用kubectl rollout restart deployment coredns -n kube-system。
排查NetworkPolicy和节点网络
如果CoreDNS本身正常,但某些Pod解析失败,检查是否存在NetworkPolicy限制了DNS出站:
kubectl get networkpolicy -A
默认拒绝所有出站流量的策略会拦掉到kube-dns的UDP/TCP 53端口。
需要放行:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
spec:
podSelector: {}
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
另外,节点上的kube-proxy或iptables规则异常也会导致DNS不通。
可以在节点上检查:iptables -t nat -L KUBE-SERVICES | grep kube-dns,确认存在对应转发规则。
验证修复结果
改完配置后,重新执行最初的测试:
kubectl exec -it dnstest -- nslookup kubernetes.default
kubectl exec -it dnstest -- nslookup ..svc.cluster.local
两条都返回正确IP,才算修复完成。
如果只有第一条成功,说明集群内部解析正常,问题在外部域名转发,重点回到Corefile的forward配置和上游DNS。
常见疑问
CoreDNS Pod反复重启怎么办?
先看日志里的loop或CrashLoopBackOff提示,多数是Corefile配置写错或上游DNS形成了循环转发。临时可以把副本数调到1并简化Corefile逐步验证。
只有某个节点的Pod解析失败?
大概率是该节点上的kube-proxy异常或iptables规则丢失。重启该节点的kube-proxy,或检查/var/log/messages中kubelet和kube-proxy的报错。
改了Corefile不生效?
ConfigMap更新后不会自动重载,执行kubectl rollout restart deployment coredns -n kube-system,等Pod全部Running后再测。
外部域名能解析但很慢?
检查ndots设置和上游DNS响应速度。如果Pod内短域名很多,ndots:5会导致多次无效查询,适当调低需要评估影响。