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. Я не уверен, есть ли хороший способ сделать это. Наконец, этот скрипт также не удалит все локальные адреса, которые вы могли удалить за это время.

Надеюсь, что это поможет вам.

Другие вопросы по тегам