1.背景说明
众所周知,业务服务器是企业用以提供服务实现盈利的核心,绝大多数情况业务服务器都部署于私有网络中,以保证安全。
在私有网络中的业务服务器提供业务功能时,对网络的诉求会分成两种类型:第一种是经由互联网被访问,可以借助负载均衡器进行服务暴露实现;第二种则是主动访问互联网。
对于第二种类型,如果需要的公网 IP 数量少于或等于 8 个,可以使用 Amazon NAT Gateway 实现;若需要的公网 IP 数量大于 8 个,则需要更加灵活的方案。
本文将介绍两种方案,用于满足“需要的公网 IP 数量大于 8 个”的场景,并在文章的最后,对这两种方案进行优劣势比较。
2.方案实现
2.1 方案 1:通过 iptables 的 SNAT 规则实现
a. 架构图(其中业务服务器 2 仅作为展示,并不会真正创建)
b. 环境搭建(执行命令的机器需要有足够的权限)
1) 创建网络资源
# 0. 进入screen模式,以保证环境变量不会因为退出Session而消失
screen
# 1. 创建VPC
ningxia_vpc_id=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --region cn-northwest-1 --query "Vpc.VpcId" --output text)
# 2. 创建Subnet
# 在AZ1中创建ningxia_subnet_az1_id1(私有子网1)
ningxia_subnet_az1_id1=$(aws ec2 create-subnet --cidr-block 10.0.0.0/24 --vpc-id $ningxia_vpc_id --region cn-northwest-1 --availability-zone cn-northwest-1a --query "Subnet.SubnetId" --output text)
# 在AZ1中创建ningxia_subnet_az1_id2(公有子网)
ningxia_subnet_az1_id2=$(aws ec2 create-subnet --cidr-block 10.0.1.0/24 --vpc-id $ningxia_vpc_id --region cn-northwest-1 --availability-zone cn-northwest-1a --query "Subnet.SubnetId" --output text)
# 3. 创建路由表
# 创建ningxia_route_table_id1(私有子网1路由表)
ningxia_route_table_id1=$(aws ec2 create-route-table --vpc-id $ningxia_vpc_id --region cn-northwest-1 --query "RouteTable.RouteTableId" --output text)
# 创建ningxia_route_table_id2(公有子网路由表)
ningxia_route_table_id2=$(aws ec2 create-route-table --vpc-id $ningxia_vpc_id --region cn-northwest-1 --query "RouteTable.RouteTableId" --output text)
# 4. 更改子网路由表
aws ec2 associate-route-table --route-table-id $ningxia_route_table_id1 --subnet-id $ningxia_subnet_az1_id1 --region cn-northwest-1
aws ec2 associate-route-table --route-table-id $ningxia_route_table_id2 --subnet-id $ningxia_subnet_az1_id2 --region cn-northwest-1
# 5. 修改安全组
# 获取宁夏的groupid
groupid_ningxia=$(aws ec2 describe-security-groups --region cn-northwest-1 --filter "Name=vpc-id,Values=$ningxia_vpc_id" --query "SecurityGroups[].GroupId" --output text)
# 基于获取的groupid,修改安全组
aws ec2 authorize-security-group-ingress --group-id "$groupid_ningxia" --protocol all --port all --cidr "0.0.0.0/0" --region cn-northwest-1
# 6. 创建并附加Internet Gateway
internet_gateway_id_ningxia=$(aws ec2 create-internet-gateway --region cn-northwest-1 --query "InternetGateway.InternetGatewayId" --output text)
aws ec2 attach-internet-gateway --region cn-northwest-1 --internet-gateway-id $internet_gateway_id_ningxia --vpc-id $ningxia_vpc_id
# 7. 修改路由表
aws ec2 create-route --destination-cidr-block 0.0.0.0/0 --gateway-id $internet_gateway_id_ningxia --region cn-northwest-1 --route-table-id $ningxia_route_table_id1
aws ec2 create-route --destination-cidr-block 0.0.0.0/0 --gateway-id $internet_gateway_id_ningxia --region cn-northwest-1 --route-table-id $ningxia_route_table_id2
2) 创建实例资源
# 8. 创建业务服务器1
business_instance_id=$(aws ec2 run-instances --region cn-northwest-1 --image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 --instance-type t3.micro --key-name id_rsa_test.pub --security-group-ids $groupid_ningxia --subnet-id $ningxia_subnet_az1_id1 --associate-public-ip-address --query 'Instances[].InstanceId' --output text)
# 等待实例创建完成
aws ec2 wait instance-status-ok --instance-ids $business_instance_id --region cn-northwest-1
# 获得business_instance_ip
business_instance_ip=$(aws ec2 describe-instances --instance-ids "$business_instance_id" --region cn-northwest-1 --query 'Reservations[0].Instances[0].PublicIpAddress' --output text)
# 9. 创建转发服务器
proxy_instance_id=$(aws ec2 run-instances --region cn-northwest-1 --image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 --instance-type t3.medium --key-name id_rsa_test.pub --security-group-ids $groupid_ningxia --subnet-id $ningxia_subnet_az1_id2 --associate-public-ip-address --query 'Instances[].InstanceId' --output text)
# 等待实例创建完成
aws ec2 wait instance-status-ok --instance-ids $proxy_instance_id --region cn-northwest-1
# 获得proxy_instance_ip
proxy_instance_ip=$(aws ec2 describe-instances --instance-ids "$proxy_instance_id" --region cn-northwest-1 --query 'Reservations[0].Instances[0].PublicIpAddress' --output text)
# 创建好转发服务器,需要修改业务服务器1的路由表,将路由条目0.0.0.0/0的下一跳指向转发服务器的主网卡,这样所有流量都将流向转发服务器。
c. 配置转发服务器
1) 原理解释
iptables 中提供两种模式实现四层负载均衡,分别是 random(随机)和 nth(轮询)。
random 模式基于概率实现负载均衡,请参考如下示例说明:
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -m statistic --mode random --probability 0.33 -j DNAT --to-destination 10.0.0.2:1234
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -m statistic --mode random --probability 0.5 -j DNAT --to-destination 10.0.0.3:1234
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -j DNAT --to-destination 10.0.0.4:1234
rules 说明:
第一条规则中,指定 –probability 0.33 ,则说明该规则有 33% 的概率会命中。
第二条规则也有 33% 的概率命中,因为规则中指定 –probability 0.5。 则命中的概率为:50% * (1 – 33%)=0.33。
第三条规则中,没有指定 –probability 参数,因此意味着当匹配走到第三条规则时,则一定命中,此时走到第三条规则的概率为:1 – 0.33 -0.33 ≈ 0.33。
由上可见,可以通过修改 –probability 参数调整规则命中率。
probability 计算规则说明:
假设有 n 个 server,则可以设定 n 条 rule 将流量均分到 n 个 server 上,其中 –probability 参数的值可通过以下公式计算得到:p=1/(n−i+1)
# 其中 i 代表规则的序号(第一条规则的序号为1)
# n 代表规则/server的总数
# p 代表第 i 条规则中 –probability 的参数值
nth 模式基于轮询实现负载均衡,请参考如下示例说明:
# every:每n个包匹配一次规则
# packet:从第p个包开始
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -m statistic --mode nth --every 1 --packet 0 -j DNAT --to-destination 10.0.0.1:1234
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -m statistic --mode nth --every 2 --packet 0 -j DNAT --to-destination 10.0.0.2:1234
iptables -A PREROUTING -t nat -p tcp -d 192.168.1.1 --dport 27017 -m statistic --mode nth --every 3 --packet 0 -j DNAT --to-destination 10.0.0.3:1234
rules 说明:
第一条规则是从第 0 个包开始计算,匹配第 1 个包
第二条规则是从第 0 个包开始计算,匹配第 2 个包
第三条规则是从第 0 个包开始计算,匹配第 3 个包
第 4 个包回到原点,再次重新匹配,以此反复循环
2) 部署转发服务器(这次实验采用 nth 方式进行)
为了实现多公网 IP 轮询,首先需要转发服务器拥有多个公网 IP,可以将 Elastic IP 与主网卡的多个 Secondary Private IP 进行绑定实现。又由于路由的原因,无法使用 Secondary Network Interface。所以,转发服务器可以拥有多少个公网 IP,将由实例的主网卡可以拥有多少个 Secondary Private IP 决定。这次实验使用的是 t3.medium,此实例类型主网卡可以拥有最多 6 个私网地址,去掉已经使用的 Primary Private IP,总计有 5 个 Secondary Private IP。具体哪种实例可以有多少 IP,请参考如下链接:Elastic network interfaces – Amazon Elastic Compute Cloud。
# 10. 创建Secondary Private IP并绑定EIP
# 获取主网卡id
network_interface_id=$(aws ec2 describe-instances --region cn-northwest-1 --instance-ids $proxy_instance_id --query "Reservations[].Instances[].NetworkInterfaces[].NetworkInterfaceId" --output text)
# 分配私网地址
private_ip_list=$(aws ec2 assign-private-ip-addresses --region cn-northwest-1 --network-interface-id $network_interface_id --secondary-private-ip-address-count 5 --query "AssignedPrivateIpAddresses[].PrivateIpAddress" --output text)
# 申请并绑定EIP
count=1; for i in $private_ip_list;
do
allocation_id=$(aws ec2 allocate-address --region cn-northwest-1 --query "AllocationId" --output text);
allocation_id_list[$count]=$allocation_id;
association_id=$(aws ec2 associate-address --region cn-northwest-1 --allocation-id $allocation_id --network-interface-id $network_interface_id --private-ip-address $i --output text)
association_id_list[$count]=$association_id
((count++));
done
创建完 Secondary Private IP 并绑定 EIP 后,下一步就是关闭实例的 source/destination check 以及登录到转发服务器进行 iptables nth 规则的设置。
# 关闭source/destination check
aws ec2 modify-instance-attribute --region cn-northwest-1 --no-source-dest-check --instance-id $proxy_instance_id
# 登录转发服务器(以下命令通过root账号执行)
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -I POSTROUTING -m statistic --mode nth --every 1 --packet 0 -j SNAT --to-source 10.0.1.184
iptables -t nat -I POSTROUTING -m statistic --mode nth --every 2 --packet 0 -j SNAT --to-source 10.0.1.177
iptables -t nat -I POSTROUTING -m statistic --mode nth --every 3 --packet 0 -j SNAT --to-source 10.0.1.9
iptables -t nat -I POSTROUTING -m statistic --mode nth --every 4 --packet 0 -j SNAT --to-source 10.0.1.252
iptables -t nat -I POSTROUTING -m statistic --mode nth --every 5 --packet 0 -j SNAT --to-source 10.0.1.46
iptables -t nat -I POSTROUTING -m statistic --mode nth --every 6 --packet 0 -j SNAT --to-source 10.0.1.63
yum install iptables-services -y
service iptables save # 持久化规则
d. 方案 1 测试
登录到业务服务器 1,通过 curl ip.sb 获取访问公网的 IP 地址,可以看到是以轮训的方式获取到了不同的 IP 地址,而这些 IP 地址就是在转发服务器上绑定的 EIP。
e. 环境清理
下载方案 1 环境清理:按照“方案 1 环境清理”中记载的步骤进行清理。
2.2 方案 2:借助 Private Hosted Zone、Amazon Network Load Balancer 和 Nginx 实现
a. 架构图(其中业务服务器 2 仅作为展示,并不会真正创建)
- 通过 Private Hosted Zone 将要访问的网站域名进行劫持到 Network Load Balancer 的域名,这次实验中使用了 com 作为域名,访问的网站是 www.baidu.com,因此会将 www.baidu.com 劫持为 NLB 的域名。
- 请求通过 Peering Connection 送达到 Network Load Balancer。使用两个 VPC 的原因在于,如果业务服务器和 Nginx 服务器同属一个 VPC,那么访问的 baidu.com 就都会被劫持为 NLB 的域名,Nginx 就无法将请求转发到正确的地址。
- Network Load Balancer 监听 TCP 443 端口,并将请求转发到后端 Nginx 集群。使用 TCP 协议的原因在于,只需要将请求 443 的流量进行转发即可。
- Nginx 运行于 Stream 模式,在握手阶段拿到访问的域名,并转发到想要访问的网站。在这次实验中就是 baidu.com。
- Nginx 集群处于 Auto Scaling Group 中,根据请求流量进行动态扩缩容(这次实验不会实施,仅供参考)。
b. 环境搭建(执行命令的机器需要有足够的权限)
1) 创建网络资源
# 0. 进入screen模式,以保证环境变量不会因为退出Session而消失
screen
# 1. 创建VPC1和VPC2
ningxia_vpc1_id=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --region cn-northwest-1 --query "Vpc.VpcId" --output text)
ningxia_vpc2_id=$(aws ec2 create-vpc --cidr-block 172.31.0.0/16 --region cn-northwest-1 --query "Vpc.VpcId" --output text)
# 修改VPC2属性
aws ec2 modify-vpc-attribute --region cn-northwest-1 --vpc-id $ningxia_vpc2_id --enable-dns-hostnames
aws ec2 modify-vpc-attribute --region cn-northwest-1 --vpc-id $ningxia_vpc2_id --enable-dns-support
# 2. 创建Subnet
# 2.1 创建VPC1的子网
# 在AZ1中创建vpc1_ningxia_subnet_az1_id1(私有子网1)
vpc1_ningxia_subnet_az1_id1=$(aws ec2 create-subnet --cidr-block 10.0.0.0/24 --vpc-id $ningxia_vpc1_id --region cn-northwest-1 --availability-zone cn-northwest-1a --query "Subnet.SubnetId" --output text)
# 2.2 创建VPC2的子网
# 在AZ1中创建vpc2_ningxia_subnet_az1_id1(私有子网1)
vpc2_ningxia_subnet_az1_id1=$(aws ec2 create-subnet --cidr-block 172.31.0.0/24 --vpc-id $ningxia_vpc2_id --region cn-northwest-1 --availability-zone cn-northwest-1a --query "Subnet.SubnetId" --output text)
# 在AZ2中创建vpc2_ningxia_subnet_az2_id2(私有子网2)
vpc2_ningxia_subnet_az2_id2=$(aws ec2 create-subnet --cidr-block 172.31.1.0/24 --vpc-id $ningxia_vpc2_id --region cn-northwest-1 --availability-zone cn-northwest-1b --query "Subnet.SubnetId" --output text)
# 在AZ1中创建vpc2_ningxia_subnet_az1_id3(公有子网1)
vpc2_ningxia_subnet_az1_id3=$(aws ec2 create-subnet --cidr-block 172.31.2.0/24 --vpc-id $ningxia_vpc2_id --region cn-northwest-1 --availability-zone cn-northwest-1a --query "Subnet.SubnetId" --output text)
# 在AZ2中创建vpc2_ningxia_subnet_az2_id4(公有子网2)
vpc2_ningxia_subnet_az2_id4=$(aws ec2 create-subnet --cidr-block 172.31.3.0/24 --vpc-id $ningxia_vpc2_id --region cn-northwest-1 --availability-zone cn-northwest-1b --query "Subnet.SubnetId" --output text)
# 3. 创建路由表
# 3.1 创建VPC1的路由表
# 创建vpc1_ningxia_route_table_id1(私有子网路由表)
vpc1_ningxia_route_table_id1=$(aws ec2 create-route-table --vpc-id $ningxia_vpc1_id --region cn-northwest-1 --query "RouteTable.RouteTableId" --output text)
# 3.2 创建VPC2的路由表
# 创建vpc2_ningxia_route_table_id1(私有子网路由表)
vpc2_ningxia_route_table_id1=$(aws ec2 create-route-table --vpc-id $ningxia_vpc2_id --region cn-northwest-1 --query "RouteTable.RouteTableId" --output text)
# 创建vpc2_ningxia_route_table_id2(公有子网路由表)
vpc2_ningxia_route_table_id2=$(aws ec2 create-route-table --vpc-id $ningxia_vpc2_id --region cn-northwest-1 --query "RouteTable.RouteTableId" --output text)
# 4. 更改子网路由表
# 4.1 更改VPC1中的子网路由表
aws ec2 associate-route-table --route-table-id $vpc1_ningxia_route_table_id1 --subnet-id $vpc1_ningxia_subnet_az1_id1 --region cn-northwest-1
# 4.2 更改VPC2中的子网路由表
# 4.2.1 更改VPC2中的私有子网路由表
aws ec2 associate-route-table --route-table-id $vpc2_ningxia_route_table_id1 --subnet-id $vpc2_ningxia_subnet_az1_id1 --region cn-northwest-1
aws ec2 associate-route-table --route-table-id $vpc2_ningxia_route_table_id1 --subnet-id $vpc2_ningxia_subnet_az2_id2 --region cn-northwest-1
# 4.2.2 更改VPC2中的公有子网路由表
aws ec2 associate-route-table --route-table-id $vpc2_ningxia_route_table_id2 --subnet-id $vpc2_ningxia_subnet_az1_id3 --region cn-northwest-1
aws ec2 associate-route-table --route-table-id $vpc2_ningxia_route_table_id2 --subnet-id $vpc2_ningxia_subnet_az2_id4 --region cn-northwest-1
# 5. 修改安全组
# 5.1 修改VPC1的安全组
# 获取VPC1的groupid
vpc1_groupid_ningxia=$(aws ec2 describe-security-groups --region cn-northwest-1 --filter "Name=vpc-id,Values=$ningxia_vpc1_id" --query "SecurityGroups[].GroupId" --output text)
# 基于获取的groupid,修改安全组
aws ec2 authorize-security-group-ingress --group-id "$vpc1_groupid_ningxia" --protocol all --port all --cidr "0.0.0.0/0" --region cn-northwest-1
# 5.2 修改VPC2的安全组
# 获取VPC2的groupid
vpc2_groupid_ningxia=$(aws ec2 describe-security-groups --region cn-northwest-1 --filter "Name=vpc-id,Values=$ningxia_vpc2_id" --query "SecurityGroups[].GroupId" --output text)
# 基于获取的groupid,修改安全组
aws ec2 authorize-security-group-ingress --group-id "$vpc2_groupid_ningxia" --protocol all --port all --cidr "0.0.0.0/0" --region cn-northwest-1
# 6. 创建并附加Internet Gateway
# 6.1 VPC1中创建并附加Internet Gateway
vpc1_internet_gateway_id_ningxia=$(aws ec2 create-internet-gateway --region cn-northwest-1 --query "InternetGateway.InternetGatewayId" --output text)
aws ec2 attach-internet-gateway --region cn-northwest-1 --internet-gateway-id $vpc1_internet_gateway_id_ningxia --vpc-id $ningxia_vpc1_id
# 6.2 VPC2中创建并附加Internet Gateway
vpc2_internet_gateway_id_ningxia=$(aws ec2 create-internet-gateway --region cn-northwest-1 --query "InternetGateway.InternetGatewayId" --output text)
aws ec2 attach-internet-gateway --region cn-northwest-1 --internet-gateway-id $vpc2_internet_gateway_id_ningxia --vpc-id $ningxia_vpc2_id
# 7. 修改路由表
# 7.1 修改VPC1中的路由表
aws ec2 create-route --destination-cidr-block 0.0.0.0/0 --gateway-id $vpc1_internet_gateway_id_ningxia --region cn-northwest-1 --route-table-id $vpc1_ningxia_route_table_id1
# 7.2 修改VPC2中的路由表
aws ec2 create-route --destination-cidr-block 0.0.0.0/0 --gateway-id $vpc2_internet_gateway_id_ningxia --region cn-northwest-1 --route-table-id $vpc2_ningxia_route_table_id1
aws ec2 create-route --destination-cidr-block 0.0.0.0/0 --gateway-id $vpc2_internet_gateway_id_ningxia --region cn-northwest-1 --route-table-id $vpc2_ningxia_route_table_id2
# 8. 创建Peering Connection
vpc_peering_connection_id=$(aws ec2 create-vpc-peering-connection --region cn-northwest-1 --vpc-id $ningxia_vpc1_id --peer-vpc-id $ningxia_vpc2_id --peer-region cn-northwest-1 --query "VpcPeeringConnection.VpcPeeringConnectionId" --output text)
aws ec2 accept-vpc-peering-connection --region cn-northwest-1 --vpc-peering-connection-id $vpc_peering_connection_id --query "VpcPeeringConnection.VpcPeeringConnectionId" --output text
# 8.1 添加路由,使VPC1和VPC2可以互通
aws ec2 create-route --region cn-northwest-1 --route-table-id $vpc1_ningxia_route_table_id1 --destination-cidr-block 172.31.0.0/16 --vpc-peering-connection-id $vpc_peering_connection_id
aws ec2 create-route --region cn-northwest-1 --route-table-id $vpc2_ningxia_route_table_id1 --destination-cidr-block 10.0.0.0/16 --vpc-peering-connection-id $vpc_peering_connection_id
2) 创建实例资源
# 9. 创建Nginx实例
# 9.1 创建Nginx1
nginx_id1=$(aws ec2 run-instances --region cn-northwest-1 --image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 --instance-type t3.micro --key-name id_rsa_test.pub --security-group-ids $vpc2_groupid_ningxia --subnet-id $vpc2_ningxia_subnet_az1_id3 --associate-public-ip-address --query 'Instances[].InstanceId' --output text)
# 等待实例创建完成
aws ec2 wait instance-status-ok --instance-ids $nginx_id1 --region cn-northwest-1
# 获得nginx_ip1
nginx_ip1=$(aws ec2 describe-instances --instance-ids "$nginx_id1" --region cn-northwest-1 --query 'Reservations[0].Instances[0].PublicIpAddress' --output text)
# 9.2 创建Nginx2
nginx_id2=$(aws ec2 run-instances --region cn-northwest-1 --image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 --instance-type t3.micro --key-name id_rsa_test.pub --security-group-ids $vpc2_groupid_ningxia --subnet-id $vpc2_ningxia_subnet_az2_id4 --associate-public-ip-address --query 'Instances[].InstanceId' --output text)
# 等待实例创建完成
aws ec2 wait instance-status-ok --instance-ids $nginx_id2 --region cn-northwest-1
# 获得nginx_ip2
nginx_ip2=$(aws ec2 describe-instances --instance-ids "$nginx_id2" --region cn-northwest-1 --query 'Reservations[0].Instances[0].PublicIpAddress' --output text)
# 10. 创建业务服务器1
business_instance_id=$(aws ec2 run-instances --region cn-northwest-1 --image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 --instance-type t3.micro --key-name id_rsa_test.pub --security-group-ids $vpc1_groupid_ningxia --subnet-id $vpc1_ningxia_subnet_az1_id1 --associate-public-ip-address --query 'Instances[].InstanceId' --output text)
# 等待实例创建完成
aws ec2 wait instance-status-ok --instance-ids $business_instance_id --region cn-northwest-1
# 获得business_instance_ip
business_instance_ip=$(aws ec2 describe-instances --instance-ids "$business_instance_id" --region cn-northwest-1 --query 'Reservations[0].Instances[0].PublicIpAddress' --output text)
c. 配置 Nginx 实例
Nginx 在 1.9.0 版本新增了 stream 模块,用以实现四层协议的代理。对于 TLS 请求,会在 TLS 建连阶段拿到需要访问的域名,并将请求转发到正确的域名。
默认情况下,Nginx 并不包含此模块。因此需要对 Nginx 进行编译安装并在编译时增加”–with-stream”参数。
下载ProxyInstanceDeploymentProcedure,按照ProxyInstanceDeploymentProcedure中记载的步骤进行配置。
d. 创建和配置 Network Load Balancer
# 11. 创建和配置NLB
# 创建目标组
target_group_arn=$(aws elbv2 create-target-group --name my-targets --protocol TCP --port 443 --target-type instance --vpc-id $ningxia_vpc2_id --region cn-northwest-1 --query "TargetGroups[].TargetGroupArn" --output text)
# 注册实例
aws elbv2 register-targets --target-group-arn $target_group_arn --targets Id=$nginx_id1,Port=443 --region cn-northwest-1
aws elbv2 register-targets --target-group-arn $target_group_arn --targets Id=$nginx_id2,Port=443 --region cn-northwest-1
# 创建NLB
load_balancer_arn=$(aws elbv2 create-load-balancer --name my-load-balancer --scheme internal --type network --subnets $vpc2_ningxia_subnet_az1_id1 $vpc2_ningxia_subnet_az2_id2 --region cn-northwest-1 --query LoadBalancers[].LoadBalancerArn --output text)
# 等待NLB创建完成
aws elbv2 wait load-balancer-available --load-balancer-arns $load_balancer_arn --region cn-northwest-1
# 创建NLB监听器
listener_arn=$(aws elbv2 create-listener --load-balancer-arn $load_balancer_arn --protocol TCP --port 443 --default-actions Type=forward,TargetGroupArn=$target_group_arn --region cn-northwest-1 --query "Listeners[].ListenerArn" --output text)
e. 创建和配置 Private Hosted Zone
# 12. 创建和配置Private Hosted Zone
private_hosted_zone_id=$(aws route53 create-hosted-zone --name baidu.com --vpc VPCRegion=cn-northwest-1,VPCId=$ningxia_vpc1_id --caller-reference "`date '+%Y_%m_%d %H:%M:%S'`" --hosted-zone-config Comment="ForBlog",PrivateZone=true --query "HostedZone.Id" --output text)
echo $load_balancer_arn
aws elbv2 describe-load-balancers --query 'LoadBalancers[?LoadBalancerArn==`arn:aws-cn:elasticloadbalancing:cn-northwest-1:332433839685:loadbalancer/net/my-load-balancer/503cc27dc92ff737`][DNSName,CanonicalHostedZoneId]' # 问号后面填写上一个命令的输出,并将这个命令的输出作为值填入sample.json中的HostedZoneId和DNSName项
cat > sample.json << EOF
{
"Comment": "Creating Alias resource record sets in Route 53",
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "www.baidu.com",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "ZQEIKTCZ8352D",
"DNSName": "my-load-balancer-503cc27dc92ff737.elb.cn-northwest-1.amazonaws.com.cn",
"EvaluateTargetHealth": false
}
}
}
]
}
EOF
aws route53 change-resource-record-sets --hosted-zone-id $private_hosted_zone_id --change-batch file://sample.json # 劫持www.baidu.com的dns请求,并指向NLB的域名
f. 方案 2 测试
登录业务服务器 1,通过如下命令进行测试:for i in {1..20}; do curl -I https://www.baidu.com; done
。
观看 Nginx1 的日志:
观看 Nginx2 的日志:
由此可见,每次访问 www.baidu.com 都是通过不同的 IP 地址进行的访问。
g. 环境清理
下载方案 2 环境清理:,按照”方案 2 环境清理”中记载的步骤进行清理
3.方案对比
|
方案 1 |
方案 2 |
优势 |
配置简单,费用低,具体费用取决于选择的实例类型 |
云原生的方案,可以集成亚马逊云科技的各个服务; 方案中的每个组件都具有高可用性,可以应对故障; Nginx 实例可以线性扩展,因此私有实例可以使用无限多个公网 IP。 |
劣势 |
无法同亚马逊云科技的监控、告警和事件等服务集成,出现问题时无法第一时间发现; 每台私有实例都只能指向一台转发服务器,无冗余能力; 私有实例可以使用的公网 IP 数量取决于实例类型,不具备线性扩展能力。 |
配置复杂,由于使用了更多的服务,费用高于方案 1 |
4.总结
在这篇文章中,介绍了两种不同方案以实现私有实例轮询使用多公网 IP 访问公网,并在最后进行了两种方案的对比,以帮助大家更好的选择适合自己的方案。
本篇作者