博客 | NGINX

使用 NGINX Plus 实现动态 A/B Kubernetes 多集群负载平衡和安全控制

NGINX-F5-horiz-black-type-RGB 的一部分
Chris Akker 缩略图
克里斯·阿克
2024 年 2 月 15 日发布

您是一位现代平台操作 (Platform Ops) 或 DevOps 工程师。 您使用开源(也可能是一些商业)工具库为您的开发团队测试、部署和管理新的应用程序和容器。 您已选择 Kubernetes 在开发、测试、暂存和生产环境中运行这些容器和 pod。 您已经接受了微服务的架构和概念,并且在大多数情况下,它运行良好。 然而,您在这趟旅程中遇到了一些障碍。

例如,当您构建和推出新的集群、服务和应用时,如何轻松地将这些新资源集成或迁移到生产中而不丢失任何流量? 传统网络设备在对 DNS 记录、负载均衡器、防火墙和代理实施配置更改时需要重新加载或重新启动。 这些调整无法重新配置,否则会导致停机,因为需要“服务中断”或“维护窗口”来更新 DNS、负载均衡器和防火墙规则。 通常情况下,您必须提交可怕的服务单并等待另一个团队批准并进行更改。

维护窗口可能会让您的团队陷入困境,阻碍应用交付,并让您宣称“必须有更好的方法来管理流量!” 因此,让我们探索一个可以让您重回快车道的解决方案。

主动-主动多集群负载平衡

如果您有多个 Kubernetes 集群,最好同时将流量路由到两个集群。 更好的选择是执行 A/B、金丝雀或蓝绿流量分割并发送一小部分流量作为测试。 为此,您可以将 NGINX Plus 与ngx_http_split_clients_module结合使用。

K8s 与 NGINX Plus 图解

HTTP Split Clients 模块由 NGINX Open Source 编写,允许根据密钥分配请求的比例。 在此用例中,集群是 NGINX 的“上游”。因此,当客户端请求到达时,流量会在两个集群之间分配。 用于确定客户端请求的关键是任何可用的 NGINX 客户端$variable 。 也就是说,为了控制每个请求,请使用$request_id变量,这是 NGINX 为每个传入请求分配的唯一编号。

要配置分割率,请确定要分配给每个集群的百分比。 在这个例子中,我们使用K8s Cluster1作为生产的“大集群”,使用Cluster2作为预生产测试的“小集群”。 如果您有一个用于暂存的小型集群,则可以采用 90:10 的比例,并在小型集群上测试 10% 的流量,以确保在对大型集群推出新的更改之前一切正常。 如果这听起来风险太大,您可以将比例更改为 95:5。 说实话,您可以选择从 0 到 100% 之间的任何您想要的比例。

对于大多数实时生产流量,您可能希望两个集群的大小为 50:50 的比例。 但是您可以根据集群大小或其他详细信息轻松提供其他比率。 您可以轻松地将比例设置为 0:100(或 100:0)并升级、修补、修复甚至更换整个集群而无需停机。 让 NGINX split_clients将请求路由到实时集群,同时您解决另一个集群上的问题。

# Nginx 多集群负载平衡
# 集群 1:集群 2 比率的 HTTP 拆分客户端配置
# 提供 100、99、50、1、0% 比率(根据需要添加/更改)
# 基于
# https://www.nginx.com/blog/dynamic-a-b-testing-with-nginx-plus/
# Chris Akker – 2024 年 1 月
#

split_clients $request_id $split100 {
* cluster1-cafe; # 所有流量到 cluster1
} 

split_clients $request_id $split99 {
99% cluster1-cafe; # 99% cluster1, 1% cluster2
* cluster2-cafe;
} 

split_clients $request_id $split50 { 
50% cluster1-cafe; # 50% cluster1, 50% cluster2
* cluster2-cafe;
}

split_clients $request_id $split1 { 
1.0% cluster1-cafe; # 1% 到 cluster1, 99% 到 cluster2
* cluster2-cafe;
}

split_clients $request_id $split0 { 
* cluster2-cafe; # 所有流量到 cluster2
}

# 根据比例选择哪个集群上游

map $split_level $upstream { 
100 $split100; 
99 $split99; 
50 $split50; 
1.0 $split1; 
0 $split0;
default $split50;
}

您可以添加或编辑上述配置以匹配您需要的比例(例如,90:10、80:20、60:40 等等)。

笔记: NGINX 还具有用于流上下文中的 TCP 连接的拆分客户端模块,可用于非 HTTP 流量。 这将根据新的 TCP 连接而不是 HTTP 请求来分割流量。

NGINX Plus 键值存储

您可以使用的下一个功能是 NGINX Plus键值存储。 这是 NGINX 共享内存区域中的键值对象,可用于许多不同的数据存储用例。 这里我们用它来存储上面提到的分流比值。 NGINX Plus 允许您更改任何键值记录而无需重新加载 NGINX。这使您可以使用 API 调用更改此拆分值,从而创建动态拆分函数。

根据我们的示例,它看起来像这样:

{“cafe.example.com”:90}

该 KeyVal 记录内容如下:
关键是“cafe.example.com”主机名
分流比的值为“90”

您不需要在 NGINX 配置文件中对分割率进行硬编码,而是可以使用键值内存。 这消除了更改 NGINX 中的静态分割值所需的 NGINX 重新加载。

在此示例中,NGINX 配置为使用 90:10 的分割比例,其中较大的Cluster1占 90%,较小的Cluster2占剩余的 10%。 因为这是一个键值记录,所以您可以使用 NGINX Plus API动态更改此比率,而无需重新加载配置! 一旦您在下一个请求中更改此新的比例值,拆分客户端模块就会使用它。

创建 KV 记录,从 50/50 的比例开始:

通过向 NGINX Plus 发送 API 命令,向 KeyValue 存储添加新记录:

curl -iX POST -d '{"cafe.example.com":50}' http://nginxlb:9000/api/8/http/keyvals/split

更改KV记录,更改为90/10比例:

将 KeyVal 分割率更改为 90,使用 HTTP PATCH 方法更新内存中的 KeyVal 记录:

curl -iX PATCH -d '{"cafe.example.com":90}' http://nginxlb:9000/api/8/http/keyvals/split

接下来,预生产测试团队验证新的应用代码是否准备就绪,将其部署到大型Cluster1 ,并将比例更改为 100%。 这会立即将所有流量发送到Cluster1 ,并且您的新应用将“上线”,不会出现任何流量中断、服务中断、维护时段、重新启动、重新加载或大量票证。 您只需调用一次 API 即可在您选择的时间更改此分割比。

当然,从 90% 移动到 100% 如此容易意味着您可以轻松地将比例从 100:0 更改为 50:50(甚至 0:100)。 因此,您可以拥有热备份集群,或者可以使用新资源水平扩展集群。 在全速运行的情况下,您甚至可以使用最新的软件、硬件和软件补丁完全构建一个新集群 - 部署应用并在一段时间内迁移流量而不会丢失任何连接!

用例

将 HTTP拆分客户端模块与动态键值存储结合使用可以提供以下用例:

  • 主动-主动负载均衡- 用于对多个集群进行负载均衡。
  • 主动-被动负载均衡– 用于对主、备份和 DR 集群和应用进行负载均衡。
  • A/B、蓝绿和金丝雀测试——与新的 Kubernetes应用一起使用。
  • 水平集群扩展——在您准备就绪时添加更多集群资源并更改比率。
  • 无中断集群升级– 能够在升级、修补或修复另一个集群时使用一个集群。
  • 即时故障转移——如果一个集群出现严重问题,您可以更改比例以使用其他集群。

配置示例

以下是键值配置的示例:

# 定义键值存储、备份状态文件、超时并启用同步 
keyval_zone zone=split:1m state=/var/lib/nginx/state/split.keyval timeout=365d sync;

keyval $host $split_level zone=split;

这是 cafe.example.com应用配置的示例:

# 为 cafe.example.com 定义服务器和位置块,使用 TLS 服务器 { listen 443 ssl; server_name cafe.example.com; status_zone https://cafe.example.com; ssl_certificate /etc/ssl/nginx/cafe.example.com.crt; ssl_certificate_key /etc/ssl/nginx/cafe.example.com.key; location / { status_zone /; proxy_set_header Host $host; proxy_http_version 1.1; proxy_set_header "Connection" ""; proxy_pass https://$upstream; # 流量拆分到上游块 } # 定义 2 个上游块 – 每个集群一个 # 由 NLK 动态管理的服务器,状态文件备份 # Cluster1 上游 upper cluster1-cafe { zone cluster1-cafe 256k; least_time last_byte; keepalive 16; #NLK 控制器管理的服务器状态 /var/lib/nginx/state/cluster1-cafe.state; } # Cluster2 上游 upper cluster2-cafe { zone cluster2-cafe 256k; least_time last_byte; keepalive 16; #NLK 控制器管理的服务器状态 /var/lib/nginx/state/cluster2-cafe.state; }

上游服务器 IP:ports 由NGINX Loadbalancer for Kubernetes管理,这是一个新的控制器,也使用 NGINX Plus API 来动态配置 NGINX Plus。 详细信息请参阅下一节

让我们使用流行的监控和可视化工具Grafana来查看随时间推移的 HTTP 拆分流量。 您使用NGINX Prometheus Exporter (基于njs )导出所有 NGINX Plus 指标,然后由 Grafana 收集并绘制图表。 有关配置 Prometheus 和 Grafana 的详细信息可以在这里找到。

图中共有四个上游服务器: 两个用于Cluster1 ,两个用于Cluster2 。 我们使用 HTTP 负载生成工具来创建 HTTP 请求并将其发送到 NGINX Plus。

在下面的三个图表中,您可以看到图表开始时的分流比是 50:50。

LB 上游请求图

然后,该比例在 12:56:30 时变为 10:90。

LB 上游请求图

然后在 13:00:00 时变为 90:10。

LB 上游请求图

您可以在NGINX Loadbalancer for Kubernetes GitHub 存储库中找到 Prometheus 和 Grafana 的工作配置。

动态 HTTP 上游: 适用于 Kubernetes 的 NGINX 负载均衡器

您可以使用 NGINX Plus API 和NGINX Loadbalancer for Kubernetes控制器将静态 NGINX Upstream 配置更改为动态集群上游。 这个免费项目是一个Kubernetes 控制器,它监视NGINX Ingress Controller并自动更新为 TCP/HTTP 负载均衡配置的外部NGINX Plus实例。 它的设计非常简单,安装和操作都很简单。 有了这个解决方案,您可以在 Kubernetes 环境中实现 TCP/HTTP 负载均衡,确保立即检测到新的应用和服务并可用于流量 - 无需重新加载。

架构与流程

Kubernetes 的 NGINX 负载均衡器位于 Kubernetes 集群内部。 它在 Kubernetes 中注册以监视 NGINX Ingress Controller ( nginx-ingress ) 服务。 当 Ingress 控制器发生变化时,Kubernetes 的 NGINX Loadbalancer 会收集 Worker Ips 和 NodePort TCP 端口号,然后通过NGINX Plus API将 IP:ports 发送到 NGINX Plus。

NGINX 上游服务器无需重新加载即可更新,NGINX Plus 会将流量负载平衡到正确的上游服务器和 Kubernetes NodePort。 可以添加额外的 NGINX Plus 实例来实现高可用性

NGINX 负载均衡器运行图

Kubernetes 上运行的 NGINX 负载均衡器快照

下面的屏幕截图中有两个窗口演示了 NGINX Loadbalancer for Kubernetes 的部署和运行:

  1. 服务类型nginx-ingress负载均衡器
  2. 外部 IP – 连接到 NGINX Plus 服务器
  3. 端口- NodePort 映射到 443:30158 并匹配 NGINX 上游服务器(如 NGINX Plus实时仪表板所示)
  4. 日志– 表明 Kubernetes 的 NGINX 负载均衡器已成功将数据发送到 NGINX Plus

NGINX Plus 窗口

笔记: 在此示例中,Kubernetes 工作节点为 10.1.1.8 和 10.1.1.10

添加 NGINX Plus 安全功能

随着 Kubernetes 中运行的越来越多的应用暴露在开放的互联网中,安全性变得必不可少。 幸运的是,NGINX Plus 具有企业级安全功能,可用于创建分层的纵深防御架构。

在您的集群前面使用 NGINX Plus 并执行split_clients功能,为什么不利用该功能并添加一些有益的安全功能呢? 以下是一些可用于增强安全性的 NGINX Plus 功能,以及可用于配置、测试和部署它们的其他文档的链接和参考。

立即开始

如果您对 Kubernetes 集群边缘的网络挑战感到沮丧,请考虑尝试此 NGINX 多集群解决方案。 试用 NGINX Loadbalancer for Kubernetes 软件并告诉我们您的想法。 源代码是开源的(根据 Apache 2.0 许可),所有安装说明均可在 GitHub 上找到

如需提供反馈,请在 repo 中给我们留言或在NGINX 社区 Slack中给我们留言。


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