引言
对于这种案例,你们的处理思路是怎么样的呢,是否真正的处理过,如果遇到,你们应该怎么处理。
我想大多数人都没有遇到过。
开始
一、现象:跨集群通信的神秘失效
某金融系统在混合云架构中部署了多套 Kubernetes 集群,用于实现跨地域容灾。某次业务切换演练时,发现跨集群服务发现完全失效,具体表现为:
- 服务发现中断:
# 在故障 Pod 中测试解析 kubectl exec -it frontend-pod -- nslookup backend-service.cluster-b.svc.cluster.local ;; Got SERVFAIL reply from 10.96.0.10, trying next server ;; connection timed out; no servers could be reached
- 集群 A 的 Pod 无法通过
service-name.cluster-b.svc.cluster.local
访问集群 B 的服务 nslookup
返回**SERVFAIL**
错误,但 CoreDNS 日志无任何异常记录
- 集群 A 的 Pod 无法通过
- 核心指标异常:
- Prometheus 监控显示
coredns_dns_request_count_total{rcode="SERVFAIL"}
激增 - 服务网格流量统计中,跨集群请求失败率高达 92%
- Prometheus 监控显示
二、根因分析:DNS 配置的「死亡组合」
1. ndots:5 的「量子纠缠」
问题本质:
Kubernetes 默认在 Pod 的 /etc/resolv.conf
中设置 options ndots:5
。该配置要求:
- 当查询的域名包含 少于 5 个点 时,DNS 客户端会尝试追加所有
searchDomains
- 对于跨集群服务域名
backend-service.cluster-b.svc.cluster.local
(4 个点),触发以下查询链:# 实际查询顺序(伪代码) for domain in searchDomains: query = "backend-service.cluster-b.svc.cluster.local.{domain}" send_to_dns_server(query)
致命冲突:
私有 DNS 服务器(如 AD DNS)无法处理这种带冗余后缀的查询,直接返回 SERVFAIL
。
2. searchDomains 的「黑洞陷阱」
问题本质:
/etc/resolv.conf
中残留无效的 searchDomains
,例如:
search default.svc.cluster.local svc.cluster.local cluster.local corp.legacy.com # 已废弃的域
灾难链:
- 客户端先尝试查询
backend-service.cluster-b.svc.cluster.local.default.svc.cluster.local
- 私有 DNS 无法解析,耗时 5 秒(默认超时)
- 继续尝试下一个后缀,最终耗尽查询时间
三、解决方案:四步破解 DNS 黑洞
1. 动态调整 ndots 配置
通过 ConfigMap 覆盖默认 DNS 策略:
# coredns-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns-custom
namespace: kube-system
data:
Corefile: |
cluster.local:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
# 关键:调整 ndots 为 3
template IN A {
match "^([^\.]+)\.([^\.]+)\.svc\.cluster\.local$"
answer "{{ .Name }}.{{ .Match.2 }}.svc.cluster.local 5 IN A $SERVICE_IP"
fallthrough
}
forward . /etc/resolv.conf {
policy sequential
prefer_udp
}
cache 30
reload 15s
# 强制 ndots=3
loop
reload
loadbalance
}
2. 清理无效 searchDomains
在 Pod 模板中注入 DNS 配置:
# deployment-patch.yaml
spec:
template:
spec:
dnsConfig:
searches: # 仅保留有效域
- cluster-b.svc.cluster.local
- svc.cluster.local
- cluster.local
options:
- name: ndots
value: "3"
3. DNS 查询链路验证
使用 netshoot
镜像进行全链路测试:
# 启动诊断容器
kubectl run dns-debug --image=nicolaka/netshoot --rm -it --restart=Never -- /bin/sh
# 分步测试解析
dig +trace backend-service.cluster-b.svc.cluster.local
nslookup -debug backend-service.cluster-b.svc.cluster.local
# 检查实际查询顺序
cat /etc/resolv.conf
4. 防御体系构建
层级 | 工具/策略 | 防护能力 |
配置校验 | OpenPolicyAgent (OPA) | 拦截无效 searchDomains |
监控预警 | Prometheus + CoreDNS 指标 | 实时检测 SERVFAIL 率 |
混沌测试 | Chaos Mesh 注入 DNS 延迟 | 提前发现链路脆弱点 |
四、核心命令速查表
# 1. 查看 Pod 的 DNS 配置
kubectl exec <pod-name> -- cat /etc/resolv.conf
# 2. 强制刷新 CoreDNS 缓存
kubectl delete pod -n kube-system -l k8s-app=kube-dns
# 3. 抓取跨集群 DNS 包
kubectl debug <pod-name> -it --image=nicolaka/netshoot -- tcpdump -i any -nn port 53
# 4. 生成 DNS 查询拓扑图
kubectl get svc -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.clusterIP}{"\n"}{end}' > dns-map.txt
五、经验总结
- DNS 配置的「蝴蝶效应」:一个
ndots
参数足以引发跨集群雪崩,理解 Kubernetes DNS 解析链(递归查询 → searchDomains 追加 → 超时控制)是关键。 - 防御性编码原则:在 CI/CD 流水线中集成 DNS 策略校验(如
kube-score
检查dnsConfig
)。 - 观测驱动运维:通过指标
coredns_dns_response_rcode_count
定位异常模式,比日志更早发现问题。
“在分布式系统中,DNS 从来不是简单的域名解析,而是连接所有组件的神经系统。”
—— 某跨国企业 SRE 团队故障复盘报告
结语
以上就是我们今天的内容,希望可以帮助到大家,在面试中游刃有余,主动出击。