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 пытается все сделать правильно, но, тем не менее, ломает рабочие сценарии (по моему довольно типичная проблема при работе с легаси кодом). Очевидно, в таком случае нужно сначала исправить логику этих сценариев.

На самом деле, осталось править не так уж и много – всего один патч, и 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.

Спасибо за внимание!