博客 | NGINX

使用 NGINX 和 NGINX Plus 的 DNS 进行服务发现

NGINX-F5-horiz-black-type-RGB 的一部分
Michael Pleshakov 缩略图
米歇尔·普列沙科夫
2016 年 4 月 27 日发布

[编辑 – 此文章已更新,引用了NGINX Plus API ,它取代并弃用了文章原始版本中提到的单独动态配置模块。]

微服务架构的一大优势是可以快速轻松地扩展服务实例。 对于多个服务实例,您需要一个负载均衡器以及某种方法来快速通知它可用服务实例集的变化。 这被称为服务发现NGINX Plus提供了两种与服务发现系统集成的选项: NGINX Plus API域名系统 (DNS) 重新解析。 这篇博文主要关注后者。

通过添加或删除虚拟机(VM)或容器来扩展服务实例(在此博客文章中我们将其称为后端)时,必须更改负载均衡器的配置以反映后端集的每个更改。 根据应用的不同,每天、每小时、甚至每分钟都可能发生多次扩展。 由于配置更改频率很高,因此需要实现自动化,而实现自动化的方法之一是通过 DNS 进行服务发现。

目前运行applications的许多平台(例如Kubernetes )都支持使用 DNS 进行服务发现。 我们在本博文末尾提供了一些文章链接,解释了如何将 NGINX Plus 与使用 DNS 的流行平台和服务发现工具集成。

主要 DNS 功能的快速回顾

在我们解释如何通过 DNS 配置服务发现之前,让我们快速了解一下 DNS 协议的一些特别相关或方便的功能。

生存时间

为了防止 DNS 客户端使用过时的信息,DNS 记录包含生存时间 (TTL) 字段来定义客户端可以认为记录有效的时间长度。 为了符合DNS 标准,当记录超过其 TTL 时,客户端必须向 DNS 服务器查询更新。 NGINX Plus 默认遵守 TTL,但也提供对记录“生命周期”的更精细控制——您可以将 NGINX Plus 配置为忽略 TTL,而是以指定的频率更新记录。 (我们将在后面的文章中讨论 NGINX Open Source 如何处理 TTL。)

TCP 上的 DNS

默认情况下,DNS 客户端和服务器通过 UDP 进行通信,但如果域名解析为大量后端 IP 地址,则完整的响应可能无法容纳单个 UDP 数据报(限制为 512 字节)。 使用 TCP 而不是 UDP 解决了这个问题:当一整套记录无法容纳在一个数据报中时,服务器会在其响应中设置一个截断标志,告诉客户端切换到 TCP 来获取所有记录。 NGINX 1.9.11 及更高版本和 NGINX Plus R9 及更高版本支持 DNS over TCP。 有关更多详细信息,请参阅我们博客上的使用 NGINX 和 NGINX Plus 负载平衡 DNS 流量

SRV记录

DNS 将主机名解析为 IP 地址,但是端口号呢? 在某些情况下 - 例如,在对 Docker 容器进行负载平衡时 - 您不能依赖众所周知的端口号,因为端口号是动态分配的。 DNS 有一种特殊类型的记录 -服务( SRV )记录- 其中包括端口号和一些其他参数。 在 R9 及更高版本中,NGINX Plus 支持SRV记录(因此可以从中提取端口信息)。

编辑器 – 有关 NGINX Plus R9 中所有新功能的概述,请参阅我们博客上的“宣布 NGINX Plus R9”

NGINX 和 NGINX Plus 使用 DNS 进行服务发现的方法

现在,我们将按复杂程度递增的顺序向您展示在 NGINX 和 NGINX Plus 中使用 DNS 进行服务发现的五种方法。 前三个在 NGINX 和 NGINX Plus 中均可用,后两个仅在 NGINX Plus 中可用。

在本次服务发现方法调查中,我们假设我们有一个区域example.com的权威名称服务器,其 IP 地址为 10.0.0.2。 有三个后端服务器与域名backends.example.com相对应,如以下nslookup实用程序的输出所示。 对于我们将要讨论的前四种方法,NGINX 和 NGINX Plus 会从 DNS 请求标准A记录;对于最后一种方法,NGINX Plus 会请求SRV记录。

$ nslookup backends.example.com 10.0.0.2服务器:		10.0.0.2 地址:	10.0.0.2#53 名称:backends.example.com 地址: 10.0.0.11 名称:backends.example.com 地址: 10.0.0.10 名称:backends.example.com 地址: 10.0.0.12

使用 DNS 进行 NGINX 服务发现

我们将首先向您展示通过NGINX 开源使用 DNS 的三种方法(正如我们上面提到的,您也可以将它们与 NGINX Plus 一起使用)。

proxy_pass指令中使用域名

定义上游服务器(后端)组的最简单方法是将域名指定为proxy_pass指令的参数:

服务器 { 位置 / {
proxy_pass http://backends.example.com:8080;
}
}

当 NGINX 启动或重新加载其配置时,它会查询 DNS 服务器来解析backends.example.com 。 DNS 服务器返回上面讨论的三个后端列表,NGINX 使用默认的 Round Robin 算法在它们之间对请求进行负载平衡。 NGINX 从操作系统配置文件/etc/resolv.conf中选择 DNS 服务器。

这种方法是进行服务发现最不灵活的方法,并且还有以下缺点:

  • 如果无法解析域名,NGINX 将无法启动或重新加载其配置。
  • NGINX 缓存 DNS 记录直到下次重启或重新加载配置,忽略记录的 TTL 值。
  • 我们不能指定另一种负载平衡算法,也不能配置被动健康检查或由服务器指令参数定义的其他功能,我们将在下一节中描述。

在上游服务器组中使用域名

为了利用 NGINX 提供的负载平衡选项,您可以在上游配置块中定义上游服务器组。 但是,不要通过 IP 地址来识别单个服务器,而是使用域名作为服务器指令的参数。

第一种方法一样,当 NGINX 启动或重新加载其配置时, backends.example.com会被解析为三个后端服务器。 但是现在我们可以定义一个更复杂的负载平衡算法,最少连接,并使用max_fails参数启用被动健康检查,指定当连续三个请求失败时 NGINX 将服务器标记为关闭。

上游后端 { least_conn;

服务器 backends.example.com:8080 max_fails=3;
}

服务器 {
位置 / {
proxy_pass http://backends;
}
}

虽然这种方法使我们能够选择负载平衡算法并配置健康检查,但它在启动、重新加载和 TTL 方面仍然存在与以前的方法相同的缺点。

在变量中设置域名

此方法是第一种方法的变体,但使我们能够控制 NGINX 重新解析域名的频率:

解析器 10.0.0.2 有效=10s;
服务器 {
位置 / {
设置 $backend_servers backends.example.com;
proxy_pass http://$backend_servers:8080;
}
}

当您使用变量在proxy_pass指令中指定域名时,NGINX 会在其 TTL 过期时重新解析该域名。 您必须包含解析器指令来明确指定名称服务器(NGINX 不像前两种方法那样引用/etc/resolv.conf )。 通过将有效参数包含在解析器指令中,您可以告诉 NGINX 忽略 TTL 并以指定的频率重新解析名称。 这里我们告诉 NGINX 每 10 秒重新解析名称。

笔记: 对于 TCP/UDP 负载平衡,NGINX 1.11.3 及更高版本以及 NGINX Plus R10 及更高版本支持在proxy_pass指令中使用变量的方法。

这种方法消除了第一种方法的两个缺点,当域名无法解析时,NGINX 启动或重新加载操作不会失败,并且我们可以控制 NGINX 重新解析名称的频率。 但是,由于它不使用上游组,因此您无法向服务器指令指定负载平衡算法或其他参数(正如我们在第二种方法中所做的那样)。

使用 NGINX Plus 的 DNS 进行服务发现

现在我们来了解一下 NGINX Plus 独有的两种使用 DNS 进行服务发现的方法。

在 NGINX Plus 中使用A记录

使用 NGINX Plus,我们可以根据需要频繁地重新解析DNS 名称,并且不会出现前三种方法中讨论的缺点。 要使用此功能,我们需要:

  • 包括解析器指令来指定名称服务器,如前一种方法。
  • 上游配置块中包含区域指令来分配共享内存区域。
  • 在我们使用域名的服务器指令中添加resolve参数。

请考虑以下示例:

解析器 10.0.0.2 有效 = 10 秒;上游后端 {区域后端 64k ;服务器 backends.example.com:8080 resolve ;} 服务器 {位置 / {proxy_pass http://backends;}}

默认情况下,NGINX Plus 尊重 TTL,当记录过期时重新解析名称。 要让 NGINX Plus 以指定的频率重新解析名称,请将有效参数包含在解析器指令中。

在代码片段中,每 10 秒 NGINX Plus 查询 10.0.0.2 的名称服务器以解析backends.example.com 。 如果无法解析名称,NGINX Plus 不会失败,无论是在启动时,重新加载配置时还是在运行时。 相反,客户看到的是标准502错误页面。

在 NGINX Plus 中使用SRV记录

NGINX Plus R9 及更高版本支持 DNS SRV记录。 这使得 NGINX Plus 不仅可以从名称服务器获取 IP 地址,还可以获取端口号、权重和优先级。 这在微服务环境中至关重要,因为服务的端口号通常是动态分配的。

编辑器 – 有关 NGINX Plus R9 中所有新功能的概述,请参阅我们博客上的“宣布 NGINX Plus R9”

SRV记录由服务名称、与服务通信的协议和域名三元组定义。 当查询名称服务器时,我们必须提供所有这三个。 我们的 10.0.0.2 名称服务器具有三条SRV记录,包括服务名称http 、协议tcp和域名backends.example.com这三组,如nslookup实用程序的输出所示:

$ nslookup -query=SRV _http._tcp.backends.example.com 10.0.0.2服务器:		10.0.0.2 地址:	10.0.0.2#53 _http._tcp.backends.example.com 服务 = 0 2 8090 backend-0.example.com。 _http._tcp.backends.example.com 服务 = 0 1 8091 backend-1.example.com。 _http._tcp.backends.example.com 服务 = 10 1 8092 backend-2.example.com。

当我们查询每个SRV记录中的主机名时,我们会获得其 IP 地址:

$ nslookup backend-0.example.com 10.0.0.2 ...
名称:backend-0.example.com 地址: 10.0.0.10 $ nslookup backend-1.example.com 10.0.0.2 ...
名称:backend-1.example.com 地址: 10.0.0.11 $ nslookup backend-2.example.com 10.0.0.2 ...
名称:backend-2.example.com 地址: 10.0.0.12

让我们更仔细地看一下第一个nslookup命令返回的第一个SRV记录中的信息:

_http._tcp.backends.example.com 服务 = 0 2 8090 backend-0.example.com。
  • _http._tcp.SRV记录的名称和协议。 我们将把它指定为 NGINX Plus 配置文件中服务器指令的服务参数的值(见下文)。
  • 0 – 优先级。 值越低,优先级越高。 NGINX Plus 将优先级最高的服务器指定为主服务器,其余服务器指定为备份服务器。 该记录在所有记录中具有最低的值(最高优先级),因此 NGINX Plus 将相应的后端指定为主服务器。
  • 2 – 重量。 NGINX Plus 在将后端添加到上游组时将后端的权重设置为该值(相当于服务器指令上的权重参数)。
  • 8090 – 端口号。 NGINX Plus 在将后端添加到上游组时将后端的端口设置为此值。
  • backend‑0.example.com – 后端服务器的主机名。 NGINX Plus 解析该名称并将相应的后端添加到上游组。 如果名称解析为多条记录,NGINX Plus 会添加多个服务器。

现在让我们看看如何配置 NGINX Plus 以使用SRV记录。 以下是示例配置文件:

解析器 10.0.0.2 有效=10s;

上游后端 {
区域后端 64k;
服务器 backends.example.com 服务=_http._tcp resolve;
}

服务器 {
位置 / {
proxy_pass http://backends;
}
}

使用服务器指令的服务参数,我们指定我们希望解析的SRV记录的名称和协议。 在我们的例子中,它们分别是_http_tcp 。 除了服务参数和我们没有指定端口之外,它看起来与上一节中的配置示例相同。

根据本节中第一个nslookup命令返回的值,NGINX Plus 配置了三个后端服务器:

  • 10.0.0.10 – 主服务器,端口为 8090,权重为 2。
  • 10.0.0.11 – 主服务器,端口为 8091,权重为 1。
  • 10.0.0.12 – 端口为 8092、权重为 1 的备份服务器。

如果我们为 NGINX Plus 配置实时活动监控,我们可以在内置仪表板上看到这些后端:

实时活动监控仪表板显示了 NGINX Plus 如何根据其 DNS SRV 记录中分配给上游服务器的权重来分配请求,可用于在以 NGINX 为负载均衡器的微服务架构中监控 NGINX

请注意请求是如何根据指定的权重分配的。 10.0.0.11:8091 服务器(权重为 1)获得三分之一的请求,而 10.0.0.10:8090 服务器(权重为 2)获得三分之二的请求。 作为备用服务器,除非其他两台服务器发生故障,否则 10.0.0.12:8092 服务器不会收到任何请求。

注意事项

当使用 DNS 通过 NGINX Plus 进行服务发现时,需要注意以下几点:

  • DNS 服务器要么需要高可用性,要么具有备份服务器。 如果 DNS 服务器不可用,NGINX Plus 将停止获取更新。 它会保留配置中的现有后端(除非您重新启动它或重新加载配置),而忽略相应记录的 TTL 值。
  • 您可以使用resolver指令指定多个名称服务器,这样如果其中一个服务器关闭,NGINX Plus 就会尝试其他服务器。
  • 正如介绍中所提到的,使用 NGINX Plus 进行服务发现的 DNS 的替代方案是NGINX Plus API ,它使您能够发出简单的 HTTP 请求来添加或删除上游组中的服务器。

示例

如果您想深入了解完整的示例,请查看这些关于将 NGINX 和 NGINX Plus 与使用 DNS 的服务发现平台集成的博客文章:

我们将在未来撰写更多有关新的集成选项的文章来更新此列表。

结论

NGINX Plus 中完全支持通过 DNS 进行服务发现,它提供了一种在微服务环境中更新负载均衡器配置的简单方法。 版本 9 及更高版本对SRV记录的支持使 NGINX Plus 更加强大,因为它让 NGINX Plus 不仅可以获取 IP 地址,还可以获取后端的端口号。

准备好尝试使用 NGINX Plus 的 DNS 进行服务发现及其其他增强功能了吗? 立即开始您的30 天免费试用联系我们讨论您的用例


“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”