这篇文章已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已失效。

CoreDNS 作为 Kubernetes 集群 DNS 进入 GA

编者注:这篇文章是关于 Kubernetes 1.11 新功能系列深度文章的一部分

简介

在 Kubernetes 1.11 中,CoreDNS 作为 kube-dns 插件的替代方案,基于 DNS 的服务发现功能已达到普遍可用 (GA) 状态。这意味着 CoreDNS 将在未来版本的各种安装工具中作为可选方案提供。实际上,kubeadm 团队选择从 Kubernetes 1.11 开始将其作为默认选项。

基于 DNS 的服务发现长期以来一直是 Kubernetes 的一部分,通过 kube-dns 集群插件实现。这通常运作良好,但人们对其实现的可靠性、灵活性和安全性存在一些担忧。

CoreDNS 是一个通用、权威的 DNS 服务器,它提供了与 Kubernetes 向后兼容但可扩展的集成。它解决了 kube-dns 存在的问题,并提供了一些独特的功能,可以解决更广泛的用例。

在本文中,您将了解 kube-dns 和 CoreDNS 实现上的差异,以及 CoreDNS 提供的一些有用的扩展。

实现差异

在 kube-dns 中,一个 Pod 内使用了多个容器:kubednsdnsmasqsidecarkubedns 容器监听 Kubernetes API 并根据Kubernetes DNS 规范提供 DNS 记录,dnsmasq 提供缓存和 stub domain 支持,sidecar 提供指标和健康检查。

这种设置随着时间的推移带来了一些问题。例如,dnsmasq 的安全漏洞在过去导致 Kubernetes 需要发布安全补丁版本。此外,由于 dnsmasq 处理 stub domain,而 kubedns 处理 External Services,因此您无法在外部服务中使用 stub domain,这极大地限制了该功能(参见dns#131)。

CoreDNS 在一个单独的容器中完成所有这些功能,该容器运行一个用 Go 编写的进程。启用的各种插件复制(并增强)了 kube-dns 中的功能。

配置 CoreDNS

在 kube-dns 中,您可以修改 ConfigMap 来改变服务发现的行为。这允许添加诸如提供 stub domain、修改上游名称服务器和启用联邦等功能。

在 CoreDNS 中,您类似地可以修改 CoreDNS Corefile 的 ConfigMap 来改变服务发现的工作方式。这个 Corefile 配置提供了比 kube-dns 多得多的选项,因为它作为主要的配置文件,CoreDNS 使用它来配置所有功能,甚至那些与 Kubernetes 无关的功能。

使用 kubeadm 从 kube-dns 升级到 CoreDNS 时,您现有的 ConfigMap 将用于为您生成定制的 Corefile,包括 stub domain、联邦和上游名称服务器的所有配置。有关更多详细信息,请参阅使用 CoreDNS 进行服务发现

错误修复和增强

kube-dns 中存在几个未解决的问题,这些问题在 CoreDNS 中已得到解决,无论是在默认配置下还是通过一些自定义配置。

指标

默认 CoreDNS 配置的功能行为与 kube-dns 相同。然而,您需要注意的一个区别是发布的指标不同。在 kube-dns 中,您可以获得 dnsmasqkubedns (skydns) 的单独指标。在 CoreDNS 中,由于它是一个单一进程,因此提供了一组完全不同的指标。您可以在 CoreDNS 的 Prometheus plugin 页面找到这些指标的更多详细信息。

一些特殊功能

标准的 CoreDNS Kubernetes 配置旨在向后兼容先前的 kube-dns 行为。但是通过一些配置更改,CoreDNS 可以让您修改集群中 DNS 服务发现的工作方式。其中许多功能旨在仍然符合Kubernetes DNS 规范;它们增强了功能但保持向后兼容。由于 CoreDNS 不仅仅是为 Kubernetes 构建的,而是一个通用的 DNS 服务器,因此您可以做的很多事情都超出了该规范。

Pods 验证模式

在 kube-dns 中,Pod 名称记录是“伪造的”。也就是说,任何形如 "a-b-c-d.namespace.pod.cluster.local" 的查询都会返回 IP 地址 "a.b.c.d"。在某些情况下,这会削弱 TLS 提供的身份保证。因此,CoreDNS 提供了一种“Pods 验证”模式,只有当指定命名空间中存在具有该 IP 地址的 Pod 时,才会返回 IP 地址。

基于 Pod 名称的端点名称

在 kube-dns 中,使用 headless 服务时,您可以使用 SRV 请求获取服务的所有端点列表

dnstools# host -t srv headless
headless.default.svc.cluster.local has SRV record 10 33 0 6234396237313665.headless.default.svc.cluster.local.
headless.default.svc.cluster.local has SRV record 10 33 0 6662363165353239.headless.default.svc.cluster.local.
headless.default.svc.cluster.local has SRV record 10 33 0 6338633437303230.headless.default.svc.cluster.local.
dnstools#

然而,端点 DNS 名称(在实际应用中)是随机的。在 CoreDNS 中,默认情况下,您会获得基于端点 IP 地址的端点 DNS 名称

dnstools# host -t srv headless
headless.default.svc.cluster.local has SRV record 0 25 443 172-17-0-14.headless.default.svc.cluster.local.
headless.default.svc.cluster.local has SRV record 0 25 443 172-17-0-18.headless.default.svc.cluster.local.
headless.default.svc.cluster.local has SRV record 0 25 443 172-17-0-4.headless.default.svc.cluster.local.
headless.default.svc.cluster.local has SRV record 0 25 443 172-17-0-9.headless.default.svc.cluster.local.

对于某些应用程序来说,最好使用 Pod 名称而不是 Pod IP 地址(例如参见kubernetes#47992coredns#1190)。要在 CoreDNS 中启用此功能,您可以在 Corefile 中指定 "endpoint_pod_names" 选项,其结果如下

dnstools# host -t srv headless
headless.default.svc.cluster.local has SRV record 0 25 443 headless-65bb4c479f-qv84p.headless.default.svc.cluster.local.
headless.default.svc.cluster.local has SRV record 0 25 443 headless-65bb4c479f-zc8lx.headless.default.svc.cluster.local.
headless.default.svc.cluster.local has SRV record 0 25 443 headless-65bb4c479f-q7lf2.headless.default.svc.cluster.local.
headless.default.svc.cluster.local has SRV record 0 25 443 headless-65bb4c479f-566rt.headless.default.svc.cluster.local.

Autopath (自动路径)

CoreDNS 还提供了一个特殊功能,可以改善外部名称 DNS 请求的延迟。在 Kubernetes 中,Pod 的 DNS 搜索路径指定了很长的后缀列表。这使得在集群中请求服务时可以使用短名称,例如上面提到的 "headless",而不是 "headless.default.svc.cluster.local"。然而,当请求外部名称(例如 "infoblox.com")时,客户端会发出多个无效的 DNS 查询,每次都需要客户端到 kube-dns 的往返(实际上是到 dnsmasq 再到 kubedns,因为禁用了负缓存

  • infoblox.com.default.svc.cluster.local -> NXDOMAIN (不存在的域)
  • infoblox.com.svc.cluster.local -> NXDOMAIN (不存在的域)
  • infoblox.com.cluster.local -> NXDOMAIN (不存在的域)
  • infoblox.com.your-internal-domain.com -> NXDOMAIN (不存在的域)
  • infoblox.com -> 返回有效记录

在 CoreDNS 中,可以启用一个称为 autopath 的可选功能,该功能将使这个搜索路径在服务器端被遵循。也就是说,CoreDNS 会根据源 IP 地址判断客户端 Pod 所在的命名空间,并遍历这个搜索列表直到获得有效答案。由于前 3 个查询在 CoreDNS 内部就能解析,这减少了客户端和服务器之间的所有来回通信,从而降低了延迟。

其他一些 Kubernetes 特有功能

在 CoreDNS 中,您可以使用标准的 DNS 区域传输来导出整个 DNS 记录集。这对于调试您的服务以及将集群区域导入到其他 DNS 服务器非常有用。

您还可以按命名空间或标签选择器进行过滤。这允许您运行特定的 CoreDNS 实例,这些实例将只提供匹配过滤条件的记录,通过 DNS 只暴露有限的服务集。

可扩展性

除了上面描述的功能外,CoreDNS 也很容易扩展。可以构建包含您自己功能的自定义 CoreDNS 版本。例如,此能力已被用于扩展 CoreDNS,以使用 unbound 插件进行递归解析,使用 pdsql 插件直接从数据库提供记录,并使用 redisc 插件允许多个 CoreDNS 实例共享一个公共的二级缓存。

已经添加了许多其他有趣的扩展,您可以在 CoreDNS 网站的外部插件页面找到它们。对于 Kubernetes 和 Istio 用户来说,有一个非常有趣的插件是 kubernetai 插件,它允许一个 CoreDNS 实例连接到多个 Kubernetes 集群并跨所有集群提供服务发现。

下一步是什么?

CoreDNS 是一个独立项目,因此正在开发许多与 Kubernetes 没有直接关联的功能。然而,其中一些功能将在 Kubernetes 中有应用。例如,即将与策略引擎集成将允许 CoreDNS 在请求 headless 服务时智能地选择返回哪个端点。这可以用于将流量路由到本地 Pod,或路由到响应更快的 Pod。许多其他功能正在开发中,当然作为一个开源项目,我们欢迎您提出并贡献自己的功能!

上面描述的功能和差异只是一些示例。CoreDNS 还有更多功能等待您探索。您可以在CoreDNS 博客上了解更多信息。

参与 CoreDNS

CoreDNS 是一个孵化中的 CNCF 项目。

我们在 Slack(和 GitHub)上最为活跃

更多资源可以在这里找到