每台EC2上可以绑定公网IP,但这个公网IP并不是直接和EC2相关联的,当我们执行ifconfig
其实还是只能看到它的私网IP:
kongpingfan:~ $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 9001
inet 172.31.60.3 netmask 255.255.240.0 broadcast 172.31.63.255
inet6 fe80::cfc:43ff:fed3:f5fd prefixlen 64 scopeid 0x20<link>
ether 0e:fc:43:d3:f5:fd txqueuelen 1000 (Ethernet)
RX packets 61231221 bytes 46057283309 (42.8 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 41031823 bytes 12811769604 (11.9 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
绑定公网IP后,这个公网IP的管理全部在Internet gateway(以下简称IGW)
上面,它上面维护着公网IP与私网IP的映射关系,例如:
公网IP | 私网IP |
---|---|
1.2.3.4 | 10.0.1.3 |
5.6.7.8 | 10.0.2.4 |
当用户访问EC2的公网IP地址时,流量会如下:
用户的请求先到达IGW,在上面获取到了映射关系,比如得知了1.2.3.4
要对应instance1-1
的私网IP地址,流量转发到instance1-1
当instance1-1
要回包时,先经过VPC路由表,上面查到公网地址的流量要转发到igw : 0.0.0.0/0 igw-001
。流量被送回到IGW
instance1-1
的回程流量到IGW时,IGW将它的私网IP地址替换成公网IP地址
回程流量最终通过互联网转发到用户
对于数据库类型的负载,我们不希望公网能够访问到它。如果它绑定上了公网IP,就有暴露在外面的安全风险。
AWS上的路由表是跟子网关联的,所以针对这种情况,可以将数据库类型的负载放到单独一个子网里,然后在子网上绑定单独的路由表,这个路由表没有进出igw
的规则:
如此一来,从互联网直接访问不到数据库,数据库也直接访问不了互联网。
上面这种有igw路由表的子网就叫公有子网(public subnet)
,没有igw路由表的子网叫私有子网(private subnet)
私有子网里的机器有时要访问互联网,例如数据库实例要从补丁服务器下载补丁进行更新。但我们又不想让外界能够直接访问私有子网里的机器,这时可以使用NAT Gateway
NAT Gateway允许私有子网
中的实例连接到 Internet,但阻止 Internet 与这些实例的连接。
上图中,我们在Subnet01中创建了NAT GW1
,然后在Subnet11中增加了一条路由表0.0.0.0/0 nat-gw-001
,此时DB1-1访问外网时:
先查路由表,发现要转发到nat-gw-001
nat-gw-001
将DB1-1过来的包进行处理,附加上源IP-源端口号-目的IP-目的端口号-协议
的五元组
nat-gw-001
查Subnet01的路由表,发现要转发到igw-001
, 通过igw将流量送出去
回程流量经过igw后,igw维护了NAT公网IP和私网IP的映射关系,以此找到nat-gw1
由于有五元组,回程的流量能被送到DB1-1
每个私有子网的连接经过NAT Gateway时,都要占用一个端口,而NAT Gateway最多支持55000个端口,所以私有子网的并发访问连接数超过55000时就会报错,这对于大流量的场景经常遇到。
解决方法是创建多个NAT Gateway,每个私有子网的路由表访问不同的NAT:
这样一来每个私有子网都可以单独拥有最大55000个并发访问的能力,但单个子网还是不能超出55000这个值。