Обзор OpenStack Neutron PTG июнь 2020
PTG (Project Team Gathering) — это мероприятие, на котором команды разработчиков встречаются для обсуждения текущих задач, статусов и планов. Несколько лет назад PTG отделилось от основного OpenStack саммита.
PTG впервые проводился в онлайн формате через Zoom и Jitsi Meet. Однако сочетание картинки и звука на встрече сделало это изменение совсем незаметным, особенно на фоне ныне привычных командных митингов через IRC.
Трехчасовые сессии, посвященные Neutron, проходили со вторника по пятницу. Основной протокол встреч опубликован в OpenStack Etherpad и в списке рассылки OpenStack. Повестка мероприятия была сформирована на основе предложений разработчиков Neutron, а расписание встреч подготовил ее председатель, PTL (Project Team Lead) команды Neutron Slawek Kaplonski.
В этой статье я расскажу о 3 топиках, которые как мне кажется заслуживают внимания, и требуют немного пояснений.
OVN
На этом PTG было много разговоров об OVN, что неудивительно, поскольку большинство членов core команды представляют RedHat — основной contributor в OVN.
Что же такое OVN?
- Open source L2/L3 network virtualization для Open vSwitch (OVS):
- Логические свитчи
- Логические IPv4 и IPv6 роутеры
- L2/L3/L4 ACLs (Security Groups)
- Multiple tunnel overlays (Geneve, STT, and VXLAN)
- Логические балансировщики нагрузки
- TOR-based логико-физические L2 шлюзы
- Software-based логико-физические L2/L3 шлюзы
- Работает на тех же платформах, что и OVS:
- Linux
- Контейнеры
- DPDK
- Интеграция с:
- OpenStack Neutron
- Docker Swarm
- Kubernetes
Архитектура OVN
«OVN в 75 словах.
Open Virtual Network управляется в рамках проекта OVS и разрабатывалась изначальным коллективом создателей OVS. Это решение является попыткой переработать ML2/OVS control plane опираясь на накопленный годами опыт. Оно предназначено для использования в OpenStack и Kubernetes. OVN построен на новой архитектуре, которая отказалась от концепции взаимодействия Python агентов с сервисом Neutron API через RabbitMQ в пользу C daemons общающихся через OpenFlow и OVSDB.» — Slawek Kaplonsky, Neutron PTL.
Изначально Neutron OVN драйвер разрабатывался как отдельный проект в Neutron stadium — networking-ovn, а в релизе Ussuri был включен в основной репозиторий Neutron.
Таким образом, в этом решении исчезает основная проблема ML2/OVS — RabbitMQ, что является несомненным плюсом, да и в целом «OVN«s design goal is to have a production-quality implementation that can operate at significant scale». Однако поддерживает ли OVN тот функционал, который доступен при использовании ML2/OVS? Кажется, что это не совсем так, что стало одной из тем для обсуждения на PTG. По итогам было выделено несколько пробелов (полный список доступен на странице проекта). В первую очередь разработчики отметили отсутствие либо неполную поддержку routed networks, некоторые QoS фичи, BGP и Availability Zones. Хоть команда OVN и готова заняться всем перечисленным, в ходе встречи они признали, что это ранее не было для них приоритетной задачей — так как внутренние интересы были важнее. Кроме того, разработка ML2/OVS, разумеется, не приостанавливается, а значит могут появляться новые пробелы.
Однако на мой взгляд, основная проблема с OVN состоит в том, что он еще не используется широко и его не тестировали на крупных инсталляциях. Кроме того, есть некоторые вопросы к High Availability:
- Один из основных компонентов, ovn-northd, на данный момент поддерживает только active/passive режим HA, active/active пока только в планах
- Другой центральный компонент, ovsdb-server, также поддерживает только active/passive режим
Не исключено, что последний пункт на самом деле уже устарел, поскольку поддержка кластера ovsdb (на основе алгоритма Raft) была добавлена с версии OVS 2.9, однако неочевидно, тестировалось ли это во варианте с OVN и OpenStack. Например, связанный с этим тикет в openstack-ansible пока не закрыт.
Кроме того, беспокойство вызывает то, что OVN использует Geneve туннели вместо VxLAN, что влияет на настройки MTU (заголовки Geneve больше VxLAN) и поддержку аппаратного ускорения обработки туннелей.
Как бы то ни было, проект быстро набирает обороты и кажется, что уже через пару релизов OVN должен стать базовым Neutron плагином. Более того, во время PTG разработчики core команды договорились сделать OVN дефолтным плагином для DevStack.
К чему приведут эти изменения:
- Поскольку большинство OpenStack проектов используют Neutron в своих CI, это нововведение потенциально имеет большое значение
- По идее оно не должно привести к сокращению поддержки ML2/OVS (однако по сути это и подразумевается)
- В самом Neutron CI джобы для других плагинов остаются, например ML2/Linuxbridge и ML2/OVS — здесь ничего не изменится, кроме названий отдельных джоб
- Сообществу станет ясно, что core команда считает OVN будущим проекта
Что касается последнего пункта, Neutron PTL опубликовал следующее сообщение: «Neutron команда полагает, что OVN и драйвер Neutron OVN построены на современной архитектуре, которая создает лучшую основу для работы более простого и производительного решения. Мы наблюдаем рост активности участия в kubernetes-ovn, что приводит к расширению core сообщества OVN, и мы бы хотели, чтобы OpenStack также воспользовался этим вложением в OVN со стороны Kubernetes.
На данный момент у Neutron OVN драйвера есть пробелы в поддерживаемом функционале по сравнению с ML2/OVS, однако наша команда старается закрыть эти бреши, и мы считаем, что этот драйвер станет будущим для Neutron, а потому мы хотим сделать его дефолтным Neutron ML2 бэкендом для DevStack.»
Пока реакция на эти новости скорее позитивная, хотя все еще есть сомнения касательно перехода от VxLAN к Geneve туннелям, способы миграции с ML2 OVS на ML2 OVN, а также производительности и поддерживаемого функционала.
Применение нового EngineFacade
EngineFacade — это фреймворк поверх sqlalchemy который объединяет логику, касающуюся баз данных, используемую во всех проектах OpenStack. Несколько релизов назад он прошел через рефакторинг, что привело к появлению так называемого «new EngineFacade». Следующим шагом стала адаптация этого фреймворка в OpenStack.
На мой взгляд, эту тему включили в повестку PTG в связи с тем, что работа над ней тянется уже на протяжении нескольких релизов и до сих пор не завершена. Причинами такого развития событий являются большой объем необходимых изменений, отдельные нетривиальные проблемы в процессе адаптации и, как мне кажется, недостаток мотивации, а значит и людских ресурсов. И действительно, зачем менять то, что уже работает и даже не выдает кучу багов? Довольно подробный ответ на этот вопрос изложен в спецификации Майка Байера. Здесь же я постараюсь дать краткий пересказ соображений в поддержку EngineFacade, чтобы вам не пришлось читать этот длиный текст:
- Старый EngineFacade предоставляет низкоуровневые API вместо высокоуровневых API подогнанных под конкретный use case, поэтому это по сути фабрика, а не фасад. В результате:
- Нет согласованности в использовании старого EngineFacade в разных проектах OpenStack
- Неправильное использование сессий, подключений БД и транзакций ведет к проблемам с производительностью, стабильностью работы и удобством поддержки
- Новый EngineFacade скрывает всю логику сессий/подключений/транзакций и предоставляет только два контекст менеджера: reader и writer, в зависимости от того, что именно необходимо в текущем методе.
Звучит просто и логично, так в чем же тогда проблема с адаптацией EngineFacade? Честно говоря, я не очень сильно вникал в детали, но кажется, что основной причиной проблем становится то, что в некоторых сложных сценариях старый EngineFacade неправильно использовался в Neutron и оно работало (!), а новый EngineFacade пытается все сделать правильно, но, тем не менее, ломает рабочие сценарии (по моему довольно типичная проблема при работе с легаси кодом : D). Очевидно, в таком случае нужно сначала исправить логику этих сценариев.
На самом деле, осталось править не так уж и много — всего один патч, и core команда договорилась совместно решить эту задачу. Разумеется, любой заинтересовавшийся может помочь с анализом и ревью!
Neutron-lib
Несколько топиков было посвящено neutron-lib. Начну с того, что напомню, что это такое для тех, кто не сильно вовлечен в разработку Neutron. Во-первых, Neutron не является единым проектом — на самом деле он состоит из нескольких репозиториев, работающих с разными областями сети OpenStack под общим названием Neutron Stadium, и «neutron» — это лишь один, хоть и основной проект. Остальные проекты — это так называемые advanced сервисы (например neutron-lbaas, -fwaas, -vpnaas, -dynamic-routing и т.д.) и сторонние/вендорские плагины (например networking-midonet, -odl, -ovn). В этот список входят проекты, которые разрабатывают Neutron PTL и core команда и непосредственно занимаются ими на ежедневной основе. Чтобы это было возможно, они следят за соблюдением общих принципов и правил работы во всем Stadium во всех аспектах разработки — структура, разработка, code style, тестирование, документирование и т.д. Честно говоря, на сегодняшний день это не совсем так, и основная нагрузка все же ложится на плечи проект мейнтейнеров.
До создания neutron-lib все проекты с префиксом networking- импортировали весь общий код — константы, интерфейсы (абстрактные базовые классы), вспомогательные функции и прочее — из основного репозитория neutron. Любые изменения такого кода в neutron могли нарушить работу зависимых проектов. Тогда в релизе Ocata для решения этой проблемы была запущена neutron-lib initiative: весь общий код теперь должен храниться в отдельным репозитории и должен был версионированным. Более конкретно цели формулировались следующим образом:
- Убрать зависимость подпроектов от Neutron (т.е. убрать прямые импорты из neutron в подпроектах)
- Сделать домашнюю работу в Neutron путем рефакторинга кода или переработки архитектуры неоптимальных паттернов в соответствующих разделах neutron-lib
По сути, neutron-lib выглядит как win-win вариант: как основной Neutron, так и сервисы сторонних проектов должны быть в плюсе по итогу. Что же пошло не так?
Недостаточная поддержка
Ни один open-source проект не может существовать без поддержки контрибьюторов и мейнтейнеров — людей, готовых инвестировать свое время в работу над проектом. Для neutron-lib таких желающих начало не хватать, и в результате перестала работать первоначальная логика, т.е. чтобы здесь хранился весь общий код, который можно было бы импортировать вместо импорта neutron. Некоторое время назад основной maintainer neutron-lib (boden) покинул проект. Во время PTG была высказано предложение отказаться от идеи переноса всего общего кода в neutron-lib или даже перенести код neutron-lib обратно в neutron. Это предложение не прошло по двум причинам:
- neutron-lib по-прежнему широко используется
- neutron-lib несет в себе определенную ценность, поскольку он выделяет стандартные интерфейсы, которые нельзя менять, чтобы не сломать сразу несколько проектов
По итогу обсуждения neutron-lib остается без изменений, однако политику перемещения и устаревания кода в neutron необходимо обновить.
Конечно, весь новый код необходимо разделять между neutron и neutron-lib, если это возможно. И это приводит нас ко второй проблеме.
Проблема с тестированием
Другая проблема связана с тестированием в процессе разработки. Если часть патча в neutron вводит новый или меняет существующий общий код, она по правилами должна отправиться в neutron-lib. Так neutron часть патча становится зависимой от этих изменений в lib. Однако сейчас патчи в neutron тестируются на релизной версии neutron-lib, чтобы проверить работу с последним релизом. В итоге такие патчи не будут проходить тесты в CI.
Переход к тестированию всех neutron патчей с neutron-lib кодом из мастера также имеет некоторые недостатки. Например, нет никаких гарантий что мастер neutron работает с последним релизом neutron-lib, а ведь конечные пользователи работают именно с этой версией.
Вот способы решения этого вопроса (спасибо Bence Romsics за отличную сводку):
- Если нет срочности, можно дождаться, пока ваш neutron-lib патч будет принят и уйдет в релиз, после чего продолжить работу над neutron патчем.
- Если нужно двигаться быстрее, то зачастую может быть приемлимо работать с временным скопированным кодом:
- Предположим, вы хотите добавить модуль «foo» в neutron-lib, но он еще не принят и не добавлен в релиз. Можно спокойно добавить в neutron патч его точную копию, назвать ее »_foo» и прикрепить TODO комментарий о том, что ее нужно убрать, когда ее оригинал появится в neutron-lib.
- Когда часть из neutron-lib появится в релизе, не забудьте добавить патч в neutron, который бы убрал _foo и заменил «import _foo» на «from neutron-lib import foo».
- Кроме того, можно запускать отдельные проверки на CI и с мастером, и с последним релизом neutron-lib. Но голосующей может быть только одна из них. Простое удвоение количества задач даст огромную дополнительную нагрузку на CI инфраструктуру OpenStack
В ходе обсуждения на PTG прозвучало три предложения:
- Использовать мастер neutron-lib для «Check CI»; использовать релиз-версию neutron-lib для «Gate CI» — однако если neutron патч будет проходить проверки «Check CI» и падать на «Gate CI», это будет выглядеть странно
- Ничего не менять: лучше проводить тесты на релиз-версии neutron-lib. Например, так сейчас делается для OSC (OpenStackClient)
- Запускать тесты с мастером neutron-lib и добавить периодическую задачу для тестов с релиз-версией neutron-lib
Итоговое решение: создать новую неголосующую задачу в «Check CI» c neutron-lib из master ветки. По сути все остается как есть, но появится возможность проверить, что фича, включающая в себя изменения в neutron и neutron-lib, проходит CI прежде чем принимать ее в master ветку.
Надеюсь, что это статья была полезной и помогла вам лучше понять, куда и почему движется Neutron.
Спасибо за внимание!