EC2:如何通过SDK将多个弹性IP分配给单个networking接口

有谁知道如何通过Amazon SDK将多个弹性IP关联到单个实例? 在Ruby中,我试图使用aws-sdk和雾gem,它们对于单个地址工作正常,但试图分配多个错误。

通过networking用户界面,这将通过添加额外的私人IPS,然后分配公共IP到networking接口+私人IP,但我没有任何私人IP参数在SDK中。

弹性IP工作

默认情况下,VPC中的实例只会从VPC中的私有子网(通常位于10.0.0.0/8子网中的某个位置)获取IP。 这意味着虽然这些实例可以访问同一子网内的其他实例,但它们将无法连接到更广泛的互联网。

让每台机器都能访问的一种方法是设置一台所有机器用来路由stream量的NAT机器。 我们不会深入这个选项。

另一种方法是为每台机器提供自己的可全球路由的弹性IP地址。 亚马逊将路由stream量到您的内部IP弹性ip。 这使得从networking拓扑的angular度来看,这个设置更简单。

VPC中的路由通过为每个子网设置的路由表工作。 您可以在AWS控制台的VPC选项卡中查看您的路由表。 默认情况下,子网内的请求将在本地路由,而范围之外的请求将通过“Internet网关”路由。

例如,假设您有一个IP 10.0.0.1的实例。 它有一个与之相关的弹性IP,比如说1.2.3.4。 现在,只要访问10.0.0.0/8子网中的其他内部计算机,您的请求将来自您的私有IP,并且stream量不会发生任何变化。

当您访问子网之外的机器时,数据包将通过Internet网关(一个名称为igw-9d7534f2的VPC设备)进行路由。 网关(不是实际的EC2实例,只是一个不透明的AWS系统)接受请求,然后查找请求源自的内部IP,并检查这个IP是否与任何弹性IP相关联。 如果是这样的话,这个请求就会被重写,就好像它的起源是有弹性的IP,然后通过互联网发送出去。 当一个包以一个弹性IP作为目的地返回到网关时,网关会检查弹性IP是否与一个内部IP相关联,如果是,则将该包重写为该IP。 该包然后被转发到私有子网中。

这就是弹性IP的一对一NAT工作原理。 这种方法的优点是子网内的机器不需要知道其弹性IP。 这使得切换正在运行的实例的弹性IP变得容易,因为唯一需要更新的是Internet网关上的映射表。 外部IP可以多次改变; 因为在到达实例之前软件包被重写为使用内部IP,所以实例永远不会知道这一点。

多个networking接口

在过去,亚马逊增加了一个选项,将多个networking接口添加到VPC实例。 这些接口在您的计算机上显示为单独的以太网卡,并具有单独的内部IP。 单独的接口也意味着您需要正确设置这些接口之间的路由:如果通过错误的接口发送数据包,数据包将被简单地丢弃。

这些networking接口是为了给你提供连接不同子网的选项:你可以在每个子网上有一个接口,然后按照你的喜好在它们之间路由交通。 由于每个子网都有自己的IP范围,所以很容易将stream量路由到正确的networking接口。

对于每个内部IP,可以关联一个外部弹性IP。 虽然这是可能的,但是现在您会遇到一些棘手的路由情况。 内部IP(在eth0和eth1上)都有一个关联的外部IP,并且应该能够通过让Internet网关将其内部IP转换为弹性IP来向更广泛的互联网发送请求。 但是,为了正确执行此操作,请求必须通过正确的界面发送出去。 亚马逊自己也承认这并不简单:

默认情况下,Linux有一个路由表,可将本地子网外部的所有stream量路由到单个接口。 你可以用route来查看:

# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default 10.0.0.1 0.0.0.0 UG 0 0 0 eth0 default 10.0.0.1 0.0.0.0 UG 100 0 0 eth0 10.0.0.0 * 255.255.255.0 U 0 0 0 eth0 10.0.0.0 * 255.255.255.0 U 0 0 0 eth1 

在这里,所有的互联网范围内的stream量将通过接口eth0。 即使是eth1接口的源IP地址的数据包也会通过eth0出去,然后会被默默丢弃,而不是NAT到正确的弹性IP。 尽pipe可以使用基于源代码的路由来解决这个问题,但这并不是一件容易的事情(注意在将另一个接口添加到机器上之后,需要运行dhclient):

 # ifconfig | grep eth\\\|inet\ eth0 Link encap:Ethernet HWaddr 02:86:10:77:7f:fe inet addr:10.0.0.76 Bcast:10.0.0.255 Mask:255.255.255.0 eth1 Link encap:Ethernet HWaddr 02:86:10:65:fd:31 inet addr:10.0.0.226 Bcast:10.0.0.255 Mask:255.255.255.0 # curl --interface 10.0.0.76 ifconfig.me 116.xxx # curl --interface 10.0.0.226 ifconfig.me << TIMEOUT >>> # ip rule add from 10.0.0.226 table out2 # ip route add default via 10.0.0.1 dev eth1 table 2 # ip route flush cache # curl --interface 10.0.0.226 ifconfig.me 116.xxx # curl --interface 10.0.0.76 ifconfig.me 116.xxx 

多个IP地址

这样我们就可以避免上面的一些路由问题了:所有的数据包将通过eth0发送,而不pipe你拥有哪个IP。 由于公有和私人地址的一对一映射,您首先需要为您的某个实例添加一些新的专用地址。

亚马逊的API已更新为支持分配次要私有IP,但对于此示例,只需转到AWS控制台即可。 在EC2选项卡中,转到实例。 find要更新的实例,右键单击并select“pipe理私有IP地址”。

在这里输入图像说明

在这里输入图像说明

现在你会看到这个实例在你的子网中有两个私有IP(因为一个接口被locking到特定的子网,那个接口上的所有的IP都必须属于同一个子网)。 太好了! 但是,如果您现在检查您的实例:

 # ifconfig eth0 eth0 Link encap:Ethernet HWaddr 02:86:10:7b:e4:f5 inet addr:10.0.0.34 Bcast:10.0.0.255 Mask:255.255.255.0 

它不会有新的IP。 让我们尝试通过DHCP检索它!

 root@ip-10-0-0-34:/# dhclient -d eth0 Listening on LPF/eth0/02:86:10:7b:e4:f5 Sending on LPF/eth0/02:86:10:7b:e4:f5 DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 3 DHCPREQUEST of 10.0.0.34 on eth0 to 255.255.255.255 port 67 DHCPOFFER of 10.0.0.34 from 10.0.0.1 DHCPACK of 10.0.0.34 from 10.0.0.1 

不,我们只得到我们的主要私人IP! 使用DHCP,你只能得到一个地址。 将来,Amazon可能会使用某些客户端标识符或其他机制来添加对多个IP的支持,但是现在您必须手动添加地址。 希望Ubuntu的cloud-init将在未来增加对此的支持,所以我们不必自己做。

亚马逊build议创build一个新的虚拟接口,然后把它。 虽然这样做会起作用,但这意味着您将接口状态存储在硬盘驱动器上,并且您在AWS上所做的任何更改都必须传播到这些文件。

为了testing,我们可以做一些简单的事情:

 MAC_ADDR=$(ifconfig eth0 | sed -n 's/.*HWaddr \([a-f0-9:]*\).*/\1/p') IP=($(curl http://169.xxx/latest/meta-data/network/interfaces/macs/$MAC_ADDR/local-ipv4s)) for ip in ${IP[@]:1}; do echo "Adding IP: $ip" ip addr add dev eth0 $ip/24 done 

这将检查与eth0关联的所有内部IP的EC2实例元数据,并添加所有的辅助IP。

您现在可以在AWS控制台中将另一个弹性ip分配给辅助IP:

在这里输入图像说明

而现在你有多个外部IP!

 root@ip-10-0-0-34:/# curl --interface 10.0.0.58 ifconfig.me 116.xxx root@ip-10-0-0-34:/# curl --interface 10.0.0.34 ifconfig.me 116.xxx 

虽然这适用于testing,但在重新启动时不会持久。 您可以创build一个暴发户或云初始化脚本为您做。 即使这样,通过EC2添加IP地址也不会自动添加。 我不确定是否有一个很好的方法来做到这一点。 最后,这个脚本也不会删除你在此期间删除的任何本地地址。

希望这会帮助你。