Сетевой стек Hetzner Cloud — история и технический обзор

Эта статья — первая часть серии материалов, посвященных эволюции сетевых стеков, лежащих в основе Hetzner Cloud, и их архитектуры. В этой статье мы рассмотрим проделанную нами разработку и то, как работает текущий сетевой стек на основе Open vSwitch. Хотя сетевой стек для облачных серверов и балансировщиков нагрузки схож, мы сосредоточимся на облачных серверах и хостах виртуализации (хостах виртуальных машин), поскольку они предоставляют больше сервисов и функций.
Для краткости мы исключим из рассмотрения плоскость управления облаком, которая управляет всеми серверами, балансировщиками нагрузки, частными сетями и т.д., и рассмотрим только сетевой стек на хостах.
Как мы работаем
Для работы всех облачных продуктов необходимы универсальные и надежные варианты подключения, чтобы наши клиенты и, возможно, их клиенты могли получать доступ к сервисам, работающим в нашей сети.
В компании Hetzner мы в целом верим в решения, которыми владеем и можем управлять самостоятельно, а также в наличие базовых элементов, на основе которых можно строить дальнейшие проекты. Сеть, и особенно сетевое подключение для наших облачных сервисов, не является исключением.
Хотя технологии за эти годы изменились, мы всегда отдавали предпочтение решениям, где движущиеся части находятся на хостах, а не сложной и замысловатой физической сетевой инфраструктуре. В результате мы разработали систему таким образом, чтобы физическая сеть обеспечивала стабильное IP-соединение с хостами, а хосты предоставляли сетевые функции более высокого уровня. К ним относятся межсетевые экраны, частные сети и вспомогательные инфраструктурные сервисы.
Запуская эти сервисы и сетевые функции на хостах, мы получаем большую свободу и гибкость при проектировании и создании нашего продукта, и не ограничиваемся тем, что предлагают поставщики оборудования. Таким образом, мы обеспечиваем четкое разделение задач между командами и технологиями и можем ограничить зону поражения одним хостом в случае (большинства) ошибок. Это также означает, что мы можем и должны полностью владеть решением и адаптировать его к нашим потребностям, но это и так заложено в нашей ДНК.
Немного истории
Исторически сложилось так, что компания Hetzner использовала различные технологии для обеспечения связи для своих облачных продуктов.
На начальном этапе, в 2011 году, виртуальные серверы Hetzner vServers использовали жесткие диски, нативные мосты Linux и статические маршруты. Они обеспечивали двухстековое подключение со скоростью до 1 Гбит/с на хост. В итоге, с такой конфигурацией работало около 25 000 экземпляров.
Следующая версия продукта была запущена в сентябре 2015 года с гиперконвергентной конфигурацией на базе Ceph. Она перешла на динамическую маршрутизацию через BGP и конфигурацию моста Linux с использованием NAT 1:1 для IPv4 и полностью маршрутизируемых префиксов IPv6. Это обеспечило лучшую мобильность IP-адресов и обслуживание хостов без влияния на клиентов. В 2016 году каналы связи с хостами были модернизированы до 2 x 10 Гбит/с. Эта конфигурация просуществовала до 2018 года и разрослась примерно до 50 000 экземпляров.
Когда Hetzner Cloud был запущен в 2018 году, мы отказались от NAT и перешли на прямую маршрутизацию IPv4. В июле 2019 года мы представили плоскость данных на основе Open vSwitch и добавили поддержку частных облачных сетей на основе инкапсуляции VXLAN. В ноябре 2020 года мы начали миграцию части публичной сети на Open vSwitch, что позволило нам запустить межсетевые экраны с сохранением состояния на основе потоков Open vSwitch, а в марте 2021 года...netfilter
Составные части хоста виртуальной машины
Мы уже выяснили, что важные части сетевого стека работают на виртуальных машинах; но что они должны предоставлять для функционирования облачного сервера?
Для большинства серверов требуется доступ к Интернету, чтобы система и её сервисы были доступны как из дома, так и из-за рубежа. Некоторые серверы используют частные сети (Private Networks), либо вместо общедоступных сетей, либо совместно с ними, которые соединяют серверы, балансировщики нагрузки и, возможно, выделенные серверы через частную виртуальную сеть, доступ к которой имеют только ваши системы. Трафик частной сети инкапсулируется с помощью виртуальной расширяемой локальной сети (VXLAN) и уникального виртуального идентификатора сети (VNI) для каждой частной сети. Сетевой стек хоста гарантирует, что только участники, подключенные к соответствующей частной сети, могут отправлять или получать трафик.
Для управления доступом к вашим сервисам, доступным из Интернета, мы предлагаем функцию облачного брандмауэра. Она позволяет контролировать доступ к определенным портам или протоколам сервера, а также ограничивать трафик, который может покидать сервер. Это должно происходить как можно ближе к серверу, то есть на хосте. Создание централизованных брандмауэров с отслеживанием состояния потребовало бы дополнительного оборудования и сетевых наложений для передачи «чистого» трафика на серверы и значительно усложнило бы задачу обеспечения высокой доступности и централизованного отслеживания соединений.
По умолчанию образы наших облачных серверов настроены на использование протокола динамической конфигурации хостов (DHCP) для динамической настройки IPv4-адресов и маршрутов. Следовательно, нам необходимо предоставить DHCP-сервер, чтобы серверы могли запрашивать конфигурацию IPv4-сети для общедоступных и частных сетевых интерфейсов.
В большинстве образов используется для настройки некоторых частей системы, например, для настройки сети IPv6, запуска DHCP для частных сетевых интерфейсов, подключения облачных томов и т.д. Для выполнения этих задач необходимо запрашивать информацию о локальной системе или конфигурационных параметрах пользователя с нашего сервера метаданных, доступного по адресу. Кроме того, сервер метаданных используется многими интеграциями, включая, помимо прочего, наш драйвер CSI, hc-utils, инструменты дистрибутивов, такие как Flatcar Linux и, или Talos Linux.cloud-initcloud-init 169.254.169.254/cloud-initAfterburnIgnition
Для обеспечения максимальной отказоустойчивости и доступности, DHCP-сервер и сервер метаданных работают локально на каждом хосте виртуальной машины.
Помимо этих сервисов, доступных пользователям, на виртуальных машинах работает множество внутренних служб, которые обеспечивают бесперебойную работу серверов, получение сетевой информацией для настройки подключения, а также отслеживание происходящего нашей системой мониторинга.
Однако в этой статье мы сосредоточимся на сетевом стеке и более подробно рассмотрим его внутреннее устройство.
Открыть vSwitch
Большая часть передачи сетевых данных осуществляется с помощью Open vSwitch, или сокращенно OVS, многоуровневого виртуального коммутатора с открытым исходным кодом. Его протокол передачи данных уже давно включен в ядро Linux, а пакеты для пользовательского пространства/управляющей плоскости доступны для всех основных дистрибутивов Linux.
Это сетевой стек по умолчанию для некоторых сред виртуализации, и многие готовые решения поддерживают OVS. К ним относятся, помимо прочих, Proxmox VE, Open Stack и oVirt. Однако мы не используем ни одну из этих сред, а управляем KVM и всеми сопутствующими компонентами с помощью собственных инструментов.
Open vSwitch — это универсальное сетевое решение, предлагающее множество функций, часть из которых мы используем в наших примерах и для настройки. Оно использует OpenFlow, открытый протокол, созданный для настройки плоскости данных сетевых устройств и определения способа пересылки пакетов. Для каждого направления связи должен существовать поток, определяющий, как должны обрабатываться пакеты и куда их необходимо отправлять.
Это могут быть точные совпадения, например, для связи со шлюзом через ARP, NDP, ICMP и т. д., трафика, предназначенного для других участников частной сети, или подключений к сервису в Интернете.
Открытая оркестрация vSwitch — Flusskrebs
Для обеспечения сетевого подключения наших серверов и балансировщиков нагрузки, а также для настройки любых межсетевых экранов, применяемых к серверу, нам необходимо установить необходимые потоки для Open vSwitch, чтобы обеспечить эти соединения и функции.
Распространенным решением для оркестрации Open vSwitch является проект Open Virtual Network (OVN) control plane, который был запущен одновременно с самим OVS и предназначен для обслуживания парка узлов, работающих под управлением Open vSwitch. Он предоставляет уровень абстракции, где можно настраивать логические маршруты и коммутаторы, которые затем преобразуются в OpenFlow.
Когда Open vSwitch был внедрен в стек Hetzner Cloud, мы решили не идти по этому пути и вместо этого разработали собственное решение под названием Flusskrebs (буквально переводится как «речной краб» или «потоковый краб»). Оно написано на Python, предоставляет REST API, используемый локальной частью нашей плоскости управления облаком, и настраивает потоки, необходимые каждой виртуальной машине или балансировщику нагрузки для корректной работы. Это включает в себя потоки для реализации любых правил брандмауэра, настроенных пользователем или нашим бэкэндом, например, для блокировки исходящего SMTP по умолчанию.
Контроллер также выступает в качестве центрального DHCP-сервера для частных сетевых интерфейсов на каждом хосте.
Сетевой стек хоста виртуальной машины
Учитывая общие архитектурные принципы и эти базовые элементы, давайте подробнее рассмотрим сетевой стек нашего хоста виртуальной машины. На следующем рисунке представлен упрощенный обзор внутренней работы сетевого стека хоста виртуальной машины.

Большинство хостов используют два восходящих интерфейса 10 Гбит/с, объединенных в группу агрегации каналов (LAG) или, в Linux, с использованием LACP, подключенных к двум физическим коммутаторам, образующим виртуальное шасси для повышения отказоустойчивости и пропускной способности. Для дальнейшего повышения отказоустойчивости в начале этого года мы начали переход на два маршрутизируемых восходящих канала с использованием BGP, подключенных к двум независимым коммутаторам. Следует отметить, что восходящие интерфейсы не подключены напрямую к мосту OVS, но система Linux осуществляет маршрутизацию между восходящими каналами и OVS. Таким образом, доступность хоста не зависит от OVS, что упрощает установку и обслуживание хоста.bond
Центральный мост Open vSwitch выступает в качестве основного компонента, обеспечивающего сетевое подключение и функции, и все облачные серверы на хосте подключены к нему. Каждый сервер может иметь один публичный сетевой интерфейс, а также до трех частных сетевых интерфейсов. Для отображения потоков, обеспечивающих исходящий трафик с сервера в сеть, используются следующие шаблоны:
# Only process packets with correct source MAC address
table=0, priority=9999, in_port={vm_port_no}, eth_src={mac}, actions=set_field:1->reg0,set_field:{vm_port_no}->reg5,resubmit(,1)
# Only accept packets with an IPv4/IPv6 address associated with the server
table=3, priority=9999, in_port={vm_port_no}, ip_src={ip}, ip, actions=resubmit(,4)
table=3, priority=9999, in_port={vm_port_no}, ipv6_src={ip}/64, ipv6, actions=resubmit(,4)
table=3, priority=9999, in_port={vm_port_no}, arp, arp_op=2, arp_spa={ip}, actions=resubmit(,4)Входящий трафик к серверу перенаправляется с использованием следующих потоков, по одному для каждого префикса IPv4 или IPv6 соответственно. Сетевой стек хоста идентифицирует себя для виртуальной машины, используя общеизвестный «MAC-адрес виртуального шлюза», который всегда равен .d2:74:7f:6e:37:e3
table=22, priority=9999, in_port={internet_port_no}, ip, ip_dst={ip}, actions=mod_dl_src:d2:74:7f:6e:37:e3,{vm_port_no}
table=22, priority=9999, in_port={internet_port_no}, ipv6, ipv6_dst={ip}/64, actions=mod_dl_src:d2:74:7f:6e:37:e3,{vm_port_no}Инфраструктурные сервисы, такие как DHCP и серверы метаданных, также подключены к Open vSwitch и работают параллельно с каждым сервером в выделенном пространстве имен Linux для каждого сервера.
Обратите внимание, что DHCP-сервер, показанный на рисунке выше, отвечает только за публичные интерфейсы любого сервера. Как описано выше, контроллер Flusskrebs содержит центральный DHCP-сервер, обрабатывающий все частные сетевые интерфейсы. Процесс подключения к публичному DHCP-серверу также прост:udhcpd
table=1, priority=9999, in_port={vm_port_no}, udp, udp_dst=67, actions={service_port_no}
table=1, priority=9999, in_port={service_port_no}, udp, udp_src=67, actions={vm_port_no}Наряду с Open vSwitch, для реализации функции межсетевого экрана с сохранением состояния используется отслеживание соединений Linux netfilter. При наличии глобальной общей таблицы отслеживания соединений необходимо предотвратить ее переполнение и обеспечить справедливое использование для всех серверов и клиентов. Это достигается с помощью другого внутреннего проекта, который отслеживает записи отслеживания соединений и устанавливает ограничение в 80 000 активных одновременных соединений на сервер. Если сервер достигает этого лимита, новые соединения не могут быть открыты до тех пор, пока не будет закрыто предыдущее.ctcount
Статус-кво
Эта платформа обработки данных на базе Open vSwitch хорошо нам служила и в основном продолжает служить до сих пор, даже при наличии более миллиона облачных серверов. Однако мы достигли некоторых ограничений и хотели улучшить масштабируемость, отказоустойчивость и гибкость с помощью более специализированного сетевого стека. В течение последних лет наша команда SDN разрабатывала именно такое решение, адаптированное к нашим потребностям, простое в эксплуатации и являющееся прочной основой для новых функций, таких как IPv6 для частных сетей.
В следующей части этой серии мы расскажем о следующих этапах нашего пути, о нашей новейшей полностью самостоятельно разработанной сетевой архитектуре и о том, как она работает. Так что оставайтесь с нами!
0 комментариев
Вставка изображения
Оставить комментарий