Введення в мережеву частину хмарної інфраструктури

Введення в мережеву частину хмарної інфраструктури

Хмарні обчислення все глибше і глибше проникають у наше життя і вже напевно немає жодної людини, яка хоча б раз не користувалася хмарними сервісами. Однак що ж така хмара і як вона працює здебільшого мало хто знає навіть на рівні ідеї. 5G стає вже реальністю і телеком інфраструктура починає переходити від стовпових рішень до хмарних рішень, як колись переходила від повністю залізних рішень до віртуалізованих «стовп».

Сьогодні поговоримо про внутрішній світ хмарної інфраструктури, зокрема, розберемо основи мережевої частини.

Що таке хмара? Та ж віртуалізація – вид у профіль?

Більш ніж логічне питання. Ні, це не віртуалізація, хоча без неї не обійшлося. Розглянемо два визначення:

Хмарні обчислення (далі Хмара) — це модель надання зручного для користувача доступу до розподілених обчислювальних ресурсів, які мають бути розгорнуті та запущені на запит із мінімально можливою затримкою та мінімальними витратами з боку сервіс провайдера.

Віртуалізація — це можливість розділити одну фізичну сутність (наприклад, сервер) на кілька віртуальних, тим самим підвищивши утилізацію ресурсів (наприклад, у вас було 3 сервери, завантажені на 25-30 відсотків, після віртуалізації ви отримуєте 1 сервер, завантажений на 80-90 відсотків). Природно, віртуалізація від'їдає частину ресурсів — вам треба прогодувати гіпервізор, проте, як показала практика, гра коштує свічок. Ідеальний приклад віртуалізації - це VMWare, яка відмінно готує віртуальні машини, або наприклад KVM, який мені більше до вподоби, але це вже справа смаку.

Ми використовуємо віртуалізацію самі цього не розуміючи, та навіть залізні маршрутизатори вже використовують віртуалізацію - наприклад, в останніх версія JunOS операційна система ставиться як віртуальна машина поверх real-time linux дистрибутива (Wind River 9). Але віртуалізація - це не хмара, проте хмара не може існувати без віртуалізації.

Віртуалізація — це одна з цеглинок, на якій хмара будується.

Зробити хмару, просто зібравши кілька гіпервізорів в один L2 домен, додавши пару yaml плейбуків для автоматичного прописування вланів через якийсь ansible і насунути на це все щось типу системи оркестрації для автоматичного створення віртуальних машин - не вийде. Точніше вийде, але отриманий Франкенштейн — не та хмара яка нам потрібна, хоча кому як, можливо для когось це межа мрій. До того ж якщо взяти той же Openstack — по суті ще той ще Франкенштейн, але гаразд не будемо поки що про це.

Але я розумію, що з представленого вище визначення не зовсім зрозуміло, що ж насправді можна назвати хмарою.

Тому в документі від NIST (National Institute of Standards and Technology) наведено 5 основних характеристик, якими має хмарна інфраструктура:

Надання сервісу на запит. Користувачеві повинен бути наданий вільний доступ до виділених йому комп'ютерних ресурсів (таких як мережі, віртуальні диски, пам'ять, ядра процесорів тощо), причому ці ресурси повинні надаватися автоматично, тобто без втручання з боку сервісу провайдера.

Широка доступність сервісу. Доступ до ресурсів повинен забезпечуватися стандартними механізмами для використання як стандартних ПК, так і тонких клієнтів і мобільних пристроїв.

Об'єднання ресурсів у пули. Пули ресурсів повинні забезпечувати одночасне надання ресурсів декільком клієнтам, забезпечуючи ізоляцію клієнтів та відсутність взаємного впливу між ними та конкуренції за ресурси. У пули включаються і мережі, що говорить про можливість використання адресації, що перетинається. Пули повинні підтримувати масштабування на запит. Використання пулів дозволяє забезпечити необхідний рівень стійкості до відмови ресурсів і абстрагування фізичних і віртуальних ресурсів — одержувачу сервісу просто надається запрошений ним набір ресурсів (де ці ресурси розташовані фізично, на скількох серверах і комутаторах — клієнту не важливо). Однак треба враховувати той факт, що провайдер має забезпечити прозоре резервування цих ресурсів.

Швидка адаптація до різних умов. Сервіси мають бути гнучкими — швидке надання ресурсів, їх перерозподіл, додавання або скорочення ресурсів на запит клієнта, причому з боку клієнта має складатися відчуття, що ресурси хмари нескінченні. Для простоти розуміння, наприклад, ви ж не бачите попередження про те, що у вас в Apple iCloud зникла частина дискового простору через те, що на сервері зламався жорсткий диск, а диски ламаються. До того ж з вашого боку можливості цього сервісу практично безмежні – потрібно вам 2 Тб – не проблема, заплатили та отримали. Аналогічно можна навести приклад із Google.Drive або Yandex.Disk.

Можливість вимірювання сервісу. Хмарні системи повинні автоматично контролювати та оптимізувати споживані ресурси, при цьому ці механізми мають бути прозорими як для користувача, так і для провайдера послуг. Тобто ви завжди можете перевірити, скільки ресурсів ви та ваші клієнти споживають.

Варто врахувати той факт, що ці вимоги здебільшого є вимогами до публічної хмари, тому для приватної хмари (тобто хмари, запущеної для внутрішніх потреб компанії) ці вимоги можуть бути дещо скориговані. Однак вони все ж таки повинні виконуватися, інакше ми не отримаємо всіх плюсів хмарних обчислень.

Навіщо нам хмара?

Однак будь-яка нова або вже існуюча технологія, будь-який новий протокол створюється для чогось (ну, крім RIP-ng, природно). Протокол заради протоколу - нікому не потрібний (ну крім RIP-ng природно). Логічно, що Хмара створюється щоб надати якийсь сервіс користувачеві/клієнту. Ми всі знайомі хоча б з парою хмарних сервісів, наприклад Dropbox або Google.Docs і я так вважаю більшість успішно ними користується - наприклад, ця стаття написана з використанням хмарного сервісу Google.Docs. Але відомі нам хмарні сервіси – це лише частина можливостей хмари – точніше – це лише сервіс типу SaaS. Надати хмарний сервіс ми можемо трьома шляхами: SaaS, PaaS або IaaS. Який сервіс потрібний саме вам залежить від ваших бажань та можливостей.

Розглянемо кожен по порядку:

Програмне забезпечення як сервіс (SaaS) — це модель надання повноцінного сервісу клієнту, наприклад, поштовий сервіс типу Yandex.Mail або Gmail. У такій моделі надання сервісу ви, як клієнт за фактом, не робите нічого, крім як користуєтеся сервісами — тобто вам не треба думати про налаштування сервісу, його стійкість до відмов або резервування. Головне не скомпрометувати свій пароль, все інше за вас зробить провайдер цього сервісу. З погляду провайдера сервісу - він відповідає повністю за весь сервіс - починаючи з серверного обладнання та хостових операційних систем, закінчуючи налаштуваннями баз даних та програмного забезпечення.

Платформа як послуга (PaaS) — при використанні даної моделі постачальник послуг надає клієнту заготівлю під сервіс, наприклад, візьмемо Web сервер. Постачальник послуг надав клієнту віртуальний сервер (за фактом набір ресурсів, таких як RAM/CPU/Storage/Nets і т.д.), і навіть встановив на даний сервер ОС і необхідне ПЗ, проте налаштування всього цього добра робить сам клієнт і за працездатність сервісу вже відповідає клієнт. Постачальник послуг, як і в минулому випадку, відповідає за працездатність фізичного обладнання, гіпервізорів, самої віртуальної машини, її мережеву доступність і т д, але сам сервіс вже поза його зоною відповідальності.

Інфраструктура як послуга (IaaS) - даний підхід вже цікавіший, за фактом постачальник послуг надає клієнту повну віртуалізовану інфраструктуру - тобто якийсь набір (пул) ресурсів, таких як CPU Cores, RAM, Networks і т.д. Все інше - справа клієнта - що клієнт хоче зробити з цими ресурсами у межах виділеного йому пулу (квоти) — постачальнику не дуже важливо. Хоче клієнт створити свій власний vEPC або взагалі зробити міні оператора та надавати послуги зв'язку – не питання – роби. У такому сценарії постачальник послуг відповідає за надання ресурсів, їх стійкість до відмов і доступність, а також за ОС, що дозволяє об'єднати дані ресурси в пули і надати їх клієнту з можливість в будь-який момент провести збільшення або зменшення ресурсів на запит клієнта. Всі віртуальні машини та іншу мішуру клієнт налаштовує сам через портал самообслуговування та консолі, включаючи прописання мереж (крім зовнішніх мереж).

Що таке OpenStack?

У всіх трьох варіантах постачальнику послуг потрібна ОС, яка дозволить створити хмарну інфраструктуру. Фактично ж при SaaS за весь стек цей стек технологій відповідає не один підрозділ — є підрозділ, який відповідає за інфраструктуру — тобто надає IaaS іншому підрозділу, цей підрозділ надає клієнту SaaS. OpenStack є однією з хмарних ОС, яка дозволяє зібрати купу комутаторів, серверів та систем зберігання в єдиний ресурсний пул, розбивати цей загальний пул на підпули (тенанти) та надавати ці ресурси клієнтам через мережу.

OpenStack — це хмарна операційна система, яка дозволяє контролювати великі пули обчислювальних ресурсів, сховищ даних та мережевих ресурсів, провіжинінг та управління якими здійснюється через API з використанням стандартних механізмів аутентифікації.

Іншими словами, це комплекс проектів вільного програмного забезпечення, який призначений для створення хмарних сервісів (як публічних, так і приватних) — тобто набір інструментів, які дозволяють об'єднати серверне та комутаційне обладнання в єдиний пул ресурсів, керувати цими ресурсами, забезпечуючи необхідний рівень відмовостійкості. .

На момент написання даного матеріалу структура OpenStack виглядає так:
Введення в мережеву частину хмарної інфраструктури
Зображення взято з openstack.org

Кожна з компонентів, що входять до складу OpenStack, виконує якусь певну функцію. Така розподілена архітектура дозволяє включати до складу рішення набір функціональних компонентів, які вам необхідні. Однак частина компонентів є кореневими компонентами і їх видалення призведе до повної або часткової непрацездатності рішення в цілому. До таких компонентів прийнято відносити:

  • Інформаційна панель - GUI на базі web для керування OpenStack сервісами
  • Наріжний камінь — централізований сервіс ідентифікації, який надає функціональність автентифікації та авторизації для інших сервісів, а також керувати обліковими даними користувачів та їх ролями.
  • нейтрон — мережна служба, що забезпечує зв'язок між інтерфейсами різних служб OpenStack (включаючи і зв'язок між VM та доступ їх до зовнішнього світу)
  • Сірник — надає доступ до блочного сховища для віртуальних машин
  • Нова зірка - Управління життєвим циклом віртуальних машин
  • Погляд - Репозиторій образів віртуальних машин та снапшотів
  • Швидко — надає доступ до об'єктного сховища
  • Стилометр — служба, що надає можливість збору телеметрії та заміру наявних та ресурсів
  • Тепло — оркестрація на базі темплейтів для автоматичного створення та провіжинінгу ресурсів

Повний список усіх проектів та їх призначення можна переглянути тут.

Кожна з компонентів OpenStack — це служба, яка відповідає за певну функцію та забезпечує API для керування цією функцією та взаємодії цієї служби з іншими службами хмарної операційної системи з метою створення єдиної інфраструктури. Наприклад, Nova забезпечує управління обчислювальними ресурсами та API для доступу до конфігурування даних ресурсів, Glance – управління образами та API для управління ними, Cinder – блокове сховище та API для управління ним тощо. Усі функції взаємопов'язані між собою дуже тісно.

Однак якщо посудити, то всі сервіси, запущені в OpenStack, представляє зрештою якусь віртуальну машину (або контейнер), підключену до мережі. Постає питання - а навіщо нам стільки елементів?

Давайте пробіжимося за алгоритмом створення віртуальної машини та підключення її до мережі та постійного сховища в Openstack.

  1. Коли ви створюєте запит на створення машини, будь то запит через Horizon (Dashboard) або запит через CLI, перше що відбувається - це авторизація вашого запиту на Keystone - чи можете ви створювати машину, чи має право використовувати дану мережу, чи вистачає у вашого проекту квоти і т.д.
  2. Keystone здійснює автентифікацію вашого запиту і генерує у відповідному повідомленні auth-токен, який буде використаний далі. Отримавши відповідь від Keystone, запит відправляється у бік Nova (nova api).
  3. Nova-api перевіряє валідність вашого запиту, звертаючись до Keystone, використовуючи раніше згенерований auth-токен
  4. Keystone здійснює автентифікацію та надає на підставі даного auth-токену інформацію щодо дозволів та обмежень.
  5. Nova-api створює в nova-database запис про нову VM і передає запит створення машини в nova-scheduler.
  6. Nova-scheduler робить вибір хоста (комп'ют ноди), на якій VM буде розгорнута на підставі заданих параметрів, ваг і зон. Запис про це та ідентифікатор VM записуються в nova-database.
  7. Далі nova-scheduler звертається до nova-compute із запитом про розгортання інстансу. Nova-compute звертається в nova-conductor для отримання інформації про параметри машини (nova-conductor є елементом nova, що виконує роль проксі сервера між nova-database і nova-compute, обмежуючи кількість запитів у бік nova-database, щоб уникнути проблем з консистентністю бази даних скорочення завантаження).
  8. Nova-conductor отримує з nova-database запитану інформацію та передає її nova-compute.
  9. Далі nova-compute звертається до glance для отримання ID образу. Glace проводить валідацію запиту в Keystone та повертає запитану інформацію.
  10. Nova-compute звертається до neutron для отримання інформації про параметри мережі. Аналогічно glance, neutron проводить валідацію запиту в Keystone, після чого створює запис у database (ідентифікатор порту тощо), створює запит створення порту і повертає запитану інформацію в nova-compute.
  11. Nova-compute звертається до cinder із запитом виділення віртуальної машині volume. Аналогічно glance, cider проводить валідацію запиту в Keystone, створює запит створення volume і повертає запитану інформацію.
  12. Nova-compute звертається до libvirt із запитом розгортання віртуальної машини із заданими параметрами.

За фактом начебто проста операція зі створення простої віртуальної машини перетворюється на такий вир api колів між елементами хмарної платформи. Причому, як ви бачите, навіть раніше зазначені служби теж складаються з дрібніших компонентів, між якими відбувається взаємодія. Створення машини - це лише мала частина того, що дає зробити хмарна платформа - є служба, що відповідає за балансування трафіку, служба, що відповідає за блокове сховище, служба, що відповідає за DNS, служба, що відповідає за провіжинінг bare metal серверів і т.д. вам ставитися до ваших віртуальних машин як до стада баранів (на відміну від віртуалізації). Якщо у віртуальному середовищі у вас щось сталося з машиною — ви її відновлюєте з бекапів і т.д., хмарні ж програми побудовані таким чином, щоб віртуальна машина не відігравала такої важливої ​​ролі — віртуальна машина «померла» — не біда — просто створюється нова машина на підставі темплейту і, як кажуть, загін не помітив втрати бійця. Звичайно це передбачає наявність механізмів оркестрації - використовуючи Heat темплейти ви без особливих проблем можете розгорнути складну функцію, що складається з десятків мереж і віртуальних машин.

Варто завжди пам'ятати те, що хмарної інфраструктури без мережі не буває — кожен елемент так чи інакше взаємодіє з іншими елементами через мережу. Крім того, хмара має абсолютно не статичну мережу. Природно underlay мережа ще більш-менш статична - не щодня додаються нові ноди і комутатори, проте overlay складова може і неминуче постійно змінювати - додаватимуться або видалятимуться нові мережі, з'являтимуться нові віртуальні машини і вмиратимуть старі. І як ви пам'ятаєте з визначення хмари, даної на початку статті - ресурси повинні виділяти користувачеві автоматично і з найменшим (а краще без) втручанням з боку сервіс провайдера. Тобто той тип надання ресурсів мережі, який є зараз у вигляді фронтенду у вигляді вашого особистого кабінету доступного по http/https та чергового мережевого інженера Василя як бекенд — це не хмара, навіть за наявності у Василя восьми рук.

Neutron, що є мережевою службою, забезпечує API для управління мережевою частиною хмарної інфраструктури. Служба забезпечує працездатність та керування мережевою частиною Openstack забезпечуючи рівень абстракції, званий Network-as-a-Service (NaaS). Тобто мережа є такою ж віртуальною вимірною одиницею, як, наприклад, віртуальні ядра CPU або обсяг RAM.

Але перед тим як переходити до архітектури мережевої частини OpenStack, розглянемо, як в OpenStack ця мережа працює і чому мережа є важливою та невід'ємною частиною хмари.

Отже, у нас є дві віртуальні машини клієнта RED та дві віртуальні машини клієнта GREEN. Припустимо, що ці машини розташовані на двох гіпервізорах таким чином:

Введення в мережеву частину хмарної інфраструктури

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

Щоб вийшла хмара, нам треба додати кілька компонентів. По-перше, віртуалізуємо мережеву частину - нам треба ці 4 машини попарно з'єднати, причому клієнти хочуть саме L2 з'єднання. Можна використовувати безперечно комутатор і налаштувати в його бік транк і розрулити все за допомогою linux bridge ну або для більш просунутих користувачів openvswitch (до нього ми ще повернемося). Але мереж може бути дуже багато, та й постійно пропихати L2 через свіч — не найкраща ідея — так різні підрозділи, сервіс-деск, місяці очікування виконання заявки, тижні траблшутингу — у світі такий підхід уже не працює. І чим раніше компанія це розуміє, тим легше їй рухатися вперед. Тому між гіпервізорами виділимо L3 мережу, через яку будуть спілкуватися наші віртуальні машини, а вже поверх цієї L3 мережі побудуємо віртуальні накладені L2 (overlay) мережі, де бігатиме трафік наших віртуальних машин. Як інкапсуляцію можна використовувати GRE, Geneve або VxLAN. Поки зупинимося на останньому, хоча це не дуже важливо.

Нам треба десь розмістити VTEP (сподіваюся всі знайомі з термінологією VxLAN). Так як з серверів у нас виходить одночасно L3 мережу, то нам нічого не заважає розмістити VTEP на самих серверах, причому OVS (OpenvSwitch) це добре вміє робити. У результаті ми отримали таку конструкцію:

Введення в мережеву частину хмарної інфраструктури

Так як трафік між VM має бути розділений, то порти у бік віртуальних машин матимуть різні номери вланів. Номер тега відіграє роль лише в межах одного віртуального комутатора, тому що при інкапсулюванні у VxLAN ми його можемо безпроблемно зняти, тому що у нас буде VNI.

Введення в мережеву частину хмарної інфраструктури

Тепер ми можемо плодити наші машини та віртуальні мережі для них без жодних проблем.

Однак що якщо клієнт має ще одну машину, але знаходиться в іншій мережі? Нам потрібний рутинг між мережами. Ми розберемо простий варіант, коли використовується централізований рутинг - тобто трафік маршрутизується через спеціальні виділені network ноди (ну, як правило, вони поєднані з control нодами, тому у нас буде теж саме).

Начебто б нічого складного — робимо бридж інтерфейс на контрольній ноді, женемо на неї трафік і звідти маршрутизуємо його куди нам треба. Але проблема в тому, що клієнт RED хоче використовувати мережу 10.0.0.0/24 і клієнт GREEN хоче використовувати мережу 10.0.0.0/24. Тобто ми починаємо перетин адресних просторів. Крім того, клієнти не хочуть, щоб інші клієнти могли маршрутизуватися в їх внутрішні мережі, що логічно. Щоб розділити мережі та трафік даних клієнтів, ми для кожного з них виділимо окремий namespace. Namespace — це за фактом копія мережевого стека Linux, тобто клієнти в namespace RED повністю ізольовані від клієнтів з namespace GREEN (або маршрутизація між даними мережами клієнтів дозволена через default namespace або вже на вищому транспортному устаткуванні).

Тобто отримуємо таку схему:

Введення в мережеву частину хмарної інфраструктури

L2 тунелі сходяться з усіх обчислювальних нод на контрольну. ноду, де розташований L3 інтерфейс для даних мереж, кожен у виділеному namespace для ізоляції.

Проте ми забули найголовніше. Віртуальна машина повинна надавати сервіс клієнту, тобто вона повинна мати хоча б один зовнішній інтерфейс, через який можна достукатися до неї. Тобто, нам потрібно вийти у зовнішній світ. Тут є різні варіанти. Зробимо найпростіший варіант. Додамо клієнтам по одній мережі, які будуть валідні у мережі провайдера та не перетинатимуться з іншими мережами. Мережі можу бути такими, що теж перетинаються і дивитися в різні VRF на стороні провайдерської мережі. Дані мережі також житимуть в namespace кожного з клієнтів. Однак виходити у зовнішній світ вони все одно будуть через один фізичний (або бонд, що логічніше) інтерфейс. Щоб розділити трафік клієнтів трафік, що виходить назовні, буде проводитися тегування VLAN тегом, виділеним клієнту.

У результаті ми отримали таку схему:

Введення в мережеву частину хмарної інфраструктури

Слушне питання — чому не зробити шлюзи на самих compute нодах? Великої проблеми у цьому немає, більше того, при включенні розподіленого маршрутизатора (DVR) це так і працюватиме. У цьому сценарії ми розглядаємо найпростіший варіант із централізованим gateway, який у Openstack використовується за умовчанням. Для високонавантажених функцій використовуватимуть як розподілений маршрутизатор, і технології прискорення типу SR-IOV і Passthrough, але це вже зовсім інша історія. Для початку розберемося з базовою частиною, а потім підемо в деталі.

Власне наша схема вже працездатна, проте є кілька нюансів:

  • Нам треба якось захистити наші машини, тобто повісити на інтерфейс свіча у бік клієнта фільтр.
  • Зробити можливість автоматичного отримання IP адреси віртуальною машиною, щоб не довелося щоразу заходити в неї через консоль і прописувати адресу.

Почнемо із захисту машин. Для цього можна використовувати банальні iptables, чому б і ні.

Тобто тепер наша топологія вже трохи ускладнилася:

Введення в мережеву частину хмарної інфраструктури

Ходімо далі. Нам потрібно додати сервер DHCP. Найідеальнішим місцем для розташування DHCP серверів для кожного з клієнтів буде вже згадана вище контрольна нода, де розташовані namespaces:

Введення в мережеву частину хмарної інфраструктури

Проте є невелика проблема. Якщо все перезавантажиться і вся інформація з оренди адрес на DHCP пропаде. Логічно, що машинам буде видано нові адреси, що не дуже зручно. Виходу тут два - або використовувати доменні імена і додати DNS сервер для кожного клієнта, тоді нам адреса буде не дуже важлива (за аналогією з мережевою частиною в k8s) - але тут є проблема із зовнішніми мережами, тому що в них адреси також можуть бути видані по DHCP - потрібна синхронізація з DNS серверів у хмарній платформі та зовнішнім DNS сервером, що на мій погляд не дуже гнучко, проте цілком можливо. Або другий варіант - використовувати метадані - тобто зберігати інформацію про видану машину адресу, щоб DHCP сервер знав, яку адресу машині видати, якщо машина вже отримувала адресу. Другий варіант простіше і гнучкіше, тому що дозволяє зберегти додаткову інформацію про машину. Тепер на схему додамо metadata агента:

Введення в мережеву частину хмарної інфраструктури

Ще одне питання, яке також варто освятити — це можливість використовувати одну зовнішню мережу всіма клієнтами, оскільки зовнішні мережі, якщо вони мають бути валідні у всій мережі, то буде складність — треба постійно виділяти та контролювати виділення цих мереж. Можливість використання єдиної для всіх клієнтів зовнішньої конфігурованої мережі буде дуже доречною при створенні публічної хмари. Це спростить розгортання машин, тому що нам не треба звірятися з базою даних адрес та вибирати унікальний адресний простір для зовнішньої мережі кожного клієнта. До того ж ми можемо прописати зовнішню мережу заздалегідь і в момент розгортання нам потрібно буде лише асоціювати зовнішні адреси з клієнтськими машинами.

І тут на допомогу нам приходить NAT – просто зробимо можливість клієнтів виходити у зовнішній світ через default namespace із використанням NAT трансляції. Та й тут невелика проблема. Це добре, якщо клієнтський сервер працює як клієнт, а не як сервер, тобто ініціює, а не приймає підключення. Але в нас буде навпаки. У такому разі нам треба зробити destination NAT, щоб при отриманні трафіку контрольна нода розуміла, що цей трафік призначений віртуальній машині А клієнта А, отже треба зробити NAT трансляцію із зовнішньої адреси, наприклад 100.1.1.1 на внутрішню адресу 10.0.0.1. У такому випадку, хоча всі клієнти будуть використовувати одну й ту саму мережу, внутрішня ізоляція повністю зберігається. Тобто нам треба на контрольній ноді зробити dNAT та sNAT. Використовувати єдину мережу з виділенням плаваючих адрес або зовнішні мережі або й те й те відразу - обумовлюється тим, що ви хочете в хмару затягнути. Ми не будемо наносити на схему ще й плаваючі адреси, а залишимо вже додані зовнішні мережі — у кожного клієнта є своя зовнішня мережа (на схемі позначені як влан 100 і 200 на зовнішньому інтерфейсі).

У результаті ми отримали цікаве і водночас продумане рішення, що має певну гнучкість, але поки що не має механізмів відмовостійкості.

По-перше, у нас лише одна контрольна нода — вихід її з ладу приведе до краху всі системи. Для усунення цієї проблеми необхідно зробити як мінімум кворум із 3-х нід. Додамо це на схему:

Введення в мережеву частину хмарної інфраструктури

Звичайно всі ноди синхронізуються і при виході активної ноди її обов'язки на себе візьме інша нода.

Наступна проблема – диски віртуальних машин. Зараз вони зберігаються на самих гіпервізорах і в разі проблем з гіпервізором ми втрачаємо всі дані - і наявність рейду тут ніяк не допоможе, якщо ми втратимо не диск, а весь сервер цілком. Для цього нам потрібно зробити службу, яка виступатиме фронтендом для якогось сховища. Яке це буде сховище нам особливо не важливо, але воно має захистити наші дані від виходу з ладу та диска та ноди, а можливо й цілої шафи. Варіантів тут кілька – є звичайно SAN мережі з Fiber Channel, але скажемо чесно – FC це вже пережиток минулого – аналог E1 у транспорті – та згоден, він ще використовується, але тільки там, де без нього ну ніяк не можна. Тому добровільно розгортати FC мережу в 2020 році я не став би, знаючи про наявність інших більш цікавих альтернатив. Хоча кожному своє і можливо знайдуться ті, хто вважає, що FC з усіма його обмеженнями - все що нам треба - не сперечатися, у кожного своя думка. Однак найцікавішим рішенням на мою думку є використання SDS, наприклад Ceph.

Ceph дозволяє побудувати доступне рішення для зберігання даних з купою можливих варіантів резервування, починаючи з кодів з перевіркою парності (аналог рейд 5 або 6) закінчуючи повною реплікацією даних на різні диски з урахуванням розташування дисків в серверах, і серверів в шафах і т.д.

Для складання Ceph потрібно ще 3 ноди. Взаємодія зі сховищем здійснюватиметься також через мережу з використанням служб блочного, об'єктного та файлового сховищ. Додамо до схеми сховища:

Введення в мережеву частину хмарної інфраструктури

Примітка: можна робити і гіперконвергентні compute ноди - це концепція поєднання кількох функцій на одній ноді - наприклад storage + compute - не виділяти спеціальні ноди під ceph storage. Ми отримаємо таку ж стійку відмову схему — оскільки SDS зарезервує дані із зазначеним нами рівнем резервування. Однак гіперконвергентні ноди - це завжди компроміс - так як storage нода не просто гріє повітря як здається на перший погляд (бо на ній немає віртуальних машин) - вона витрачає ресурси CPU на обслуговування SDS (за фактом вона у фоні робить усі реплікації, відновлення після збоїв нод, дисків тощо). Тобто ви втратите частину потужності compute ноди якщо поєднаєте її з storage.

Всім цим добром треба якось керувати - потрібно що те, через що ми можемо створити машину, мережу, віртуальний маршрутизатор і т.д. Для цього на контрольну ноду додамо службу, яка буде виконувати роль dashboard - клієнт зможе підключитися до цього порталу через http/ https і зробити все, що йому потрібно (ну майже).

У результаті тепер ми маємо стійку до відмови систему. Всіми елементами даної інфраструктури треба якось керувати. Раніше було описано, що Openstack - це набір проектів, кожен з яких забезпечує якусь певну функцію. Як бачимо елементів, які треба конфігурувати і контролювати більш ніж достатньо. Сьогодні ми поговоримо про мережну частину.

Архітектура Neutron

У OpenStack саме Neutron відповідає за підключення портів віртуальних машин до загальної мережі L2, забезпечення маршрутизації трафіку між VM, що знаходяться в різних мережах L2 а також маршрутизацію назовні, надання таких сервісів як NAT, Floating IP, DHCP і т.д.

Високорівневу роботу мережевої служби (базова частина) можна описати так.

При запуску VM мережна служба:

  1. Створює порт для цієї VM (або порти) і повідомляє про це DHCP сервіс;
  2. Створюється новий віртуальний мережевий девайс (через libvirt);
  3. VM підключається до створеного на 1 кроці порту (портів);

Як не дивно, але в основі роботи Neutron лежать стандартні механізми, знайомі всім, що колись занурювався в Linux - це namespaces, iptables, linux bridges, openvswitch, conntrack і т.д.

Слід одразу уточнити, що Neutron не є контролером SDN.

Neutron складається з кількох взаємопов'язаних між собою компонентів:

Введення в мережеву частину хмарної інфраструктури

Openstack-neutron-server — це демон, який через API працює з запитами користувача. Даний демон не займається прописуванням будь-яких мережевих зв'язків, а дає необхідну для цього інформацію своїм плагінам, які налаштовують потрібний елемент мережі. Neutron-агенти на вузлах OpenStack реєструються на сервері Neutron.

Neutron-server це фактично додаток, написаний на python, що складається з двох частин:

  • Послуга ВІДПОЧИНОК
  • Neutron Plugin (core/service)

REST сервіс призначений для прийому API викликів від інших компонентів (наприклад запит на надання будь-якої інформації тощо)

Плагіни це програмні компоненти/модулі, що підключаються, які викликаються при API запитах — тобто приписування якогось сервісу відбувається через них. Плагіни поділяються на два види - сервісний та кореневий. Як правило, коньовий плагін відповідає в основному за керування адресним простором і L2 з'єднання між VM, а сервісні плагіни вже забезпечують додатковий функціонал наприклад VPN або FW.

Список доступних на сьогодні плагінів можна переглянути наприклад тут

Сервісних плагінів може бути кілька, проте коньовий плагін може бути лише один.

Openstack-neutron-ml2 - Це стандартний кореневий плагін Openstack. Даний плагін має модульну архітектуру (на відміну від свого попередника) і через драйвери, що підключаються до нього, здійснює конфігурування мережевого сервісу. Сам плагін розглянемо трохи пізніше, тому що фактично він дає ту гнучкість, яку має OpenStack в мережній частині. Кореневий плагін може бути замінений (наприклад, Contrail Networking робить таку заміну).

RPC service (rabbitmq-server) - сервіс, що забезпечує управління чергами та взаємодію з іншими службами OpenStack а також взаємодію між агентами мережевої служби.

Network agents - Агенти, які розташовані в кожній ноді, через які і проводиться конфігурування мережевих сервісів.

Агенти бувають кількох видів.

Основний агент - це L2 agent. Ці агенти запускаються на кожному з гіпервізорів включаючи і контрольні ноди (точніше сказати на всіх вузлах, які надають якийсь сервіс для тенантів) та їх основна функція - підключення віртуальних машин до загальної мережі L2, а також генерувати оповіщення при виникненні яких-небудь подій (наприклад відключення/увімкнення порту).

Наступним, не менш важливим агентом є L3 agent. За замовчуванням цей агент запускається виключно на network ноді (часто network node поєднується з control node) і забезпечує маршрутизацію між мережами тенантів (як між мережами та мережами інших тенатів, так і доступний у зовнішній світ, забезпечуючи NAT, а також DHCP сервіс). Однак при використанні DVR (розподілений маршрутизатор) необхідність у L3 плагіні з'являється і на compute нодах.

L3 агент використовує Linux namespaces для надання кожному тенанту набору власних ізольованих мереж та функціонал віртуальних маршрутизаторів, які маршрутизують трафік та надають послуги шлюзу для Layer 2 мереж.

Database - База даних ідентифікаторів мереж, підмереж, портів, пулів і т.д.

Фактично Neutron приймає API запити від створення будь-яких мережевих сутностей аутентифікує запит, і через RPC (якщо звертається до якогось плагіну або агенту) або REST API (якщо спілкується в SDN) передає агентам (через плагіни) інструкції, необхідні організації запрошеного сервісу .

Тепер звернемося до тестової інсталяції (як вона розгорнута і що в її складі подивимося пізніше в практичній частині) і подивимося, де яка компонента розташована:

(overcloud) [stack@undercloud ~]$ openstack network agent list  
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
| ID                                   | Agent Type         | Host                                | Availability Zone | Alive | State | Binary                    |
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
| 10495de9-ba4b-41fe-b30a-b90ec3f8728b | Open vSwitch agent | overcloud-novacompute-1.localdomain | None              | :-)   | UP    | neutron-openvswitch-agent |
| 1515ad4a-5972-46c3-af5f-e5446dff7ac7 | L3 agent           | overcloud-controller-0.localdomain  | nova              | :-)   | UP    | neutron-l3-agent          |
| 322e62ca-1e5a-479e-9a96-4f26d09abdd7 | DHCP agent         | overcloud-controller-0.localdomain  | nova              | :-)   | UP    | neutron-dhcp-agent        |
| 9c1de2f9-bac5-400e-998d-4360f04fc533 | Open vSwitch agent | overcloud-novacompute-0.localdomain | None              | :-)   | UP    | neutron-openvswitch-agent |
| d99c5657-851e-4d3c-bef6-f1e3bb1acfb0 | Open vSwitch agent | overcloud-controller-0.localdomain  | None              | :-)   | UP    | neutron-openvswitch-agent |
| ff85fae6-5543-45fb-a301-19c57b62d836 | Metadata agent     | overcloud-controller-0.localdomain  | None              | :-)   | UP    | neutron-metadata-agent    |
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
(overcloud) [stack@undercloud ~]$ 

Введення в мережеву частину хмарної інфраструктури

Ось і вся структура Neutron. Тепер варто приділити якийсь час ML2 плагіну.

Modular Layer 2

Як уже сказано вище, плагін є стандартним кореневим плагіном OpenStack і має модульну архітектуру.

Попередник ML2 плагіна мав монолітну структуру, що не дозволяло наприклад використовувати мікс з декількох технологій в одній інсталяції. Наприклад, ви не могли використовувати і openvswitch і linuxbridge одночасно — або перше, або друге. З цієї причини було створено ML2 плагін з його архітектурою.

ML2 має дві складові - два типи драйверів: Type drivers та Mechanism drivers.

Type drivers визначають технології, які будуть використані для організації мережевих зв'язків, наприклад, VxLAN, VLAN, GRE. Драйвер дозволяє використовувати різні технології. Стандартною технологією є VxLAN інкапсуляція для overlay мереж та vlan зовнішніх мереж.

До Type drivers є такі типи мереж:

Flat - Мережа без тегування
VLAN - Тегована мережа
Місцевий - Спеціальний тип мережі для інсталяцій типу all-in-one (такі інсталяції потрібні або для розробників або для навчання)
GRE - overlay мережа, що використовує GRE тунелі
VxLAN - overlay мережа, що використовує VxLAN тунелі

Mechanism drivers визначають засоби, які забезпечують організацію зазначених у типі driver технологій - наприклад, openvswitch, sr-iov, opendaylight, OVN і т.д.

Залежно від реалізації даного драйвера буде використано або агенти, які управляються Neutron, або використовуватися з'єднання із зовнішнім SDN контролером, який бере на себе всі питання щодо організації L2 мереж, маршрутизації тощо.

Приклад якщо ми використовуємо ML2 разом з OVS, то на кожній обчислювальній ноді встановлюється агент L2, який управляє OVS. Однак якщо ми використовуємо наприклад OVN або OpenDayLight, то управління OVS переходить під їхню юрисдикцію - Neutron через кореневий плагін дає команди контролеру, а він уже робить те, що йому сказали.

Освіжимо в пам'яті Open vSwitch

На даний момент одним із ключових компонентів OpenStack є Open vSwitch.
При установці OpenStack без будь-якого додаткового вендорського SDN типу Juniper Contrail або Nokia Nuage, OVS є основною мережевою компонентою хмарної мережі та в сукупності з iptables, conntrack, namespaces дозволяє організовувати повноцінний оверлейні мережі з мультитенансами. Природно, дана компонента може бути замінена, наприклад при використанні сторонніх пропрієтарних (вендорських) SDN рішень.

OVS це програмний комутатор з відкритим вихідним кодом, який призначений для використання у віртуалізованих середовищах як віртуальний форвардер трафіку.

На даний момент OVS має дуже пристойний функціонал, який включає такі технології, як QoS, LACP, VLAN, VxLAN, GENEVE, OpenFlow, DPDK і т.д.

Примітка: спочатку OVS не замислювався як програмний комутатор для високонавантажених телеком функцій і був більш розрахований під менш вимогливі до пропускної спроможності ІТ функції типу WEB-сервера або поштового сервера. Однак OVS допрацьовується і поточні реалізації OVS сильно покращили його продуктивність та можливості, що дозволяє його використовувати операторам зв'язку з високонавантаженими функціями, наприклад є реалізація OVS з підтримкою DPDK прискорення.

Існує три важливі компоненти OVS, про які необхідно знати:

  • Модуль ядра - компонента, розташована в kernel space, яка виконує обробку трафік на основі одержаних від керуючого елемента правил;
  • vSwitch daemon (ovs-vswitchd) - це процес, запущений в user space, який відповідає за програмування kernel модуля - тобто представляє безпосередньо логіку роботи комутатора
  • Сервер баз даних — локальна база даних, розміщена кожному хості, у якому запущено OVS, у якій зберігається конфігурація. Через цей модуль за протоколом OVSDB можуть спілкуватися контролери SDN.

До цього всього додається набір діагностичних і керуючих утиліт, таких як ovs-vsctl, ovs-appctl, ovs-ofctl і т.д.

На даний момент Openstack широко використовується телеком операторами для міграції в нього мережевих функцій, таких як EPC, SBC, HLR і т.д. Частина функцій може без проблем жити з OVS у тому вигляді в якому він є, але наприклад EPC обробляє трафік абонентів тобто пропускає через себе величезну кількість трафіку (зараз обсяги трафіку досягають кількох сотень гігабіт на секунду). Природно гнати такий трафік через kernel space (оскільки за замовчуванням форвардер розташований саме там) — не найкраща ідея. Тому часто OVS розгортають повністю в user space з використанням технології прискорення DPDK для прокидання трафіку з NIC в user space минаючи kernel.

Примітка: для хмари, розгорнутого для телевізорів функцій можливий варіант виведення трафіку з комп'ютерної ноди минаючи OVS безпосередньо в комутаційне обладнання. З цією метою використовуються механізми SR-IOV і Passthrough.

Як це працює на реальному макеті?

Ну і тепер перейдемо до практичної частини та подивимося як це все працює на практиці.

Для початку розгорнемо просту Openstack інсталяцію. Так як у мене під рукою під експерименти немає набору серверів, то збиратимемо макет на одному фізичному сервері з віртуальних машин. Так, звичайно під комерційні цілі таке рішення не підходить, але щоб подивитися на прикладі, як працює мережа в Openstack такої інсталяції, вистачить за очі. Причому така інсталяція для цілей навчання навіть цікавіша — оскільки можна відловити трафік і т.д.

Так як нам треба побачити тільки базову частину, то ми можемо не використовувати декілька мереж, а все підняти з використанням всього двох мереж, причому друга мережа в даному макеті буде використовуватися виключно для доступу до undercloud та dns серверу. Зовнішні мережі ми поки що не зачіпатимемо — це тема для окремої великої статті.

Отже, почнемо по порядку. Спочатку трохи теорії. Ставити ми будемо Openstack за допомогою TripleO (Openstack on Openstack). Суть TripleO полягає в тому, що ми встановлюємо Openstack all-in-one (тобто одну ноду), званий undercloud, і далі використовуємо можливості розгорнутого Openstack щоб встановити Openstack, призначений для експлуатації, званий overcloud. Undercloud використовуватиме закладену в нього можливість управляти фізичними серверами (bare metal) — проект Ironic — для провіжинінгу гіпервізорів, які виконуватимуть ролі compute, control, storage нод. Тобто, ми не використовуємо жодних сторонніх засобів для розгортання Openstack — ми розгортаємо Openstack силами Openstack. Далі по ходу установки стане набагато зрозумілішим, тому не зупинятимемо на цьому і підемо вперед.

Примітка: З метою спрощення я не став використовувати мережну ізоляцію для внутрішніх мереж Openstack, а все розгорнуто з використанням лише однієї мережі. Однак наявність або відсутність ізоляції мереж не впливає на базову функціональність рішення - все працюватиме так само, як і при використанні ізоляції, але трафік ходитиме в одній мережі. Для комерційної інсталяції, звичайно, необхідно використовувати ізоляцію з використанням різних вланів та інтерфейсів. Наприклад трафік управління ceph сховищем і трафік безпосередньо даних (звернення машин до дисків і т д) при ізоляції використовують різні підмережі (Storage management і Storage) і це дозволяє зробити рішення більш стійким до відмови, розділивши даний трафік наприклад по різних портах, або використовувати різні QoS профілі для різного трафіку, щоби трафік даних не видавив сигнальний трафік. У нашому випадку вони будуть йти в одній і тій же мережі і за фактом це ніяк не лімітує нас.

Примітка: Так як ми збираємося запускати віртуальні машини у віртуальному середовищі, що базується на віртуальних машинах, то спочатку потрібно включити nested віртуалізацію.

Перевірити, чи включена nested віртуалізація чи ні можна так:


[root@hp-gen9 bormoglotx]# cat /sys/module/kvm_intel/parameters/nested
N
[root@hp-gen9 bormoglotx]# 

Якщо ви бачите букву N, то включаємо підтримку nested віртуалізації за будь-яким гайдом, який знайдете в мережі, наприклад такий .

Нам треба зібрати таку схему з віртуальних машин:

Введення в мережеву частину хмарної інфраструктури

У моєму випадку для зв'язності віртуальних машин, що входять до складу майбутньої інсталяції (а їх у мене вийшло 7 штук, але можна обійтися 4, якщо у вас небагато ресурсів) я використав OpenvSwitch. Я створив один ovs бридж і підключив до нього віртуальні машини через port-groups. Для цього створив xml файл такого вигляду:


[root@hp-gen9 ~]# virsh net-dumpxml ovs-network-1        
<network>
  <name>ovs-network-1</name>
  <uuid>7a2e7de7-fc16-4e00-b1ed-4d190133af67</uuid>
  <forward mode='bridge'/>
  <bridge name='ovs-br1'/>
  <virtualport type='openvswitch'/>
  <portgroup name='trunk-1'>
    <vlan trunk='yes'>
      <tag id='100'/>
      <tag id='101'/>
      <tag id='102'/>
    </vlan>
  </portgroup>
  <portgroup name='access-100'>
    <vlan>
      <tag id='100'/>
    </vlan>
  </portgroup>
  <portgroup name='access-101'>
    <vlan>
      <tag id='101'/>
    </vlan>
  </portgroup>
</network>

Тут оголошено три порт групи - дві access і одна trunk (остання потрібна була для DNS сервера, але можна обійтися і без нього, або підняти його на хостовій машині - це як вам зручніше). Далі за допомогою даного шаблону оголошуємо нашу їжу через virsh net-define:


virsh net-define ovs-network-1.xml 
virsh net-start ovs-network-1 
virsh net-autostart ovs-network-1 

Тепер правимо конфігурації портів гіпервізора:


[root@hp-gen9 ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens1f0   
TYPE=Ethernet
NAME=ens1f0
DEVICE=ens1f0
TYPE=OVSPort
DEVICETYPE=ovs
OVS_BRIDGE=ovs-br1
ONBOOT=yes
OVS_OPTIONS="trunk=100,101,102"
[root@hp-gen9 ~]
[root@hp-gen9 ~]# cat /etc/sysconfig/network-scripts/ifcfg-ovs-br1 
DEVICE=ovs-br1
DEVICETYPE=ovs
TYPE=OVSBridge
BOOTPROTO=static
ONBOOT=yes
IPADDR=192.168.255.200
PREFIX=24
[root@hp-gen9 ~]# 

Примітка: у цьому сценарії адреса на порту ovs-br1 не буде доступна, оскільки вона не має лан тега. Щоб це виправити, треба дати команду sudo ovs-vsctl set port ovs-br1 tag=100. Однак після перезавантаження цей тег пропаде (якщо хтось знає як змусити його залишитися на місці — буду дуже вдячний). Але це не так важливо, бо ця адреса нам знадобиться тільки на час інсталяції і буде не потрібна, коли Openstack буде повністю розгорнутий.

Далі створюємо undercloud машину:


virt-install  -n undercloud --description "undercloud"  --os-type=Linux  --os-variant=centos7.0  --ram=8192  --vcpus=8  --disk path=/var/lib/libvirt/images/undercloud.qcow2,bus=virtio,size=40,format=qcow2 --network network:ovs-network-1,model=virtio,portgroup=access-100 --network network:ovs-network-1,model=virtio,portgroup=access-101 --graphics none  --location /var/lib/libvirt/boot/CentOS-7-x86_64-Minimal-2003.iso --extra-args console=ttyS0

У ході установки виставляєте всі потрібні параметри, такі як ім'я машини, паролі, користувачі, ntp сервери і т.д., можна відразу налаштувати порти, але мені особисто простіше після установки зайти в машину через консоль і підправити потрібні файли. Якщо у вас вже є готовий образ, то можете використовувати його, або вчинити як я - завантажити мінімальний образ Centos 7 і використовувати його для встановлення VM.

Після успішної установки у вас має з'явитися віртуальна машина, на яку можна буде ставити undercloud


[root@hp-gen9 bormoglotx]# virsh list
 Id    Name                           State
----------------------------------------------------
 6     dns-server                     running
 62    undercloud                     running

Спочатку ставимо необхідні в процесі встановлення інструменти:

sudo yum update -y
sudo yum install -y net-tools
sudo yum install -y wget
sudo yum install -y ipmitool

Установка Undercloud

Створюємо користувача stack, задаємо пароль, додаємо в sudoer і даємо можливість виконувати root команди через sudo без необхідності введення пароля:


useradd stack
passwd stack

echo “stack ALL=(root) NOPASSWD:ALL” > /etc/sudoers.d/stack
chmod 0440 /etc/sudoers.d/stack

Тепер вказуємо у файлі hosts повне ім'я undercloud:


vi /etc/hosts

127.0.0.1   undercloud.openstack.rnd localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

Далі додаємо репозиторії та ставимо потрібний нам софт:


sudo yum install -y https://trunk.rdoproject.org/centos7/current/python2-tripleo-repos-0.0.1-0.20200409224957.8bac392.el7.noarch.rpm
sudo -E tripleo-repos -b queens current
sudo -E tripleo-repos -b queens current ceph
sudo yum install -y python-tripleoclient
sudo yum install -y ceph-ansible

Примітка: якщо ви не плануєте ставити ceph, команди, що відносяться до ceph, вводити не треба. Я використав реліз Queens, але ви можете використати будь-який інший, який вам сподобається.

Далі копіюємо файл конфігурації undercloud в домашню директорію користувача stack:


cp /usr/share/instack-undercloud/undercloud.conf.sample ~/undercloud.conf

Тепер необхідно виправити цей файл, підлаштувавши його під нашу інсталяцію.

На початок файлу треба додати рядки:

vi undercloud.conf
[DEFAULT]
undercloud_hostname = undercloud.openstack.rnd
local_ip = 192.168.255.1/24
network_gateway = 192.168.255.1
undercloud_public_host = 192.168.255.2
undercloud_admin_host = 192.168.255.3
undercloud_nameservers = 192.168.255.253
generate_service_certificate = false
local_interface = eth0
local_mtu = 1450
network_cidr = 192.168.255.0/24
masquerade = true
masquerade_network = 192.168.255.0/24
dhcp_start = 192.168.255.11
dhcp_end = 192.168.255.50
inspection_iprange = 192.168.255.51,192.168.255.100
scheduler_max_attempts = 10

Отже, пройдемо за налаштуваннями:

undercloud_hostname - повне ім'я undercloud сервера, має збігатися із записом на DNS сервері

local_ip — локальна адреса undercloud у бік провіженінг мережі

network_gateway — ця ж локальна адреса, яка виступатиме як gateway для доступу до зовнішнього світу під час встановлення overcloud нод, теж збігається з local ip

undercloud_public_host — адреса зовнішнього API, призначається будь-яка вільна адреса з провіжинінгу мережі

undercloud_admin_host адреса внутрішнього API, призначається будь-яка вільна адреса з провіжинінгу мережі

undercloud_nameservers - DNS сервер

generate_service_certificate — цей рядок дуже важливий у поточному прикладі, оскільки якщо його не встановити у значення false ви отримаєте помилку під час встановлення, проблема описана на багтрекері Red Hat

local_interface інтерфейс у провіжинінг мережі. Цей інтерфейс буде переконфігурований під час розгортання undercloud, тому на undercloud необхідно мати два інтерфейси - один для доступу до нього, другий для провіжинінгу

local_mtu - MTU. Так як у нас тестова лабораторія і MTU у мене 1500 на портах OVS свіча, то необхідно виставити в значення 1450, щоб пройшли інкапсульовані в VxLAN пакети

network_cidr - провіжинінг мережа

маскарад — використання NAT для доступу до зовнішньої мережі

masquerade_network - мережа, яка буде NAT-ся

dhcp_start — початкова адреса пулу адрес, з якої призначатимуться адреси нодам під час деплою overcloud

dhcp_end — кінцева адреса пулу адрес, з якої призначатимуться адреси нодам під час деплою overcloud

inspection_iprange - Пул адрес, необхідних для проведення інтроспекції (не повинен перетинатися з вищезазначеним пулом)

scheduler_max_attempts — максимальна кількість спроб встановлення overcloud (має бути більше або дорівнює кількості нод)

Після того, як файл описаний, можна дати команду на деплой undercloud:


openstack undercloud install

Процедура займає від 10 до 30 хвилин, залежно від вашого заліза. Зрештою, ви повинні побачити такий висновок:

vi undercloud.conf
2020-08-13 23:13:12,668 INFO: 
#############################################################################
Undercloud install complete.

The file containing this installation's passwords is at
/home/stack/undercloud-passwords.conf.

There is also a stackrc file at /home/stack/stackrc.

These files are needed to interact with the OpenStack services, and should be
secured.

#############################################################################

Цей висновок говорить, що ви успішно встановили undercloud і тепер можна перевірити стан undercloud і переходити до установки overcloud.

Якщо подивитися висновок ifconfig, ви побачите, що з'явився новий бридж інтерфейс

[stack@undercloud ~]$ ifconfig
br-ctlplane: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 192.168.255.1  netmask 255.255.255.0  broadcast 192.168.255.255
        inet6 fe80::5054:ff:fe2c:89e  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:2c:08:9e  txqueuelen 1000  (Ethernet)
        RX packets 14  bytes 1095 (1.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20  bytes 1292 (1.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Через даний інтерфейс тепер проводитиметься робота з розгортання overcloud.

З висновку нижче видно, що всі послуги у нас на одній ноді:

(undercloud) [stack@undercloud ~]$ openstack host list
+--------------------------+-----------+----------+
| Host Name                | Service   | Zone     |
+--------------------------+-----------+----------+
| undercloud.openstack.rnd | conductor | internal |
| undercloud.openstack.rnd | scheduler | internal |
| undercloud.openstack.rnd | compute   | nova     |
+--------------------------+-----------+----------+

Нижче показана конфігурація мережної частини undercloud:


(undercloud) [stack@undercloud ~]$ python -m json.tool /etc/os-net-config/config.json 
{
    "network_config": [
        {
            "addresses": [
                {
                    "ip_netmask": "192.168.255.1/24"
                }
            ],
            "members": [
                {
                    "dns_servers": [
                        "192.168.255.253"
                    ],
                    "mtu": 1450,
                    "name": "eth0",
                    "primary": "true",
                    "type": "interface"
                }
            ],
            "mtu": 1450,
            "name": "br-ctlplane",
            "ovs_extra": [
                "br-set-external-id br-ctlplane bridge-id br-ctlplane"
            ],
            "routes": [],
            "type": "ovs_bridge"
        }
    ]
}
(undercloud) [stack@undercloud ~]$

Установка overcloud

На даний момент у нас тільки undercloud, і нам не вистачає нід, з яких буде збиратися overcloud. Тому насамперед розгорнемо потрібні нам віртуальні машини. У ході деплою undercloud сам поставить ОС і потрібний софт на overcloud машини - тобто нам не потрібно повністю розгортати машину, а тільки створити для неї диск (або диски) і визначити її параметри - тобто за фактом отримуємо голий сервер без встановленої ОС .

Переходимо до папки з дисками наших віртуальних машин і створимо диски потрібного об'єму:


cd /var/lib/libvirt/images/
qemu-img create -f qcow2 -o preallocation=metadata control-1.qcow2 60G
qemu-img create -f qcow2 -o preallocation=metadata compute-1.qcow2 60G
qemu-img create -f qcow2 -o preallocation=metadata compute-2.qcow2 60G
qemu-img create -f qcow2 -o preallocation=metadata storage-1.qcow2 160G
qemu-img create -f qcow2 -o preallocation=metadata storage-2.qcow2 160G

Оскільки ми діємо від рута, то нам треба змінити власника цих дисків, щоб не отримати проблему з правами:


[root@hp-gen9 images]# ls -lh
total 5.8G
drwxr-xr-x. 2 qemu qemu 4.0K Aug 13 16:15 backups
-rw-r--r--. 1 root root  61G Aug 14 03:07 compute-1.qcow2
-rw-r--r--. 1 root root  61G Aug 14 03:07 compute-2.qcow2
-rw-r--r--. 1 root root  61G Aug 14 03:07 control-1.qcow2
-rw-------. 1 qemu qemu  41G Aug 14 03:03 dns-server.qcow2
-rw-r--r--. 1 root root 161G Aug 14 03:07 storage-1.qcow2
-rw-r--r--. 1 root root 161G Aug 14 03:07 storage-2.qcow2
-rw-------. 1 qemu qemu  41G Aug 14 03:07 undercloud.qcow2
[root@hp-gen9 images]# 
[root@hp-gen9 images]# 
[root@hp-gen9 images]# chown qemu:qemu /var/lib/libvirt/images/*qcow2
[root@hp-gen9 images]# ls -lh
total 5.8G
drwxr-xr-x. 2 qemu qemu 4.0K Aug 13 16:15 backups
-rw-r--r--. 1 qemu qemu  61G Aug 14 03:07 compute-1.qcow2
-rw-r--r--. 1 qemu qemu  61G Aug 14 03:07 compute-2.qcow2
-rw-r--r--. 1 qemu qemu  61G Aug 14 03:07 control-1.qcow2
-rw-------. 1 qemu qemu  41G Aug 14 03:03 dns-server.qcow2
-rw-r--r--. 1 qemu qemu 161G Aug 14 03:07 storage-1.qcow2
-rw-r--r--. 1 qemu qemu 161G Aug 14 03:07 storage-2.qcow2
-rw-------. 1 qemu qemu  41G Aug 14 03:08 undercloud.qcow2
[root@hp-gen9 images]# 

Примітка: якщо ви не плануєте ставити ceph з метою його вивчення, то команди не створюйте як мінімум 3 ноди з мінімум двома дисками, а в темплі вкажіть, що будуть використовуватися віртуальні диски vda, vdb і т.д.

Відмінно, тепер нам треба всі ці машини визначити:


virt-install --name control-1 --ram 32768 --vcpus 8 --os-variant centos7.0 --disk path=/var/lib/libvirt/images/control-1.qcow2,device=disk,bus=virtio,format=qcow2 --noautoconsole --vnc  --network network:ovs-network-1,model=virtio,portgroup=access-100 --network network:ovs-network-1,model=virtio,portgroup=trunk-1 --dry-run --print-xml > /tmp/control-1.xml  

virt-install --name storage-1 --ram 16384 --vcpus 4 --os-variant centos7.0 --disk path=/var/lib/libvirt/images/storage-1.qcow2,device=disk,bus=virtio,format=qcow2 --noautoconsole --vnc  --network network:ovs-network-1,model=virtio,portgroup=access-100 --dry-run --print-xml > /tmp/storage-1.xml  

virt-install --name storage-2 --ram 16384 --vcpus 4 --os-variant centos7.0 --disk path=/var/lib/libvirt/images/storage-2.qcow2,device=disk,bus=virtio,format=qcow2 --noautoconsole --vnc  --network network:ovs-network-1,model=virtio,portgroup=access-100 --dry-run --print-xml > /tmp/storage-2.xml  

virt-install --name compute-1 --ram 32768 --vcpus 12 --os-variant centos7.0 --disk path=/var/lib/libvirt/images/compute-1.qcow2,device=disk,bus=virtio,format=qcow2 --noautoconsole --vnc  --network network:ovs-network-1,model=virtio,portgroup=access-100 --dry-run --print-xml > /tmp/compute-1.xml  

virt-install --name compute-2 --ram 32768 --vcpus 12 --os-variant centos7.0 --disk path=/var/lib/libvirt/images/compute-2.qcow2,device=disk,bus=virtio,format=qcow2 --noautoconsole --vnc  --network network:ovs-network-1,model=virtio,portgroup=access-100 --dry-run --print-xml > /tmp/compute-2.xml 

Наприкінці є команди -print-xml > /tmp/storage-1.xml, яка створює xml файл з описом кожної машини в папці /tmp/, якщо її не додати, то не зможете визначити віртуальні машини.

Тепер нам треба всі ці машини визначити у virsh:


virsh define --file /tmp/control-1.xml
virsh define --file /tmp/compute-1.xml
virsh define --file /tmp/compute-2.xml
virsh define --file /tmp/storage-1.xml
virsh define --file /tmp/storage-2.xml

[root@hp-gen9 ~]# virsh list --all
 Id    Name                           State
----------------------------------------------------
 6     dns-server                     running
 64    undercloud                     running
 -     compute-1                      shut off
 -     compute-2                      shut off
 -     control-1                      shut off
 -     storage-1                      shut off
 -     storage-2                      shut off

[root@hp-gen9 ~]#

Тепер невеликий нюанс - tripleO використовує IPMI для того, щоб керувати серверами під час встановлення та інтроспекції.

Інтроспекція - це процес інспекції апратної частини з метою отримання її параметрів, необхідних для подальшого провіжинінгу нід. Інтроспекція проводиться за допомогою ironic - служби, призначеної для роботи з bare metal серверами.

Але тут проблема — якщо в залізних серверів IPMI це окремий порт (або shared порт, але це не принципово), то у віртуальних машин таких портів немає. Тут нам на допомогу приходить милиця під назвою vbmc – утиліта, яка дозволяє емулювати IPMI порт. На цей нюанс варто звернути увагу особливо тим, хто захоче підняти таку лабораторію на ESXI гіпервізорі — якщо, не знаю, чи є в ньому аналог vbmc, тому варто спантеличитися цим питанням перед тим, як усе розгортати.

Встановлюємо vbmc:


yum install yum install python2-virtualbmc

Якщо ваша ОС не може знайти пакет, додайте репозиторій:

yum install -y https://www.rdoproject.org/repos/rdo-release.rpm

Тепер налаштовуємо утиліту. Тут все банально до неподобства. Зараз логічно, що у списку vbmc немає жодних серверів


[root@hp-gen9 ~]# vbmc list

[root@hp-gen9 ~]# 

Щоб вони з'явилися, їх необхідно вручну оголосити таким чином:


[root@hp-gen9 ~]# vbmc add control-1 --port 7001 --username admin --password admin
[root@hp-gen9 ~]# vbmc add storage-1 --port 7002 --username admin --password admin
[root@hp-gen9 ~]# vbmc add storage-2 --port 7003 --username admin --password admin
[root@hp-gen9 ~]# vbmc add compute-1 --port 7004 --username admin --password admin
[root@hp-gen9 ~]# vbmc add compute-2 --port 7005 --username admin --password admin
[root@hp-gen9 ~]#
[root@hp-gen9 ~]# vbmc list
+-------------+--------+---------+------+
| Domain name | Status | Address | Port |
+-------------+--------+---------+------+
| compute-1   | down   | ::      | 7004 |
| compute-2   | down   | ::      | 7005 |
| control-1   | down   | ::      | 7001 |
| storage-1   | down   | ::      | 7002 |
| storage-2   | down   | ::      | 7003 |
+-------------+--------+---------+------+
[root@hp-gen9 ~]#

Думаю, синтаксис команди зрозумілий і без пояснень. Однак поки що всі наші сесії у статусі DOWN. Щоб вони перейшли у статус UP, необхідно їх увімкнути:


[root@hp-gen9 ~]# vbmc start control-1
2020-08-14 03:15:57,826.826 13149 INFO VirtualBMC [-] Started vBMC instance for domain control-1
[root@hp-gen9 ~]# vbmc start storage-1 
2020-08-14 03:15:58,316.316 13149 INFO VirtualBMC [-] Started vBMC instance for domain storage-1
[root@hp-gen9 ~]# vbmc start storage-2
2020-08-14 03:15:58,851.851 13149 INFO VirtualBMC [-] Started vBMC instance for domain storage-2
[root@hp-gen9 ~]# vbmc start compute-1
2020-08-14 03:15:59,307.307 13149 INFO VirtualBMC [-] Started vBMC instance for domain compute-1
[root@hp-gen9 ~]# vbmc start compute-2
2020-08-14 03:15:59,712.712 13149 INFO VirtualBMC [-] Started vBMC instance for domain compute-2
[root@hp-gen9 ~]# 
[root@hp-gen9 ~]# 
[root@hp-gen9 ~]# vbmc list
+-------------+---------+---------+------+
| Domain name | Status  | Address | Port |
+-------------+---------+---------+------+
| compute-1   | running | ::      | 7004 |
| compute-2   | running | ::      | 7005 |
| control-1   | running | ::      | 7001 |
| storage-1   | running | ::      | 7002 |
| storage-2   | running | ::      | 7003 |
+-------------+---------+---------+------+
[root@hp-gen9 ~]#

І останній штрих - потрібно виправити правила фаєрвола (ну або відключити його зовсім):


firewall-cmd --zone=public --add-port=7001/udp --permanent
firewall-cmd --zone=public --add-port=7002/udp --permanent
firewall-cmd --zone=public --add-port=7003/udp --permanent
firewall-cmd --zone=public --add-port=7004/udp --permanent
firewall-cmd --zone=public --add-port=7005/udp --permanent
firewall-cmd --reload

Тепер зайдемо в undercloud і перевіримо, що все працює. Адреса хостової машини - 192.168.255.200, на undercloud ми додали потрібний пакет ipmitool під час підготовки до деплою:


[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power status          
Chassis Power is off
[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power on
Chassis Power Control: Up/On
[stack@undercloud ~]$ 

[root@hp-gen9 ~]# virsh list 
 Id    Name                           State
----------------------------------------------------
 6     dns-server                     running
 64    undercloud                     running
 65    control-1                      running

Як бачите, ми успішно запустили control ноду через vbmc. Тепер вимкнемо її і підемо далі:


[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power off
Chassis Power Control: Down/Off
[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power status
Chassis Power is off
[stack@undercloud ~]$ 

[root@hp-gen9 ~]# virsh list --all
 Id    Name                           State
----------------------------------------------------
 6     dns-server                     running
 64    undercloud                     running
 -     compute-1                      shut off
 -     compute-2                      shut off
 -     control-1                      shut off
 -     storage-1                      shut off
 -     storage-2                      shut off

[root@hp-gen9 ~]#

Наступний крок - це інтроспекція нід, на які буде ставитися overcloud. Для цього нам потрібно підготувати файл json з описом наших нод. Зверніть увагу, що на відміну від установки на голі сервери у файлі вказаний порт, на якому запущено vbmc для кожної машини.


[root@hp-gen9 ~]# virsh domiflist --domain control-1 
Interface  Type       Source     Model       MAC
-------------------------------------------------------
-          network    ovs-network-1 virtio      52:54:00:20:a2:2f
-          network    ovs-network-1 virtio      52:54:00:3f:87:9f

[root@hp-gen9 ~]# virsh domiflist --domain compute-1
Interface  Type       Source     Model       MAC
-------------------------------------------------------
-          network    ovs-network-1 virtio      52:54:00:98:e9:d6

[root@hp-gen9 ~]# virsh domiflist --domain compute-2
Interface  Type       Source     Model       MAC
-------------------------------------------------------
-          network    ovs-network-1 virtio      52:54:00:6a:ea:be

[root@hp-gen9 ~]# virsh domiflist --domain storage-1
Interface  Type       Source     Model       MAC
-------------------------------------------------------
-          network    ovs-network-1 virtio      52:54:00:79:0b:cb

[root@hp-gen9 ~]# virsh domiflist --domain storage-2
Interface  Type       Source     Model       MAC
-------------------------------------------------------
-          network    ovs-network-1 virtio      52:54:00:a7:fe:27

Примітка: на контрольній ноді два інтерфейси, але в даному випадку це не важливо, у цій інсталяції нам вистачить одного.

Тепер готуємо файл json. Нам треба вказати мак адресу порту, через який буде проводитися провіжинінг, параметри нод, задати їм імена та вказати як потрапити на ipmi:


{
    "nodes":[
        {
            "mac":[
                "52:54:00:20:a2:2f"
            ],
            "cpu":"8",
            "memory":"32768",
            "disk":"60",
            "arch":"x86_64",
            "name":"control-1",
            "pm_type":"pxe_ipmitool",
            "pm_user":"admin",
            "pm_password":"admin",
            "pm_addr":"192.168.255.200",
            "pm_port":"7001"
        },
        {
            "mac":[
                "52:54:00:79:0b:cb"
            ],
            "cpu":"4",
            "memory":"16384",
            "disk":"160",
            "arch":"x86_64",
            "name":"storage-1",
            "pm_type":"pxe_ipmitool",
            "pm_user":"admin",
            "pm_password":"admin",
            "pm_addr":"192.168.255.200",
            "pm_port":"7002"
        },
        {
            "mac":[
                "52:54:00:a7:fe:27"
            ],
            "cpu":"4",
            "memory":"16384",
            "disk":"160",
            "arch":"x86_64",
            "name":"storage-2",
            "pm_type":"pxe_ipmitool",
            "pm_user":"admin",
            "pm_password":"admin",
            "pm_addr":"192.168.255.200",
            "pm_port":"7003"
        },
        {
            "mac":[
                "52:54:00:98:e9:d6"
            ],
            "cpu":"12",
            "memory":"32768",
            "disk":"60",
            "arch":"x86_64",
            "name":"compute-1",
            "pm_type":"pxe_ipmitool",
            "pm_user":"admin",
            "pm_password":"admin",
            "pm_addr":"192.168.255.200",
            "pm_port":"7004"
        },
        {
            "mac":[
                "52:54:00:6a:ea:be"
            ],
            "cpu":"12",
            "memory":"32768",
            "disk":"60",
            "arch":"x86_64",
            "name":"compute-2",
            "pm_type":"pxe_ipmitool",
            "pm_user":"admin",
            "pm_password":"admin",
            "pm_addr":"192.168.255.200",
            "pm_port":"7005"
        }
    ]
}

Тепер нам треба підготувати образи для ironic. Для цього завантажуємо їх через wget та встановлюємо:

(undercloud) [stack@undercloud ~]$ sudo wget https://images.rdoproject.org/queens/delorean/current-tripleo-rdo/overcloud-full.tar --no-check-certificate
(undercloud) [stack@undercloud ~]$ sudo wget https://images.rdoproject.org/queens/delorean/current-tripleo-rdo/ironic-python-agent.tar --no-check-certificate
(undercloud) [stack@undercloud ~]$ ls -lh
total 1.9G
-rw-r--r--. 1 stack stack 447M Aug 14 10:26 ironic-python-agent.tar
-rw-r--r--. 1 stack stack 1.5G Aug 14 10:26 overcloud-full.tar
-rw-------. 1 stack stack  916 Aug 13 23:10 stackrc
-rw-r--r--. 1 stack stack  15K Aug 13 22:50 undercloud.conf
-rw-------. 1 stack stack 2.0K Aug 13 22:50 undercloud-passwords.conf
(undercloud) [stack@undercloud ~]$ mkdir images/
(undercloud) [stack@undercloud ~]$ tar -xpvf ironic-python-agent.tar -C ~/images/
ironic-python-agent.initramfs
ironic-python-agent.kernel
(undercloud) [stack@undercloud ~]$ tar -xpvf overcloud-full.tar -C ~/images/                       
overcloud-full.qcow2
overcloud-full.initrd
overcloud-full.vmlinuz
(undercloud) [stack@undercloud ~]$ 
(undercloud) [stack@undercloud ~]$ ls -lh images/
total 1.9G
-rw-rw-r--. 1 stack stack 441M Aug 12 17:24 ironic-python-agent.initramfs
-rwxr-xr-x. 1 stack stack 6.5M Aug 12 17:24 ironic-python-agent.kernel
-rw-r--r--. 1 stack stack  53M Aug 12 17:14 overcloud-full.initrd
-rw-r--r--. 1 stack stack 1.4G Aug 12 17:18 overcloud-full.qcow2
-rwxr-xr-x. 1 stack stack 6.5M Aug 12 17:14 overcloud-full.vmlinuz
(undercloud) [stack@undercloud ~]$

Завантажуємо образи в undercloud:

(undercloud) [stack@undercloud ~]$ openstack overcloud image upload --image-path ~/images/
Image "overcloud-full-vmlinuz" was uploaded.
+--------------------------------------+------------------------+-------------+---------+--------+
|                  ID                  |          Name          | Disk Format |   Size  | Status |
+--------------------------------------+------------------------+-------------+---------+--------+
| c2553770-3e0f-4750-b46b-138855b5c385 | overcloud-full-vmlinuz |     aki     | 6761064 | active |
+--------------------------------------+------------------------+-------------+---------+--------+
Image "overcloud-full-initrd" was uploaded.
+--------------------------------------+-----------------------+-------------+----------+--------+
|                  ID                  |          Name         | Disk Format |   Size   | Status |
+--------------------------------------+-----------------------+-------------+----------+--------+
| 949984e0-4932-4e71-af43-d67a38c3dc89 | overcloud-full-initrd |     ari     | 55183045 | active |
+--------------------------------------+-----------------------+-------------+----------+--------+
Image "overcloud-full" was uploaded.
+--------------------------------------+----------------+-------------+------------+--------+
|                  ID                  |      Name      | Disk Format |    Size    | Status |
+--------------------------------------+----------------+-------------+------------+--------+
| a2f2096d-c9d7-429a-b866-c7543c02a380 | overcloud-full |    qcow2    | 1487475712 | active |
+--------------------------------------+----------------+-------------+------------+--------+
Image "bm-deploy-kernel" was uploaded.
+--------------------------------------+------------------+-------------+---------+--------+
|                  ID                  |       Name       | Disk Format |   Size  | Status |
+--------------------------------------+------------------+-------------+---------+--------+
| e413aa78-e38f-404c-bbaf-93e582a8e67f | bm-deploy-kernel |     aki     | 6761064 | active |
+--------------------------------------+------------------+-------------+---------+--------+
Image "bm-deploy-ramdisk" was uploaded.
+--------------------------------------+-------------------+-------------+-----------+--------+
|                  ID                  |        Name       | Disk Format |    Size   | Status |
+--------------------------------------+-------------------+-------------+-----------+--------+
| 5cf3aba4-0e50-45d3-929f-27f025dd6ce3 | bm-deploy-ramdisk |     ari     | 461759376 | active |
+--------------------------------------+-------------------+-------------+-----------+--------+
(undercloud) [stack@undercloud ~]$

Перевіряємо, що всі образи завантажилися


(undercloud) [stack@undercloud ~]$  openstack image list
+--------------------------------------+------------------------+--------+
| ID                                   | Name                   | Status |
+--------------------------------------+------------------------+--------+
| e413aa78-e38f-404c-bbaf-93e582a8e67f | bm-deploy-kernel       | active |
| 5cf3aba4-0e50-45d3-929f-27f025dd6ce3 | bm-deploy-ramdisk      | active |
| a2f2096d-c9d7-429a-b866-c7543c02a380 | overcloud-full         | active |
| 949984e0-4932-4e71-af43-d67a38c3dc89 | overcloud-full-initrd  | active |
| c2553770-3e0f-4750-b46b-138855b5c385 | overcloud-full-vmlinuz | active |
+--------------------------------------+------------------------+--------+
(undercloud) [stack@undercloud ~]$

Ще один штрих — треба додати сервер dns:


(undercloud) [stack@undercloud ~]$ openstack subnet list
+--------------------------------------+-----------------+--------------------------------------+------------------+
| ID                                   | Name            | Network                              | Subnet           |
+--------------------------------------+-----------------+--------------------------------------+------------------+
| f45dea46-4066-42aa-a3c4-6f84b8120cab | ctlplane-subnet | 6ca013dc-41c2-42d8-9d69-542afad53392 | 192.168.255.0/24 |
+--------------------------------------+-----------------+--------------------------------------+------------------+
(undercloud) [stack@undercloud ~]$ openstack subnet show f45dea46-4066-42aa-a3c4-6f84b8120cab
+-------------------+-----------------------------------------------------------+
| Field             | Value                                                     |
+-------------------+-----------------------------------------------------------+
| allocation_pools  | 192.168.255.11-192.168.255.50                             |
| cidr              | 192.168.255.0/24                                          |
| created_at        | 2020-08-13T20:10:37Z                                      |
| description       |                                                           |
| dns_nameservers   |                                                           |
| enable_dhcp       | True                                                      |
| gateway_ip        | 192.168.255.1                                             |
| host_routes       | destination='169.254.169.254/32', gateway='192.168.255.1' |
| id                | f45dea46-4066-42aa-a3c4-6f84b8120cab                      |
| ip_version        | 4                                                         |
| ipv6_address_mode | None                                                      |
| ipv6_ra_mode      | None                                                      |
| name              | ctlplane-subnet                                           |
| network_id        | 6ca013dc-41c2-42d8-9d69-542afad53392                      |
| prefix_length     | None                                                      |
| project_id        | a844ccfcdb2745b198dde3e1b28c40a3                          |
| revision_number   | 0                                                         |
| segment_id        | None                                                      |
| service_types     |                                                           |
| subnetpool_id     | None                                                      |
| tags              |                                                           |
| updated_at        | 2020-08-13T20:10:37Z                                      |
+-------------------+-----------------------------------------------------------+
(undercloud) [stack@undercloud ~]$ 
(undercloud) [stack@undercloud ~]$ neutron subnet-update f45dea46-4066-42aa-a3c4-6f84b8120cab --dns-nameserver 192.168.255.253                                    
neutron CLI is deprecated and will be removed in the future. Use openstack CLI instead.
Updated subnet: f45dea46-4066-42aa-a3c4-6f84b8120cab
(undercloud) [stack@undercloud ~]$

Тепер ми можемо дати команду на інтроспекцію:

(undercloud) [stack@undercloud ~]$ openstack overcloud node import --introspect --provide inspection.json 
Started Mistral Workflow tripleo.baremetal.v1.register_or_update. Execution ID: d57456a3-d8ed-479c-9a90-dff7c752d0ec
Waiting for messages on queue 'tripleo' with no timeout.


5 node(s) successfully moved to the "manageable" state.
Successfully registered node UUID b4b2cf4a-b7ca-4095-af13-cc83be21c4f5
Successfully registered node UUID b89a72a3-6bb7-429a-93bc-48393d225838
Successfully registered node UUID 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e
Successfully registered node UUID bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8
Successfully registered node UUID 766ab623-464c-423d-a529-d9afb69d1167
Waiting for introspection to finish...
Started Mistral Workflow tripleo.baremetal.v1.introspect. Execution ID: 6b4d08ae-94c3-4a10-ab63-7634ec198a79
Waiting for messages on queue 'tripleo' with no timeout.
Introspection of node b89a72a3-6bb7-429a-93bc-48393d225838 completed. Status:SUCCESS. Errors:None
Introspection of node 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e completed. Status:SUCCESS. Errors:None
Introspection of node bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 completed. Status:SUCCESS. Errors:None
Introspection of node 766ab623-464c-423d-a529-d9afb69d1167 completed. Status:SUCCESS. Errors:None
Introspection of node b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 completed. Status:SUCCESS. Errors:None
Successfully introspected 5 node(s).
Started Mistral Workflow tripleo.baremetal.v1.provide. Execution ID: f5594736-edcf-4927-a8a0-2a7bf806a59a
Waiting for messages on queue 'tripleo' with no timeout.
5 node(s) successfully moved to the "available" state.
(undercloud) [stack@undercloud ~]$

Як видно з висновку, все завершилося без помилок. Перевіримо, що всі ноди можуть available:


(undercloud) [stack@undercloud ~]$ openstack baremetal node list
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
| UUID                                 | Name      | Instance UUID | Power State | Provisioning State | Maintenance |
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
| b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 | control-1 | None          | power off   | available          | False       |
| b89a72a3-6bb7-429a-93bc-48393d225838 | storage-1 | None          | power off   | available          | False       |
| 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e | storage-2 | None          | power off   | available          | False       |
| bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 | compute-1 | None          | power off   | available          | False       |
| 766ab623-464c-423d-a529-d9afb69d1167 | compute-2 | None          | power off   | available          | False       |
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
(undercloud) [stack@undercloud ~]$ 

Якщо ноди будуть в іншому стані, як правило manageable, то щось пішло не так і треба дивитися лог, розбиратися, чому так вийшло. Майте на увазі, що в даному сценарії ми використовуємо віртуалізацію і можуть бути баги, пов'язані з використанням віртуальних машин або vbmc.

Далі нам треба вказати яка нода яку функцію виконуватиме — тобто вказати профіль, з яким нода деплоїться:


(undercloud) [stack@undercloud ~]$ openstack overcloud profiles list
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| Node UUID                            | Node Name | Provision State | Current Profile | Possible Profiles |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 | control-1 | available       | None            |                   |
| b89a72a3-6bb7-429a-93bc-48393d225838 | storage-1 | available       | None            |                   |
| 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e | storage-2 | available       | None            |                   |
| bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 | compute-1 | available       | None            |                   |
| 766ab623-464c-423d-a529-d9afb69d1167 | compute-2 | available       | None            |                   |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
(undercloud) [stack@undercloud ~]$ openstack flavor list
+--------------------------------------+---------------+------+------+-----------+-------+-----------+
| ID                                   | Name          |  RAM | Disk | Ephemeral | VCPUs | Is Public |
+--------------------------------------+---------------+------+------+-----------+-------+-----------+
| 168af640-7f40-42c7-91b2-989abc5c5d8f | swift-storage | 4096 |   40 |         0 |     1 | True      |
| 52148d1b-492e-48b4-b5fc-772849dd1b78 | baremetal     | 4096 |   40 |         0 |     1 | True      |
| 56e66542-ae60-416d-863e-0cb192d01b09 | control       | 4096 |   40 |         0 |     1 | True      |
| af6796e1-d0c4-4bfe-898c-532be194f7ac | block-storage | 4096 |   40 |         0 |     1 | True      |
| e4d50fdd-0034-446b-b72c-9da19b16c2df | compute       | 4096 |   40 |         0 |     1 | True      |
| fc2e3acf-7fca-4901-9eee-4a4d6ef0265d | ceph-storage  | 4096 |   40 |         0 |     1 | True      |
+--------------------------------------+---------------+------+------+-----------+-------+-----------+
(undercloud) [stack@undercloud ~]$

Вказуємо профіль для кожної ноди:


openstack baremetal node set --property capabilities='profile:control,boot_option:local' b4b2cf4a-b7ca-4095-af13-cc83be21c4f5
openstack baremetal node set --property capabilities='profile:ceph-storage,boot_option:local' b89a72a3-6bb7-429a-93bc-48393d225838
openstack baremetal node set --property capabilities='profile:ceph-storage,boot_option:local' 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e
openstack baremetal node set --property capabilities='profile:compute,boot_option:local' bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8
openstack baremetal node set --property capabilities='profile:compute,boot_option:local' 766ab623-464c-423d-a529-d9afb69d1167

Перевіряємо, що ми зробили все коректно:


(undercloud) [stack@undercloud ~]$ openstack overcloud profiles list
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| Node UUID                            | Node Name | Provision State | Current Profile | Possible Profiles |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 | control-1 | available       | control         |                   |
| b89a72a3-6bb7-429a-93bc-48393d225838 | storage-1 | available       | ceph-storage    |                   |
| 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e | storage-2 | available       | ceph-storage    |                   |
| bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 | compute-1 | available       | compute         |                   |
| 766ab623-464c-423d-a529-d9afb69d1167 | compute-2 | available       | compute         |                   |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
(undercloud) [stack@undercloud ~]$

Якщо все правильно, даємо команду на деплой overcloud:

openstack overcloud deploy --templates --control-scale 1 --compute-scale 2  --ceph-storage-scale 2 --control-flavor control --compute-flavor compute  --ceph-storage-flavor ceph-storage --libvirt-type qemu

У реальній інсталяції природно використовуватимуть кастомізовані темплейти, в нашому випадку це дуже ускладнить процес, оскільки треба буде пояснити кожну правку в шаблоні. Як було написано раніше, навіть простої інсталяції нам буде достатньо, щоб подивитися, як це працює.

Примітка: змінна -libvirt-type qemu в даному випадку необхідна, тому що ми будемо використовувати віртуалізацію nested. В іншому випадку у вас не запускатимуть віртуальні машини.

Тепер у вас є близько години, а може і більше (залежить від можливостей заліза) і вам залишається сподіватися, що після цього часу ви побачите такий напис:


2020-08-14 08:39:21Z [overcloud]: CREATE_COMPLETE  Stack CREATE completed successfully

 Stack overcloud CREATE_COMPLETE 

Host 192.168.255.21 not found in /home/stack/.ssh/known_hosts
Started Mistral Workflow tripleo.deployment.v1.get_horizon_url. Execution ID: fcb996cd-6a19-482b-b755-2ca0c08069a9
Overcloud Endpoint: http://192.168.255.21:5000/
Overcloud Horizon Dashboard URL: http://192.168.255.21:80/dashboard
Overcloud rc file: /home/stack/overcloudrc
Overcloud Deployed
(undercloud) [stack@undercloud ~]$

Тепер у вас є майже повноцінна версія опенстак, на якій ви можете вчитися, ставити досліди тощо.

Перевіримо, що все нормально працює. У домашній директорії користувача stack є два файли — один stackrc (керувати undercloud) і другий overcloudrc (керувати overcloud). Ці файли необхідно вказати як source, оскільки у них міститься необхідна аутентифікації інформація.


(undercloud) [stack@undercloud ~]$ openstack server list
+--------------------------------------+-------------------------+--------+-------------------------+----------------+--------------+
| ID                                   | Name                    | Status | Networks                | Image          | Flavor       |
+--------------------------------------+-------------------------+--------+-------------------------+----------------+--------------+
| fd7d36f4-ce87-4b9a-93b0-add2957792de | overcloud-controller-0  | ACTIVE | ctlplane=192.168.255.15 | overcloud-full | control      |
| edc77778-8972-475e-a541-ff40eb944197 | overcloud-novacompute-1 | ACTIVE | ctlplane=192.168.255.26 | overcloud-full | compute      |
| 5448ce01-f05f-47ca-950a-ced14892c0d4 | overcloud-cephstorage-1 | ACTIVE | ctlplane=192.168.255.34 | overcloud-full | ceph-storage |
| ce6d862f-4bdf-4ba3-b711-7217915364d7 | overcloud-novacompute-0 | ACTIVE | ctlplane=192.168.255.19 | overcloud-full | compute      |
| e4507bd5-6f96-4b12-9cc0-6924709da59e | overcloud-cephstorage-0 | ACTIVE | ctlplane=192.168.255.44 | overcloud-full | ceph-storage |
+--------------------------------------+-------------------------+--------+-------------------------+----------------+--------------+
(undercloud) [stack@undercloud ~]$ 


(undercloud) [stack@undercloud ~]$ source overcloudrc 
(overcloud) [stack@undercloud ~]$ 
(overcloud) [stack@undercloud ~]$ openstack project list
+----------------------------------+---------+
| ID                               | Name    |
+----------------------------------+---------+
| 4eed7d0f06544625857d51cd77c5bd4c | admin   |
| ee1c68758bde41eaa9912c81dc67dad8 | service |
+----------------------------------+---------+
(overcloud) [stack@undercloud ~]$ 
(overcloud) [stack@undercloud ~]$ 
(overcloud) [stack@undercloud ~]$ openstack network agent list  
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
| ID                                   | Agent Type         | Host                                | Availability Zone | Alive | State | Binary                    |
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
| 10495de9-ba4b-41fe-b30a-b90ec3f8728b | Open vSwitch agent | overcloud-novacompute-1.localdomain | None              | :-)   | UP    | neutron-openvswitch-agent |
| 1515ad4a-5972-46c3-af5f-e5446dff7ac7 | L3 agent           | overcloud-controller-0.localdomain  | nova              | :-)   | UP    | neutron-l3-agent          |
| 322e62ca-1e5a-479e-9a96-4f26d09abdd7 | DHCP agent         | overcloud-controller-0.localdomain  | nova              | :-)   | UP    | neutron-dhcp-agent        |
| 9c1de2f9-bac5-400e-998d-4360f04fc533 | Open vSwitch agent | overcloud-novacompute-0.localdomain | None              | :-)   | UP    | neutron-openvswitch-agent |
| d99c5657-851e-4d3c-bef6-f1e3bb1acfb0 | Open vSwitch agent | overcloud-controller-0.localdomain  | None              | :-)   | UP    | neutron-openvswitch-agent |
| ff85fae6-5543-45fb-a301-19c57b62d836 | Metadata agent     | overcloud-controller-0.localdomain  | None              | :-)   | UP    | neutron-metadata-agent    |
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
(overcloud) [stack@undercloud ~]$

У моїй інсталяції ще потрібно один невеликий штрих — додати маршрут на контролері, оскільки машина, з якою я працюю, знаходиться в іншій мережі. Для цього зайдемо на control-1 під обліком heat-admin та пропишемо маршрут


(undercloud) [stack@undercloud ~]$ ssh [email protected]         
Last login: Fri Aug 14 09:47:40 2020 from 192.168.255.1
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$ sudo ip route add 10.169.0.0/16 via 192.168.255.254

Ну і тепер ви можете зайти в обрій. Вся інформація – адреси, логін та пароль – лежать у файлі /home/stack/overcloudrc. Підсумкова схема виглядає так:

Введення в мережеву частину хмарної інфраструктури

До речі, в нашій інсталяції адреси машин видавалися через DHCP і як бачите, вони видаються "як завгодно". Ви можете у темплейте жорстко задати, яку адресу якій машині потрібно прикріпити під час деплою, якщо вам це необхідно.

Як ходить трафік між віртуальними машинами?

У цій статті ми розглянемо три варіанти проходження трафік

  • Дві машини на одному гіпервізорі в одній мережі L2
  • Дві машини на різних гіпервізорах в одній мережі L2
  • Дві машини у різних мережах (рутинг між мережами)

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

Для перевірки зберемо таку схему:

Введення в мережеву частину хмарної інфраструктури

У нас створено 4 віртуальні машини — 3 в одній мережі L2 — net-1, і ще 1 в мережі net-2

(overcloud) [stack@undercloud ~]$ nova list --tenant 5e18ce8ec9594e00b155485f19895e6c             
+--------------------------------------+------+----------------------------------+--------+------------+-------------+-----------------+
| ID                                   | Name | Tenant ID                        | Status | Task State | Power State | Networks        |
+--------------------------------------+------+----------------------------------+--------+------------+-------------+-----------------+
| f53b37b5-2204-46cc-aef0-dba84bf970c0 | vm-1 | 5e18ce8ec9594e00b155485f19895e6c | ACTIVE | -          | Running     | net-1=10.0.1.85 |
| fc8b6722-0231-49b0-b2fa-041115bef34a | vm-2 | 5e18ce8ec9594e00b155485f19895e6c | ACTIVE | -          | Running     | net-1=10.0.1.88 |
| 3cd74455-b9b7-467a-abe3-bd6ff765c83c | vm-3 | 5e18ce8ec9594e00b155485f19895e6c | ACTIVE | -          | Running     | net-1=10.0.1.90 |
| 7e836338-6772-46b0-9950-f7f06dbe91a8 | vm-4 | 5e18ce8ec9594e00b155485f19895e6c | ACTIVE | -          | Running     | net-2=10.0.2.8  |
+--------------------------------------+------+----------------------------------+--------+------------+-------------+-----------------+
(overcloud) [stack@undercloud ~]$ 

Подивимося, на яких гіпервізорах розташовані створені машини:

(overcloud) [stack@undercloud ~]$ nova show f53b37b5-2204-46cc-aef0-dba84bf970c0 | egrep "hypervisor_hostname|instance_name|hostname"
| OS-EXT-SRV-ATTR:hostname             | vm-1                                                     |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | overcloud-novacompute-0.localdomain                      |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000001                                        |
(overcloud) [stack@undercloud ~]$ nova show fc8b6722-0231-49b0-b2fa-041115bef34a | egrep "hypervisor_hostname|instance_name|hostname"
| OS-EXT-SRV-ATTR:hostname             | vm-2                                                     |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | overcloud-novacompute-1.localdomain                      |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000002                                        |
(overcloud) [stack@undercloud ~]$ nova show 3cd74455-b9b7-467a-abe3-bd6ff765c83c | egrep "hypervisor_hostname|instance_name|hostname"
| OS-EXT-SRV-ATTR:hostname             | vm-3                                                     |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | overcloud-novacompute-0.localdomain                      |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000003                                        |
(overcloud) [stack@undercloud ~]$ nova show 7e836338-6772-46b0-9950-f7f06dbe91a8 | egrep "hypervisor_hostname|instance_name|hostname"
| OS-EXT-SRV-ATTR:hostname             | vm-4                                                     |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | overcloud-novacompute-1.localdomain                      |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000004                                        |

(overcloud) [stack@undercloud ~]$
Машини vm-1 та vm-3 розташовані на compute-0, машини vm-2 та vm-4 розташовані на ноді compute-1.

Крім того, створено віртуальний маршрутизатор для можливості маршрутизації між зазначеними мережами:

(overcloud) [stack@undercloud ~]$ openstack router list  --project 5e18ce8ec9594e00b155485f19895e6c
+--------------------------------------+----------+--------+-------+-------------+-------+----------------------------------+
| ID                                   | Name     | Status | State | Distributed | HA    | Project                          |
+--------------------------------------+----------+--------+-------+-------------+-------+----------------------------------+
| 0a4d2420-4b9c-46bd-aec1-86a1ef299abe | router-1 | ACTIVE | UP    | False       | False | 5e18ce8ec9594e00b155485f19895e6c |
+--------------------------------------+----------+--------+-------+-------------+-------+----------------------------------+
(overcloud) [stack@undercloud ~]$ 

У маршрутизатора два віртуальні порти, які виконують роль шлюзів для мереж:

(overcloud) [stack@undercloud ~]$ openstack router show 0a4d2420-4b9c-46bd-aec1-86a1ef299abe | grep interface
| interfaces_info         | [{"subnet_id": "2529ad1a-6b97-49cd-8515-cbdcbe5e3daa", "ip_address": "10.0.1.254", "port_id": "0c52b15f-8fcc-4801-bf52-7dacc72a5201"}, {"subnet_id": "335552dd-b35b-456b-9df0-5aac36a3ca13", "ip_address": "10.0.2.254", "port_id": "92fa49b5-5406-499f-ab8d-ddf28cc1a76c"}] |
(overcloud) [stack@undercloud ~]$ 

Але перед тим як дивитися, як ходить трафік, давайте розглянемо, що ми маємо на даний момент на контрольній ноді (яка за сумісництвом та network нода) та на compute ноду. Почнемо з compute ноди.


[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-vsctl show
[heat-admin@overcloud-novacompute-0 ~]$ sudo sudo ovs-appctl dpif/show
system@ovs-system: hit:3 missed:3
  br-ex:
    br-ex 65534/1: (internal)
    phy-br-ex 1/none: (patch: peer=int-br-ex)
  br-int:
    br-int 65534/2: (internal)
    int-br-ex 1/none: (patch: peer=phy-br-ex)
    patch-tun 2/none: (patch: peer=patch-int)
  br-tun:
    br-tun 65534/3: (internal)
    patch-int 1/none: (patch: peer=patch-tun)
    vxlan-c0a8ff0f 3/4: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.19, remote_ip=192.168.255.15)
    vxlan-c0a8ff1a 2/4: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.19, remote_ip=192.168.255.26)
[heat-admin@overcloud-novacompute-0 ~]$

В даний момент на ноді три ovs бриджі - br-int, br-tun, br-ex. Між ними, як ми бачимо, є набір інтерфейсів. Для простоти сприйняття нанесемо всі ці інтерфейси на схему і подивимося, що вийде.

Введення в мережеву частину хмарної інфраструктури

За адресами, на які піднято VxLAN тунелі видно, що один тунель піднято на compute-1 (192.168.255.26), другий тунель дивиться на control-1 (192.168.255.15). Але найцікавіше те, що br-ex немає фізичних інтерфейсів, а якщо подивитися, які флоу налаштовані, то видно, що даний бридж на даний момент може лише драпати трафік.


[heat-admin@overcloud-novacompute-0 ~]$ ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 192.168.255.19  netmask 255.255.255.0  broadcast 192.168.255.255
        inet6 fe80::5054:ff:fe6a:eabe  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:6a:ea:be  txqueuelen 1000  (Ethernet)
        RX packets 2909669  bytes 4608201000 (4.2 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1821057  bytes 349198520 (333.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[heat-admin@overcloud-novacompute-0 ~]$ 

Як видно з висновку адреса прикручена безпосередньо на фізичний порт, а не на віртуальний бридж інтерфейс.


[heat-admin@overcloud-novacompute-0 ~]$  sudo ovs-appctl fdb/show br-ex
 port  VLAN  MAC                Age
[heat-admin@overcloud-novacompute-0 ~]$  sudo ovs-ofctl dump-flows br-ex
 cookie=0x9169eae8f7fe5bb2, duration=216686.864s, table=0, n_packets=303, n_bytes=26035, priority=2,in_port="phy-br-ex" actions=drop
 cookie=0x9169eae8f7fe5bb2, duration=216686.887s, table=0, n_packets=0, n_bytes=0, priority=0 actions=NORMAL
[heat-admin@overcloud-novacompute-0 ~]$ 

Згідно з першим правилом, все, що прийшло з порту phy-br-ex, необхідно відкинути.
Власне в даний бридж поки що більше нема звідки взятися трафіку, крім як з даного інтерфейсу (стик з br-int), і судячи з дроп в бридж вже прилітав BUM трафік.

Тобто з цієї ноди трафік може піти тільки через VxLAN тунель і більше. Однак якщо увімкнути DVR ситуація зміниться, але з цим розберемося в інший раз. При використанні ізоляції мереж, наприклад, за допомогою ланів, у вас буде не один L3 інтерфейс в 0-му лані, а кілька інтерфейсів. Однак VxLAN трафік буде виходити з ноди так само, але інкапсульований ще й у якийсь виділений влан.

З compute нодою розібралися, переходимо до control ноді.


[heat-admin@overcloud-controller-0 ~]$ sudo ovs-appctl dpif/show
system@ovs-system: hit:930491 missed:825
  br-ex:
    br-ex 65534/1: (internal)
    eth0 1/2: (system)
    phy-br-ex 2/none: (patch: peer=int-br-ex)
  br-int:
    br-int 65534/3: (internal)
    int-br-ex 1/none: (patch: peer=phy-br-ex)
    patch-tun 2/none: (patch: peer=patch-int)
  br-tun:
    br-tun 65534/4: (internal)
    patch-int 1/none: (patch: peer=patch-tun)
    vxlan-c0a8ff13 3/5: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.15, remote_ip=192.168.255.19)
    vxlan-c0a8ff1a 2/5: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.15, remote_ip=192.168.255.26)
[heat-admin@overcloud-controller-0 ~]$

За фактом можна сказати, що все те саме, проте ip адреса вже знаходиться не на фізичному інтерфейсі, а на віртуальному бриджі. Це зроблено через те, що цей порт є портом, через який виходитиме трафік у зовнішній світ.


[heat-admin@overcloud-controller-0 ~]$ ifconfig br-ex
br-ex: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 192.168.255.15  netmask 255.255.255.0  broadcast 192.168.255.255
        inet6 fe80::5054:ff:fe20:a22f  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:20:a2:2f  txqueuelen 1000  (Ethernet)
        RX packets 803859  bytes 1732616116 (1.6 GiB)
        RX errors 0  dropped 63  overruns 0  frame 0
        TX packets 808475  bytes 121652156 (116.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$ sudo ovs-appctl fdb/show br-ex
 port  VLAN  MAC                Age
    3   100  28:c0:da:00:4d:d3   35
    1     0  28:c0:da:00:4d:d3   35
    1     0  52:54:00:98:e9:d6    0
LOCAL     0  52:54:00:20:a2:2f    0
    1     0  52:54:00:2c:08:9e    0
    3   100  52:54:00:20:a2:2f    0
    1     0  52:54:00:6a:ea:be    0
[heat-admin@overcloud-controller-0 ~]$ 

Даний порт прив'язаний до бриджу br-ex і так як на ньому немає ніяких лан тегів, то цей порт є транковим портом на якому дозволені всі влади, зараз трафік виходить назовні без тега, про що говорить vlan-id 0 у висновку вище.

Введення в мережеву частину хмарної інфраструктури

Все інше зараз аналогічно compute ноді - ті ж бриджі, ті ж тунелі, що йдуть на дві compute ноди.

Storage ноди ми розглядати в цій статті не будемо, але для розуміння необхідно сказати, що мережева частина даних нод банальна до неподобства. У нашому випадку там всього один фізичний порт (eth0) з навішеним на нього адресою ip і все. Там немає ніяких VxLAN тунелів, тунельних бриджів і т.д. - там немає ovs взагалі, тому що немає від нього сенсу. При використанні ізоляції мереж — на цій ноді буде два інтерфейси (фізичні порти, бадні, або просто дві волана — це не важливо — залежить від того, що ви хочете) — один під керування, другий під трафік (запис на диск VM, читання з диска та т д).

Розібралися що у нас є на нодах без будь-яких сервісів. Тепер запустимо 4 віртуальні машини та подивимося, як зміниться описана вище схема — у нас мають з'явитися порти, віртуальні роутери тощо.

Поки що наша мережа виглядає так:

Введення в мережеву частину хмарної інфраструктури

У нас по дві віртуальні машини на кожній комп'юті ноді. На прикладі compute-0 подивимося, як увімкнено.


[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh list 
 Id    Name                           State
----------------------------------------------------
 1     instance-00000001              running
 3     instance-00000003              running

[heat-admin@overcloud-novacompute-0 ~]$ 

Машина має лише один віртуальний інтерфейс — tap95d96a75-a0:

[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000001
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tap95d96a75-a0 bridge     qbr95d96a75-a0 virtio      fa:16:3e:44:98:20

[heat-admin@overcloud-novacompute-0 ~]$ 

Цей інтерфейс дивиться в linux bridge:

[heat-admin@overcloud-novacompute-0 ~]$ sudo brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242904c92a8       no
qbr5bd37136-47          8000.5e4e05841423       no              qvb5bd37136-47
                                                        tap5bd37136-47
qbr95d96a75-a0          8000.de076cb850f6       no              qvb95d96a75-a0
                                                        tap95d96a75-a0
[heat-admin@overcloud-novacompute-0 ~]$ 

Як видно з висновку в брижі всього два інтерфейси - tap95d96a75-a0 і qvb95d96a75-a0.

Тут варто трохи зупинитися на типах віртуальних мережевих пристроїв OpenStack:
vtap - віртуальний інтерфейс, приєднаний до інстансу (ВМ)
qbr - Linux bridge
qvb і qvo — vEth пара, підключена до Linux bridge та Open vSwitch bridge
br-int, br-tun, br-vlan — Open vSwitch bridges
patch-, int-br-, phy-br- — Open vSwitch інтерфейси, що з'єднують bridges
qg, qr, ha, fg, sg — порти Open vSwitch, які використовуються віртуальними пристроями для підключення до OVS

Як ви розумієте, якщо у нас в брижі є qvb95d96a75-a0 порт, який є vEth парою, то де тобто його сторона у відповідь, яка логічно повинна називатися qvo95d96a75-a0. Дивимося, які порти на OVS.


[heat-admin@overcloud-novacompute-0 ~]$ sudo sudo ovs-appctl dpif/show
system@ovs-system: hit:526 missed:91
  br-ex:
    br-ex 65534/1: (internal)
    phy-br-ex 1/none: (patch: peer=int-br-ex)
  br-int:
    br-int 65534/2: (internal)
    int-br-ex 1/none: (patch: peer=phy-br-ex)
    patch-tun 2/none: (patch: peer=patch-int)
    qvo5bd37136-47 6/6: (system)
    qvo95d96a75-a0 3/5: (system)
  br-tun:
    br-tun 65534/3: (internal)
    patch-int 1/none: (patch: peer=patch-tun)
    vxlan-c0a8ff0f 3/4: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.19, remote_ip=192.168.255.15)
    vxlan-c0a8ff1a 2/4: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.19, remote_ip=192.168.255.26)
[heat-admin@overcloud-novacompute-0 ~]$ 

Як бачимо порт знаходиться в br-int. Br-int виконує роль комутатора, який термінує порти віртуальних машин. Крім qvo95d96a75-a0 у виведенні видно порт qvo5bd37136-47. Це порт у другу віртуальну машину. У результаті наша схема тепер виглядає так:

Введення в мережеву частину хмарної інфраструктури

Питання, яке має відразу зацікавити уважного читача - на який linux bridge між портом віртуальної машини і портом OVS? Справа в тому, що для захисту машини використовуються security groups, які є не що інше як iptables. OVS не працює з iptables, тому був придуманий такий милиця. Однак він відживає своє - йому на зміну приходить conntrack у нових релізах.

Тобто зрештою схема виглядає так:

Введення в мережеву частину хмарної інфраструктури

Дві машини на одному гіпервізорі в одній мережі L2

Так як дві дані VM знаходяться в одній і тій же мережі L2 і на одному і тому ж гіпервізорі, то трафік між ними буде логічно ходити локально через br-int, так як обидві машини будуть в одному і тому ж VLAN:


[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000001
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tap95d96a75-a0 bridge     qbr95d96a75-a0 virtio      fa:16:3e:44:98:20

[heat-admin@overcloud-novacompute-0 ~]$ 
[heat-admin@overcloud-novacompute-0 ~]$ 
[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000003
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tap5bd37136-47 bridge     qbr5bd37136-47 virtio      fa:16:3e:83:ad:a4

[heat-admin@overcloud-novacompute-0 ~]$ 
[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-appctl fdb/show br-int 
 port  VLAN  MAC                Age
    6     1  fa:16:3e:83:ad:a4    0
    3     1  fa:16:3e:44:98:20    0
[heat-admin@overcloud-novacompute-0 ~]$ 

Дві машини на різних гіпервізорах в одній мережі L2

Тепер подивимося, як піде трафік між двома машинами в одній мережі L2, але розташованими на різних гіпервізорах. Якщо бути чесним, то особливо сильно нічого не зміниться, просто трафік між гіпервізорами піде через vxlan тунель. Подивимося на прикладі.

Адреси віртуальних машин, між якими дивитися трафік:

[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000001
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tap95d96a75-a0 bridge     qbr95d96a75-a0 virtio      fa:16:3e:44:98:20

[heat-admin@overcloud-novacompute-0 ~]$ 


[heat-admin@overcloud-novacompute-1 ~]$ sudo virsh domiflist instance-00000002
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tape7e23f1b-07 bridge     qbre7e23f1b-07 virtio      fa:16:3e:72:ad:53

[heat-admin@overcloud-novacompute-1 ~]$ 

Дивимося таблицю форвардингу в br-int на compute-0:

[heat-admin@overcloud-novacompute-0 ~]$  sudo ovs-appctl fdb/show br-int | grep fa:16:3e:72:ad:53
    2     1  fa:16:3e:72:ad:53    1
[heat-admin@overcloud-novacompute-0 ~]

Трафік повинен піти в порт 2 - дивимося, що це за порт:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-ofctl show br-int | grep addr
 1(int-br-ex): addr:7e:7f:28:1f:bd:54
 2(patch-tun): addr:0a:bd:07:69:58:d9
 3(qvo95d96a75-a0): addr:ea:50:9a:3d:69:58
 6(qvo5bd37136-47): addr:9a:d1:03:50:3d:96
 LOCAL(br-int): addr:1a:0f:53:97:b1:49
[heat-admin@overcloud-novacompute-0 ~]$

Це patch-tun – тобто інтерфейс у br-tun. Дивимося, що відбувається з пакетом на br-tun:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-ofctl dump-flows br-tun | grep fa:16:3e:72:ad:53
 cookie=0x8759a56536b67a8e, duration=1387.959s, table=20, n_packets=1460, n_bytes=138880, hard_timeout=300, idle_age=0, hard_age=0, priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:72:ad:53 actions=load:0->NXM_OF_VLAN_TCI[],load:0x16->NXM_NX_TUN_ID[],output:2
[heat-admin@overcloud-novacompute-0 ~]$ 

Пакет упаковується в VxLAN і відправляється в порт 2. Дивимося, куди веде порт 2:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-ofctl show br-tun | grep addr   
 1(patch-int): addr:b2:d1:f8:21:96:66
 2(vxlan-c0a8ff1a): addr:be:64:1f:75:78:a7
 3(vxlan-c0a8ff0f): addr:76:6f:b9:3c:3f:1c
 LOCAL(br-tun): addr:a2:5b:6d:4f:94:47
[heat-admin@overcloud-novacompute-0 ~]$

Це vxlan тунель compute-1:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-appctl dpif/show | egrep vxlan-c0a8ff1a
    vxlan-c0a8ff1a 2/4: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.19, remote_ip=192.168.255.26)
[heat-admin@overcloud-novacompute-0 ~]$

Ідемо на compute-1 і дивимося, що далі відбувається з пакетом:

[heat-admin@overcloud-novacompute-1 ~]$ sudo ovs-appctl fdb/show br-int | egrep fa:16:3e:44:98:20
    2     1  fa:16:3e:44:98:20    1
[heat-admin@overcloud-novacompute-1 ~]$ 

Мак є в таблиці форвардингу br-int на compute-1, і як видно з виводу вище видно через порт 2, який є портів у бік br-tun:

[heat-admin@overcloud-novacompute-1 ~]$ sudo ovs-ofctl show br-int | grep addr   
 1(int-br-ex): addr:8a:d7:f9:ad:8c:1d
 2(patch-tun): addr:46:cc:40:bd:20:da
 3(qvoe7e23f1b-07): addr:12:78:2e:34:6a:c7
 4(qvo3210e8ec-c0): addr:7a:5f:59:75:40:85
 LOCAL(br-int): addr:e2:27:b2:ed:14:46

Ну і далі дивимося, що у br-int на compute-1 є мак призначення:

[heat-admin@overcloud-novacompute-1 ~]$ sudo ovs-appctl fdb/show br-int | egrep fa:16:3e:72:ad:53
    3     1  fa:16:3e:72:ad:53    0
[heat-admin@overcloud-novacompute-1 ~]$ 

Тобто отриманий пакет відлетить до порту 3, за яким вже знаходиться віртуальна машина instance-00000003.

Вся принадність розгортання Openstack для вивчення на віртуальній інфраструктурі в тому, що ми можемо без проблем відловити трафік між гіпервізорами та подивитися, що відбувається з ним. Це ми зараз і зробимо, запустимо tcpdump на порту vnet в бік compute-0:


[root@hp-gen9 bormoglotx]# tcpdump -vvv -i vnet3
tcpdump: listening on vnet3, link-type EN10MB (Ethernet), capture size 262144 bytes

*****************omitted*******************

04:39:04.583459 IP (tos 0x0, ttl 64, id 16868, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.19.39096 > 192.168.255.26.4789: [no cksum] VXLAN, flags [I] (0x08), vni 22
IP (tos 0x0, ttl 64, id 8012, offset 0, flags [DF], proto ICMP (1), length 84)
    10.0.1.85 > 10.0.1.88: ICMP echo request, id 5634, seq 16, length 64
04:39:04.584449 IP (tos 0x0, ttl 64, id 35181, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.26.speedtrace-disc > 192.168.255.19.4789: [no cksum] VXLAN, flags [I] (0x08), vni 22
IP (tos 0x0, ttl 64, id 59124, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.1.88 > 10.0.1.85: ICMP echo reply, id 5634, seq 16, length 64
	
*****************omitted*******************

Перший рядок показує, що патек з адреси 10.0.1.85 йде на адресу 10.0.1.88 (ICMP трафік), причому він загорнутий у VxLAN пакет з vni 22 і пакет йде з хоста 192.168.255.19 (compute-0) на хост192.168.255.26. compute-1). Можемо перевірити, що VNI відповідає тому, що вказано в ovs.

Повернемося до цього рядка actions=load:0->NXM_OF_VLAN_TCI[],load:0x16->NXM_NX_TUN_ID[],output:2. 0х16 - це vni в 16-річній системі числення. Переведемо це число до 10-ї системи:


16 = 6*16^0+1*16^1 = 6+16 = 22

Тобто vni відповідає дійсності.

Другий рядок показує зворотний трафік, ну його пояснювати немає сенсу, там і так все ясно.

Дві машини у різних мережах (маршрутизація між мережами)

Останній кейс на сьогоднішній день — це маршрутизація між мережами всередині одного проекту з використанням віртуального маршрутизатора. Ми розглядаємо випадок без DVR (його розглянемо в іншій статті), тому маршрутизація відбувається на network-ноді. У нашому випадку мережа нода не винесена в окрему сутність і розташована на control ноді.

Для початку подивимося, що маршрутизація працює:

$ ping 10.0.2.8
PING 10.0.2.8 (10.0.2.8): 56 data bytes
64 bytes from 10.0.2.8: seq=0 ttl=63 time=7.727 ms
64 bytes from 10.0.2.8: seq=1 ttl=63 time=3.832 ms
^C
--- 10.0.2.8 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 3.832/5.779/7.727 ms

Так як в даному випадку пакет повинен піти на шлюз і там зматрутизований, нам треба дізнатися мак адресу шлюзу, для чого подивимося ARP таблицю в інстансі:

$ arp
host-10-0-1-254.openstacklocal (10.0.1.254) at fa:16:3e:c4:64:70 [ether]  on eth0
host-10-0-1-1.openstacklocal (10.0.1.1) at fa:16:3e:e6:2c:5c [ether]  on eth0
host-10-0-1-90.openstacklocal (10.0.1.90) at fa:16:3e:83:ad:a4 [ether]  on eth0
host-10-0-1-88.openstacklocal (10.0.1.88) at fa:16:3e:72:ad:53 [ether]  on eth0

Тепер подивимося, куди має бути відправлений трафік із призначенням (10.0.1.254) fa:16:3e:c4:64:70:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-appctl fdb/show br-int | egrep fa:16:3e:c4:64:70
    2     1  fa:16:3e:c4:64:70    0
[heat-admin@overcloud-novacompute-0 ~]$ 

Дивимося куди веде порт 2:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-ofctl show br-int | grep addr
 1(int-br-ex): addr:7e:7f:28:1f:bd:54
 2(patch-tun): addr:0a:bd:07:69:58:d9
 3(qvo95d96a75-a0): addr:ea:50:9a:3d:69:58
 6(qvo5bd37136-47): addr:9a:d1:03:50:3d:96
 LOCAL(br-int): addr:1a:0f:53:97:b1:49
[heat-admin@overcloud-novacompute-0 ~]$ 

Все логічно, трафік йде у br-tun. Подивимося, в який vxlan тунель він буде загорнутий:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-ofctl dump-flows br-tun | grep fa:16:3e:c4:64:70
 cookie=0x8759a56536b67a8e, duration=3514.566s, table=20, n_packets=3368, n_bytes=317072, hard_timeout=300, idle_age=0, hard_age=0, priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:c4:64:70 actions=load:0->NXM_OF_VLAN_TCI[],load:0x16->NXM_NX_TUN_ID[],output:3
[heat-admin@overcloud-novacompute-0 ~]$ 

Третій порт – це vxlan тунель:

[heat-admin@overcloud-controller-0 ~]$ sudo ovs-ofctl show br-tun | grep addr
 1(patch-int): addr:a2:69:00:c5:fa:ba
 2(vxlan-c0a8ff1a): addr:86:f0:ce:d0:e8:ea
 3(vxlan-c0a8ff13): addr:72:aa:73:2c:2e:5b
 LOCAL(br-tun): addr:a6:cb:cd:72:1c:45
[heat-admin@overcloud-controller-0 ~]$ 

Що дивиться на control ноду:

[heat-admin@overcloud-controller-0 ~]$ sudo sudo ovs-appctl dpif/show | grep vxlan-c0a8ff1a
    vxlan-c0a8ff1a 2/5: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.15, remote_ip=192.168.255.26)
[heat-admin@overcloud-controller-0 ~]$ 

Трафік долетів до control ноди, тому нам треба перейти на неї та подивитися, як відбуватиметься маршрутизація.

Як ви пам'ятаєте, контрольна нода всередині виглядала так само, як і compute нода — ті ж три бриджі, тільки у br-ex був фізичний порт, через який нода могла слати трафік назовні. Створення інстансів змінило конфігурацію на compute нодах - додалися linux bridge, iptables та інтерфейси в ноди. Створення мереж та віртуального маршрутизатора також залишило свій відбиток на конфігурації control ноди.

Отже, очевидно, що мак адреса gateway має бути в таблиці форвардингу br-int на control ноді. Перевіримо, що він там є і куди він дивиться:

[heat-admin@overcloud-controller-0 ~]$ sudo ovs-appctl fdb/show br-int | grep fa:16:3e:c4:64:70
    5     1  fa:16:3e:c4:64:70    1
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$  sudo ovs-ofctl show br-int | grep addr
 1(int-br-ex): addr:2e:58:b6:db:d5:de
 2(patch-tun): addr:06:41:90:f0:9e:56
 3(tapca25a97e-64): addr:fa:16:3e:e6:2c:5c
 4(tap22015e46-0b): addr:fa:16:3e:76:c2:11
 5(qr-0c52b15f-8f): addr:fa:16:3e:c4:64:70
 6(qr-92fa49b5-54): addr:fa:16:3e:80:13:72
 LOCAL(br-int): addr:06:de:5d:ed:44:44
[heat-admin@overcloud-controller-0 ~]$ 

Мак видно з порту qr-0c52b15f-8f. Якщо повернутися до списку віртуальних портів у Openstack, цей тип порту використовується для підключення до OVS різних віртуальних пристроїв. Якщо бути точнішим qr — це порт у бік віртуального маршрутизатора, який представлений у вигляді namespace.

Подивимося, які namespace є на сервері:

[heat-admin@overcloud-controller-0 ~]$ sudo  ip netns
qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe (id: 2)
qdhcp-7d541e74-1c36-4e1d-a7c4-0968c8dbc638 (id: 1)
qdhcp-67a3798c-32c0-4c18-8502-2531247e3cc2 (id: 0)
[heat-admin@overcloud-controller-0 ~]$ 

Цілих три екземпляри. Але судячи з імен можна здогадатися про призначення кожного з них. До інстансів з ID 0 і 1 ми повернемося пізніше, зараз нам цікавий namespace qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe:


[heat-admin@overcloud-controller-0 ~]$ sudo  ip netns exec qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe ip route
10.0.1.0/24 dev qr-0c52b15f-8f proto kernel scope link src 10.0.1.254 
10.0.2.0/24 dev qr-92fa49b5-54 proto kernel scope link src 10.0.2.254 
[heat-admin@overcloud-controller-0 ~]$ 

У цьому namespace дві внутрішні, які були нами створені раніше. Обидва віртуальні порти додані в br-int. Перевіримо масу адресу порту qr-0c52b15f-8f, оскільки трафік, судячи з мак адресою призначення йшов саме в цей інтерфейс.

[heat-admin@overcloud-controller-0 ~]$ sudo  ip netns exec qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe ifconfig qr-0c52b15f-8f
qr-0c52b15f-8f: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.0.1.254  netmask 255.255.255.0  broadcast 10.0.1.255
        inet6 fe80::f816:3eff:fec4:6470  prefixlen 64  scopeid 0x20<link>
        ether fa:16:3e:c4:64:70  txqueuelen 1000  (Ethernet)
        RX packets 5356  bytes 427305 (417.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5195  bytes 490603 (479.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[heat-admin@overcloud-controller-0 ~]$ 

Тобто в цьому випадку все працює за законами стандартної маршрутизації. Так як трафік призначений хосту 10.0.2.8, він повинен вийти через другий інтерфейс qr-92fa49b5-54 і піти через vxlan тунель на compute ноду:


[heat-admin@overcloud-controller-0 ~]$ sudo  ip netns exec qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe arp
Address                  HWtype  HWaddress           Flags Mask            Iface
10.0.1.88                ether   fa:16:3e:72:ad:53   C                     qr-0c52b15f-8f
10.0.1.90                ether   fa:16:3e:83:ad:a4   C                     qr-0c52b15f-8f
10.0.2.8                 ether   fa:16:3e:6c:ad:9c   C                     qr-92fa49b5-54
10.0.2.42                ether   fa:16:3e:f5:0b:29   C                     qr-92fa49b5-54
10.0.1.85                ether   fa:16:3e:44:98:20   C                     qr-0c52b15f-8f
[heat-admin@overcloud-controller-0 ~]$ 

Все логічно, жодних сюрпризів. Дивимося, звідки видно мак адресу хоста 10.0.2.8 в br-int:

[heat-admin@overcloud-controller-0 ~]$ sudo ovs-appctl fdb/show br-int | grep fa:16:3e:6c:ad:9c
    2     2  fa:16:3e:6c:ad:9c    1
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$ sudo ovs-ofctl show br-int | grep addr
 1(int-br-ex): addr:2e:58:b6:db:d5:de
 2(patch-tun): addr:06:41:90:f0:9e:56
 3(tapca25a97e-64): addr:fa:16:3e:e6:2c:5c
 4(tap22015e46-0b): addr:fa:16:3e:76:c2:11
 5(qr-0c52b15f-8f): addr:fa:16:3e:c4:64:70
 6(qr-92fa49b5-54): addr:fa:16:3e:80:13:72
 LOCAL(br-int): addr:06:de:5d:ed:44:44
[heat-admin@overcloud-controller-0 ~]$ 

Як ведеться, трафік йде в br-tun, подивимося, в який тунель трафік піде далі:

[heat-admin@overcloud-controller-0 ~]$ sudo ovs-ofctl dump-flows br-tun | grep fa:16:3e:6c:ad:9c
 cookie=0x2ab04bf27114410e, duration=5346.829s, table=20, n_packets=5248, n_bytes=498512, hard_timeout=300, idle_age=0, hard_age=0, priority=1,vlan_tci=0x0002/0x0fff,dl_dst=fa:16:3e:6c:ad:9c actions=load:0->NXM_OF_VLAN_TCI[],load:0x63->NXM_NX_TUN_ID[],output:2
[heat-admin@overcloud-controller-0 ~]$
[heat-admin@overcloud-controller-0 ~]$ sudo ovs-ofctl show br-tun | grep addr
 1(patch-int): addr:a2:69:00:c5:fa:ba
 2(vxlan-c0a8ff1a): addr:86:f0:ce:d0:e8:ea
 3(vxlan-c0a8ff13): addr:72:aa:73:2c:2e:5b
 LOCAL(br-tun): addr:a6:cb:cd:72:1c:45
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$ sudo sudo ovs-appctl dpif/show | grep vxlan-c0a8ff1a
    vxlan-c0a8ff1a 2/5: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.15, remote_ip=192.168.255.26)
[heat-admin@overcloud-controller-0 ~]$ 

Трафік йде у тунель до compute-1. Ну і на compute-1 все просто - з br-tun пакет потрапляє до br-int і звідти в інтерфейс віртуальної машини:

[heat-admin@overcloud-controller-0 ~]$ sudo sudo ovs-appctl dpif/show | grep vxlan-c0a8ff1a
    vxlan-c0a8ff1a 2/5: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.15, remote_ip=192.168.255.26)
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-novacompute-1 ~]$ sudo ovs-appctl fdb/show br-int | grep fa:16:3e:6c:ad:9c
    4     2  fa:16:3e:6c:ad:9c    1
[heat-admin@overcloud-novacompute-1 ~]$ sudo ovs-ofctl show br-int | grep addr                  
 1(int-br-ex): addr:8a:d7:f9:ad:8c:1d
 2(patch-tun): addr:46:cc:40:bd:20:da
 3(qvoe7e23f1b-07): addr:12:78:2e:34:6a:c7
 4(qvo3210e8ec-c0): addr:7a:5f:59:75:40:85
 LOCAL(br-int): addr:e2:27:b2:ed:14:46
[heat-admin@overcloud-novacompute-1 ~]$ 

Перевіримо, що це справді правильний інтерфейс:

[heat-admin@overcloud-novacompute-1 ~]$ brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02429c001e1c       no
qbr3210e8ec-c0          8000.ea27f45358be       no              qvb3210e8ec-c0
                                                        tap3210e8ec-c0
qbre7e23f1b-07          8000.b26ac0eded8a       no              qvbe7e23f1b-07
                                                        tape7e23f1b-07
[heat-admin@overcloud-novacompute-1 ~]$ 
[heat-admin@overcloud-novacompute-1 ~]$ sudo virsh domiflist instance-00000004
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tap3210e8ec-c0 bridge     qbr3210e8ec-c0 virtio      fa:16:3e:6c:ad:9c

[heat-admin@overcloud-novacompute-1 ~]$

Власне ми пройшли весь шлях пакету. Думаю ви помітили, що трафік йшов через різні тунелі vxlan і виходив з різними VNI. Давайте подивимося, які це VNI, після чого зберемо дамп на порту control ноди і переконаємося, що трафік ходить саме так, як описано вище.
Отже, тунель до compute-0 має наступний actions=load:0->NXM_OF_VLAN_TCI[],load:0x16->NXM_NX_TUN_ID[],output:3. Перекладемо 0x16 в десяткову систему числення:


0x16 = 6*16^0+1*16^1 = 6+16 = 22

Тунель до compute-1 має наступний VNI:actions=load:0->NXM_OF_VLAN_TCI[],load:0x63->NXM_NX_TUN_ID[],output:2. Перекладемо 0x63 в десяткову систему числення:


0x63 = 3*16^0+6*16^1 = 3+96 = 99

Ну і тепер подивимося дамп:

[root@hp-gen9 bormoglotx]# tcpdump -vvv -i vnet4 
tcpdump: listening on vnet4, link-type EN10MB (Ethernet), capture size 262144 bytes

*****************omitted*******************

04:35:18.709949 IP (tos 0x0, ttl 64, id 48650, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.19.41591 > 192.168.255.15.4789: [no cksum] VXLAN, flags [I] (0x08), vni 22
IP (tos 0x0, ttl 64, id 49042, offset 0, flags [DF], proto ICMP (1), length 84)
    10.0.1.85 > 10.0.2.8: ICMP echo request, id 5378, seq 9, length 64
04:35:18.710159 IP (tos 0x0, ttl 64, id 23360, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.15.38983 > 192.168.255.26.4789: [no cksum] VXLAN, flags [I] (0x08), vni 99
IP (tos 0x0, ttl 63, id 49042, offset 0, flags [DF], proto ICMP (1), length 84)
    10.0.1.85 > 10.0.2.8: ICMP echo request, id 5378, seq 9, length 64
04:35:18.711292 IP (tos 0x0, ttl 64, id 43596, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.26.42588 > 192.168.255.15.4789: [no cksum] VXLAN, flags [I] (0x08), vni 99
IP (tos 0x0, ttl 64, id 55103, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.2.8 > 10.0.1.85: ICMP echo reply, id 5378, seq 9, length 64
04:35:18.711531 IP (tos 0x0, ttl 64, id 8555, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.15.38983 > 192.168.255.19.4789: [no cksum] VXLAN, flags [I] (0x08), vni 22
IP (tos 0x0, ttl 63, id 55103, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.2.8 > 10.0.1.85: ICMP echo reply, id 5378, seq 9, length 64
	
*****************omitted*******************

Перший пакет - це vxlan пакет з хоста 192.168.255.19 (compute-0) на хост 192.168.255.15 (control-1) з vni 22, всередині якого упакований пакет ICMP з хоста 10.0.1.85 на хост 10.0.2.8. Як ми порахували вище, vni відповідає тому, що ми бачили у висновках.

Другий пакет - це vxlan пакет з хоста 192.168.255.15 (control-1) на хост 192.168.255.26 (compute-1) з vni 99, усередині якого упакований пакет ICMP з хоста 10.0.1.85 на хост 10.0.2.8. Як ми порахували вище, vni відповідає тому, що ми бачили у висновках.

Два наступні пакети - це зворотний трафік з 10.0.2.8 не 10.0.1.85.

Тобто в результаті вийшла така схема control ноди:

Введення в мережеву частину хмарної інфраструктури

Наче все? Ми забули про два namespace:

[heat-admin@overcloud-controller-0 ~]$ sudo  ip netns
qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe (id: 2)
qdhcp-7d541e74-1c36-4e1d-a7c4-0968c8dbc638 (id: 1)
qdhcp-67a3798c-32c0-4c18-8502-2531247e3cc2 (id: 0)
[heat-admin@overcloud-controller-0 ~]$ 

Як ми говорили про архітектуру хмарної платформи — було б добре, щоб машини отримували адреси автоматично від сервера DHCP. Це і є два DHCP сервери на наші дві мережі 10.0.1.0/24 та 10.0.2.0/24.

Перевіримо, що це так. У даному namespace лише одна адреса - 10.0.1.1 - адреса самого DHCP сервера, і він також включений в br-int:

[heat-admin@overcloud-controller-0 ~]$ sudo ip netns exec qdhcp-67a3798c-32c0-4c18-8502-2531247e3cc2 ifconfig
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 1  bytes 28 (28.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1  bytes 28 (28.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

tapca25a97e-64: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.0.1.1  netmask 255.255.255.0  broadcast 10.0.1.255
        inet6 fe80::f816:3eff:fee6:2c5c  prefixlen 64  scopeid 0x20<link>
        ether fa:16:3e:e6:2c:5c  txqueuelen 1000  (Ethernet)
        RX packets 129  bytes 9372 (9.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 49  bytes 6154 (6.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Подивимося, якщо процеси, що містять у своїй назві qdhcp-67a3798c-32c0-4c18-8502-2531247e3cc2 на control ноді:


[heat-admin@overcloud-controller-0 ~]$ ps -aux | egrep qdhcp-7d541e74-1c36-4e1d-a7c4-0968c8dbc638 
root      640420  0.0  0.0   4220   348 ?        Ss   11:31   0:00 dumb-init --single-child -- ip netns exec qdhcp-7d541e74-1c36-4e1d-a7c4-0968c8dbc638 /usr/sbin/dnsmasq -k --no-hosts --no-resolv --pid-file=/var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/pid --dhcp-hostsfile=/var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/host --addn-hosts=/var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/addn_hosts --dhcp-optsfile=/var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/opts --dhcp-leasefile=/var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/leases --dhcp-match=set:ipxe,175 --local-service --bind-dynamic --dhcp-range=set:subnet-335552dd-b35b-456b-9df0-5aac36a3ca13,10.0.2.0,static,255.255.255.0,86400s --dhcp-option-force=option:mtu,1450 --dhcp-lease-max=256 --conf-file= --domain=openstacklocal
heat-ad+  951620  0.0  0.0 112944   980 pts/0    S+   18:50   0:00 grep -E --color=auto qdhcp-7d541e74-1c36-4e1d-a7c4-0968c8dbc638
[heat-admin@overcloud-controller-0 ~]$ 

Є такий процес і виходячи з інформації, представленої у висновку вище, ми можемо наприклад подивитися, що у нас в оренді зараз:

[heat-admin@overcloud-controller-0 ~]$ cat /var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/leases
1597492111 fa:16:3e:6c:ad:9c 10.0.2.8 host-10-0-2-8 01:fa:16:3e:6c:ad:9c
1597491115 fa:16:3e:76:c2:11 10.0.2.1 host-10-0-2-1 *
[heat-admin@overcloud-controller-0 ~]$

У результаті ми отримуємо такий набір сервісів на control ноді:

Введення в мережеву частину хмарної інфраструктури

Ну і майте на увазі - це всього лише - 4 машини, 2 внутрішні мережі і один віртуальний маршрутизатор ... У нас тут немає зараз зовнішніх мереж, купи різних проектів, кожен зі своїми мережами (що перетинаються), і у нас вимкнений розподілений маршрутизатор, та в кінці Зрештою в тестовому стенді була лише одна control нода (для відмовостійкості повинен бути кворум з трьох нод). Логічно, що в комерції все "трохи" складніше, але на даному простому прикладі ми розуміємо, як це має працювати - буде у вас 3 або 300 namespace, звичайно важливо, але з точки зору роботи всієї конструкції - особливо нічого не зміниться ... правда поки ви не вставте якийсь вендорський SDN. Але це вже зовсім інша історія.

Сподіваюся було цікаво. Якщо є зауваження/доповнення ну або десь я відверто збрехав (я людина і моя думка завжди буде суб'єктивно) — пишіть що треба поправити/додати — все поправимо/додамо.

Наприкінці хотілося б сказати кілька слів про порівняння Openstack (як ванільного, так і вендорських) з хмарним рішенням від компанії VMWare — надто частину мені ставили це питання останні кілька років і я вже чесно кажучи від нього втомився, але все ж таки. На мій погляд ці два рішення порівняти дуже складно, але можна однозначно сказати, що мінуси є в обох рішеннях і вибираючи якесь одне рішення треба зважити всі за і проти.

Якщо OpenStack є community-driven рішенням, то VMWare має право робити тільки те, що вона хоче (читайте - те, що їй вигідно) і це логічно - бо це комерційна компанія, яка звикла заробляти гроші на своїх клієнтах. Але тут є одне велике і жирне АЛЕ - ви можете злізти з OpenStack наприклад від Nokia і малою кров'ю перейти на рішення від Juniper (Contrail Cloud), але злізти з VMWare у вас навряд чи вийде. Для мене ці два рішення виглядають так – Openstack (вендорський) це проста клітина, в яку вас садять, але у вас є ключ і ви можете вийти будь-якої миті. VMWare - це золота клітка, ключ від клітки у хазяїна і обійдеться він вам дуже дорого.

Я не агітую ні за перший продукт, ні за другий — ви вибираєте те, що вам треба. Але якби я мав такий вибір то я вибрав обидва рішення — VMWare для IT хмари (малі навантаження, зручне управління), OpenStack від якогось вендора (Nokia і Juniper надають дуже непогані рішення під ключ) — для Телеком хмари. Я не став би використовувати Openstack для чистого IT — це як стріляти з гармати по горобцях, але протипоказань використовувати його, окрім як надмірність — я не бачу. Однак використовувати VMWare у телекомі - як возити щебінь на Ford Raptor - красиво збоку, але водієві доводиться робити 10 рейсів замість одного.

На мій погляд, найбільшим недоліком VMWare є її повна закритість — компанія вам не видасть ніякої інформації про те, як у неї влаштований наприклад vSAN або що там в ядрі гіпервізора — їй це просто не вигідно — тобто ви ніколи не станете експертом у VMWare. без підтримки вендора ви приречені (дуже частину зустрічаю експертів з VMWare яких ставлять у глухий кут банальні питання). Для мене VMWare - це покупка машини із закритим на замок капотом - так, можливо у вас є фахівці, які можуть поміняти ремінь ГРМ, але відкрити капот зможе тільки той, хто продав вам це рішення. Особисто я не люблю рішень, у які не можу влізти. Ви скажете, що вам, можливо, не доведеться лізти під капот. Так таке можливо, але я подивлюся на вас, коли вам треба буде зібрати в хмарі велику функцію з 20-30 віртуальних машин, 40-50 мереж, половина з яких хоче вийти назовні, а друга половина просить SR-IOV прискорення інакше вам треба буде ще пару десяток таких машин - інакше перфомансу не вистачить.

Існують і інші точки зору, тому тільки вам вирішувати, що вибирати і найголовніше — вам же за ваш вибір потім відповідати. Це всього лише моя думка - людину, яка бачила і чіпала руками як мінімум 4 продукти - Nokia, Juniper, Red Hat і VMWare. Тобто, мені є з чим порівняти.

Джерело: habr.com

Додати коментар або відгук