EC2: как назначить несколько эластичных IP-адресов одному сетевому интерфейсу через SDK
Кто-нибудь знает, как связать несколько Elastic IP-адресов с одним экземпляром через Amazon SDK? В Ruby я попытался использовать как aws-sdk, так и fog, которые отлично работают для одного адреса, но из-за ошибки пытались назначить несколько.
Через веб-интерфейс это можно сделать, добавив дополнительные частные IP-адреса, а затем назначив общий IP-адрес сетевому интерфейсу + частный IP-адрес, однако я не являюсь частным параметром IP-адреса в SDK.
1 ответ
Эластичные IP работают
По умолчанию экземпляр в VPC получает IP-адрес только из частной подсети внутри VPC, обычно где-то в подсети 10.0.0.0/8. Это означает, что, хотя эти экземпляры могут обращаться к другим экземплярам в той же подсети, они не смогут подключаться к более широкому Интернету.
Одним из способов предоставления доступа каждой машине является настройка машины NAT, которую все машины используют для маршрутизации трафика. Мы не будем углубляться в этот вариант.
Альтернативой является предоставление каждой машине своего собственного универсального IP-адреса. Amazon перенаправит трафик на эластичный ip на ваш внутренний IP. Это упрощает настройку с точки зрения топологии сети.
Маршрутизация в VPC работает через таблицы маршрутизации, которые настраиваются для каждой подсети. Вы можете просмотреть свою таблицу маршрутизации на вкладке VPC консоли AWS. По умолчанию запросы в вашей подсети маршрутизируются локально, а запросы вне этого диапазона направляются через "интернет-шлюз".
Например, предположим, что у вас есть экземпляр с IP 10.0.0.1. С ним связан Elastic IP, скажем, 1.2.3.4. Теперь, когда вы обращаетесь к другим внутренним машинам в подсети 10.0.0.0/8, ваш запрос будет исходить из вашего личного IP-адреса, и с трафиком ничего не произойдет.
Когда вы получаете доступ к машине за пределами вашей подсети, пакеты маршрутизируются через интернет-шлюз, устройство VPC с именем, например, igw-9d7534f2. Шлюз (который не является действительным экземпляром EC2, просто непрозрачная система AWS) принимает запрос, а затем ищет внутренний IP-адрес, с которого исходит запрос, и проверяет, связан ли этот IP-адрес с каким-либо Elastic IP-адресом. Если это так, запрос переписывается так, чтобы он выглядел так, как если бы источником был эластичный IP, а затем отправлялся через Интернет. Когда пакет возвращается к шлюзу с эластичным IP-адресом в качестве пункта назначения, шлюз проверяет, связан ли эластичный IP-адрес с внутренним IP-адресом, и, если это так, перезаписывает пакет на этот IP-адрес. Затем пакет перенаправляется в частную подсеть.
Так работает индивидуальный NAT эластичных IP. Преимущество этого подхода заключается в том, что машинам внутри подсети не нужно знать свои эластичные IP-адреса. Это позволяет легко переключать эластичные IP-адреса работающего экземпляра, поскольку единственное, что необходимо обновить, - это таблица сопоставления на интернет-шлюзе. Внешний IP может меняться много раз; поскольку пакеты переписываются для использования внутренних IP-адресов до того, как они попадут в экземпляр, экземпляр никогда не узнает об этом.
Несколько сетевых интерфейсов
В прошлом Amazon добавлял возможность добавления нескольких сетевых интерфейсов к экземпляру VPC. Эти интерфейсы отображаются в виде отдельных сетевых карт на вашем компьютере и имеют отдельный внутренний IP-адрес. Отдельные интерфейсы также означают, что вам необходимо правильно настроить маршрутизацию между этими интерфейсами: если вы отправите пакет через неправильный интерфейс, пакет будет просто отброшен.
Эти сетевые интерфейсы были введены, чтобы дать вам возможность соединять различные подсети вместе: вы можете иметь один интерфейс в каждой подсети, а затем маршрутизировать трафик между ними, как вам нравится. Поскольку каждая подсеть имеет свой собственный диапазон IP-адресов, легко направить трафик к нужному сетевому интерфейсу.
Для каждого внутреннего IP можно связать внешний Elastic IP. Хотя это возможно, теперь вы попадаете в сложную ситуацию с маршрутизацией. Оба внутренних IP-адреса (на eth0 и eth1) имеют связанный внешний IP-адрес и должны иметь возможность отправлять запросы в более широкий Интернет, поскольку интернет-шлюз преобразует их внутренний IP-адрес в Elastic IP-адрес. Однако для того, чтобы сделать это правильно, запросы должны быть отправлены через правильный интерфейс. Сам Amazon признает, что это не просто:
По умолчанию в Linux есть таблица маршрутизации, которая направляет весь трафик за пределы вашей локальной подсети в один интерфейс. Вы можете посмотреть это с помощью маршрута:
# 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
Здесь весь интернет-трафик будет выходить через интерфейс eth0. Даже пакеты с исходным ip интерфейса eth1 будут выходить за пределы eth0, а затем будут автоматически отбрасываться вместо того, чтобы преобразовываться в NAT для правильного эластичного IP. Хотя это можно сделать с помощью маршрутизации на основе исходного кода, это не так просто настроить (обратите внимание, что вам нужно запустить 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.x.x.x
# 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.x.x.x
# curl --interface 10.0.0.76 ifconfig.me
116.x.x.x
Несколько IP-адресов
Таким образом, мы можем избежать некоторых проблем с маршрутизацией сверху: все пакеты будут отправляться через eth0 независимо от того, какой у вас IP. Из-за взаимно однозначного сопоставления общедоступных и личных адресов сначала необходимо добавить несколько новых частных адресов в один из ваших экземпляров.
API Amazon был обновлен для поддержки назначения вторичных частных IP-адресов, но для этого примера проще перейти на консоль AWS. На вкладке EC2 перейдите к Экземплярам. Найдите экземпляр, который вы хотите обновить, щелкните правой кнопкой мыши и выберите "Управление частными IP-адресами".
Теперь вы увидите, что у экземпляра есть два частных IP-адреса в вашей подсети (поскольку интерфейс заблокирован для определенной подсети, все 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 добавит поддержку для этого, поэтому нам не нужно делать это самим.
Amazon предлагает создать новый виртуальный интерфейс, а затем поднять его. Хотя это будет работать, это означает, что вы сохраняете состояние вашего интерфейса на жестком диске, и любые изменения, которые вы вносите в AWS, вам придется распространять на эти файлы.
Для тестирования мы можем сделать что-то попроще:
MAC_ADDR=$(ifconfig eth0 | sed -n 's/.*HWaddr \([a-f0-9:]*\).*/\1/p')
IP=($(curl http://169.x.x.x/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
Это проверит метаданные экземпляра EC2 для всех внутренних IP-адресов, связанных с eth0, и добавит все вторичные IP-адреса.
Теперь вы можете назначить другой эластичный IP-адрес дополнительному IP-адресу в консоли AWS:
И теперь у вас есть несколько внешних IP-адресов!
root@ip-10-0-0-34:/# curl --interface 10.0.0.58 ifconfig.me
116.x.x.x
root@ip-10-0-0-34:/# curl --interface 10.0.0.34 ifconfig.me
116.x.x.x
Хотя это работает для тестирования, оно не является постоянным при перезагрузке. Вы можете создать сценарий upstart или cloud-init, чтобы сделать это за вас. Даже тогда IP-адреса не добавляются автоматически, когда вы добавляете их через EC2. Я не уверен, есть ли хороший способ сделать это. Наконец, этот скрипт также не удалит все локальные адреса, которые вы могли удалить за это время.
Надеюсь, что это поможет вам.