NLB与ALB类型的目标群组结合,为应用提供固定IP

背景

应用程序负载均衡器(Application Load Balancer,以下简称ALB)是一个托管的七层代理,它可以根据请求(例如Host、Header、Path)进行流量路由,ALB的网络接口会根据请求量进行弹性伸缩,即ALB的IP是变化的。ALB最适合HTTP和HTTPS流量的负载均衡,面向交付包括微服务和容器在内的现代应用程序架构。

网络负载均衡器(Network Load Balancer,以下简称NLB)运行在四层上,对需要极高性能的传输控制协议 (TCP)、用户数据报协议 (UDP) 和传输层安全性 (TLS) 协议流量进行负载均衡。NLB可以提供PrivateLink和可用区级别静态IP,同时可以对源IP进行保留。

在一些场景下,我们需要固定对外服务的IP。

这时就需要将ALB与NLB结合起来,AWS在此之前提供了一个ALB、NLB、Lambda结合的方式,来完成这个过程,具体可以参考

https://aws.amazon.com/cn/blogs/networking-and-content-delivery/using-aws-lambda-to-enable-static-ip-addresses-for-application-load-balancers/

简单描述是,使用Lambda定期解析ALB的IP,然后将ALB的IP注册到NLB的目标群组上。

博客提供了一种内部ALB集成的方法,但是也存在以下几个问题:

1. 内部ALB可以通过定期域名解析的方式拿到ALB的所有内网IP,但是当ALB是面向互联网时,ALB的内网IP是无法使用域名解析的方式来获得,需要通过Lambda结合EC2的API拿到ALB的全部网络接口,然后才能拿到网络接口的内网IP,这样既增加了复杂度,又需要增加相应的IAM权限来进行AWS API的调用;

2. 使用IP注册到NLB,目标群组的类型必须是IP类型,这将导致NLB的源IP保留的特性失效,如果在这个架构中需要保留源IP,便需要开启代理协议,否则后端只能看到NLB的内网IP,而且也只会将这个内网IP在ALB处理后加入XFF头部,如果NLB面向的是最终用户,则最终用户的IP实际上就丢失了。

AWS在2021年9月27日发布了一种新的目标群组类型——ALB类型的目标群组,目标群组可以是内部ALB或者面向互联网的ALB,NLB将流量转发到ALB类型的目标群组,以获得:

1. 通过NLB固定对外服务的IP,并且获得源IP保留的能力

2. 获得ALB的高级请求流量路由的能力

具体可以参考

https://aws.amazon.com/cn/blogs/networking-and-content-delivery/application-load-balancer-type-target-group-for-network-load-balancer/

本文简化一种场景,即,原有ALB对外服务,在一些客户端一些场景下需要使用固定的IP,通过使用ALB类型的目标群组改造,来完成这个目标。

架构

上图是一个典型的应用架构(略去了数据库层),ALB置放于公有子网,ALB将流量路由到私有子网的应用服务器上。

这个结构中客户端IP通过XFF的头的方式传递,ALB在流量变化是会伸缩,ALB的IP也会随之变化。

验证

1. 单ALB场景

Applications上安装了Nginx,并且提供了以下location配置

location /{
	default_type text/plain;
	return 200 "remote_addr is $remote_addr\nx_forwarded_for is $http_x_forwarded_for";
}

客户端访问ALB时,会将请求IP和XFF头中的IP都打印出来,在以上架构中,响应往往是这样的:

$ curl http://applications-alb-523762887.cn-northwest-1.elb.amazonaws.com.cn:8881/
remote_addr is 10.0.2.132
x_forwarded_for is 113.200.x.x

可以看到客户端的真实IP在XFF头中,而remote_addr是ALB的内网IP(ALB网络接口如下图)

2. ALB+NLB场景

我们创建ALB类型的目标群组如下

可以看到,源IP保留的特性是默认打开的

这时我们通过NLB的DNS来请求,有如下结果

$ curl http://Applications-NLB-4c2c130bf8c1b010.elb.cn-northwest-1.amazonaws.com.cn:8881
remote_addr is 10.0.3.132
x_forwarded_for is 113.200.x.x

可以看到,客户端的真实IP,保留请求到了ALB,这时就等同于直接请求ALB,所以返回结果与直接访问ALB时相同。

NLB在各个可用区提供了一个固定IP,这样我们便可以在用户有需求时(可能出于客户端要求,也可能出于安全要求),给到用户这个固定的IP。

注意事项:

1. TLS的监听器不能将流量路由到ALB类型的目标群组,你需要创建TCP的监听器,转发到ALB的HTTPS上;

2. 每个ALB类型的目标群组只能包含一个ALB;

3. NLB空闲超时350s,是硬限制。

建议限制使用该场景,当流量通过NLB到达ALB时,两个负载均衡器均消耗了LCU,这会增加费用。所以我们仍然建议在DNS结构允许的情况下,使用ALB来做为流量的入口。