AWS EC2 出口多IP轮询

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 规则的设置。

添加网卡

sudo ip addr add 10.0.1.98/24 dev ens5
sudo ip addr add 10.0.1.97/24 dev ens5
sudo ip addr add 10.0.1.96/24 dev ens5

echo 'ip addr add 172.31.2.249/20 dev ens5' >> /etc/rc.local  ## 2、加入开机启动

关闭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 # 持久化规则
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇