【Kubernetes笔记】为什么DNS解析会超时?

【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 查询的效率,减少不必要的网络流量。但也会产生一些问题:

  1. 影响域名恢复的实时性:如果一个域名一开始不可用,但在负缓存时间内域名恢复正常,客户端仍可能会因为负缓存的存在继续收到失败的响应,直到缓存过期。因此,负缓存可能在一定时间内影响恢复服务的及时性。。
  2. 错误的解析结果:负缓存可能会导致客户端继续收到错误的解析结果,甚至当 Pod 或 Service 已经处于健康状态时依然无法访问。
  3. 集群内不同 DNS 服务器的缓存差异:不同的 DNS 服务器对负缓存的处理策略和 TTL 设置不同的话,可能会导致查询结果在不同客户端中表现不一致。

3. DNS 负缓存工作原理

当 DNS 查询无法成功解析域名时,DNS 服务器会返回一个错误响应。通常,这种错误包括:

  1. NXDOMAIN(Non-Existent Domain):表示域名不存在。
  2. SERVFAIL:表示 DNS 服务器遇到问题或无法处理请求。
  3. 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:

    bash 复制代码
    kubectl delete pod -n kube-system -l k8s-app=kube-dns

    Kubernetes 会自动重启 CoreDNS Pod,从而清除 DNS 缓存。

5. 总结

Kubernetes 中的 DNS 负缓存问题,通常发生在 Pod 动态变化或 Service 创建的瞬间,导致 DNS 查询失败并被缓存。如果你在实际的业务场景也遇到这种情况,可以通过以上的方式尝试缓解或处理负缓存的影响。

相关推荐
最新小梦2 小时前
Docker日志管理
运维·docker·容器
掘根2 小时前
【网络】高级IO——poll版本TCP服务器
网络·数据库·sql·网络协议·tcp/ip·mysql·网络安全
2401_872514973 小时前
深入探究HTTP网络协议栈:互联网通信的基石
网络·网络协议·http
ZHOU西口3 小时前
微服务实战系列之玩转Docker(十五)
nginx·docker·微服务·云原生·swarm·docker swarm·dockerui
有你的晚安._3 小时前
pod基本概念
kubernetes
lgbisha4 小时前
828华为云征文|华为云Flexus X实例docker部署最新Appsmith社区版,搭建自己的低代码平台
低代码·docker·华为云
记得开心一点嘛4 小时前
在Linux系统上使用Docker部署javaweb项目
linux·运维·docker
不良人天码星5 小时前
HTTP 协议的基本格式
网络·网络协议·http
Persistence is gold6 小时前
cassandra指定配置文件的docker启动方法
运维·docker·容器
广东数字化转型6 小时前
SSL/TSL 总结
网络·网络协议·ssl