Привет, меня зовут Костя Крамлих, я ведущий разработчик подразделения Virtual Private Cloud в Яндекс.Облаке. Я занимаюсь виртуальной сетью, и, как можно догадаться, в этой статье расскажу об устройстве Virtual Private Cloud (VPC) в целом и виртуальной сети в частности. А ещё вы узнаете, почему мы, разработчики сервиса, ценим обратную связь от наших пользователей. Но обо всём по порядку.



Что такое VPC?


В наше время для разворачивания сервисов есть самые разные возможности. Уверен, кто-то до сих пор держит сервер под столом администратора, хотя, надеюсь, таких историй становится всё меньше.

Сейчас сервисы стараются уходить в публичные облака, и как раз тут они сталкиваются с VPC. VPC – это часть публичного облака, которая провязывает пользовательские, инфраструктурные, платформенные и прочие мощности воедино, где бы они ни находились, в нашем Облаке или за его пределами. При этом VPC позволяет не выставлять без необходимости эти мощности в интернет, они остаются в пределах вашей изолированной сети.

Как виртуальная сеть выглядит снаружи




Под VPC мы понимаем прежде всего оверлейную сеть и сетевые сервисы, такие как VPNaaS, NATaas, LBaas и т. д. И всё это работает поверх отказоустойчивой сетевой инфраструктуры, о которой уже была отличная статья здесь же, на Хабре.

Давайте посмотрим на виртуальную сеть и ее устройство повнимательнее.



Рассмотрим две зоны доступности. Мы предоставляем виртуальную сеть – то, что мы назвали VPC. Фактически она определяет пространство уникальности ваших «серых» адресов. В рамках каждой виртуальной сети вы полностью управляете пространством адресов, которые можете назначать вычислительным ресурсам.

Сеть глобальна. При этом она проецируется на каждую из зон доступности в виде сущности под названием Subnet. Для каждой Subnet вы назначаете некий CIDR размером 16 или меньше. В каждой зоне доступности может быть больше одной такой сущности, при этом между ними всегда есть прозрачный routing. Это значит, что все ваши ресурсы в пределах одной VPC могут «общаться» друг с другом, даже если они находятся в разных зонах доступности. «Общаться» без выхода в интернет, по нашим внутренним каналам, «думая», что находятся в пределах одной частной сети.

На схеме выше показана типичная ситуация: две VPC, которые где-то пересекаются по адресам. Обе могут принадлежать вам. Например, одна для разработки, другая – для тестирования. Могут быть просто разные пользователи – в данном случае это неважно. И в каждую VPC воткнуто по одной виртуальной машине.



Усугубим схему. Можно сделать так, чтобы одна виртуальная машина втыкалась сразу в несколько Subnet. И не просто так, а в разных виртуальных сетях.



При этом, если вам нужно выставить машины в интернет, это можно сделать через API или UI. Для этого необходимо настроить трансляцию NAT вашего «серого», внутреннего адреса, в «белый» – публичный. Выбрать «белый» адрес вы не можете, он назначается случайным образом из нашего пула адресов. Как только вы перестаёте пользоваться внешним IP, он возвращается в пул. Платите вы только за время использования «белого» адреса.



Также есть возможность выдать машине доступ в интернет с помощью NAT-инстанса. На инстанс можно зароутить трафик через статическую таблицу маршрутизации. Мы предусмотрели такой кейс, потому что он бывает нужен пользователям, и мы об этом знаем. Соответственно, в нашем каталоге образов лежит специально сконфигурированный NAT-образ.



Но даже когда есть готовый NAT-образ, настройка может быть сложной. Мы понимали, что для некоторых пользователей это не самый удобный вариант, поэтому в итоге сделали возможность включать NAT для нужной Subnet в один клик. Эта фича пока ещё в закрытом preview-доступе, где обкатывается с помощью участников сообщества.

Как виртуальная сеть устроена изнутри





Как взаимодействует с виртуальной сетью пользователь? Сеть смотрит наружу своим API. Пользователь приходит в API и работает с целевым состоянием. Через API пользователь видит, как всё должно быть устроено и настроено, при этом он видит статус, насколько действительное состояние отличается от желаемого. Это картина пользователя. А что происходит внутри?

Мы записываем желаемое состояние в Yandex Database и идем конфигурировать разные части нашей VPC. Оверлейная сеть в Яндекс.Облаке построена на основе избранных компонентов OpenContrail, который с недавнего времени носит название Tungsten Fabric. Сетевые сервисы реализованы на единой платформе CloudGate. В CloudGate мы тоже использовали некоторое количество open source компонентов: GoBGP – для обращения контрольной информации, а также VPP – для реализации программного роутера, работающего поверх DPDK для data path.

Tungsten Fabric общается с CloudGate через GoBGP. Рассказывает, что происходит в оверлейной сети. CloudGate, в свою очередь, связывает оверлейные сети друг с другом и с интернетом.



Теперь давайте посмотрим, как виртуальная сеть решает задачи масштабирования и доступности. Рассмотрим простой случай. Вот есть одна зона доступности и в ней созданы две VPC. Мы развернули один инстанс Tungsten Fabric, и он тянет в себе несколько десятков тысяч сетей. Сети связываются с CloudGate. CloudGate, как мы уже говорили, обеспечивает их связанность между собой и с интернетом.



Допустим, добавляется вторая зона доступности. Она должна выходить из строя совершенно независимо от первой. Поэтому во второй зоне доступности мы должны поставить отдельный инстанс Tungsten Fabric. Это будет отдельная система, которая занимается оверлеем и мало что знает о первой системе. А видимость, что наша виртуальная сеть глобальна, собственно, и создаёт наш VPC API. Это его задача.

VPC1 проецируется в зону доступности B, если в зоне доступности B есть ресурсы, которые втыкаются в VPC1. Если ресурсов из VPC2 в зоне доступности B нет, VPC2 в этой зоне мы не материализуем. В свою очередь, поскольку ресурсы из VPC3 существуют только в зоне B, VPC3 нет в зоне A. Всё просто и логично.

Давайте пойдём немного глубже и посмотрим, как устроен конкретный хост в Я.Облаке. Главное, что хочется отметить, – все хосты устроены одинаково. Мы делаем так, что только необходимый минимум сервисов крутится на «железе», все остальные работают на виртуальных машинах. Мы строим сервисы более высокого порядка на основе базовых инфраструктурных сервисов, а также используем Облако для решения некоторых инженерных задач, например, в рамках Continuous Integration.



Если мы посмотрим на конкретный хост, мы увидим, что в ОС хоста крутятся три компонента:
  • Compute – часть, отвечающая за распределение вычислительных ресурсов на хосте.
  • VRouter – часть Tungsten Fabric, которая организует оверлей, то есть туннелирует пакеты через андерлей (underlay).
  • VDisk – это куски виртуализации хранилища.

Кроме этого в виртуальных машинах запущены сервисы: инфраструктурные сервисы Облака, платформенные сервисы и мощности заказчиков. Мощности заказчиков и платформенные сервисы всегда ходят в оверлей через VRouter.

Инфраструктурные сервисы могут втыкаться в оверлей, но в основном хотят работать именно в андерлее. В андерлей они втыкаются с помощью SR-IOV. Фактически мы режем карту на виртуальные сетевые карточки (виртуальные функции) и просовываем их в инфраструктурные виртуалки, чтобы не терять производительность. Например, тот самый CloudGate запущен в виде одной из таких инфраструктурных виртуальных машин.

Теперь, когда мы описали глобальные задачи виртуальной сети и устройство базовых компонентов облака, давайте посмотрим, как именно разные части виртуальной сети взаимодействуют друг с другом.

Мы выделяем в нашей системе три слоя:
  • Config Plane – задает целевое состояние системы. Это то, что конфигурирует пользователь через API.
  • Control Plane – обеспечивает заданную пользователем семантику, то есть доводит состояние Data Plane до того, что было описано пользователем в Config Plane.
  • Data Plane – непосредственно обрабатывает пакеты пользователя.



Как я уже говорил выше, все начинается с того, что пользователь или внутренний платформенный сервис приходит в API и описывает определенное целевое состояние.

Это состояние сразу записывается в Yandex Database, возвращает через API ID асинхронной операции и запускает нашу внутреннюю машинерию, чтобы выдать состояние, которое хотел пользователь. Конфигурационные таски идут в SDN-контроллер и рассказывают Tungsten Fabric, что нужно сделать в оверлее. Например, они резервируют порты, виртуальные сети и тому подобное.



Config Plane в Tungsten Fabric отгружает в Control Plane требуемое состояние. Через него же Config Plane общается с хостами, рассказывая, что именно на них будет крутиться в скором времени.



Теперь посмотрим, как выглядит система на хостах. В виртуальной машине есть некий сетевой адаптер, воткнутый в VRouter. VRouter – это ядерный модуль Tungsten Fabric, который смотрит на пакеты. Если для некоторого пакета уже есть flow, модуль его обрабатывает. Если flow нет, модуль делает так называемый punting, то есть посылает пакет в юзермод-процесс. Процесс разбирает пакет и либо отвечает на него сам, как, например, на DHCP и DNS, либо говорит VRouter, что с ним делать. После этого VRouter может обрабатывать пакет.

Дальше трафик между виртуальными машинами в пределах одной виртуальной сети ходит прозрачно, он не направляется на CloudGate. Хосты, на которых развернуты виртуальные машины, общаются друг с другом напрямую. Туннелируют трафик и прокидывают его друг для друга через андерлей.



Control Plane общаются друг с другом между зонами доступности по BGP, как с другим роутером. Они рассказывают, какие машины где подняты, чтобы виртуальные машины в одной зоне могли напрямую взаимодействовать с другими виртуальными машинами.



А ещё Control Plane общается с CloudGate. Аналогично сообщает, где и какие виртуалки подняты, какие у них адреса. Это позволяет направлять на них внешний трафик и трафик от балансировщиков.

Трафик, который выходит из VPC, приходит на CloudGate, в data path, где быстро пережевывается VPP с нашими плагинами. Дальше трафик выстреливается либо в другие VPC, либо наружу, в пограничные маршрутизаторы, которые настраиваются через Control Plane самого CloudGate.

Планы на ближайшее будущее


Если обобщить все сказанное выше в нескольких предложениях, можно сказать, что VPC в Яндекс.Облаке решает две важные задачи:

  • Обеспечивает изоляцию между разными клиентами.
  • Объединяет ресурсы, инфраструктуру, платформенные сервисы, другие облака и on-premise в единую сеть.

А чтобы решать эти задачи хорошо, нужно обеспечивать масштабируемость и отказоустойчивость на уровне внутренней архитектуры, что VPC и делает.

Постепенно VPC обрастает функциями, мы реализуем новые возможности, стараемся улучшать что-то в плане удобства для пользователей. Некоторые идеи озвучиваются и попадают в лист приоритетов благодаря участниками нашего сообщества.

Сейчас у нас примерно такой список планов на ближайшее будущее:

  • VPN как сервис.
  • Private DNS инстансы – образы для быстрой настройки виртуальных машин с заранее сконфигурированным DNS-сервером.
  • DNS как сервис.
  • Внутренний балансировщик нагрузки.
  • Добавление «белого» IP-адреса без пересоздания виртуальной машины.

Балансировщик и возможность переключать IP-адрес для уже созданной виртуалки оказались в этом перечне по запросу пользователей. Скажу честно, без явной обратной связи мы взялись бы за эти функции несколько позже. А так мы уже работаем над задачей про адреса.

Изначально «белый» IP-адрес можно было добавить только при создании машины. Если пользователь забывал это сделать, виртуальную машину приходилось пересоздавать. То же самое и при необходимости убрать внешний IP. Скоро можно будет включить и выключить публичный IP, не пересоздавая машину.

Не стесняйтесь высказывать свои идеи и поддерживать предложения других пользователей. Вы помогаете нам делать Облако лучше и быстрее получаете важные и полезные функции!