(Я не имел дела с Амазоном, но и там та же петрушка, насколько я понимаю.)
Ответ: в общем, да.
В Azure решают проблему создания миллионов виртуальных сетей поверх единой физической благодаря протоколу VXLAN - если Ethernet-фрейм, посылаемый виртуалкой, предназначается для виртуалки на другом хосте, то он инкапсулируется виртуальным свитчем (процессом, бегущим на гипервизоре) внутрь UDP-пакета, и этот пакет доставляется по физической сети этому другому хосту. Там виртуальный свитч извлекает оригинальный фрейм и передаёт его своей виртуалке. Для обоих виртуальных машин всё выглядит так, словно они сидят в одном сегменте Ethernet.
Как в такой архитектуре можно передавать multicast или broadcast трафик? Два способа:
1. Рассовывать его по пакетам-носителям типа multicast и посылать их всем хостам, на которых определёна та же виртуальная Ethernet-сеть (насколько я понимаю, ей в Azure соответствует объект Subnet).
2. Рассовывать его по пакетам-носителям типа unicast и размножать их: посылать отдельную копию для каждого хоста из того же списка.
Обе опции проблемны. Допустим, у нас есть 1000 хостов, но из них виртуалки в этой сети существуют лишь на 20-ти. Тогда:
- В первом случае нам придётся доставлять пакет-носитель всей тысяче хостов. Раутеры и свитчи в физической сети между ними понятия не имеют, какие виртуальные сети существуют на каких хостах, и потому оптимизировать трафик, доставляя такой пакет лишь заинтересованным в нём хостам (подобно тому, как это делается функцией IGMP snooping в традиционных VLAN-ах) не могут. Стало быть, если у нас какая-то виртуалка сгенерирует multicast-поток в 100Mbps, то каждый хост в датацентре получит все эти 100Mbps, в большинстве случаев совершенно для него бесполезные.
- Во втором же случае поток в 100Mbps приведёт к тому, что хосту-отправителю придётся высылать 1.9Gbps (и даже слегка больше, учитывая overhead), высылая на каждый пакет с виртуалки девятнадцать своих, по одному на каждый хост с той же сетью.
Тут внимательный читатель воскликнет - позвольте, а как же ARP? Как же виртуалки будут узнавать MAC-адреса друг друга или раутеров, и что вообще будет писаться в поле "destination MAC" исходящих пакетов?
А вот что: на любой ARP-запрос с виртуалки vSwitch, то есть процесс, бегущий на хосте, ответит одним и тем же фальшивым MAC-адресом: 12:34:56:78:9a:bc. То есть любой пакет, на любой IP-адрес, будет послан виртуалкой на этот destination MAC.
Ну хорошо, а как же тогда пакеты доставлять? На адрес A в той же сети пакет ушёл с этим MAC, и на адрес B в ней же, и на адрес C в другой сети, и на адрес D вообще где-то в Интернете - и у всех MAC одинаковый. Что же с ним делать?
Ответ: а ничего не делать. Облаку плевать на MAC, доставка происходит прямо по IP-адресу получателя. То есть - к примеру, vSwitch получает от виртуалки пакет, где dst IP = 1.2.3.4 и dst MAC = 12:34:56:78:9a:bc. Если адрес 1.2.3.4 принадлежит другой виртуалке на том же хосте и той же сети, то пакет будет передан ей, и конец делу. Если же на другом хосте - то пакет будет обёрнут в VXLAN-пакет на адрес того хоста, и послан туда. Там, соответственно, будет декапсулирован и передан по назначению.
То есть традиционный Ethernet-свитчинг в Azure customer networks реально не используется - Ethernet лишь эмулируется для виртуалок. Этим эти сети отличаются от customer networks в OpenStack или CloudStack, где виртуальные и физические свитчи по-прежнему имеют дело с MAC-адресами.
Отсюда следуют несколько важных следствий:
1. Любой протокол не на основе IP (скажем, IPX, если кто ещё помнит такой) работать в Azure не может по определению.
2. Нельзя просто раздать виртуалкам дополнительные адреса (secondary IPs, loopback adapters) или передавать через них трафик из других сетей (скажем, использовать их для VPN) и ожидать, что всё будет работать. Нет. Облако должно знать, какие адреса относятся к каким машинам. Если машина посылает пакет с source IP, который ей не принадлежит и о котором облако не знает, он будет выкинут нафиг.
Есть два способа это починить:
- если этот source IP относится к тому же сабнету - то можно облаку указать его как secondary IP этой виртуалки.
- или же можно указать, что виртуалка занимается передачей чужого трафика (включить IP forwarding) и настроить на неё user-defined route (UDR), чтобы ответы на эти адреса приходили к ней. Обычно это делают, если виртуалка работает как firewall / VPN gateway.
И допустим, что вторая виртуалка работает VPN-гейтом, передавая трафик от удалённой сети 192.168.12.0/24.
Тогда чтобы позволить первой машинке общаться с этой удалённой сетью, в обычных сетях нам надо было бы определить на ней маршрут через вторую:
route -p add 192.168.12.0/24 10.10.10.12
Но в Azure в этом нет необходимости. Поскольку в тот момент, что первая виртуалка пошлёт пакет на адрес, скажем, 192.168.12.222 - будет совершенно неважно, имела ли она в мыслях передать его напрямую, или на дефолтовый гейт 10.10.10.1, или на VPN-гейт 10.10.10.12, и чей именно MAC-адрес она запрашивала по ARP миллисекундой ранее. Пакет будет выглядеть совершенно одинаково:
src IP = 10.10.10.11, dst IP = 192.168.12.222
src MAC = some_MAC_of_VM1, dst MAC = 12:34:56:78:9a:bc
После чего произойдёт следующее: vSwitch проверит свою таблицу маршрутов и узрит в ней user-defined route: на сеть 192.168.12.0/24 ступай через 10.10.10.12. После чего пакет передан второй виртуалке - либо напрямую, если она на том же хосте, что и первая, либо, если она на другом хосте - то через туннель VXLAN между этими хостами.
Вот такие пироги.
No comments:
Post a Comment