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

jon*_*ini 3 ruby amazon-ec2 amazon-web-services sdk

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

通过 Web UI,这可以通过添加额外的私有 ip,然后将公共 ip 分配给网络接口 + 私有 ip 来完成,但是我在 SDK 中没有任何私有 ip 参数。

小智 5

弹性IP工作正常

\n\n

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

\n\n

为每台计算机提供访问权限的一种方法是设置一台 NAT 计算机,所有计算机都使用该计算机来路由流量。我们不会\xe2\x80\x99 更深入地讨论这个选项。

\n\n

另一种方法是为每台计算机提供其\xe2\x80\x99 自己的全球可路由的弹性 IP 地址。Amazon 会将弹性 IP 的流量路由到您的内部 IP。从网络拓扑的角度来看,这使得此设置更简单。

\n\n

VPC 中的路由通过为每个子网设置的路由表进行工作。您可以在 AWS 控制台的 VPC 选项卡中查看路由表。默认情况下,子网内的请求在本地路由,该范围之外的请求通过 \xe2\x80\x98internet gateway\xe2\x80\x99 路由。

\n\n

例如,令\xe2\x80\x99s 表示您有一个 IP 为 10.0.0.1 的实例。它有一个与之关联的弹性 IP,假设\xe2\x80\x99s 为 1.2.3.4。现在,每当您访问 10.0.0.0/8 子网上的其他内部计算机时,您的请求都将源自您的私有 IP,并且流量不会发生任何变化。

\n\n

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

\n\n

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

\n\n

多个网络接口

\n\n

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

\n\n

引入这些网络接口是为了让您可以选择将不同的子网连接在一起:您可以在每个子网中拥有一个接口,然后根据需要在它们之间路由流量。由于每个子网都有自己的 IP 范围,因此可以轻松地将流量路由到正确的网络接口。

\n\n

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

\n\n

默认情况下,Linux 有一个路由表,它将本地子网之外的所有流量路由到单个接口。您可以使用路线查找:

\n\n
# route\nKernel IP routing table\nDestination     Gateway         Genmask         Flags Metric Ref    Use Iface\ndefault         10.0.0.1        0.0.0.0         UG    0      0        0 eth0\ndefault         10.0.0.1        0.0.0.0         UG    100    0        0 eth0\n10.0.0.0        *               255.255.255.0   U     0      0        0 eth0\n10.0.0.0        *               255.255.255.0   U     0      0        0 eth1\n
Run Code Online (Sandbox Code Playgroud)\n\n

在这里,所有互联网范围内的流量都将通过接口 eth0 流出。即使源 ip 为 eth1 接口的数据包也会通过 eth0 发出,然后将被静默丢弃,而不是通过 NAT\xe2\x80\x99d 到正确的弹性 IP。虽然可以通过基于源的路由来解决此问题,但设置起来并不简单(请注意,您需要在向计算机添加另一个接口后运行 dhclient):

\n\n
# ifconfig | grep eth\\\\\\|inet\\ \neth0      Link encap:Ethernet  HWaddr 02:86:10:77:7f:fe  \n          inet addr:10.0.0.76  Bcast:10.0.0.255  Mask:255.255.255.0\neth1      Link encap:Ethernet  HWaddr 02:86:10:65:fd:31  \n          inet addr:10.0.0.226  Bcast:10.0.0.255  Mask:255.255.255.0\n\n# curl --interface 10.0.0.76 ifconfig.me\n116.x.x.x\n# curl --interface 10.0.0.226 ifconfig.me\n<< TIMEOUT >>>\n\n# ip rule add from 10.0.0.226 table out2\n# ip route add default via 10.0.0.1 dev eth1 table 2\n# ip route flush cache\n\n# curl --interface 10.0.0.226 ifconfig.me\n116.x.x.x\n# curl --interface 10.0.0.76 ifconfig.me\n116.x.x.x\n
Run Code Online (Sandbox Code Playgroud)\n\n

多个IP地址

\n\n

这样我们就可以避免上面的一些路由问题:所有数据包都将通过 eth0 发送,无论您拥有哪个 IP。由于公共地址和私有地址是一对一映射的,因此您首先需要向其中一个实例添加一些新的私有地址。

\n\n

Amazon\xe2\x80\x99s API 已更新为支持分配辅助私有 IP\xe2\x80\x99s,但对于此示例,\xe2\x80\x99s 更容易直接转到 AWS 控制台。在 EC2 选项卡中,转到实例。找到要更新的实例,右键单击并选择\xe2\x80\x9c管理私有IP地址\xe2\x80\x9d。

\n\n

在此输入图像描述

\n\n

在此输入图像描述

\n\n

您\xe2\x80\x99现在将看到该实例在您的子网中有两个私有IP\xe2\x80\x99(由于接口被锁定到特定子网,因此该接口上的所有IP\xe2\x80\x99都必须落入相同的子网)。好的!但是,如果您现在检查您的实例:

\n\n
# ifconfig eth0\neth0      Link encap:Ethernet  HWaddr 02:86:10:7b:e4:f5  \n          inet addr:10.0.0.34  Bcast:10.0.0.255  Mask:255.255.255.0\n
Run Code Online (Sandbox Code Playgroud)\n\n

它\xe2\x80\x99还没有新的IP。让\xe2\x80\x99s 尝试通过 DHCP 检索它!

\n\n
root@ip-10-0-0-34:/# dhclient -d eth0\nListening on LPF/eth0/02:86:10:7b:e4:f5\nSending on   LPF/eth0/02:86:10:7b:e4:f5\nDHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 3\nDHCPREQUEST of 10.0.0.34 on eth0 to 255.255.255.255 port 67\nDHCPOFFER of 10.0.0.34 from 10.0.0.1\nDHCPACK of 10.0.0.34 from 10.0.0.1\n
Run Code Online (Sandbox Code Playgroud)\n\n

不,我们只获得我们的主要私有 IP!使用 DHCP,您只能获得一个地址。将来,亚马逊也许会使用某些客户端标识符或其他机制添加对多个 IP\xe2\x80\x99 的支持,但现在您\xe2\x80\x99 必须手动添加地址。希望 Ubuntu\xe2\x80\x99s cloud-init 将来会添加对此的支持,所以我们不必\xe2\x80\x99自己做。

\n\n

亚马逊建议创建一个新的虚拟界面,然后将其提出。虽然这可行,但这意味着您将接口状态存储在硬盘上,并且您在 AWS 上所做的任何更改都必须传播到这些文件。

\n\n

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

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

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

\n\n

您现在可以在 AWS 控制台中将另一个弹性 IP 关联到辅助 IP:

\n\n

在此输入图像描述

\n\n

现在你有多个外部IP\xe2\x80\x99s!

\n\n
root@ip-10-0-0-34:/# curl --interface 10.0.0.58 ifconfig.me\n116.x.x.x\nroot@ip-10-0-0-34:/# curl --interface 10.0.0.34 ifconfig.me\n116.x.x.x\n
Run Code Online (Sandbox Code Playgroud)\n\n

虽然这适用于测试,但它\xe2\x80\x99在重新启动后不会持续存在。您可以创建一个 upstart 或 cloud-init 脚本来为您执行此操作。即使这样,当您通过 EC2 添加 IP 地址时,也不会自动添加\xe2\x80\x99。我\xe2\x80\x99m 不确定是否有\xe2\x80\x99s 一个好方法来做到这一点。最后,此脚本也不会\xe2\x80\x99 删除您可能同时删除的任何本地地址。

\n\n

希望对你有帮助。

\n

  • 如果您要无耻地复制粘贴别人的工作,我强烈建议您至少参考一下他们​​:http://engineering.silk.co/post/31923247961/multiple-ip-addresses-在亚马逊 EC2 上 (4认同)