本文档可帮助您确定 Cloud DNS for GKE 是否是适合您集群的 DNS 解决方案。您可以使用 Cloud DNS 来处理 Pod 和 Service DNS 解析,作为 kube-dns 等集群托管 DNS 提供商的替代方案。
对于 Autopilot 集群,Cloud DNS 已是默认 DNS 提供商。对于 Standard 集群,您可以从 kube-dns 切换到 Cloud DNS。
本文档适用于 GKE 用户,包括开发者、管理员和架构师。如需详细了解 Google Cloud中的常见角色和示例任务,请参阅常见的 GKE Enterprise 用户角色和任务。
本文档假定您熟悉以下概念:
Cloud DNS for GKE 的工作原理
将 Cloud DNS 用作 GKE 的 DNS 提供商时,Cloud DNS 可提供 Pod 和 Service DNS 解析,而无需集群托管的 DNS 提供商。系统会自动在 Cloud DNS 中为集群 IP 地址、无头和外部名称 Service 预配 Pod 和 Service 的 DNS 记录。
Cloud DNS 支持完整的 Kubernetes DNS 规范,并为 GKE 集群中的 Service 提供 A、AAAA、SRV 和 PTR 记录的解析。PTR 记录通过响应政策规则实现。与集群托管的 DNS 相比,使用 Cloud DNS 作为 GKE 的 DNS 提供商具有以下优势:
- 减少开销:无需管理集群托管的 DNS 服务器。 Cloud DNS 是一项全托管式服务,因此无需手动扩缩、监控或管理 DNS 实例。
- 高可伸缩性和性能:为每个 GKE 节点在本地解析查询,以提供低延迟且高度可伸缩的 DNS 解析。为了获得最佳性能(尤其是在大规模集群中),请考虑启用 NodeLocal DNSCache,它可在节点上提供额外的缓存层。
- 与 Google Cloud Observability 集成:用于 DNS 监控和日志记录。如需了解详情,请参阅为专用代管区域启用和停用日志记录功能。
架构
当 Cloud DNS 是 GKE 的 DNS 提供商时,控制器作为 GKE 管理的 Pod 运行。此 Pod 在集群的控制平面节点上运行,并将集群 DNS 记录同步到托管的专用 DNS 区域。
下图展示了 Cloud DNS 控制平面和数据平面如何解析集群名称:
在该图中,服务后端选择正在运行的后端 Pod。clouddns-controller 为服务后端创建 DNS 记录。
Pod 前端向 169.254.169.254 处的 Compute Engine 本地元数据服务器发送 DNS 请求,以解析名为 backend 的 Service 的 IP 地址。元数据服务器在节点上本地运行,并向 Cloud DNS 发送未命中的缓存。
Cloud DNS 会根据 Kubernetes 服务的类型将服务名称解析为不同的 IP 地址。对于 ClusterIP 服务,Cloud DNS 会将服务名称解析为其虚拟 IP 地址;对于无头服务,它会将服务名称解析为端点 IP 地址列表。
Pod 前端解析 IP 地址后,Pod 可以将流量发送到 Service 后端以及 Service 后面的任何 Pod。
DNS 范围
Cloud DNS 具有以下 DNS 范围。集群不能同时在多种模式下运行。
- GKE 集群范围:DNS 记录只能在集群中解析,这与
kube-dns的行为相同。只有在 GKE 集群中运行的节点才能解析服务名称。默认情况下,集群的 DNS 名称以*.cluster.local结尾。这些 DNS 名称仅在集群中可见,并且不会与同一项目中的其他 GKE 集群的*.cluster.localDNS 名称重叠或冲突。此模式为默认模式。- Cloud DNS 附加 VPC 范围:Cloud DNS 附加 VPC 范围是一项可选功能,可扩展 GKE 集群范围,从而可从 VPC 中的其他资源(例如 Compute Engine 虚拟机,或是使用 Cloud VPN 或 Cloud Interconnect 连接的本地客户端)解析无头 Service。此模式是与集群范围一起启用的附加模式。您可以在集群中启用或停用此模式,而不会影响 DNS 正常运行时间或集群范围功能。
- VPC 范围:DNS 记录在整个 VPC 中可解析。Compute Engine 虚拟机和本地客户端可以使用 Cloud Interconnect 或 Cloud VPN 进行连接,并可以直接解析 GKE 服务名称。您必须为每个集群设置唯一自定义网域,这意味着所有 Service 和 Pod DNS 记录在 VPC 中都是唯一的。此模式可以减少 GKE 与非 GKE 资源之间的通信冲突。
下表列出了 DNS 范围之间的区别:
| 特性 | GKE 集群范围 | Cloud DNS 额外的 VPC 范围 | VPC 范围 |
|---|---|---|---|
| DNS 公开范围 | 仅在 GKE 集群中 | 仅限集群,无头服务可在整个 VPC 网络中解析 | 整个 VPC 网络 |
| 无头 Service 解析 | 可在集群中解析 | 可使用“cluster.local”网域在集群内解析,并使用集群后缀在整个 VPC 中解析 | 可使用集群后缀在集群内和整个 VPC 中解析 |
| 唯一网域要求 | 否;使用默认的“*.cluster.local”网域 | 有,您必须设置唯一自定义网域 | 有,您必须设置唯一自定义网域 |
| 设置配置 | 默认,无额外步骤 | 创建集群时可选 可以随时启用或停用 |
必须在创建集群期间配置 |
Cloud DNS 资源
使用 Cloud DNS 作为 GKE 集群的 DNS 提供商时,Cloud DNS 控制器会在 Cloud DNS 中为您的项目创建资源。GKE 创建的资源取决于 Cloud DNS 范围。
| 范围 | 正向查找区域 | 反向查找区域 |
|---|---|---|
| 集群范围 | 每个 Compute Engine 区域的每个集群有 1 个专用区域(在地区中) | 每个 Compute Engine 区域的每个集群有 1 个响应政策区域(在地区中) |
| Cloud DNS 额外的 VPC 范围 | 每个集群(全球区域)的每个 Compute Engine 区域(在地区中)的每个集群有 1 个专用区域
每个集群(全球区域)有 1 个 VPC 范围专用区域 |
每个集群(全球区域)的每个 Compute Engine 区域(在地区中)的每个集群有 1 个响应政策区域
每个集群(全球区域)有 1 个 VPC 范围响应政策区域 |
| VPC 范围 | 每个集群有 1 个专用区域(全球区域) | 每个集群有 1 个响应政策区域(全球区域) |
这些 Cloud DNS 资源使用的命名惯例如下:
| 范围 | 正向查找区域 | 反向查找区域 |
|---|---|---|
| 集群范围 | gke-CLUSTER_NAME-CLUSTER_HASH-dns |
gke-CLUSTER_NAME-CLUSTER_HASH-rp |
| Cloud DNS 额外的 VPC 范围 | gke-CLUSTER_NAME-CLUSTER_HASH-dns(适用于集群范围区域)
gke-CLUSTER_NAME-CLUSTER_HASH-dns-vpc(适用于 VPC 范围区域)
|
gke-CLUSTER_NAME-CLUSTER_HASH-rp(适用于集群范围区域)
gke-NETWORK_NAME_HASH-rp(适用于 VPC 范围区域)
|
| VPC 范围 | gke-CLUSTER_NAME-CLUSTER_HASH-dns |
gke-NETWORK_NAME_HASH-rp |
除了上表提到的区域之外,Cloud DNS 控制器还会根据您的配置在项目中创建以下区域:
| 自定义 DNS 配置 | 区域类型 | 区域命名惯例 |
|---|---|---|
| 存根网域 | 转发(全球区域) | gke-CLUSTER_NAME-CLUSTER_HASH-DOMAIN_NAME_HASH |
| 自定义上游域名服务器 | 转发(全球区域) | gke-CLUSTER_NAME-CLUSTER_HASH-upstream |
如需详细了解如何创建自定义存根域或自定义上游域名服务器,请参阅为存根域添加自定义解析器。
代管区域和转发区域
对于使用集群范围来处理内部 DNS 流量的集群,Cloud DNS 控制器会在集群所属区域的每个 Compute Engine 可用区中创建一个托管式 DNS 区域。
例如,如果您在 us-central1-c 区域中部署集群,则 Cloud DNS 控制器会在 us-central1-a、us-central1-b、us-central1-c 和 us-central1-f 中创建托管式区域。
对于每个 DNS stubDomain,Cloud DNS 控制器都会创建一个转发区域。
Cloud DNS 使用具有 . DNS 名称的一个托管区域来处理每个上游 DNS。
配额
Cloud DNS 使用配额来限制 GKE 可为 DNS 条目创建的资源数量。Cloud DNS 的配额和限制可能与项目的 kube-dns 限制不同。
使用 Cloud DNS for GKE 时,系统会为项目中的每个托管区域应用以下默认配额:
| Kubernetes DNS 资源 | 相应的 Cloud DNS 资源 | Quota |
|---|---|---|
| DNS 记录数 | 每个代管区域的字节数上限 | 2,000,000(托管区域最大 50 MB) |
| 每个无头 Service 的 Pod 数 (IPv4 或 IPv6) | 每个资源记录集的记录数 | GKE 1.24 到 1.25:1,000(IPv4 或 IPv6) GKE 1.26 及更高版本:IPv4 为 3,500;IPv6 为 2,000 |
| 项目中的 GKE 集群数量 | 每个项目的响应政策数 | 100 |
| 每个集群的 PTR 记录数 | 每项响应政策的规则数 | 100,000 |
资源限制
您为每个集群创建的 Kubernetes 资源会计入 Cloud DNS 资源限制,如下表所示:
| 限制 | 计入限制 |
|---|---|
| 每个托管式区域的资源记录集数 | 每个集群的服务数加上具有有效主机名的无头服务端点数。 |
| 每个资源记录集的记录数 | 每个无头服务的端点数。不会影响其他服务类型。 |
| 每项响应政策的规则数 | 对于集群范围,每个集群的服务数加上具有有效主机名的无头服务端点数。 对于 VPC 范围,VPC 中所有集群的服务数加上具有主机名的无头端点数。 |
如需详细了解如何为 Kubernetes 创建 DNS 记录,请参阅 Kubernetes 基于 DNS 的服务发现。
每个服务项目有多个集群
从 1.22.3-gke.700 和 1.21.6-gke.1500 版开始,您可以在多个引用同一宿主项目中的 VPC 的服务项目中创建集群。
支持自定义存根域和上游域名服务器
Cloud DNS for GKE 支持使用 kube-dns ConfigMap 配置的自定义存根域和上游域名服务器。此支持仅适用于 GKE Standard 集群。
Cloud DNS 会将 stubDomains 和 upstreamNameservers 值转换为 Cloud DNS 转发区域。
规范扩展
为了改进服务发现并提高与各种客户端和系统的兼容性,您可以在常规 Kubernetes DNS 规范的基础上使用附加功能。
已命名端口
本部分介绍了命名端口如何影响 Cloud DNS 为 Kubernetes 集群创建的 DNS 记录。Kubernetes 定义了一组最低限度的必需 DNS 记录,但 Cloud DNS 可能会创建额外的记录,以供自身运行并支持各种 Kubernetes 功能。下表列出了预期的最少记录集数量,其中“E”表示端点数量,“P”表示端口数量。
Cloud DNS 可能会创建其他记录。
| IP 栈类型 | 服务类型 | 记录集 |
|---|---|---|
| 单栈 | ClusterIP | $$2+P$$ |
| 无头 | $$2+P+2E$$ |
|
| 双栈 | ClusterIP | $$3+P$$ |
| 无头 | $$3+P+3E$$ |
|
| 如需详细了解单栈和双栈服务,请参阅单栈和双栈服务。 | ||
由 Cloud DNS 创建的其他 DNS 记录
Cloud DNS 可能会创建超出最少记录集数量的其他 DNS 记录。这些记录有多种用途,包括:
- SRV 记录:对于服务发现,Cloud DNS 通常会创建 SRV 记录。这些记录提供有关服务端口和协议的信息。
- AAAA 记录(适用于双栈):在同时使用 IPv4 和 IPv6 的双栈配置中,Cloud DNS 会为每个端点创建 A 记录(适用于 IPv4)和 AAAA 记录(适用于 IPv6)。
- 内部记录:Cloud DNS 可能会创建内部记录以进行自我管理和优化。这些记录通常与用户没有直接关系。
- LoadBalancer 服务:对于类型为
LoadBalancer的服务,Cloud DNS 会创建与外部负载平衡器 IP 地址关联的记录。 - 无头服务:无头服务具有独特的 DNS 配置。每个 Pod 都有自己的 DNS 记录,这让客户端可以直接连接到 Pod。正是由于这种方法,在无头服务记录计算中,端口号才不会相乘。
示例:假设有一个名为 my-http-server 且位于 backend 命名空间中的服务。此服务为具有三个 pod 的部署公开了两个端口:80 和 8080。因此,E = 3,P = 2。
| IP 栈类型 | 服务类型 | 记录集 |
|---|---|---|
| 单栈 | ClusterIP | $$2+2$$ |
| 无头 | $$2+2+2*3$$ |
|
| 双栈 | ClusterIP | $$3+2$$ |
| 无头 | $$3+2+3*3$$ |
除了这些最低限度的记录之外,Cloud DNS 可能会创建 SRV 记录,如果是双栈网络,还会创建 AAAA 记录。如果 my-http-server 是 LoadBalancer 类型的服务,系统将为负载均衡器 IP 创建额外的记录。注意:Cloud DNS 会根据需要添加补充 DNS 记录。创建的具体记录取决于服务类型和配置等因素。
已知问题
本部分介绍了将 Cloud DNS 与 GKE 搭配使用时可能会遇到的常见问题,以及可能的解决方法。
由于 dns_config 更改,Terraform 尝试重新创建 Autopilot 集群
如果使用 terraform-provider-google 或 terraform-provider-google-beta,您可能会遇到 Terraform 尝试重新创建 Autopilot 集群的问题。发生此错误是因为运行 1.25.9-gke.400、1.26.4-gke.500 或 1.27.1-gke.400 及更高版本的新建 Autopilot 集群使用 Cloud DNS(而不是 kube-dns)作为 DNS 提供商。
此问题已在 Google Cloud的 Terraform 提供程序 4.80.0 版中得到解决。
如果您无法更新 terraform-provider-google 或 terraform-provider-google-beta 的版本,则可以将 lifecycle.ignore_changes 设置添加到资源中,以帮助确保 google_container_cluster 忽略对 dns_config 的更改:
lifecycle {
ignore_changes = [
dns_config,
]
}
从 kube-dns 迁移到 Cloud DNS 后,DNS 解析失败(NodeLocal DNSCache 已启用)
本部分介绍了 GKE 集群(位于 Cloud DNS 中且已在集群范围内启用 NodeLocal DNSCache)的一个已知问题。
在集群上启用 NodeLocal DNSCache 并从 kube-dns 迁移到 Cloud DNS 后,集群可能会遇到间歇性解析错误。
如果您在集群上启用 NodeLocal DNSCache 的情况下使用 kube-dns,NodeLocal DNSCache 会配置为同时监听这两个地址:NodeLocal DNSCache 地址和 kube-dns 地址。
如需检查 NodeLocal DNSCache 的状态,请运行以下命令:
kubectl get cm -n kube-system node-local-dns -o json | jq .data.Corefile -r | grep bind
输出类似于以下内容:
bind 169.254.20.10 x.x.x.10
bind 169.254.20.10 x.x.x.10
如果集群上启用了 GKE Dataplane V2,并且集群使用 kube-dns,NodeLocal DNSCache 会在隔离的网络中运行,并配置为监听所有 Pod IP 地址 (0.0.0.0)。输出类似于以下内容:
bind 0.0.0.0
bind 0.0.0.0
将集群更新为 Cloud DNS 后,NodeLocal DNSCache 配置会发生变化。如需检查 NodeLocal DNSCache 配置,请运行以下命令:
kubectl get cm -n kube-system node-local-dns -o json | jq .data.Corefile -r | grep bind
输出类似于以下内容:
bind 169.254.20.10
bind 169.254.20.10
以下工作流说明了 resolv.conf 文件在迁移和节点重新创建之前和之后的条目:
迁移前
- Pod 的
resolv.conf文件已配置为kube-dnsIP 地址(例如x.x.x.10)。 - NodeLocal DNSCache Pod 会截取来自 Pod 的 DNS 请求,并监听以下内容:
- (DPv1) 两个地址(绑定 169.254.20.10 x.x.x.10)。
- (DPv2) 所有 Pod IP 地址(绑定 0.0.0.0)。
- NodeLocal DNSCache 用作缓存,
kube-dnsPod 上的负载极小。
迁移后
- 在控制平面更新为使用 Cloud DNS 后,Pod 仍具有配置为
kube-dnsIP 地址(例如x.x.x.10)的resolv.conf文件。Pod 会保留此resolv.conf配置,直到其节点重新创建。启用 Cloud DNS 和 NodeLocal DNSCache 后,必须将 Pod 配置为使用169.254.20.10作为域名服务器,但此更改仅适用于迁移到 Cloud DNS 后创建或重新创建的节点上的 Pod。 - NodeLocal DNSCache Pod 仅侦听 NodeLocal DNSCache 地址(绑定 169.254.20.10)。请求不会发送到 NodeLocal DNSCache Pod。
- 来自 Pod 的所有请求都会直接发送到
kube-dnsPod。此设置会在 pod 上生成高流量。
在节点重新创建或节点池升级后
- Pod 已配置
resolv.conf文件,以使用 NodeLocal DNSCache IP 地址 (169.254.20.10)。 - NodeLocal DNSCache Pod 仅侦听 NodeLocal DNSCache 地址 (bind 169.254.20.10),并接收来自此 IP 地址上 Pod 的 DNS 请求。
当节点池在重新创建之前使用 resolv.conf 文件中的 kube-dns IP 地址时,DNS 查询流量的增加也会增加 kube-dns Pod 上的流量。这种增加可能会导致 DNS 请求间歇性失败。为尽量减少错误,您必须在停机期间规划此迁移。