使用 Cloud DNS for GKE

本文档介绍了如何设置和使用 Cloud DNS 作为 Google Kubernetes Engine (GKE) 集群的 DNS 提供商。

Cloud DNS 会自动管理 Kubernetes Service 的 DNS 记录。默认情况下,这些记录只能从集群(集群范围)内部访问。

如果您需要从集群外部(例如从 Compute Engine 虚拟机)解析无头 Service,则必须启用 VPC 范围额外的 VPC 范围

本文档适用于 GKE 用户,包括开发者、管理员和架构师。如需详细了解 Google Cloud中的常见角色和示例任务,请参阅常见的 GKE Enterprise 用户角色和任务

为了充分理解本文档,您应该熟悉以下内容:

如需使 ClusterIPNodePort Service 可从集群外部访问,您必须使用 LoadBalancer 或其他方法公开该 Service,并在 Cloud DNS 中注册其外部 IP 地址。

如需详细了解如何将 kube-dns 用作 DNS 提供商,请参阅服务发现和 DNS

如需了解如何使用自定义版本的 kube-dns 或自定义 DNS 提供商,请参阅设置自定义 kube-dns Deployment

价格

当 Cloud DNS 是 GKE Standard 集群的 DNS 提供商时,GKE 集群内的 Pod 发出的 DNS 查询根据 Cloud DNS 价格结算。

对由 GKE 管理的 VPC 范围的 DNS 区域的查询按标准 Cloud DNS 价格计费。

限制和局限

存在以下限制:

  • Autopilot 集群不支持 VPC 范围;仅支持集群范围。如果您需要解析在 GKE Autopilot 集群中运行的无头 Service 名称,则必须使用额外的 VPC 范围。
  • 您只能在创建 GKE Autopilot 集群时启用额外的 VPC 范围。不支持在现有 GKE Autopilot 集群中启用或停用附加 VPC 范围。
  • 不支持在共享 VPC 网络的服务项目中创建额外的 VPC 范围集群。
  • Cloud DNS for GKE 不适用于采用 IL4 合规性制度的 Assured Workload。在此类受监管的环境中,系统会强制使用 kube-dns
  • 对托管式专用 DNS 区域所做的手动更改不受支持,会被 Cloud DNS 控制器覆盖。控制器重启时不会保留这些区域中的 DNS 记录修改。
  • 在集群中启用 Cloud DNS for GKE 后,kube-dns 会继续在集群中运行。您可以通过kube-dns Deployment 和自动扩缩器缩容到零来停用 kube-dns
  • 使用 --cluster-dns-scope 标志设置范围后,您将无法更改集群中的 DNS 范围。如果您需要更改 DNS 范围,则必须重新创建具有其他 DNS 范围的集群。
  • 存在 CloudDNS 资源的限制。具体而言,一个 VPC 网络一次最多只能绑定一个响应政策区域。对于 VPC 和额外的 VPC 范围,如果已存在不遵循命名惯例且绑定到集群 VPC 网络的响应政策区域,则集群创建会失败。
  • 自定义存根网域和上游 DNS 服务器配置适用于 Pod 和节点的 DNS 配置。使用主机网络的 Pod 或直接在主机上运行的进程也会使用存根网域和上游域名服务器配置。仅 Standard 支持此行为。
  • 通过 kube-dns Configmap 配置的自定义存根网域和上游域名服务器会自动应用于 Cloud DNS 以获取集群范围 DNS。VPC 范围 DNS 会忽略 kube-dns ConfigMap,您必须直接在 Cloud DNS 上应用这些配置。仅 Standard 支持此行为。
  • kube-dns 迁移到 VPC 范围是中断性操作。从 kube-dns 切换到 VPC 范围或反向切换时,请重新创建集群。
  • 对于 VPC 范围,Service 的次要 IP 地址范围不得与该子网中的任何其他集群共享。
  • 对于 VPC 范围,与 PTR 记录关联的响应政策会附加到 VPC 网络。如果有任何其他响应政策绑定到集群网络,则 Kubernetes Service IP 地址的 PTR 记录解析会失败。
  • 如果您尝试创建无头 Service,但使用的 Pod 数量超出允许的配额,Cloud DNS 不会为该 Service 创建记录集或记录。
  • 服务和端口名称长度不得超过 62 个字符,即使 DNS 标签的长度上限为 63 个字符也是如此。出现这种行为的原因是,GKE 会为 DNS 记录添加下划线前缀。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请通过运行 gcloud components update 命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。
  • 在您的项目中启用 Cloud DNS API。

    启用 Cloud DNS API

  • 如需在集群范围内使用 Cloud DNS,您需要使用以下版本之一:

    • 对于 Standard:GKE 1.24.7-gke.800 或 1.25.3-gke.700 版,或者更高版本。
    • 对于 Autopilot:GKE 1.25.9-gke.400 或 1.26.4-gke.500 版,或者更高版本。
    • Google Cloud CLI 411.0.0 或更高版本。
  • 如需在额外的 VPC 范围中使用 Cloud DNS,您需要使用以下版本之一:

    • GKE 1.28.3-gke.1430000 版或更高版本。
    • Google Cloud CLI 503.0.0 版或更高版本。

启用集群范围 DNS

在集群范围 DNS 中,只有在 GKE 集群中运行的节点才能解析服务名称,并且服务名称在集群之间不会冲突。此行为与 GKE 集群中的 kube-dns 相同,这意味着您可以将集群从 kube-dns 迁移到 Cloud DNS 集群范围,而无需停机或更改您的应用。

下图展示了 Cloud DNS 如何为 GKE 集群创建专用 DNS 区域。只有在集群节点上运行的进程和 Pod 才能解析集群的 DNS 记录,因为只有节点位于 DNS 范围内。

不同节点上的 Pod 解析 GKE 集群中的 Service。
图表 :集群范围 DNS

在新集群中启用集群范围

1.25.9-gke.400、1.26.4-gke.500 或更高版本中的新 Autopilot 集群默认使用 Cloud DNS 集群范围。以下部分展示了如何在新的 Standard 集群中启用集群范围。

创建启用了集群范围的 Standard 集群

您可以使用 gcloud CLI 或 Google Cloud 控制台创建启用了 Cloud DNS 集群范围的 GKE Standard 集群:

gcloud

使用 --cluster-dns 标志创建集群:

gcloud container clusters create CLUSTER_NAME \
    --cluster-dns=clouddns \
    --cluster-dns-scope=cluster \
    --location=COMPUTE_LOCATION

替换以下内容:

--cluster-dns-scope=cluster 标志在命令中是可选的,因为 cluster 是默认值。

控制台

  1. 在 Google Cloud 控制台中,前往创建一个 Kubernetes 集群页面。

    前往“创建一个 Kubernetes 集群”页面

  2. 在导航窗格的集群下,点击网络

  3. DNS 提供商部分,点击 Cloud DNS

  4. 选择集群范围

  5. 根据需要配置集群。

  6. 点击创建

在现有集群中启用集群范围

不支持将现有 Autopilot 集群从 kube-dns 迁移到 Cloud DNS 集群范围。如需启用 Cloud DNS 集群范围,请在 GKE 1.25.9-gke.400、1.26.4-gke.500 或更高版本中重新创建 Autopilot 集群。

您可以使用 gcloud CLI 或Google Cloud 控制台将现有 Standard 集群从 kube-dns 迁移到 Cloud DNS 集群范围。

将现有集群从 kube-dns 迁移到 Cloud DNS 时,您必须重新创建节点,以便更改生效。通过单独将 Cloud DNS 作为每个节点池中的 DNS 提供商来迁移正在运行应用的集群,这样不会中断集群通信。部分节点始终处于运行状态,因为某些节点池使用 kube-dns 而部分节点池使用 Cloud DNS。

gcloud

  1. 更新现有集群:

    gcloud container clusters update CLUSTER_NAME \
        --cluster-dns=clouddns \
        --cluster-dns-scope=cluster \
        --location=COMPUTE_LOCATION
    

    替换以下内容:

    --cluster-dns-scope=cluster 标志在命令中是可选的,因为 cluster 是默认值。

    响应类似于以下示例:

    All the node-pools in the cluster need to be re-created by the user to start using Cloud DNS for DNS lookups. It is highly recommended to complete this step
    shortly after enabling Cloud DNS.
    Do you want to continue (Y/n)?
    

    确认后,Cloud DNS 控制器会在 GKE 控制平面上运行。不过,Pod 不会使用 Cloud DNS 进行 DNS 解析,除非您升级节点池或向集群添加新节点池。

  2. 升级集群中的节点池以使用 Cloud DNS:

    gcloud container clusters upgrade CLUSTER_NAME \
        --node-pool=POOL_NAME \
        --location=COMPUTE_LOCATION
    

    替换以下内容:

    • CLUSTER_NAME:集群的名称。
    • POOL_NAME:要升级的节点池的名称。

    如果节点池和控制平面运行相同的版本,请先升级控制平面(如手动升级控制平面中所述),然后执行节点池升级。

    确认响应并为集群中的每个节点池重复此命令。如果集群只有一个节点池,请省略 --node-pool 标志。

控制台

  1. 前往 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 点击要修改的集群的名称。

  3. 网络下的 DNS 提供商字段中,点击 修改 DNS 提供商

  4. 点击 Cloud DNS

  5. 点击集群范围

  6. 点击保存更改

启用额外的 VPC 范围

本部分介绍了启用或停用额外的 VPC 范围(作为 Cloud DNS 集群范围的附加组件)的步骤。

在新集群中启用额外的 VPC 范围

您可以使用 gcloud CLI 或 Google Cloud 控制台在新 GKE 集群中启用额外的 VPC 范围 DNS。

创建具有额外 VPC 范围的 Autopilot 集群

gcloud container clusters create-auto CLUSTER_NAME \
    --additive-vpc-scope-dns-domain=UNIQUE_CLUSTER_DOMAIN

替换以下内容:

  • CLUSTER_NAME:集群的名称。
  • UNIQUE_CLUSTER_DOMAIN:网域的名称。您必须确保此名称在 VPC 中具有唯一性,因为 GKE 不会确认此值。此值一经设置便无法更改。请勿使用以 .local 结尾的网域,否则 DNS 解析可能会失败。

创建具有额外 VPC 范围的 Standard 集群

gcloud container clusters create CLUSTER_NAME \
    --cluster-dns=clouddns \
    --cluster-dns-scope=cluster \
    --additive-vpc-scope-dns-domain=UNIQUE_CLUSTER_DOMAIN

--cluster-dns-scope=cluster 标志是可选的,因为 cluster 是默认值。

替换以下内容:

  • CLUSTER_NAME:集群的名称。
  • UNIQUE_CLUSTER_DOMAIN:网域的名称。您必须确保此名称在 VPC 中具有唯一性,因为 GKE 不会确认此值。此值一经设置便无法更改。请勿使用以 .local 结尾的网域,否则 DNS 解析可能会失败。

在现有 Standard 集群中启用额外的 VPC 范围

不支持在现有 Autopilot 集群中启用额外的 VPC 范围。

如需在现有 Standard 集群中启用额外的 VPC 范围,请运行以下命令:

gcloud container clusters update CLUSTER_NAME \
    --additive-vpc-scope-dns-domain=UNIQUE_CLUSTER_DOMAIN \
    --location=COMPUTE_LOCATION

替换以下内容:

  • CLUSTER_NAME:集群的名称。
  • UNIQUE_CLUSTER_DOMAIN:网域的名称。您必须确保此名称在 VPC 中具有唯一性,因为 GKE 不会确认此值。此值一经设置便无法更改。请勿使用以 .local 结尾的网域,否则 DNS 解析可能会失败。
  • COMPUTE_LOCATION:集群的 Compute Engine 位置

启用 VPC 范围 DNS

在 VPC 范围的 DNS 中,集群的 DNS 名称可在整个 VPC 内进行解析。VPC 中的任何客户端都可以解析集群 DNS 记录。

VPC 范围 DNS 可实现以下使用场景:

  • 同一 VPC 中非 GKE 客户端的无头服务发现。
  • 来自本地或第三方云客户端的 GKE 服务解析。如需了解详情,请参阅入站服务器政策
  • 客户端可以使用自定义集群 DNS 网域决定要与哪个集群通信的服务解析。

在下图中,两个 GKE 集群在同一 VPC 中使用 VPC 范围 DNS。这两个集群都具有自定义 DNS 网域 .cluster1.cluster2,而不是默认的 .cluster.local 网域。虚拟机通过解析 backend.default.svc.cluster1 与无头后端服务进行通信。Cloud DNS 将无头 Service 解析为 Service 中的各个 Pod IP 地址,并且虚拟机直接与 Pod IP 地址进行通信。

从 GKE 集群外部解析到无头服务的客户端。
图:VPC 范围 DNS

当通过 Cloud Interconnect 或 Cloud VPN 连接到 VPC 时,您还可以在其他网络中执行此类解析。DNS 服务器政策允许来自 VPC 所连接网络的客户端解析 Cloud DNS 中的名称;如果集群使用 VPC 范围 DNS,则包括 GKE 服务。

在现有集群中启用 VPC 范围

只有 Standard 支持迁移到 VPC 范围,Autopilot 则不支持。

您可以使用 gcloud CLI 或 Google Cloud 控制台将现有 Standard 集群从 kube-dns 迁移到 Cloud DNS VPC 范围。

迁移到 VPC 范围后,您必须重新创建节点才能使更改生效。

gcloud

  1. 更新现有集群:

    gcloud container clusters update CLUSTER_NAME \
        --cluster-dns=clouddns \
        --cluster-dns-scope=vpc \
        --cluster-dns-domain=CUSTOM_DOMAIN \
        --location=COMPUTE_LOCATION
    

    替换以下内容:

    • CLUSTER_NAME:集群的名称。
    • COMPUTE_LOCATION:集群的 Compute Engine 位置
    • CUSTOM_DOMAIN:网域的名称。您必须确保此名称在 VPC 中具有唯一性,因为 GKE 不会确认此值。此值一经设置便无法更改。请勿使用以 .local 结尾的网域,否则 DNS 解析可能会失败。

    响应类似于以下示例:

    All the node-pools in the cluster need to be re-created by the user to start using Cloud DNS for DNS lookups. It is highly recommended to complete this step
    shortly after enabling Cloud DNS.
    Do you want to continue (Y/n)?
    

    确认后,Cloud DNS 控制器会在 GKE 控制平面上运行。除非您升级节点池或向集群添加新节点池,否则 Pod 不会使用 Cloud DNS 进行 DNS 解析。

  2. 升级集群中的节点池以使用 Cloud DNS:

    gcloud container clusters upgrade CLUSTER_NAME \
        --node-pool=POOL_NAME
    

    替换以下内容:

    • CLUSTER_NAME:集群的名称。
    • POOL_NAME:要升级的节点池的名称。

    如果节点池和控制平面运行相同的版本,请先升级控制平面(如手动升级控制平面中所述),然后执行节点池升级。

    确认响应并为集群中的每个节点池重复此命令。如果集群只有一个节点池,请省略 --node-pool 标志。

控制台

  1. 前往 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 点击要修改的集群的名称。

  3. 网络下的 DNS 提供商字段中,点击 修改 DNS 提供商

  4. 点击 Cloud DNS

  5. 点击 VPC 范围

  6. 点击保存更改

验证 Cloud DNS

验证 Cloud DNS for GKE 是否在集群中正常运行:

  1. 通过连接到节点上的 Pod 并运行 cat /etc/resolv.conf 命令,验证您的节点是否使用 Cloud DNS:

    kubectl exec -it POD_NAME -- cat /etc/resolv.conf | grep nameserver
    

    POD_NAME 替换为 Pod 的名称。

    根据集群模式,输出类似于以下内容:

    GKE Autopilot 集群

    nameserver 169.254.20.10
    

    由于 GKE Autopilot 中默认启用 NodeLocal DNSCache,因此 Pod 使用 NodeLocal DNSCache

    如果本地缓存没有正在查找的名称的条目,NodeLocal DNSCache 会将请求转发到 Cloud DNS。

    GKE Standard 集群

    nameserver 169.254.169.254
    

    此 Pod 示例使用 169.254.169.254 作为 nameserver,这是元数据服务器的 IP 地址,Cloud DNS 数据平面在其中监听端口 53 上的请求。节点不再使用 kube-dns 服务地址进行 DNS 解析,并且所有 DNS 解析都在本地节点上进行。

    如果输出是类似于 10.x.y.10 的 IP 地址,则说明 Pod 使用的是 kube-dns。如需了解您的 Pod 仍在使用 kube-dns 的原因,请参阅问题排查部分。

    如果输出为 169.254.20.10,则表示您已在集群中启用 NodeLocal DNSCache,并且 Pod 使用的是 NodeLocal DNSCache

  2. 将示例应用部署到您的集群:

    kubectl run dns-test --image us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
    
  3. 使用 Service 公开示例应用:

    kubectl expose pod dns-test --name dns-test-svc --port 8080
    
  4. 验证 Service 已成功部署:

    kubectl get svc dns-test-svc
    

    输出类似于以下内容:

    NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    dns-test-svc   ClusterIP   10.47.255.11    <none>        8080/TCP   6m10s
    

    CLUSTER-IP 列的值是集群的虚拟 IP 地址。在此示例中,虚拟 IP 地址为 10.47.255.11

  5. 验证您的 Service 名称是否已在集群的专用 DNS 区域中作为记录创建:

    gcloud dns record-sets list \
        --zone=PRIVATE_DNS_ZONE \
        --name=dns-test-svc.default.svc.DOMAIN_NAME.
    

    替换以下内容:

    • PRIVATE_DNS_ZONE:由 GKE 创建的托管式 DNS 区域的名称。如需查找区域名称,您可以访问 Google Cloud 控制台的 Cloud DNS 区域页面,也可以参阅命名惯例
    • DOMAIN_NAME:如果您使用不含额外 VPC 范围的集群范围,则为 cluster.local;或者是您在启用 VPC 范围或额外的 VPC 范围时配置的自定义网域。

    输出类似于以下内容:

    NAME: dns-test-svc.default.svc.cluster.local.
    TYPE: A
    TTL: 30
    DATA: 10.47.255.11
    

在 Standard 集群中停用 Cloud DNS

在创建时默认启用了 Cloud DNS 的 Autopilot 集群中,不支持停用 Cloud DNS。

不支持在 Standard 中停用 VPC 范围。您必须重新创建集群,并将 kube-dns 用作 DNS 提供商。

您可以使用 gcloud CLI 或Google Cloud 控制台在 Standard 集群中停用集群范围并还原为 kube-dns

gcloud

更新集群以使用 kube-dns

gcloud container clusters update CLUSTER_NAME \
    --cluster-dns=kube-dns \
    --location=COMPUTE_LOCATION

替换以下内容:

控制台

  1. 前往 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 点击要修改的集群的名称。

  3. 网络下的 DNS 提供商字段中,点击 修改 DNS 提供商

  4. 点击 Kube-dns

  5. 点击保存更改

停用 Cloud DNS 后,您必须重新创建节点池,然后节点才能使用 kube-dns 进行解析。如果您之前kube-dns 缩容到零个节点,则必须先扩容 kube-dns,然后节点才能使用它进行 DNS 解析。如果您不重新创建节点池,现有节点上的 Pod 将继续使用 Cloud DNS 进行 DNS 解析,因为它们的 /etc/resolv.conf 文件在重新创建节点之前不会更新。

停用额外的 VPC 范围

为集群停用额外的 VPC 范围时,只有连接到 VPC 网络的专用区域中的 DNS 记录会被删除。GKE 集群的专用 DNS 区域中的记录将保留并由 Cloud DNS for GKE 管理,直到无头 Service 从集群中删除。

如需停用额外的 VPC 范围,请运行以下命令:

gcloud container clusters update CLUSTER_NAME \
    --disable-additive-vpc-scope

CLUSTER_NAME 替换为您的集群的名称。

此设置会使集群的 Cloud DNS 集群范围保持启用状态,以便从集群内部提供 DNS 解析。

清理

完成本文档中的练习后,请按照以下步骤移除资源,防止您的账号产生不必要的费用:

  1. 删除服务:

    kubectl delete service dns-test-svc
    
  2. 删除 Pod:

    kubectl delete Pod dns-test
    
  3. 您还可以删除集群

问题排查

如需了解如何排查 Cloud DNS 问题,请参阅以下页面:

后续步骤