TranslateProject/translated/tech/20170531 DNS Infrastructure at GitHub.md
2017-09-08 08:54:05 +08:00

8.8 KiB
Raw Blame History

GitHub 的 DNS 基础设施

在 GitHub我们最近从头改进了 DNS。这包括了我们如何与外部 DNS 提供商交互以及我们如何在内部向我们的主机提供记录。为此,我们必须设计和构建一个新的 DNS 基础设施,它可以随着 GitHub 的增长扩展并跨越多个数据中心。

以前GitHub 的 DNS 基础设施相当简单直接。它包括每台服务器上本地的,只有转发的 DNS 缓存,以及被所有这些主机使用的缓存和权威的一对主机。这些主机在内部网络以及公共互联网上都可用。我们在缓存守护程序中配置了域记录,以在本地进行查询,而不是在互联网上进行递归。我们还在我们的 DNS 提供商处设置了 NS 记录,它们将特定的内部域指向这对主机的公共 IP以便我们网络外部的查询。

这个配置使用了很多年,但并非没有它的缺点。许多程序对于解析 DNS 查询非常敏感,我们遇到的任何性能或可用性问题最好情况会导致排队和性能降级,最坏情况下客户会停机。配置和代码更改可能会导致查询率的大幅意外更改。因此超出这两台主机的扩展成为了一个问题。由于这些主机的网络配置,我们只需要继续添加有问题的 IP 和主机。在试图解决和补救这些问题的同时,由于缺乏指标和可见性,老旧的系统难以识别原因。在许多情况下,我们使用 tcpdump 来识别有问题的流量和查询。另一个问题是在公共 DNS 服务器上运行,我们冒着泄露内部网络信息的风险。因此,我们决定建立更好的东西,并开始确定我们对新系统的要求。

我们着手设计一个新的 DNS 基础设施,以改善上述的操作问题,包括扩展和可见性,并引入了一些额外的要求。我们希望通过外部 DNS 提供商继续运行我们的公共 DNS 域,因此我们构建的系统需要与供应商无关。此外,我们希望该系统能够服务于我们的内部和外部域,这意味着内部域仅在我们的内部网络上可用,除非另有特别配置,否则外部域是可解析的,而不会离开我们的内部网络。我们希望新的 DNS 架构允许更改基于部署的工作流,并通过我们的仓库和配置系统使用 API 自动更改记录。新系统不能有任何外部依赖,太依赖于 DNS 功能而被陷入级联故障。这包括连接到其他数据中心和其中可能有的 DNS 服务。我们的旧系统将缓存和权威在同一台主机上混合使用。我们想转到具有独立角色的分层设计。最后,我们希望系统能够支持多数据中心环境,无论是 EC2 还是裸机。

实现

为了构建这个系统,我们确定了三类主机:缓存主机、边缘主机和权威主机。缓存作为递归解析器和 DNS “路由器”缓存来自边缘层的响应。边缘层运行 DNS 权威守护程序,用于响应缓存层对权威层的响应。权威层作为隐藏的 DNS 主机是 DNS 数据的常规来源,为来自边缘主机的域传输服务,并提供用于创建、修改或删除记录的 HTTP API。

在我们的新配置中,缓存存在每个数据中心中,这意味着程序主机不需要遍历数据中心边界来检索记录。缓存被配置为将域映射到其域内的边缘主机,以便将我们的内部域路由到我们自己的主机。未明确配置的任何域将通过互联网递归解析。

边缘主机是区域主机,存在我们的网络边缘 PoP存在点。我们的 PoP 有一个或多个依赖于它们的数据中心进行外部连接,没有 PoP 数据中心无法访问互联网,互联网也无法访问它们。边缘对所有的权威执行区域传输,无论它们存在什么域或位置,并将这些域存在本地的磁盘上。

我们的权威主机也是区域主机,只包含适用于其所在区域的域。我们的仓库和配置系统决定区域权威存在哪里,通过 HTTP API 创建和删除服务器记录。 OctoDNS 将域映射到区域权威,并使用相同的 API 创建静态记录,并确保动态源处于同步状态。对于外部域 (如 github.com),我们有另外一个单独的权威,允许我们在连接中断期间查询我们的外部域。所有记录都存储在 MySQL 中。

可操作性

迁移到更现代的 DNS 基础设施的巨大好处是可观察性。我们的旧 DNS 系统几乎没有指标和有限的日志。决定使用哪些 DNS 服务器的一个重要因素是它们产生的指标的广度和深度。我们最终用 Unbound 作为缓存,NSD 作为边缘主机,PowerDNS 作为权威,所有这些都已在 DNS 基础架构中被证明比 GitHub 好很多。

当在我们的裸机数据中心运行时,缓存通过私有广播 IP 访问,从而到达最近的可用缓存主机。缓存已经以机架感知的方式部署,在它们之间提供一定程度的平衡负载,并且与一些电源和网络故障模式隔离。当缓存主机出现故障时,通常将其用于查找的服务器现在将自动路由到下一个最接近的缓存,保持低延迟并提供对某些故障模式的容错。广播允许我们扩展单个 IP 地址后面的缓存数量,这与先前的配置不同,使我们能够按 DNS 需求运行尽可能多的缓存主机。

无论区域或位置如何,边缘主机使用权威层进行域传输。我们的域不够大,在每个区域保留所有域的副本是一个问题。这意味着对于每个域,即使某个区域处于脱机状态,或者上游提供存在连接问题,所有缓存都可以访问具有所有域的本地副本的本地边缘服务器。这种变化在面对连接问题方面已被证明是相当有弹性的,并且在不久前会导致客户面临停机的故障期间帮助保持 GitHub 可用。

这些域从它们相应的权威服务器同时转移内部和外部域。正如你可能会猜想像 github.com 这样的域是外部的,像 github.net 这样的域通常是内部的。它们之间的区别仅在于我们使用的类型和存储的数据。了解哪些域是内部和外部的,为我们在配置中提供了一些灵活性。

$ dig +short github.com
192.30.253.112
192.30.253.113

公共域被同步到外部 DNS 提供商,并且是 GitHub 用户每天使用的记录。另外,公共域在我们的网络中是完全可解析的,而不需要与我们的外部提供商进行通信。这意味着需要查询 api.github.com的任何服务都可以这样做,而无需依赖外部网络连接。我们还使用 Unbound 的 stub-first 配置选项,如果我们的内部 DNS 服务由于某些原因在外部查询失败,则可以进行第二次查找。

$ dig +short time.github.net
10.127.6.10

github.net 域大部分是完全私有的,无法从互联网访问,它只包含 RFC 1918 IP地址。每个区域和站点都划分了私有域。每个区域和/或站点都具有适用于该位置的一组子域,用于管理网络的子域、服务发现、特定服务记录,并且还包括在我们仓库中的配置主机。私有域还包括 PTR 反向查找域。

总结

用一个可以为数百万客户提供服务的新系统替换旧的系统并不容易。使用实用的,以需求为基础的方法来设计和实施我们的新 DNS 系统,来让 DNS 基础设施能迅速有效地运行,并有希望与 GitHub 一起成长。

想帮助 GitHub SRE 团队解决有趣的问题吗?我们很乐意你加入我们。在这申请


via: https://githubengineering.com/dns-infrastructure-at-github/

作者:Joe Williams 译者:geekpi 校对:校对者ID

本文由 LCTT 原创编译,Linux中国 荣誉推出