使用 kube-dns


本页面介绍 Google Kubernetes Engine (GKE) 如何使用 kube-dns(GKE 集群的默认 DNS 提供商)实现服务发现。

对于 Autopilot 集群,您无法修改默认的 kube-dns 配置。

架构

创建集群时,GKE 会自动在 kube-system 命名空间中部署 kube-dns pod。Pod 通过相应的 Service 访问 kube-dns 部署,该 Service 会对 Kube-dns Pod 进行分组并为其提供单一 IP 地址 (ClusterIP)。默认情况下,集群中的所有 Pod 均使用此服务来解析 DNS 查询。下图显示了 pod 与 kube-dns 服务之间的关系。

kube-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 只会为具有端点的 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

后续步骤