Pod在K8S中DNS解析流程和顺序
核心概念
- CoreDNS: 从Kubernetes 1.11开始,CoreDNS是默认的DNS服务。它作为一个或多个Pod运行在kube-system命名空间下,并配有一个Kubernetes Service(通常叫
kube-dns)。 - resolv.conf 文件: 每个Pod的
/etc/resolv.conf文件是DNS解析的蓝图。Kubelet会自动生成这个文件并挂载到Pod中。 - DNS策略: 你可以通过Pod Spec中的
dnsPolicy字段来配置DNS策略。
Pod 的 /etc/resolv.conf 解析
这是一个典型的Pod内的/etc/resolv.conf文件内容:
nameserver 10.96.0.10
search <namespace>.svc.cluster.local svc.cluster.local cluster.local
options ndots:5让我们逐行分析:
1. nameserver 10.96.0.10
- 这是CoreDNS Service的集群IP地址。所有Pod的DNS查询默认都会发送到这个地址。
- 这个IP来自kubelet的
--cluster-dns标志,在启动时确定。
2. search <namespace>.svc.cluster.local svc.cluster.local cluster.local
- 搜索域列表。当你使用不完整的域名(即不是FQDN)时,系统会按照这个列表的顺序,依次将搜索域附加到主机名后面,直到找到匹配的记录。
<namespace>是你的Pod所在的命名空间,例如default。- 搜索顺序:
<pod-namespace>.svc.cluster.localsvc.cluster.localcluster.local
3. options ndots:5
- 这是一个关键的优化/控制选项。
- 规则: 如果一个域名中的点(
.)数量大于或等于这个值(这里是5),系统会将其视为绝对域名(FQDN),并首先尝试直接解析,不会走搜索域列表。 - 反之,如果点数少于5,系统会先依次尝试搜索域,如果都失败了,最后再尝试名称本身。
DNS 解析流程与顺序(详解)
假设你的Pod在default命名空间,并且resolv.conf如上所示。
场景1:解析Kubernetes Service(短名称)
你想解析同一个命名空间下的Service:my-svc。
- 应用程序请求解析
my-svc。 - 系统检查名称
my-svc,点数(0) < 5。 - 进入搜索流程:
- 第一次尝试:
my-svc.default.svc.cluster.local-> 成功! 返回ClusterIP。 - 解析结束。
- 第一次尝试:
场景2:解析不同命名空间的Service
你想解析另一个命名空间prod下的Service:my-svc.prod。
- 应用程序请求解析
my-svc.prod。 - 系统检查名称
my-svc.prod,点数(1) < 5。 - 进入搜索流程:
- 第一次尝试:
my-svc.prod.default.svc.cluster.local-> 失败(因为该Service不在default命名空间)。 - 第二次尝试:
my-svc.prod.svc.cluster.local-> 成功! 返回ClusterIP。 - 解析结束。
- 第一次尝试:
场景3:解析外部域名(例如 www.google.com)
- 应用程序请求解析
www.google.com。 - 系统检查名称
www.google.com,点数(3) < 5。 - 进入搜索流程:
- 第一次尝试:
www.google.com.default.svc.cluster.local-> 失败。 - 第二次尝试:
www.google.com.svc.cluster.local-> 失败。 - 第三次尝试:
www.google.com.cluster.local-> 失败。
- 第一次尝试:
- 所有搜索域都失败了,系统最后尝试名称本身:
www.google.com-> 成功! CoreDNS会将其转发给上游DNS服务器(例如宿主机上的DNS或网络中配置的DNS)。
场景4:解析被认为是FQDN的域名(点数 >= 5)
假设你有一个StatefulSet,Pod的FQDN是web-0.nginx.default.svc.cluster.local。
- 应用程序请求解析
web-0.nginx.default.svc.cluster.local。 - 系统检查名称,点数(4) < 5?注意:这里是4个点,仍然小于5! 所以它仍然会走搜索流程。
- 这会先尝试
web-0.nginx.default.svc.cluster.local.default.svc.cluster.local,显然是错误的。 - 为了避免这种低效行为,最佳实践是在应用程序中配置或使用绝对域名(尾部带点)。
- 这会先尝试
绝对域名示例:
应用程序请求解析 web-0.nginx.default.svc.cluster.local.(注意最后有一个点)。
- 系统识别其为FQDN,直接查询,不经过任何搜索域。这是最有效的方式。
DNS 策略
Pod的dnsPolicy字段决定了如何生成resolv.conf。
ClusterFirst(默认): DNS查询首先被发送到Kubernetes集群的CoreDNS。如果域名不在集群域内(例如cluster.local),查询会被转发到上游DNS。ClusterFirstWithHostNet: 对于使用hostNetwork: true的Pod,如果你想让它使用集群DNS,就需要设置这个策略。Default: Pod直接从宿主机继承DNS配置(即使用宿主的/etc/resolv.conf)。这意味着它不会使用CoreDNS。None: 忽略所有默认的DNS设置。你必须使用dnsConfig字段来提供自定义的DNS配置。
总结与流程图
解析顺序可以简化为以下决策流程:
flowchart TD
A[应用程序发起DNS查询] --> B{查询名称的<br>点数 '.' >= 5?}
B -- 是<br>(视为FQDN) --> C[直接查询该名称]
C --> D{解析成功?}
D -- 是 --> E[返回结果]
D -- 否 --> F[解析失败]
B -- 否<br>(视为短名称) --> G
subgraph G [循环搜索域列表]
direction LR
H[依次将搜索域附加<br>到名称后并查询] --> I{解析成功?}
I -- 是 --> J[返回结果]
end
I -- 循环结束仍失败 --> K[直接查询原始名称]
K --> L{解析成功?}
L -- 是 --> E
L -- 否 --> F关键要点:
- 默认流向: Pod -> CoreDNS Service -> CoreDNS Pod -> (根据域判断)返回K8s记录或转发到上游DNS。
- 搜索域顺序: 命名空间 ->
svc->cluster.local。 ndots:5的影响: 这是为了在便利性和性能之间取得平衡。对于需要频繁访问的外部域名,为了性能最好在应用程序中配置FQDN(尾部带点)或调整ndots选项。- 调试技巧: 进入Pod并执行
cat /etc/resolv.conf和nslookup或dig命令是诊断DNS问题的第一步。