【Kubernetes笔记】为什么DNS解析会超时?
目录
- [1 问题背景](#1 问题背景)
- [2 产生后续的问题](#2 产生后续的问题)
- [3 DNS 负缓存工作原理:](#3 DNS 负缓存工作原理:)
- [4 如何解决和缓解 DNS 负缓存](#4 如何解决和缓解 DNS 负缓存)
- [4.1 减小负缓存 TTL](#4.1 减小负缓存 TTL)
- [4.2 重试机制](#4.2 重试机制)
- [4.3 减少 Pod 的频繁重启或调度](#4.3 减少 Pod 的频繁重启或调度)
- [4.4 使用 Headless Service](#4.4 使用 Headless Service)
- [4.5 手动刷新 DNS 缓存](#4.5 手动刷新 DNS 缓存)
- [5 总结](#5 总结)
❤️ 摘要:本文是作者在Kubernetes环境中遇到的一个实际问题,即使Pod和服务正常运行,DNS解析仍可能出现超时或失败。文章分析了两种常见场景及原因,并介绍了DNS负缓存机制及其带来的问题。为解决这些问题,可以根据场景采取不同的措施,有助于提高DNS解析的实时性和准确性,保障应用的稳定运行。
1. 问题背景
❓ 思考:当部署的Pod、Service已经正常运行了, 但是为什么DNS解析有时会出现超时的情况?
bash
/ # nslookup redis-0.redis.default.svc.cluster.local
Server: 10.245.0.254
Address: 10.245.0.254:53
Server: 10.245.0.254
Address: 10.245.0.254#53
** server can't find redis-0.redis.default.svc.cluster.local: NXDOMAIN
通常出现的场景有两个:
- Pod 出现变化导致解析失败:当 Pod 被删除、重启或者调度到其他节点时,Pod 的 IP 地址会发生变化。在这种情况下需要更新服务与 Pod 之间的 IP 映射。如果 DNS 缓存未及时更新,在查询时可能会返回失败的 DNS 记录。
- Service 创建后短时间内不可解析:在 Service 刚创建或更新时,DNS 系统需要一段时间来将新的 Service 名称解析到 ClusterIP。如果在这个时间间隙内有请求到该 Service 的域名,DNS 系统可能返回负缓存,并且影响后续的解析请求。
2. 产生后续的问题
每当解析出现失败后,DNS服务器会存在DNS 负缓存(DNS Negative Caching)。
DNS 负缓存(DNS Negative Caching):当 DNS 查询结果为失败时(即查询的域名不存在,或者请求失败),DNS 服务器会将该失败信息缓存一段时间,以避免频繁重复查询同一个不存在的域名。这种机制可以提高 DNS 查询的效率,减少不必要的网络流量。但也会产生一些问题:
- 影响域名恢复的实时性:如果一个域名一开始不可用,但在负缓存时间内域名恢复正常,客户端仍可能会因为负缓存的存在继续收到失败的响应,直到缓存过期。因此,负缓存可能在一定时间内影响恢复服务的及时性。。
- 错误的解析结果:负缓存可能会导致客户端继续收到错误的解析结果,甚至当 Pod 或 Service 已经处于健康状态时依然无法访问。
- 集群内不同 DNS 服务器的缓存差异:不同的 DNS 服务器对负缓存的处理策略和 TTL 设置不同的话,可能会导致查询结果在不同客户端中表现不一致。
3. DNS 负缓存工作原理:
当 DNS 查询无法成功解析域名时,DNS 服务器会返回一个错误响应。通常,这种错误包括:
- NXDOMAIN(Non-Existent Domain):表示域名不存在。
- SERVFAIL:表示 DNS 服务器遇到问题或无法处理请求。
- REFUSED:表示查询被拒绝。
缓存的时间由错误响应中的 TTL
(Time To Live) 值控制,通常会设置为较短的一段时间(例如几秒或几分钟)。
4. 如何解决和缓解 DNS 负缓存
4.1 减小负缓存 TTL
如果你使用的是 CoreDNS 作为 Kubernetes 集群的 DNS 服务,可以通过修改 CoreDNS 配置文件来减少 NXDOMAIN
负缓存的时间。
例如,修改 coredns
ConfigMap,调整 cache
插件的负缓存时间:
bash
kubectl edit configmap coredns -n kube-system
在 Corefile
中找到 cache
的配置部分:
text
data:
Corefile: |-
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus 0.0.0.0:9153
forward . /etc/resolv.conf
cache 30 {
denial 5 # 将负缓存时间设置为 5 秒
}
loop
reload
loadbalance
}
这里的 denial
表示缓存 NXDOMAIN
结果的时间,单位是秒。通过将其设置为较小的值(如 5 秒),可以减少负缓存对解析的影响。
4.2 重试机制
应用程序在对 Pod 或 Service 进行 DNS 查询时,可以实现重试机制。由于 DNS 负缓存的时间通常很短(几秒钟),简单的重试策略可以避免因临时 DNS 解析失败导致的应用程序中断。
4.3 减少 Pod 的频繁重启或调度
- 确保 Liveness 和 Readiness 探针设置合理,避免因过于敏感的探针配置导致 Pod 频繁重启。
- 检查 Pod 的资源限制,确保为每个 Pod 分配了足够的 CPU 和内存资源,避免因资源不足导致 Pod 宕机或调度失败。
4.4 使用 Headless Service
- 在使用 Headless Service 时,DNS 直接解析为 Pod 的 IP 地址,因此 Pod 之间可以直接通过 DNS 名称通信,不会受到 Service 的负缓存影响。
- 适用于有状态应用(如 StatefulSet),可以直接通过 Pod 的 DNS 名称(如
redis-0.redis.default.svc.cluster.local
)进行访问。
4.5 手动刷新 DNS 缓存
在一些情况下,如果负缓存对应用产生了严重影响,你可以尝试手动刷新 DNS 缓存,确保新的 DNS 解析结果生效。
-
删除并重启 CoreDNS Pod:
bashkubectl delete pod -n kube-system -l k8s-app=kube-dns
Kubernetes 会自动重启 CoreDNS Pod,从而清除 DNS 缓存。
5. 总结
Kubernetes 中的 DNS 负缓存问题,通常发生在 Pod 动态变化或 Service 创建的瞬间,导致 DNS 查询失败并被缓存。如果你在实际的业务场景也遇到这种情况,可以通过以上的方式尝试缓解或处理负缓存的影响。