本页面介绍 Google Kubernetes Engine (GKE) 如何使用 kube-dns(GKE 集群的默认 DNS 提供商)实现服务发现。
对于 Autopilot 集群,您无法修改默认的 kube-dns 配置。
架构
创建集群时,GKE 会自动在 kube-system
命名空间中部署 kube-dns Pod。Pod 通过相应的服务访问 kube-dns 部署,该服务会对 Kube-dns Pod 进行分组并为其提供单一 IP 地址 (ClusterIP)。默认情况下,集群中的所有 Pod 均使用此服务来解析 DNS 查询。下图显示了 Pod 与 kube-dns 服务之间的关系。
Kube-dns 会从容扩缩以满足集群的 DNS 需求。此扩缩过程由 kube-dns-autoscaler
控制,该 Pod 默认部署在所有 GKE 集群中。kube-dns-autoscaler
会根据集群中的节点数和核心数调整 kube-dns 部署中的副本数。
kube-dns 最多支持每个无头服务 1,000 个端点。
Pod DNS 的配置方式
每个节点上运行的 kubelet 代理会将 Pod 的 etc/resolv.conf
配置为使用 kube-dns 服务的 ClusterIP。以下示例配置显示 kube-dns 服务的 IP 地址为 10.0.0.10
。此 IP 地址在其他集群中是不同的。
nameserver 10.0.0.10
search default.svc.cluster.local svc.cluster.local cluster.local c.my-project-id.internal google.internal
options ndots:5
kube-dns 是集群网域 (cluster.local) 的权威域名服务器,可以递归方式解析外部名称。非完全限定的简称(如 myservice
)会首先填充本地搜索路径,
为存根网域添加自定义解析器
您可以修改 kube-dns 的 ConfigMap,以将存根网域作为集群中的 DNS 基础架构的一部分。
存根网域允许您配置每个网域的自定义解析器,以便 kube-dns 在解析这些网域时将 DNS 请求转发到特定的上游 DNS 服务器。
以下示例 kube-dns 的 ConfigMap 清单包括为网域 example.com 设置自定义解析器的 stubDomains
配置。
apiVersion: v1
kind: ConfigMap
metadata:
labels:
addonmanager.kubernetes.io/mode: EnsureExists
name: kube-dns
namespace: kube-system
data:
stubDomains: |
{
"example.com": [
"8.8.8.8",
"8.8.4.4",
"1.1.1.1",
"1.0.0.1"
]
}
运行以下命令以打开文本编辑器:
kubectl edit configmap kube-dns -n kube-system
将文件内容替换为清单,然后退出文本编辑器以将清单应用到集群。
上游域名服务器
如果您修改 kube-dns 的 ConfigMap 以包含 upstreamNameservers
,则 kube-dns 会将除 *.cluster.local
之外的所有 DNS 请求转发到这些服务器。这包括上游服务器无法解析的 metadata.internal
和 *.google.internal
。
如果您启用 GKE 的工作负载身份联合或任何依赖于 metadata.internal
解析的工作负载来保留 *.internal
域名解析,请将 stubDomain
添加到 ConfigMap。
data:
stubDomains: |
{
"internal": [
"169.254.169.254"
]
}
upstreamNameservers: |
["8.8.8.8"]
问题排查
如需了解如何排查 kube-dns 问题,请参阅以下页面:
- 如需有关 GKE 中 kube-dns 的建议,请参阅排查 GKE 中的 kube-dns 的问题。
- 如需了解诊断 Kubernetes DNS 问题的一般建议,请参阅调试 DNS 解析。
限制
如需了解 kube-dns 限制,请参阅以下部分。
搜索网域限制
/etc/resolv.conf
最多只能有 32 个 DNS 搜索网域。如果您定义超过 32 个搜索网域,则 Pod 创建会失败,并显示以下错误:
The Pod "dns-example" is invalid: spec.dnsConfig.searches: Invalid value: []string{"ns1.svc.cluster-domain.example", "my.dns.search.suffix1", "ns2.svc.cluster-domain.example", "my.dns.search.suffix2", "ns3.svc.cluster-domain.example", "my.dns.search.suffix3", "ns4.svc.cluster-domain.example", "my.dns.search.suffix4", "ns5.svc.cluster-domain.example", "my.dns.search.suffix5", "ns6.svc.cluster-domain.example", "my.dns.search.suffix6", "ns7.svc.cluster-domain.example", "my.dns.search.suffix7", "ns8.svc.cluster-domain.example", "my.dns.search.suffix8", "ns9.svc.cluster-domain.example", "my.dns.search.suffix9", "ns10.svc.cluster-domain.example", "my.dns.search.suffix10", "ns11.svc.cluster-domain.example", "my.dns.search.suffix11", "ns12.svc.cluster-domain.example", "my.dns.search.suffix12", "ns13.svc.cluster-domain.example", "my.dns.search.suffix13", "ns14.svc.cluster-domain.example", "my.dns.search.suffix14", "ns15.svc.cluster-domain.example", "my.dns.search.suffix15", "ns16.svc.cluster-domain.example", "my.dns.search.suffix16", "my.dns.search.suffix17"}: must not have more than 32 search paths.
此错误消息由 kube-apiserver
返回,以响应 Pod 创建尝试。
要解决此问题,请从配置中移除多余的搜索路径。
考虑 upstreamNameservers
限制
Kubernetes 施加了最多 upstreamNameservers
个值的限制。如果您定义的 upstreamNameservers
超过三个,则会在 Cloud Logging 的 kube-dns
部署日志中看到以下错误:
Invalid configuration: upstreamNameserver cannot have more than three entries (value was &TypeMeta{Kind:,APIVersion:,}), ignoring update
在这种情况下,kube-dns 的行为就像没有配置 upstreamNameservers
一样。如需解决此问题,请从配置中移除多余的 upstreamNameservers
。
kube-dns 的性能限制
如果您在使用默认的 kube-dns 提供商时遇到 DNS 查找延迟过高或 DNS 解析失败的问题,则可能是因为:
- 在您的工作负载中频繁执行 DNS 查找
- 每个节点部署的 Pod 密度过高。
- 超出每个 kube-dns Pod 的每秒查询次数 (QPS) 限制(20 次)。
- 在 Spot 或抢占式虚拟机上运行 kube-dns,这可能会导致意外的节点删除和后续 DNS 解析问题。
如需缩短 DNS 查找时间,您可以选择以下选项之一:
- 避免在 Spot 或抢占式虚拟机上运行 kube-dns 等关键系统组件。将 Spot 或抢占式虚拟机用于 DNS 可能会导致故障并中断集群。
- 最佳实践是至少创建一个由标准(非 Spot 或抢占式)虚拟机组成的节点池,以托管 kube-dns 等关键系统组件。如需确保关键工作负载仅在可靠的节点池上进行调度,以阻止它们在 Spot 或抢占式虚拟机上运行,您可以对 Spot 虚拟机使用污点和容忍。
- 启用 NodeLocal DNSCache。
- 扩容 kube-dns。
- 请确保您的应用使用基于 dns.resolve* 的函数,而非基于 dns.lookup 的函数,因为 dns.lookup 是同步的。dns.resolve* 函数始终会对网络执行异步 DNS 查询。
Service DNS 记录
kube-dns 只会为具有端点的 Service 创建 DNS 记录。
DNS 上游服务器的较大 TTL
如果 kube-dns 从具有较大或“无限”TTL 的上游 DNS 解析器接收 DNS 响应,则会在缓存中保留 DNS 条目的此 TTL 值。此条目永不过期,可能导致该条目与为 TTL 名称解析的实际 IP 地址之间产生差异。
GKE 在以下控制平面版本中,针对 TTL 高于 30 秒的 DNS 响应,将 TTL 值上限设置为 30 秒,从而解决此问题:
- 1.21.14-gke.9100
- 1.22.15-gke.2100
- 1.23.13-gke.500
- 1.24.7-gke.500
- 1.25.2-gke.500 或更高版本
此行为类似于 NodeLocal DNSCache。
记录 kube-dns 或 dnsmasq 指标
您可以获取有关 GKE 集群中 DNS 查询的指标。这是一种快速获取 kube-dns 或 dnsmasq 指标的方法,无需修改部署。
列出 kube-dns Deployment 下的 Pod。
$ kubectl get pods -n kube-system --selector=k8s-app=kube-dns
输出将如下所示:
NAME READY STATUS RESTARTS AGE kube-dns-548976df6c-98fkd 4/4 Running 0 48m kube-dns-548976df6c-x4xsh 4/4 Running 0 47m
选择一个 Pod,并将其名称设置为一个变量。
POD="kube-dns-548976df6c-98fkd"
为所选的 kube-dns Pod 设置端口转发。
$ kubectl port-forward pod/${POD} -n kube-system 10054:10054 10055:10055
输出将如下所示:
Forwarding from 127.0.0.1:10054 -> 10054 Forwarding from 127.0.0.1:10055 -> 10055
通过在端点上运行以下 curl 命令来获取指标。
$ curl http://127.0.0.1:10054/metrics; curl http://127.0.0.1:10055/metrics
端口 10054 包含 dnsmasq 指标,端口 10055 包含 kube-dns 指标。
输出将如下所示:
kubedns_dnsmasq_errors 0 kubedns_dnsmasq_evictions 0 kubedns_dnsmasq_hits 3.67351e+06 kubedns_dnsmasq_insertions 254114 kubedns_dnsmasq_max_size 1000 kubedns_dnsmasq_misses 3.278166e+06
后续步骤
- 阅读 GKE 中的集群 DNS 概览。
- 阅读服务和 Pod 的 DNS,大致了解如何在 Kubernetes 集群中使用 DNS。
- 了解如何设置 NodeLocal DNSCache。
- 了解如何设置自定义 kube-dns Deployment。