本文发表时间已超过一年。较旧的文章可能包含过时的内容。请检查页面上的信息自发布以来是否已变为不正确。
用于 Kubernetes 集群 DNS 的 CoreDNS GA
编者按:这篇文章是关于 Kubernetes 1.11 中新特性的系列深入文章的一部分。
简介
在 Kubernetes 1.11 中,CoreDNS 作为 kube-dns 插件的替代方案,已达到基于 DNS 的服务发现的正式可用性 (GA)。这意味着在即将发布的各种安装工具版本中,CoreDNS 将作为一种选择提供。事实上,kubeadm 团队选择将其作为 Kubernetes 1.11 的默认选项。
基于 DNS 的服务发现作为 kube-dns 集群插件,已成为 Kubernetes 的一部分很长时间了。它通常运行良好,但人们对该实现的可靠性、灵活性和安全性存在一些担忧。
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 中得到解决,无论是在默认配置中还是在某些自定义配置中。
dns#55 - kube-dns 的自定义 DNS 条目可以使用 kubernetes 插件中的“fallthrough”机制,使用rewrite 插件,或者简单地使用不同的插件(例如 file 插件)来提供子区域。
dns#116 - 具有单个主机名的 Pod 的无头服务只有一个 A 记录集。此问题已修复,无需任何其他配置。
dns#131 - externalName 不使用 stubDomains 设置。此问题已修复,无需任何其他配置。
dns#167 - 启用 skyDNS 循环 A/AAAA 记录。可以使用 load balance 插件配置等效功能。
dns#190 - kube-dns 无法以非 root 用户身份运行。此问题目前通过使用非默认镜像来解决,但在未来的版本中将成为默认的 CoreDNS 行为。
dns#232 - 将 pod 主机名修复为 dns srv 记录的 podname 是一项增强功能,通过下面描述的“endpoint_pod_names”功能支持。
指标
默认 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 提供“已验证的 Pod”模式,仅当指定的命名空间中存在具有该 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#47992 和 coredns#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 所在的命名空间,并遍历此搜索列表,直到获得有效答案。由于前 3 个在 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)上最活跃
- Slack:https://slack.cncf.io 上的 #coredns
- GitHub:https://github.com/coredns/coredns
可以找到更多资源
- 网站:https://coredns.golang.ac.cn
- 博客:https://blog.coredns.io
- Twitter:@corednsio
- 邮件列表/群组:[email protected]