本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

CoreDNS 正式成为 Kubernetes 集群 DNS

编者按:此文章是关于 Kubernetes 1.11 新功能的一系列深度文章之一

引言

在 Kubernetes 1.11 中,CoreDNS 已达到通用可用性 (GA),可作为 kube-dns 插件的替代方案,用于基于 DNS 的服务发现。这意味着 CoreDNS 将在即将发布的各种安装工具版本中作为选项提供。事实上,kubeadm 团队选择将其作为 Kubernetes 1.11 默认选项。

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

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

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

实现差异

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

这种设置导致了一些长期存在的问题。例如,`dnsmasq` 中的安全漏洞曾导致 Kubernetes 在过去需要发布安全补丁。此外,由于 `dnsmasq` 处理存根域,而 `kubedns` 处理外部服务,因此您不能在外部服务中使用存根域,这极大地限制了该功能(参见 dns#131)。

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

配置 CoreDNS

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

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

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

错误修复和增强

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

指标

默认 CoreDNS 配置的功能行为与 kube-dns 相同。但是,您需要注意的一个区别是,发布的指标不同。在 kube-dns 中,您会获得 `dnsmasq` 和 `kubedns` (skydns) 的单独指标。在 CoreDNS 中,由于它是一个单独的进程,因此有一组完全不同的指标。您可以在 CoreDNS Prometheus 插件页面上找到有关这些指标的更多详细信息。

一些特殊功能

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

Pod 验证模式

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

基于 Pod 名称的端点名称

在 kube-dns 中,当使用无头服务时,您可以使用 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.

自动路径

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 所在的命名空间,并遍历此搜索列表,直到获得有效答案。由于前三个查询在 CoreDNS 内部自行解决,因此它消除了客户端和服务器之间的所有来回通信,从而降低了延迟。

其他一些 Kubernetes 特有功能

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

您还可以按命名空间或标签选择器进行过滤。这允许您运行仅提供与过滤器匹配的记录的特定 CoreDNS 实例,从而仅通过 DNS 公开有限的服务集。

可扩展性

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

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

接下来呢?

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

上面描述的功能和差异只是一些例子。您可以用 CoreDNS 做更多的事情。您可以在 CoreDNS 博客上找到更多信息。

参与 CoreDNS

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

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

更多资源可以在以下网站找到