本页面介绍 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"]
已知问题
搜索网域限制
/etc/resolv.conf
最多只能有 6 个 DNS 搜索网域。如果您定义超过 6 个搜索网域,则在运行 kubectl describe pod
命令时会显示以下警告:
Search Line limits were exceeded, some search paths have been omitted, the applied search line is: default.svc.cluster.local svc.cluster.local cluster.local c.<project ID>.internal google.internal
此警告记录在 Cloud Logging 的“容器日志”部分中。
要解决此问题,请从配置中移除多余的搜索路径。
考虑 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 密度过高。
- 在 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 只会为具有端点{track-name="k8sLink" track-type="concept"}的服务创建 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。
后续步骤
- 阅读 GKE 中的集群 DNS 概览。
- 阅读服务和 Pod 的 DNS,大致了解如何在 Kubernetes 集群中使用 DNS。