您是一位现代平台操作 (Platform Ops) 或 DevOps 工程师。 您使用开源(也可能是一些商业)工具库为您的开发团队测试、部署和管理新的应用程序和容器。 您已选择 Kubernetes 在开发、测试、暂存和生产环境中运行这些容器和 pod。 您已经接受了微服务的架构和概念,并且在大多数情况下,它运行良好。 然而,您在这趟旅程中遇到了一些障碍。
例如,当您构建和推出新的集群、服务和应用时,如何轻松地将这些新资源集成或迁移到生产中而不丢失任何流量? 传统网络设备在对 DNS 记录、负载均衡器、防火墙和代理实施配置更改时需要重新加载或重新启动。 这些调整无法重新配置,否则会导致停机,因为需要“服务中断”或“维护窗口”来更新 DNS、负载均衡器和防火墙规则。 通常情况下,您必须提交可怕的服务单并等待另一个团队批准并进行更改。
维护窗口可能会让您的团队陷入困境,阻碍应用交付,并让您宣称“必须有更好的方法来管理流量!” 因此,让我们探索一个可以让您重回快车道的解决方案。
如果您有多个 Kubernetes 集群,最好同时将流量路由到两个集群。 更好的选择是执行 A/B、金丝雀或蓝绿流量分割并发送一小部分流量作为测试。 为此,您可以将 NGINX Plus 与ngx_http_split_clients_module
结合使用。
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 共享内存区域中的键值对象,可用于许多不同的数据存储用例。 这里我们用它来存储上面提到的分流比值。 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拆分客户端模块与动态键值存储结合使用可以提供以下用例:
以下是键值配置的示例:
# 定义键值存储、备份状态文件、超时并启用同步
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。
然后,该比例在 12:56:30 时变为 10:90。
然后在 13:00:00 时变为 90:10。
您可以在NGINX Loadbalancer for Kubernetes GitHub 存储库中找到 Prometheus 和 Grafana 的工作配置。
您可以使用 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 Loadbalancer for Kubernetes 的部署和运行:
nginx-ingress
的负载均衡器
笔记: 在此示例中,Kubernetes 工作节点为 10.1.1.8 和 10.1.1.10
随着 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 内容。”