点赞
评论
收藏
分享
举报
启用声明式 DNS 只需一个 POST
发表于2024-12-10 17:52

浏览 3k

文章标签

原文作者:Eric Chen - F5 云解决方案架构师
原文来源:启用声明式 DNS 只需一个 POST
转载来源:NGINX 中文官网


NGINX 唯一中文官方社区 ,尽在 nginx.org.cn

   


 

在 1990 年的电影《猎杀红色十月号》中,由 Sean Connery 饰演的苏联新型核潜艇舰长 Marko Ramius 打算指挥潜艇叛逃到美国。由年轻的 Alec Baldwin 饰演的中央情报局 (CIA) 分析师 Jack Ryan 凭直觉判断出了 Ramius 的动机,他必须说服美国海军相信他的推断,以防止超级大国之间爆发暴力冲突。为了证明自己的判断,Ryan 首先需要与 Ramius 对话。随着他花费过多的时间寻找 Ramius,悬念也在不断累积。


从表面上看,Ryan 的搜索如同浏览器客户端尝试在互联网上查找一个网站,只不过这些网站在域名系统 (DNS) 中注册了其位置,因此客户端可以不费吹灰之力就找到它们。如果 Ramius 公布了他的位置,这部电影就不会那么惊心动魄了,但在我们的应用上,我们还是希望能够快速、轻松地解决问题。


在本文中,我们使用了 F5 的两项 DNS 技术。借助 BIG-IP DNS,我们通过将私有地址(最初在 RFC 1918 中定义)的 DNS 记录发布到内部客户端,为它们提供一条优化路径以访问数据中心托管的服务。然后通过 DNS 负载均衡器云服务,我们可以为外部客户端提供基于云的 DNS 服务。


本文的标题灵感源自这部电影中的另一情节。一旦找到 Ramius,Ryan 就会发送一条信息,而 Ramius 则会在收到消息后发出单个 ping 作为回应。在我们的设置中,只需通过 API 发送一条 HTTP POST 消息,便可更新 DNS 记录。我们使用 NGINX Plus 和 NGINX JavaScript 模块来实现这一点。



多个名称,一个 IP 地址


我们的示例解决了跨多个数据中心的平台即服务 (PaaS) 部署的常见问题。每个位置的 DNS 记录中公布的单个 IP 地址背后通常部署了许多服务。通配符 DNS 条目的问题是,您会丢失有关每项服务的位置及其是否健康的详细信息。


在我们的示例中,我们使用 NGINX Plus 主动健康检查来跟踪多个位置的应用程序运行的健康状况,而无需重复执行监控任务,并随着应用程序的启用和下线时更新内部和外部 DNS 记录。

 

我们如何使用 F5 和 NGINX 技术


我们的示例同时利用了 F5 和 NGINX 软件:

  • F5 BIG-IP DNS — BIG-IP 不仅支持传统的负载均衡,而且还能够实现全局服务器负载均衡 (GSLB)。它既可作为硬件或虚拟设备部署在本地,也可作为虚拟设备部署至云环境中。
  • F5 DNS 负载均衡器云服务 — DNS 负载均衡器以云托管 SaaS 服务的形式提供 GSLB,内置 DDoS 防护和 API 优先方法。

BIG-IP DNS 和 DNS 负载均衡器都有一个用于更新 DNS 记录的声明式 API。这样,只需通过单个 POST API 即可执行更新。

  • NGINX Plus — 我们即将用到多项 NGINX Plus 功能:
    • 主动健康检查,用于监控上游服务器(我们的应用)的状态。
    • NGINX Plus API,用于更新记录应用状态的键值存储。
    • NGINX Plus 区域同步,用于在多个 NGINX 实例之间同步键值存储(类似于 memcache 或 Redis 等分布式数据库)。
  • NGINX JavaScript 模块 — NGINX JavaScript (njs) 支持我们向内部 NGINX Plus API 发出子请求、解析 JSON 响应、更新内部 NGINX 变量,并将非原生函数纳入 NGINX Plus 流量处理序列中。


在详细介绍示例解决方案的工作原理之前,我们先来简要了解一下这些技术如何协同工作:

  1. 我们使用 NGINX Plus 主动健康检查来获取在多个数据中心运行的后端应用的状态。
  2. 接下来,我们使用 njs 函数汇总健康信息和更新键值存储。因为我们启用了 NGINX Plus 区域同步,所以键值存储会在所有 NGINX Plus 实例之间自动同步。
  3. 我们向 NGINX Plus 发出经过身份验证的请求,该请求调用 njs 函数更新 DNS 记录。


有关如何配置 NGINX Plus 并处理应用程序运行状况的详细信息,请查看下文“收集、存储并更新应用程序运行状况信息”一节。有关如何将信息传递给 DNS 服务器的详细信息,请查看下文“更新 DNS 记录”一节。


(请注意,本文既不涉及 NGINX Plus 配置中的所有 location 指令,也不会对所有相关 njs 函数进行深入探讨。)

[编者按——本文是探讨 NGINX JavaScript 模块用例的系列文章之一。查看完整列表,请参阅《NGINX JavaScript 模块的用例》。]

 

收集、存储并更新应用程序运行状况信息


在我们的示例拓扑中,有两个数据中心,即 dc1 和 dc2 — 该解决方案可轻松推广到许多部署类型(混合云、多云、多个可用区、多个 Kubernetes 集群或单个位置或设备)。

在每个数据中心,NGINX Plus 实例对四个应用(app001 到 app004)的自定义组合进行负载均衡。为了存储每个应用的上游服务器的健康状态,我们配置了一个名为 pools 的键值存储。以下 keyval 指令(来自 dc1 的 NGINX Plus 配置文件)将 NGINX Plus 实例的 IP 地址 10.1.20.54 映射到 $pool 变量,该变量存储数据中心内应用的健康状态信息。(在 dc2 的配置中,NGINX Plus 实例的 IP 地址为 10.1.20.55。)

keyval_zone zone=pools:32k state=pools.keyval sync timeout=300; 
keyval "10.1.20.54" $pool zone=pools;


为了填充 $pool 变量,我们调用了 UpdatePools njs 函数。该函数使用 NGINX Plus API 检查每个应用的上游服务器的健康状况。在伪代码中,向 NGINX Plus API 发出的子请求如下所示:

r.subrequest('/api/5/http/upstreams' ...


对该输出进行处理后,会生成一组键值对,其中包括被视为健康应用的应用名称和上游服务器的数量。下面是两个应用的示例输出,表示每个应用都有三台健康的服务器:

{"app001":3,"app002":3}


我们调用 JavaScript JSON.stringify 函数将该输出转换为 JSON,伪代码如下:

r.variables.pool = JSON.stringify(output);


我们使用 NGINX Plus 区域同步模块在两个数据中心之间同步 pool 键值存储的内容(示例配置文件中未显示)。此示例显示了两个数据中心内 app001 到 app003 的健康服务器数量:

{ 
  "10.1.20.54": "{\"app001\":3,\"app002\":3}", 
  "10.1.20.55": "{\"app001\":2,\"app003\":4}" 
}


我们使用 health_check 指令每 30 秒调用一次 njs 函数,以更新本地实例上键值存储中的运行状况信息。

location /poll { 
    internal; 
    proxy_pass http://127.0.0.1/pools/update; 
    health_check uri=/pools/update interval=30; 
}


我们的 Summarize njs 函数按应用(而非数据中心)对健康信息进行分组;要显示其输出结果,我们需要向 /pools URI 发出请求。在下面的示例输出结果中,app001 在两个数据中心内都运行正常,app002 仅在 dc1 中运行,app003 仅在 dc2 中运行,app004 部署在两个数据中心内,但仅在 dc2 中运行正常(dc1 中健康服务器的数量为 0)。

$ curl localhost:8245/pools
{"app001.f5demo.com":{"dc1":[{"10.1.20.54":3}], 
                      "dc2":[{"10.1.20.55":2}]}, 
 "app002.f5demo.com":{"dc1":[{"10.1.20.54":3}]}, 
 "app003.f5demo.com":{"dc2":[{"10.1.20.55":4}]},
 "app004.f5demo.com":{"dc1":[{"10.1.20.54":0}], 
                      "dc2":[{"10.1.20.55":3}]}}


下面是当前应用健康状态的图示。


 

更新 DNS 记录


我们更新 BIG-IP DNS 和 DNS 负载均衡器中的记录,以反映我们后端应用的健康状况;如果某个应用在其中一个数据中心内不可用,(例如上面示例中 dc1 中的 app004),我们会将该应用的客户端转移到另一个数据中心。BIG-IP DNS 和 DNS 负载均衡器使用不同的模板和数据表示,因此要更新两个系统中的 DNS 记录,我们需要将 njs 子请求定向到不同的 URL,并调用不同的函数。


更新 BIG-IP DNS 记录

BIG-IP 设备的配置可按照特定模式,以 F5 Application Service 3 Extension (AS3) 格式的单个 JSON 文档表示。借助 njs,我们可以构建想要部署的服务模板。

var template = { 
  "class": "ADC", 
  "schemaVersion": "3.7.0", 
  "id": "NGINXPLUS",


我们使用每个应用的池成员 pool members(在 BIG-IP 中,相当于 NGINX Plus 上游组 upstream group)信息更新模板,如本例中的 app001 所示:

"app001_domain": { 
     "class": "GSLB_Domain", 
      "domainName": "app001.f5demo.com", 
      "pools": [ { "use": "dc1_app001_pool" }, 
                   { "use": "dc2_app001_pool"} ], 
      "resourceRecordType": "A" 
},


在 NGINX Plus 配置中,我们为 BIG-IP DNS 服务器创建一个名为 bigip 的上游组 upstream group,并让 NGINX Plus 将请求从 /mgmt/shared/appsvcs/declare location 转发到 bigip:

upstream bigip { 
    server 10.1.1.5:443; 
} 
 
location /mgmt/shared/appsvcs/declare { 
    internal; 
    proxy_pass https://bigip; 
}


我们的 generateAS3Dns njs 函数包含一个子请求,该子请求通过发送 POST 请求携带使用前面构建的部署服务模板的字符串化 JSON payload 信息,为我们的应用配置 BIG-IP DNS 和 DNS 记录。下面是子请求的伪代码:

r.subrequest('/mgmt/shared/appsvcs/declare', 
             { method: 'POST', body: JSON.stringify(template) },


我们通过向 /pools/push/dns 发出请求来调用 generateAS3Dns 函数。在本例中,我们使用 curl 命令的 -u 参数,以管理员用户身份在 BIG-IP DNS 服务器上进行身份验证。因为我们使用的是子请求,所以当我们连接到 BIG-IP DNS 服务器时,NGINX Plus 会转发我们的凭证。或者,我们也可以将凭证存储在 njs 文件中。

$ curl localhost:8245/pools/push/dns -u admin:admin_password


更新 DNS 负载均衡器记录

DNS 负载均衡器记录更新方法类似于 BIG-IP DNS 记录更新方法,但用于生成 DNS 负载均衡器 API 所需格式的模板不同:

"load_balanced_records": { 
      "app001": { 
        ... 
        "proximity_rules": [ 
            { ... "pool": "pools_dc1_app001" ...}, 
            { ... "pool": "pools_dc1_app001" ...}, 
             
        ], 
          ...


在 NGINX Plus 配置中,我们为 DNS 负载均衡器 API 创建一个名为 cloud 的上游组 upstream group,并让 NGINX Plus 将请求从 /v1/svc-subscription/subscriptions location 转发到 cloud。

upstream cloud { 
    server api.cloudservices.f5.com:443; 
} 
#... 
location /v1/svc-subscription/subscriptions { 
    internal; 
    proxy_pass https://cloud; 
}


我们的 generateCloudDns njs 函数包含一个子请求,该子请求通过发送 PUT 请求携带使用部署服务模板的字符串化 JSON payload 信息,为我们的应用配置 DNS 负载均衡器和 DNS 记录。下面是子请求的伪代码(URL 中的最后一个元素 s-aabbcc1234 是 DNS 负载均衡器订阅 ID):

r.subrequest(' /svc-subscription/subscriptions/s-aabbcc1234, 
             { method: 'PUT', body: JSON.stringify(template) },


我们通过向 /pools/push/cloud-dns 发出请求来调用 generateCloudDns 函数。

$ curl localhost:8245/pools/push/cloud_dns?account_id=... -H "Authorization: ..."

 

在 BIG-IP DNS GUI 中跟踪应用健康状况


虽然使用了 NGINX Plus 和 njs 子请求创建并更新 BIG-IP DNS 记录,但我们仍可使用 BIG-IP DNS GUI 来验证应用的健康状况。此截图显示,app004 在 dc1 中运行不正常,在 dc2 中运行正常(在 Status(状态)列中分别用黑色菱形和绿色圆圈表示)。因此,BIG-IP DNS 在响应 app004 的位置请求时仅包含 dc2 的地址。



此截图显示了如何在私有 (10/8) 地址空间中查找 BIG-IP DNS 记录。


 

在 DNS Load Balancer GUI 中跟踪应用健康状况


与 BIG-IP DNS 一样,尽管我们使用了 NGINX Plus 和 njs 子请求创建并更新 DNS 记录,但我们仍可使用 DNS 负载均衡器 GUI 来验证应用的健康状况。此截图显示,app004 在 dc1 中运行不正常,在 dc2 中运行正常(在 Status 列中分别用 Disabled(禁用)和 Enabled(启用)表示)。

下面的截图显示了如何使用 DNS 负载均衡器记录(与 BIG-IP DNS 记录不同)查找公共 IP 地址(我们只显示了前四条记录)。

   

结语

回顾一下,我们使用 NGINX Plus 进行了以下操作:

  • 对上游应用执行主动健康检查
  • 将健康信息存储至键值存储中
  • 在多个 NGINX 实例之间同步键值存储


我们利用 njs 进行了以下操作:

  • 以每项 DNS 技术所需的格式汇总上游应用的状态
  • 对 DNS 服务进行模板化处理
  • 将 DNS 服务推送到相应的 API 端点


其结果可能不像《猎杀红色十月号》的结局那样史诗般宏大,但对任何运营网站的人员来说都更有价值。

 


NGINX 唯一中文官方社区 ,尽在 nginx.org.cn

更多 NGINX 相关的技术干货、互动问答、系列课程、活动资源: 开源社区官网 | 微信公众号 | B 站


已修改于2024-12-10 18:02
本作品系原创
创作不易,留下一份鼓励
NGINX官方账号

暂无个人介绍

关注



写下您的评论
发表评论
全部评论(0)

按点赞数排序

按时间排序

关于作者
NGINX官方账号
这家伙很懒还未留下介绍~
331
文章
21
问答
201
粉丝
相关文章
介绍nginx网页配置工具QQ技术交流群1:1106758598QQ技术交流群2:560797506邮箱: cym1102@qq.com官网地址: http://www.nginxwebui.cn码云: https://gitee.com/cym1102/nginxWebUIgithub: https://github.com/cym1102/nginxWebUI功能特点nginxWebUI也可管理多个nginx服务器集群,随时一键切换到对应服务器上进行nginx配置,也可以一键将某台服务器配置同步到其他服务器,方便集群管理.部署此项目后,配置nginx再也不用上网各种搜索配置代码,再也不用手动申请和配置ssl证书,只需要在本项目中进行增删改查就可方便的配置和启动nginx。技术说明本项目是基于springBoot的web系统,数据库使用sqlite,因此服务器上不需要安装任何数据库项目启动时会释放一个.sqlite.db到系统用户文件夹中,注意进行备份本系统通过Let'sencrypt申请证书,使用acme.sh脚本
点赞 6
浏览 23.4k
  前三周学习了陶辉老师的“NGINX基础培训系列课程”,感觉受益良多,在这里想把一些知识点记录一下,和大家分享一下知识点,也方便日后的随手查看,温故知新。  首先,我们了解到了Nginx的版本,Nginx发布版本分为主线版本和稳定版本,区分两个版本也非常简单,主线版本版本号为单数,比如1.19,稳定版本为双数,比如1.18,今天我要说的是稳定版本,这个版本会尽量少的减少Nginx的bug问题,适用于生产环境,这里我不建议使用Nginx和其他软件一样在生产环境中落后一个或多个大版本使用,之前生产环境做过漏扫,发现我们编译自带的Nginx版本为:nginx/1.13.3(查询命令为nginx-V),结果出现了多个漏洞,四个高危和一个中危漏洞:        通过升级Nginx到稳定版最新版本后修复!  其次,是Nginx发行版本的选择,目前比较流行的有:nginx、nginxplus、Tengine、openresty、ope
点赞 1
浏览 16.8k
感谢您参加“NGINX从入门到精通进阶系列培训”!以下为培训的问答、课件和录像,希望您能通过此培训学有所得,祝学习进步!>问与答:- 基础篇+高级篇 - 应用篇+实战篇(New)>课件(PPT):基础篇:-NGINX概要、安装、配置:https://interact.f5.com/rs/653-SMC-783/images/CNFEB22-NginxCoreCourse-Setup.pdf-NGINX日志、运维:https://interact.f5.com/rs/653-SMC-783/images/cnfeb22-nginxcorecourse-maintenance.pdf高级篇:-NGINX变量、API:https://interact.f5.com/rs/653-SMC-783/images/CNFEB22-NginxCoreCourse-API.pdf-NGINXSSL、NJS:https://interact.f5.com/rs/653-SMC-783/images/CNFEB22-NginxCoreCourse-SSL.pdf
点赞 10
浏览 19.3k