您是一名现代平台运维或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 Multi Cluster Load Balancing
# HTTP Split Clients Configuration for Cluster1:Cluster2 ratios
# Provide 100, 99, 50, 1, 0% ratios (add/change as needed)
# Based on
# https://www.nginx.com/blog/dynamic-a-b-testing-with-nginx-plus/
# Chris Akker – Jan 2024
#
split_clients $request_id $split100 {
* cluster1-cafe; # All traffic to 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% to cluster1, 99% to cluster2
* cluster2-cafe;
}
split_clients $request_id $split0 {
* cluster2-cafe; # All traffic to cluster2
}
# Choose which cluster upstream based on the ratio
map $split_level $upstream {
100 $split100;
99 $split99;
50 $split50;
1.0 $split1;
0 $split0;
default $split50;
}可以添加或编辑上述配置,以匹配所需的流量分配比例(例如90:10、80:20、60:40等)。
注意:NGINX还提供一个用于stream上下文中TCP连接的Split Clients module,可用于非HTTP流量。该模块根据新建的TCP连接(而非HTTP请求)拆分流量。
NGINX Plus键值存储
接下来可以使用的功能是NGINX Plus的键值存储。这是NGINX共享内存区中的键值对象,可用于多种不同的数据存储场景。在此,我们用它存储上一节提到的拆分比例值。无需重新加载NGINX,即可通过NGINX Plus更改任意键值记录。因此,可以通过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 Split Clients模块与动态键值存储结合使用,可实现以下用例:
- 双活负载均衡,用于在多个集群之间进行负载均衡。
- 主动-被动负载均衡,用于在主集群、备份集群、灾难恢复集群及应用之间进行负载均衡。
- A/B、蓝绿和金丝雀测试,用于新的Kubernetes应用。
- 集群横向扩展,可增加集群资源,并在准备就绪后调整比例。
- 无中断集群升级,可在升级、修补或修复一个集群时继续使用另一个集群。
- 即时故障转移:如果一个集群出现严重问题,可以调整流量比例,改用另一个集群。
配置示例
以下是键值配置示例:
# Define Key Value store, backup state file, timeout, and enable sync
keyval_zone zone=split:1m state=/var/lib/nginx/state/split.keyval timeout=365d sync;
keyval $host $split_level zone=split;以下是cafe.example.com应用配置的示例:
# Define server and location blocks for cafe.example.com, with TLS
server {
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; # traffic split to upstream blocks
}
# Define 2 upstream blocks – one for each cluster
# Servers managed dynamically by NLK, state file backup
# Cluster1 upstreams
upstream cluster1-cafe {
zone cluster1-cafe 256k;
least_time last_byte;
keepalive 16;
#servers managed by NLK Controller
state /var/lib/nginx/state/cluster1-cafe.state;
}
# Cluster2 upstreams
upstream cluster2-cafe {
zone cluster2-cafe 256k;
least_time last_byte;
keepalive 16;
#servers managed by NLK Controller
state /var/lib/nginx/state/cluster2-cafe.state;
}上游服务器的IP地址和端口由NGINX Loadbalancer for Kubernetes管理。这款新控制器还使用NGINX Plus API动态配置NGINX Plus。详情请参阅下一节。
下面使用Grafana这一常用的监控和可视化工具,查看HTTP拆分流量随时间的变化。使用NGINX Prometheus Exporter(基于njs)导出所有NGINX Plus指标,然后由Grafana收集这些指标并绘制成图表。有关Prometheus和Grafana的配置详情,请参阅此处。
图中有4台上游服务器:2台用于Cluster1,2台用于Cluster2。我们使用HTTP负载生成工具创建HTTP请求,并将其发送到NGINX Plus。
在下面三张图的起始部分,可以看到流量分配比例为50:50。

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

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

可在NGINX Loadbalancer for Kubernetes GitHub存储库中找到Prometheus和Grafana的可用配置。
动态HTTP上游:NGINX Loadbalancer for Kubernetes
可以使用NGINX Plus API和NGINX Loadbalancer for Kubernetes控制器,将静态NGINX上游配置更改为动态集群上游。这个免费项目是一个Kubernetes控制器,可监视NGINX Ingress Controller并自动更新已配置TCP/HTTP负载均衡的外部NGINX Plus实例。其设计非常直观,安装和操作也很简单。借助此解决方案,可以在Kubernetes环境中实现TCP/HTTP负载均衡,确保系统立即检测到新的应用和服务并将其用于流量处理,无需重新加载。
架构与流程
NGINX Loadbalancer for Kubernetes位于Kubernetes集群内。它已在Kubernetes中注册,用于监视NGINX Ingress Controller(nginx-ingress)服务。当Ingress控制器发生变化时,NGINX Loadbalancer for Kubernetes会收集工作节点IP和NodePort TCP端口号,然后通过NGINX Plus API将IP:端口发送到NGINX Plus。
无需重新加载即可更新NGINX上游服务器,NGINX Plus会将流量负载均衡到正确的上游服务器和Kubernetes NodePort。还可添加更多NGINX Plus实例,以实现高可用性。
NGINX Loadbalancer for Kubernetes 实际运行概览
以下屏幕截图中的两个窗口展示了NGINX Loadbalancer for Kubernetes部署并运行后的情况:
- 服务类型:
LoadBalancer,用于nginx-ingress - 外部IP,连接到NGINX Plus服务器
- 端口:NodePort映射到443:30158,并与NGINX上游服务器相匹配(如NGINX Plus实时仪表板所示)
- 日志,表示NGINX Loadbalancer for Kubernetes正在成功向NGINX Plus发送数据

注意:在此示例中,Kubernetes工作节点为10.1.1.8和10.1.1.10
添加NGINX Plus安全功能
随着越来越多在Kubernetes中运行的应用暴露于开放互联网,安全防护变得必不可少。NGINX Plus提供企业级安全功能,可用于构建分层的纵深防御架构。
NGINX Plus已部署在集群前端并执行split_clients函数,不妨利用这一部署位置添加一些有助于提升安全性的功能。以下列出了几项可用于增强安全性的NGINX Plus功能,并提供了其他文档的链接和参考资料,以便配置、测试和部署这些功能。
- IP 阻止/允许列表,根据源 IP 地址控制访问。有关如何通过 Plus API 使用 NGINX Plus 键值存储实现动态 IP 阻止/允许列表的配置指南,请参阅 NGINX 文档中的“动态拒绝 IP 地址”页面。
- 速率限制:控制应用、API端点和媒体下载的TCP连接数、HTTP请求数及带宽使用量。有关使用NGINX进行速率限制的更多信息,请参阅NGINX文档中的限制对代理HTTP资源的访问,以及以下博客文章:使用NGINX和NGINX Plus进行速率限制和使用NGINX Plus键值存储动态限制带宽。
- GeoIP2动态模块:根据源IP地址收集位置元数据。有关详细信息,请参阅NGINX文档中的“按地理位置限制访问”页面。
- JWT和OpenID Connect(OIDC)模块,使用行业标准协议控制用户访问。有关详细信息,请参阅NGINX文档中的“设置JWT身份验证”页面。
- NGINX App Protect,一款轻量级、低延迟的Web应用防火墙,可抵御现有及不断演变的威胁。
立即开始
如果Kubernetes集群边缘的网络问题令您困扰,不妨试用这款NGINX多集群解决方案。欢迎试用NGINX Loadbalancer for Kubernetes软件,并告诉我们您的使用感受。源代码已根据Apache 2.0许可证开源,所有安装说明均可在GitHub上获取。
如需提供反馈,请在代码仓库中留言,或通过NGINX Community Slack向我们发送消息。
相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。
