ROS一键搭建 NatGateway 让阿里 VPC 与 Internet 的互访教程
ROS搭建SNAT网关使专有网络访问Internet
背景
专有网络环境下,云服务器ECS实例不能直接访问公网,一种方法是给需要访问公网的ECS实例申请弹性IP,但是如果有大量的ECS实例同时需要访问公网,这种方法就不可行。今天将介绍一种SNAT网关访问公网的方式。如下图所示 :
::__IHACKLOG_REMOTE_IMAGE_AUTODOWN_BLOCK__::0
这种方法需要申请一台额外的ECS实例绑定EIP做VPC网络的SNAT网关。首先这台ECS实例要在指定的VPC网络中,要绑定EIP,配置这台ECS实例上的iptables, 最后在指定VPC网络的路由表中添加下一跳是这台ECS的路由项。详细的手动配置过程请参考这里。
ROS资源介绍
下面将介绍如何通过ROS自动化创建配置VPC SNAT网关。在模版中使用了ROS的如下资源:
- InternetChargeType:计费方式,按带宽或者按照流量
- Bandwidth: 带宽在[1~200]取值,单位是Mbps
创建EIP资源
- AllocationId:分配的EIP ID
- InstanceId: 需要绑定EIP的ECS instance ID
本资源资源将绑定EIP到指定的ECS实例
- RouteId: 指定VPC网络中的路由器ID
- RouteTableId: 指定VPC网络中路由表ID
- DestinationCidrBlock: 路由项的目标网段
- NextHopId:路由项的下一跳
本资源将会添加一条路由到指定VPC网络的路由表中,它的下一跳是SNAT网关
- 本例中主要使用了UserData属性,用户通过指定脚本给UserData,当ECS启动的时候,就会自动配置iptables。
本资源就是创建SNAT网关
编写ROS模版
在模版中,首先说明此stack需要一个EIP资源,一台ECS实例,并且把EIP绑定到ECS资源上,最终通过执行我们传给ECS的UserData脚本自动化的配置iptbales,最终把下一跳指向ECS的路由项添加到VPC路由器的路由表里面。最终的ROS模版如下:
{
"ROSTemplateFormatVersion": "2015-09-01",
"Description": "一键创建SNAT网关",
"Parameters": {
"SecurityGroupId": {
"Description": "安全组ID",
"Type": "String"
},
"RouteTableId": {
"Description": "专有网络中路由器ID",
"Type": "String"
},
"RouteId": {
"Description": "专有网络中路由器ID",
"Type": "String"
},
"EIPBandwidth": {
"Default": 5,
"MinValue": 1,
"Description": "弹性公网IP的限速,默认为 5Mbps。",
"Type": "Number",
"MaxValue": 200
},
"ECSZoneId": {
"Description": "可用区, , <a href='#/product/cn-shenzhen/list/zoneList' target='_blank'>查看可用区</a>",
"Type": "String"
},
"ECSPassword": {
"NoEcho": true,
"MaxLength": 30,
"Description": "实例的密码",
"Type": "String",
"ConstraintDescription": "8-30个字符, 必须同时包含三项(大、小写字母,数字和特殊符号).",
"MinLength": 8
},
"VSwitchId": {
"Type": "String"
},
"VpcId": {
"Type": "String"
},
"VSwitchCidrBlock": {
"Description": "通过SNAT网关访问外网的VSwitch网段,此网段必须属于VPC",
"Type": "String"
},
"EIPInternetChargeType": {
"Default": "PayByTraffic",
"AllowedValues": [
"PayByBandwidth",
"PayByTraffic"
],
"Description": "弹性公网IP计费类型,PayByBandwidth(按固定带宽计费),PayByTraffic(按使用流量计费),固定带宽的费用以天计,使用流量的费用以小时计",
"Type": "String"
},
"ECSSysDiskSize": {
"Default": 40,
"MinValue": 40,
"Description": "系统盘大小,40-500之间",
"Type": "Number",
"MaxValue": 500
},
"ECSDiskCategory": {
"Default": "cloud_efficiency",
"AllowedValues": [
"cloud",
"cloud_efficiency",
"cloud_ssd"
],
"Description": "系统盘的磁盘种类, 普通云盘(cloud)、高效云盘(cloud_efficiency)或SSD云盘(cloud_ssd)",
"Type": "String"
},
"ECSInstanceType": {
"Default": "ecs.s2.large",
"AllowedValues": [
"ecs.t1.small",
"ecs.s1.small",
"ecs.s1.medium",
"ecs.s1.large",
"ecs.s2.small",
"ecs.s2.large",
"ecs.s2.xlarge",
"ecs.s2.2xlarge",
"ecs.s3.medium",
"ecs.s3.large",
"ecs.m1.medium",
"ecs.m2.medium",
"ecs.m1.xlarge",
"ecs.c1.small",
"ecs.c1.large",
"ecs.c2.medium",
"ecs.c2.large",
"ecs.c2.xlarge",
"ecs.n1.tiny",
"ecs.n1.small",
"ecs.n1.medium",
"ecs.n1.large",
"ecs.n1.xlarge"
],
"Description": "实例规格, <a href='#/product/cn-shenzhen/list/typeList' target='_blank'>查看实例规格</a>",
"Type": "String"
},
"ECSImageId": {
"Default": "ubuntu1404_64_40G_cloudinit_20160427.raw",
"Description": "镜像文件 ID,表示启动实例时选择的镜像资源, <a href='#/product/cn-shenzhen/list/imageList' target='_blank'>查看实例规格</a>",
"Type": "String"
},
"ECSTag": {
"Description": "ECS的标签",
"Type": "String"
}
},
"Resources": {
"ElasticIpAssociation": {
"Type": "ALIYUN::ECS::EIPAssociation",
"Properties": {
"InstanceId": {
"Fn::Select": [
"0",
{
"Fn::GetAtt": [
"ECSSnatGateWay",
"InstanceIds"
]
}
]
},
"AllocationId": {
"Fn::GetAtt": [
"ElasticIp",
"AllocationId"
]
}
}
},
"VRoute": {
"Type": "ALIYUN::ECS::Route",
"Properties": {
"NextHopId": {
"Fn::Select": [
"0",
{
"Fn::GetAtt": [
"ECSSnatGateWay",
"InstanceIds"
]
}
]
},
"RouteId": {
"Ref": "RouteId"
},
"RouteTableId": {
"Ref": "RouteTableId"
},
"DestinationCidrBlock": "0.0.0.0/0"
}
},
"ECSSnatGateWay": {
"Type": "ALIYUN::ECS::InstanceGroup",
"Properties": {
"SecurityGroupId": {
"Ref": "SecurityGroupId"
},
"ImageId": {
"Ref": "ECSImageId"
},
"Password": {
"Ref": "ECSPassword"
},
"MinAmount": "1",
"InternetMaxBandwidthIn": 100,
"UserData": {
"Fn::Replace": [
{
"ros-notify": {
"Fn::GetAtt": [
"ECSSnatGateWayConditionHandle",
"CurlCli"
]
}
},
{
"Fn::Join": [
"",
[
"#!/bin/sh",
"\n",
"PostRouting=",
{
"Ref": "VSwitchCidrBlock"
},
"\n",
"SourceRouting=`ifconfig eth0|grep inet|awk '{print $2}'|tr -d 'addr:'`",
"\n",
"echo 'net.ipv4.ip_forward=1'>> /etc/sysctl.conf \n",
"sysctl -p \n",
"iptables -t nat -I POSTROUTING -s $PostRouting -j SNAT --to-source $SourceRouting \n",
"apt-get update\n",
"apt-get install -y curl\n",
"ros-notify -d '{\"data\" : \" docker swarm created\"}'\n"
]
]
}
]
},
"ZoneId": {
"Ref": "ECSZoneId"
},
"VSwitchId": {
"Ref": "VSwitchId"
},
"InternetChargeType": "PayByTraffic",
"VpcId": {
"Ref": "VpcId"
},
"InstanceType": {
"Ref": "ECSInstanceType"
},
"SystemDisk_Category": {
"Ref": "ECSDiskCategory"
},
"IoOptimized": "optimized",
"Tags": [
{
"Value": {
"Ref": "ECSTag"
},
"Key": "ECS_SNAT_GATEWAY"
}
],
"InternetMaxBandwidthOut": 100,
"SystemDisk_Size": {
"Ref": "ECSSysDiskSize"
},
"MaxAmount": "1"
}
},
"ECSSnatGateWayConditionHandle": {
"Type": "ALIYUN::ROS::WaitConditionHandle"
},
"ECSSnatGateWayGroupWaitCondition": {
"Type": "ALIYUN::ROS::WaitCondition",
"DependsOn": "ECSSnatGateWay",
"Properties": {
"Handle": {
"Ref": "ECSSnatGateWayConditionHandle"
},
"Timeout": 600,
"Count": 1
}
},
"ElasticIp": {
"Type": "ALIYUN::ECS::EIP",
"Properties": {
"InternetChargeType": {
"Ref": "EIPInternetChargeType"
},
"Bandwidth": {
"Ref": "EIPBandwidth"
}
}
}
},
"Outputs": {
"ECSSnatGateWay_INNER_IPS": {
"Value": {
"Fn::GetAtt": [
"ECSSnatGateWay",
"PrivateIps"
]
},
"Description": "Inner IP address of the ECS instance."
},
"ECSSnatGateWay_InstanceIds": {
"Value": {
"Fn::GetAtt": [
"ECSSnatGateWay",
"InstanceIds"
]
},
"Description": "The instance id of created ecs instance"
},
"EipAddress": {
"Value": {
"Fn::GetAtt": [
"ElasticIp",
"EipAddress"
]
},
"Description": "IP address of created EIP."
},
"ECSSnatGateWay_ZoneIds": {
"Value": {
"Fn::GetAtt": [
"ECSSnatGateWay",
"ZoneIds"
]
},
"Description": "Zone id of created instance."
}
}
}
在上边的文章中,总结了ROS搭建SNAT网关使专有网络访问Internet,它的主要思路是在VPC网络里面创建一个ECS做NAT网关的角色以便实现VPC网络访问internet的功能。坦白的说,这个方法是比较复杂的。今天介绍一个ROS的新资源NAT Gateway,通过它能非常方便的实现这个功能,在专有网络中的机器与Internet互访不是梦。
Nat Gateway介绍
NAT网关(NAT Gateway)是一款企业级的VPC公网网关,提供NAT代理(SNAT、DNAT)、10Gbps级别的转发能力、Region级别的高可用性(跨可用区的容灾能力)。
共享带宽包(Bandwidth Package)是对NAT网关上的公网IP与公网带宽的封装;一个共享带宽包由一份公网带宽和一组公网IP组成,这些公网IP共享带宽。
NAT网关与共享带宽包需要配合使用,组合成为高性能、配置灵活的企业级网关。
NAT Gateway在VPC中的拓扑如下图所示:
::__IHACKLOG_REMOTE_IMAGE_AUTODOWN_BLOCK__::1
关键特性:
DNAT:目的网络地址转换(入方向代理),用于VPC内的ECS面向互联网提供服务;支持端口映射、IP映射;
SNAT:源网络地址转换(出方向代理),用于VPC内的ECS访问互联网内容;
多IP共享带宽:NAT网关上购买公网IP和公网带宽时以“共享带宽包”形式购买,一个带宽包内的所有IP共享带宽;
高性能:NAT网关可以支撑单实例10Gbps级别的转发能力;
高可用:NAT网关基于SDN技术,采用跨可用区分布式架构,每个实例均具备应对可用区级别故障;
按需购买:所有费用均为先使用后结算,实例规格、带宽大小、公网IP个数均可随时调整、即时生效;
ROS Nat Gateway相关资源介绍
ALIYUN::ECS::NatGateway
这个资源是申明要在那个VPC中创建一个NAT Gateway。在创建NAT Gateway的时候必须指定VPC的ID,VSWITCH的ID,以及至少一个带宽包。NAT Gateway
资源创建成功后会自动在VPC的路有表中添加一条指向NAT Gateway的路由表项。通过ROS可以输出NAT Gateway的ID, 所有带宽包的ID,所有带宽包中申明的所有公网IP,Forward 表ID,SNAT表ID。
"NatGateway": {
"DependsOn": "VSwitch",
"Properties": {
"BandwidthPackage": [
{
"Bandwidth": 5,
"IpCount": 1,
"ZoneId": "cn-hangzhou-b"
},
{
"Bandwidth": 5,
"IpCount": 1,
"ZoneId": "cn-hangzhou-b"
}
],
"Description": "hhhhh",
"NatGatewayName": "nat_gateway_1",
"Spec": "Middle",
"VSwitchId": {
"Fn::GetAtt": [
"VSwitch",
"VSwitchId"
]
},
"VpcId": {
"Fn::GetAtt": [
"Vpc",
"VpcId"
]
}
},
"Type": "ALIYUN::ECS::NatGateway"
}
ALIYUN::ECS::BandwidthPackage
带宽包也可以单独作为一个资源创建,然后关联到一个具体的NAT Gateway。创建带宽包必须要指定NAT Gateway的ID,带宽大小,以及所需要的公网IP数量。
资源创建完成后,通过ROS可以输出带宽包ID和带宽包中所申请的所有IP
BandwidthPackage": {
"Type": "ALIYUN::ECS::BandwidthPackage",
"Properties": {
"BandwidthPackageName": "pkg_2",
"Description": "new bandwidth package",
"NatGatewayId": "ngw-h1xoxepyf",
"IpCount": 2,
"Bandwidth": 5,
"ZoneId": "cn-beijing-c"
}
}
ALIYUN::ECS::ForwardEntry
本资源是给NAT Gateway的目的网络转换表添加访问规则,通过这条规则可以让外网主动访问VPC网络中的机器。创建一条规则必须传入Forward表的ID,网络协议,VPC内部机器的IP,内部机器的端口,暴漏给外网访问的IP和端口。外网的IP,就是带宽包中所申请的IP资源。
资源创建完成,通过ROS可以输出这条规则的ID
下面的例子展示如何配置一个外网通过22端口访问在VPC网络的机器。
"ForwardEntry": {
"Properties": {
"ExternalIp": {
"Fn::Select": [
"1",
{
"Fn::GetAtt": [
"NatGateway",
"BandwidthPackageIps"
]
}
]
},
"ExternalPort": "22",
"ForwardTableId": {
"Fn::GetAtt": [
"NatGateway",
"ForwardTableId"
]
},
"InternalIp": "192.168.0.1",
"InternalPort": "22",
"IpProtocol": "TCP"
},
"Type": "ALIYUN::ECS::ForwardEntry"
}
ALIYUN::ECS::SNatEntry
本资源给源网络地址转换表配置一条规则,通过这个规则可以让VPC中的机器能主动访问外网。创建一条规则必须传入SNAT表的ID,将要访问外网的VSWITCH ID,以及通过那个外网IP访问外网,这个IP也是带宽包中所申请的IP。如果同时需要主动,被动访问外网的,就必须至少有两个外网IP。也就是SNAT和Forward表的公网IP不能相同。
"SNatEntry": {
"Properties": {
"SNatIp": {
"Fn::Select": [
"0",
{
"Fn::GetAtt": [
"NatGateway",
"BandwidthPackageIps"
]
}
]
},
"SNatTableId": {
"Fn::GetAtt": [
"NatGateway",
"SNatTableId"
]
},
"SourceVSwitchId": {
"Fn::GetAtt": [
"VSwitch",
"VSwitchId"
]
}
}
下面是一个完整的模版创建一个VPC网络,然后配置NAT Gateway,让VPC的中的ECS实例能和Internet互访。完整模版下载 ->>