Въведение в мрежовата част на облачната инфраструктура

Въведение в мрежовата част на облачната инфраструктура

Облачните изчисления все повече навлизат в живота ни, и вероятно няма човек, който поне веднъж да не е използвал облачни услуги. Но какво точно е облакът и как работи, малко хора знаят дори на ниво идея. 5G вече е реалност, и телекомуникационната инфраструктура започва да преминава от класическите решения към облачните, както преди е преминала от напълно физически решения към виртуализирани "стълбове".

Днес ще говорим за вътрешния свят на облачната инфраструктура, и по-специално ще разгледаме основите на мрежовата част.

Какво е облак? Същата виртуализация — вид отстрани?

По-логичен въпрос. Не — това не е виртуализация, въпреки че не е минало без нея. Нека разгледаме две определения:

Облачните изчисления (наричани по-нататък Облак) — това е модел за предоставяне на удобен достъп до разпределени изчислителни ресурси, които трябва да бъдат внедрени и стартирани по заявка с минимално възможно забавяне и минимални разходи от страна на доставчика на услуги.

Виртуализация — това е възможността да се раздели една физическа единица (например сървър) на няколко виртуални, увеличавайки така използването на ресурсите (например, ако преди имате 3 сървъра със заетост 25-30 процента, след виртуализация получавате 1 сървър със заетост 80-90 процента). Разбира се, виртуализацията отнема част от ресурсите — трябва да поддържате хипервизора, но както показва практиката, играта си струва. Идеален пример за виртуализация е VMWare, който отлично подготвя виртуални машини, или например KVM, който ми допада повече, но това вече е въпрос на вкус.

Използваме виртуализация, без да осъзнаваме, дори физическите маршрутизатори вече използват виртуализация — например в последните версии на JunOS операционната система се инсталира като виртуална машина върху дистрибуция на real-time linux (Wind River 9). Но виртуализацията не е облак, обаче облак не може да съществува без виртуализация.

Виртуализацията е един от строителните блокове, върху които се изгражда облакът.

Създаването на облак само чрез събиране на няколко хипервизора в един L2 домейн, добавяне на няколко yaml плейбука за автоматично конфигуриране на VLAN чрез някакъв ansible и добавяне на нещо като система за оркестрация за автоматично създаване на виртуални машини — няма да сработи. По-точно ще сработи, но полученият Франкенщайн не е това облако, от което имаме нужда. Въпреки това, за някои може да е предел на мечтанията. Освен това, ако вземем същия OpenStack — по същество също е един вид Франкенщайн, но нека не разглеждаме това в момента.

Но разбирам, че от предоставеното по-горе определение не е съвсем ясно какво всъщност може да наречем облак.

Затова в документа на NIST (Национален институт за стандарти и технологии) са посочени 5 основни характеристики, които облачната инфраструктура трябва да притежава:

Предлагане на услугата при поискване. На потребителя трябва да се предостави свободен достъп до определените му компютърни ресурси (като мрежи, виртуални дискове, памет, процесорни ядра и т.н.), като тези ресурси трябва да се предоставят автоматично — т.е. без намеса от страна на доставчика на услуги.

Широка наличност на услугата. Достъпът до ресурсите трябва да се осигури чрез стандартни механизми, за да е възможно използването както на стандартни компютри, така и на тънки клиенти и мобилни устройства.

Обединяване на ресурсите в пулове. Пуловете от ресурси трябва да осигурят simultaneous предоставяне на ресурси за няколко клиента, осигурявайки изолация на клиентите и отсъствие на взаимно влияние между тях, както и конкуренция за ресурси. В пуловете се включват и мрежи, което показва възможността за използване на пресичаща се адресация. Пуловете трябва да поддържат мащабиране при поискване. Използването на пулове позволява осигуряване на необходимото ниво на отказоустойчивост на ресурсите и абстракция на физическите и виртуалните ресурси — получателят на услугата просто получава искания набор от ресурси (къде физически са разположени тези ресурси, на колко сървъра и комутатори — на клиента не му е важно). Въпреки това, е необходимо да се вземе предвид фактът, че доставчикът трябва да осигури прозрачно резервиране на данните ресурси.

Бърза адаптация към различни условия. Услугите трябва да са гъвкави — бързо предоставяне на ресурси, преразпределение, добавяне или намаляване на ресурси по искане на клиента, като клиентът трябва да има чувството, че ресурсите на облака са безкрайни. За улеснение, например, вие не получавате предупреждение, че част от дисковото пространство в Apple iCloud е изчезнало, защото на сървъра е повреден твърдия диск, а дисковете наистина се повреждат. Освен това, от ваша страна, възможностите на тази услуга са почти безкрайни — нужни ли са ви 2 Тб — без проблем, платили сте и сте получили. Аналогично можем да посочим пример с Google.Drive или Yandex.Disk.

Възможност за измерване на предоставената услуга. Облачните системи трябва автоматично да контролират и оптимизират консумираните ресурси, като тези механизми трябва да бъдат прозрачни както за потребителя, така и за доставчика на услуги. Тоест, вие винаги можете да проверите колко ресурси вие и вашите клиенти консумирате.

Трябва да се вземе предвид, че тези изисквания в повечето случаи са изисквания към публичното облако, затова за частното облако (т.е. облако, стартирано за вътрешните нужди на компанията) тези изисквания могат да бъдат леко коригирани. Въпреки това, те все пак трябва да бъдат изпълнени, иначе няма да получим всички предимства на облачните изчисления.

Защо ни е облак?

Въпреки това, всяка нова или вече съществуваща технология, всеки нов протокол се създава с цел (освен RIP-ng, разбира се). Протоколът ради протокола — на никого не му е нужен (освен RIP-ng, разбира се). Логично е, че облакът се създава, за да предостави някаква услуга на потребителя/клиента. Всички сме запознати поне с няколко облачни услуги, например Dropbox или Google.Docs и предполагам, че повечето успешно ги използват — например, тази статия е написана с помощта на облачната услуга Google.Docs. Но известните ни облачни услуги са само част от възможностите на облака — по-точно, те са само услуги от тип SaaS. За да предоставим облачна услуга, можем да го направим по три начина: под формата на SaaS, PaaS или IaaS. Каква услуга точно ви е необходима, зависи от вашите желания и възможности.

Нека разгледаме всеки по ред:

Софтуер като услуга (SaaS) — това е модел на предоставяне на пълноценна услуга на клиента, например пощенска услуга като Yandex.Mail или Gmail. В такъв модел на предоставяне на услуга вие, като клиент, всъщност не правите нищо, освен да ползвате услугата — тоест не е нужно да се притеснявате за настройката на услугата, нейната отказоустойчивост или резервиране. Важно е да не компрометирате паролата си, всичко останало ще бъде направено от доставчика на услугата. От гледна точка на доставчика на услугата — той носи пълна отговорност за цялата услуга — от сървърното оборудване и хост операционни системи до настройките на бази данни и софтуер.

Platform as a Service (PaaS) — при използване на този модел доставчикът на услуги предоставя на клиента шаблон за услуга, например, нека вземем уеб сървър. Доставчикът на услуги е предоставил на клиента виртуален сървър (всъщност набор от ресурси, като RAM/CPU/Storage/Networks и т.н.), и дори е инсталирал операционната система и необходимия софтуер на този сървър, но настройката на всичко това вече е задача на клиента, а клиентът носи отговорност за функционирането на услугата. Доставчикът на услуги, както и в предишния случай, отговаря за функционирането на физическото оборудване, хипервизорите, самата виртуална машина, нейното мрежово достъпност и т.н., но самата услуга вече е извън неговата зона на отговорност.

Infrastructure as a Service (IaaS) — този подход е по-интригуващ, всъщност доставчикът на услуги предоставя на клиента пълна виртуализирана инфраструктура — тоест набор (пул) от ресурси, като CPU ядра, RAM, мрежи и т.н. Всичко останало — работа на клиента — какво клиентът иска да направи с тези ресурси в рамките на предоставения му пул (квота) — на доставчика не му е особено важно. Иска ли клиентът да създаде свой собствен vEPC или да стане мини оператор и да предлага услуги за комуникация — няма проблем — действайте. В такъв сценарий доставчикът на услуги отговаря за предоставянето на ресурси, тяхната отказоустойчивост и достъпност, както и за операционната система, която позволява обединение на тези ресурси в пулове и предоставянето им на клиента с възможност по всяко време да увеличи или намали ресурсите по искане на клиента. Всички виртуални машини и друга свързана инфраструктура клиентът сам настроива чрез портала за самообслужване и консолата, включително и настройката на мрежите (с изключение на външните мрежи).

Какво е OpenStack?

При всички три варианта на доставчиците на услуги е необходима операционна система, която да позволи създаването на облачна инфраструктура. Всъщност при SaaS за целия стек от технологии не отговаря едно подразделение — има подразделение, което отговаря за инфраструктурата — т.е. предоставя IaaS на друго подразделение, а това подразделение предоставя SaaS на клиента. OpenStack е една от облачните ОС, която позволява да се съберат много комутатори, сървъри и системи за съхранение в единен ресурсен пул, да се раздели този общ пул на подпули (тенанти) и да се предоставят тези ресурси на клиентите през мрежата.

OpenStack е облачна операционна система, която позволява контролиране на големи пулове изчислителни ресурси, хранилища от данни и мрежови ресурси, при което провижининг и управлението се извършва през API с използване на стандартни механизми за аутентификация.

С други думи, това е комплекс от проекти с отворен код, предназначен за създаване на облачни услуги (както публични, така и частни) — т.е. набор от инструменти, които позволяват обединяване на сървърното и комутационно оборудване в единен ресурсен пул, управление на тези ресурси и осигуряване на необходимото ниво на отказоустойчивост.

По време на написването на този материал структурата на OpenStack изглежда така:
Въведение в мрежовата част на облачната инфраструктура
Снимката е взета от openstack.org

Всяка от компонентите, включени в OpenStack, изпълнява определена функция. Тази разпределена архитектура позволява включване в решението на необходимия набор от функционални компоненти. Въпреки това, част от компонентите са основни и тяхното изтриване ще доведе до пълна или частична неработоспособност на решението. Към такъв тип компоненти спадат:

  • Дашборд — уеб базиран GUI за управление на OpenStack услугите
  • Keystone — централизирана услуга за идентификация, която предоставя функционалност за аутентификация и авторизация за другите услуги, както и управление на потребителските данни и техните роли.
  • Neutron е мрежова услуга, осигуряваща свързаност между интерфейсите на различните OpenStack услуги (включително свързаност между VM и достъп до външния свят)
  • Cinder осигурява достъп до блочно хранилище за виртуални машини
  • Nova — управление жизнения на виртуални машини
  • Glance — хранилище на образи на виртуални машини и моментни снимки
  • Swift — предоставя достъп до обектно хранилище
  • Ceilometer — услуга, която предоставя възможност за събиране на телеметрични данни и измерване на наличните и потребяваните ресурси
  • Heat — оркестрация на базата на шаблони за автоматично създаване и предоставяне на ресурси

Пълен списък на всички проекти и тяхното предназначение можете да видите тук.

Всяка от компонентите на OpenStack е услуга, която отговаря за определена функция и осигурява API за управление на тази функция и взаимодействие на тази услуга с други услуги в облачната операционна система с цел създаване на единна инфраструктура. Например, Nova осигурява управление на изчислителните ресурси и API за достъп до конфигуриране на тези ресурси, Glance – управление на образи и API за управление на тях, Cinder – блочно хранилище и API за управление на него и т.н. Всички функции са много тясно свързани помежду си.

Обаче, ако размислите, всички услуги, стартирани в OpenStack, в крайна сметка представляват някаква виртуална машина (или контейнер), свързана в мрежа. Изниква въпросът — защо ни е толкова много елементи?

Нека да прегледаме алгоритъма за създаване на виртуална машина и свързването ѝ към мрежата и постоянното хранилище в OpenStack.

  1. Когато подавате заявка за създаване на машина, независимо дали е чрез Horizon (табло) или чрез CLI, първото, което се случва — е удостоверяване на вашата заявка в Keystone — можете ли да създадете машина, имате ли право да използвате тази мрежа, достатъчни ли са квотите на вашия проект и т.н.
  2. Keystone удостоверява вашата заявка и генерира в отговор auth-токен, който ще бъде използван по-късно. След получаване на отговора от Keystone, заявката се изпраща към Nova (nova api).
  3. Nova-api проверява валидността на вашата заявка, като се обръща към Keystone, използвайки предварително сгенерирания auth-токен
  4. Keystone извършва удостоверяване и предоставя информация относно разрешенията и ограниченията на базата на този auth-токен.
  5. Nova-api създава запис за нова VM в nova-database и предава заявката за създаване на машина към 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 на образа. Glance извършва проверка на валидността на искането в Keystone и връща исканата информация.
  10. Nova-compute се свързва с neutron за получаване информация относно параметрите на мрежата. Подобно на glance, neutron извършва проверка на валидността на искането в Keystone, след което създава запис в базата данни (идентификатор на порта и т.н.), създава искане за създаване на порт и връща исканата информация обратно на nova-compute.
  11. Nova-compute се свързва с cinder с искане за предоставяне на том на виртуалната машина. Подобно на glance, cinder извършва проверка на валидността на искането в Keystone, създава искане за създаване на том и връща исканата информация.
  12. Nova-compute се свързва с libvirt с искане за разполагане на виртуалната машина с зададени параметри.

Фактически проста операция по създаването на виртуална машина се превръща в порой от API колове между компонентите на облачната платформа. Както виждате, дори преди обозначените услуги са съставени от по-малки компоненти, между които се осъществява взаимодействие. Създаването на машина е само малка част от функционалността, която облачната платформа предоставя — съществуват услуги за балансировка на трафика, услуги за блочно хранилище, услуги за DNS, услуги за провизиране на bare metal сървъри и т.н. Облачното решение ви позволява да разглеждате вашите виртуални машини като стадо овце (в отличие от виртуализацията). Ако нещо се случи с машината в виртуалната среда — вие я възстановявате от резервни копия и т.н., облачните приложения са изградени така, че виртуалната машина да не играе толкова важна роля — ако виртуалната машина „умре“ — няма проблем — просто се създава нова машина от шаблон и, както се казва, отрядът не забелязва загубата на бойца. Това, разбира се, предполага наличието на механизми за оркестрация — използвайки шаблони Heat, можете без особени проблеми да разгръщате сложна функция, състояща се от десетки мрежи и виртуални машини.

Винаги трябва да имате предвид, че облачната инфраструктура не съществува без мрежа — всеки елемент взаимодействува по един или друг начин с другите елементи през мрежата. Освен това, облакът има абсолютно нестатична мрежа. Разбира се, подлежащата мрежа е повече или по-малко статична — нови възли и суичове не се добавят всеки ден, обаче надстройката непременно ще се променя постоянно — нови мрежи ще се добавят или премахват, нови виртуални машини ще възникват, а старите ще изчезват. И както помните от определението на облака, дадено в самото начало на статията — ресурсите трябва да се предоставят на потребителя автоматично и с минимално (а по-добре без) вмешателство от страна на обслужващия доставчик. Тоест, този тип предоставяне на ресурси в мрежата, който в момента съществува в формата на фронтенд в личния ви кабинет, достъпен по http/https, и дежурния мрежов инженер Василий в ролята на бекенд — това не е облак, дори с наличието на осемте ръце на Василий.

Neutron, като мрежова услуга, осигурява API за управление на мрежовата част на облачната инфраструктура. Услугата гарантира работоспособността и управляемостта на мрежовата част на OpenStack, предоставяйки ниво на абстракция, наречено Network-as-a-Service (NaaS). Тоест, мрежата е виртуализирана измерима единица, подобно на виртуалните ядра на CPU или обема на RAM.

Но преди да преминем към архитектурата на мрежовата част на OpenStack, нека разгледаме как работи мрежата в OpenStack и защо тя е важна и неразривна част от облака.

И така, притежаваме две виртуални машини на клиент RED и две виртуални машини на клиент GREEN. Да предположим, че тези машини са разположени на два хипервизора по следния начин:

Въведение в мрежовата част на облачната инфраструктура

В момента това е просто виртуализация на 4 сървъра и не повече от това, тъй като всичко, което направихме досега, е да виртуализираме 4 сървъра, разположени на два физически сървъра. Освен това, те дори не са свързани в мрежа.

За да създадем облак, трябва да добавим няколко компонента. Първо, трябва да виртуализираме мрежовата част — трябва да свържем четирите машини по двойки, като клиентите искат именно L2 свързване. Можем, разбира се, да използваме комутатор и да настроим транк в неговата посока и да управляваме всичко с помощта на linux bridge, или за по-напреднали потребители openvswitch (върнем се към него по-късно). Но мрежите могат да бъдат изключително много, а и постоянно да пробутваме L2 през комутатора — не е най-добрата идея — така различни отдели, сървис-деск, месеци чакане за изпълнение на заявка, седмици дипломиране на проблеми — в съвременния свят такъв подход вече не работи. И колкото по-рано компанията осъзнае това, толкова по-лесно ще напредва. Следователно, между хипервизорите, трябва да определим L3 мрежа, чрез която ще комуникират нашите виртуални машини, а вече над тази L3 мрежа ще изградим виртуални наложени L2 (overlay) мрежи, където ще тече трафикът на нашите виртуални машини. За инкапсулация можем да използваме GRE, Geneve или VxLAN. Засега ще спрем на последното, макар че това не е особено важно.

Трябва да намерим място за VTEP (надявам се всички сте запознати с терминологията VxLAN). Тъй като от сървърите излиза веднага L3 мрежа, нищо не пречи да разположим VTEP на самите сървъри, а OVS (OpenvSwitch) изключително добре умее да го прави. В крайна сметка получаваме такава конструкция:

Въведение в мрежовата част на облачната инфраструктура

Тъй като трафикът между виртуалните машини трябва да бъде разделен, портовете към виртуалните машини ще имат различни номера на VLAN. Номерата на таговете имат значение само в рамките на един виртуален комутатор, тъй като при инкапсулация в VxLAN можем лесно да ги премахнем, тъй като ще имаме VNI.

Въведение в мрежовата част на облачната инфраструктура

Сега можем да създаваме множество виртуални машини и виртуални мрежи за тях без никакви проблеми.

Но какво ще стане, ако клиентът има още една машина, но тя е в друга мрежа? Нуждаем се от маршрутизиране между мрежите. Ще разгледаме прост вариант, при който се използва централизирано маршрутизиране — трафикът се маршрутизира чрез специално определени мрежови възли (обикновено те са комбинирани с контролни възли, така че ще имаме същото).

На пръв поглед няма нищо сложно — правим интерфейс на моста на контролния възел, насочваме трафика към него и оттам го маршрутизираме там, където ни е нужно. Но проблемът е, че клиентът 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) това наистина ще работи. В този сценарий разглеждаме най-простия вариант със централизирана шлюзова точка, която в Openstack се използва по подразбиране. За функции с високо натоварване ще се използват както разпределен маршрутизатор, така и технологии за ускорение като SR-IOV и Passthrough, но както казват, това е съвсем друга история. Първо, нека се справим с основната част, а после ще се задълбочим в детайлите.

Собствено казано, нашата схема вече работи, но има няколко нюанса:

  • Нужно е по някакъв начин да защитим нашите машини, тоест да поставим филтър на интерфейса на суича в посока клиента.
  • Да направим възможност за автоматично получаване на IP адрес от виртуалната машина, за да не се налага всеки път да влизаме в нея през конзолата и да задаваме адрес.

Нека започнем със защитата на машините. За тази цел можем да използваме обикновените iptables, защо не.

Тоест, сега нашата топология вече е малко усложнена:

Въведение в мрежовата част на облачната инфраструктура

Да продължим. Трябва да добавим DHCP сървър. Най-идеалното място за разполагане на DHCP сървъри за всеки от клиентите ще бъде вече споменатата контролна нода, където са разположени namespaces:

Въведение в мрежовата част на облачната инфраструктура

Но има малък проблем. Какво ще стане, ако всичко се рестартира и информацията за отдаване на адреси по DHCP изчезне? Логично е, че машините ще получат нови адреси, което не е много удобно. Има два варианта — или да използваме доменни имена и да добавим DNS сървър за всеки клиент, тогава адресът няма да е особено важен (по аналогия с мрежовата част в k8s) — но тук възниква проблем с външните мрежи, тъй като и там адресите също могат да се раздават по DHCP — необходима е синхронизация между DNS сървърите в облачната платформа и външния DNS сървър, което, на моя поглед, не е много гъвкаво, но е напълно възможно. Или вторият вариант — да използваме метаданни — тоест да запазим информация за предоставения адрес на машината, за да знае DHCP сървърът кой адрес да предостави на машината, ако тя вече е получила адрес. Вторият вариант е по-прост и гъвкав, тъй като позволява да се запази допълнителна информация за машината. Сега ще добавим метаданните на агента към схемата:

Въведение в мрежовата част на облачната инфраструктура

Друг въпрос, който също заслужава внимание, е възможността за използване на една външна мрежа от всички клиенти, тъй като външните мрежи, ако трябва да бъдат валидни в цялата мрежа, създават сложност — необходимо е постоянно да се разпределят и контролират тези мрежи. Възможността за използване на единна предварително конфигурирана външна мрежа за всички клиенти ще бъде много полезна при създаването на публично облако. Това ще улесни разгръщането на машините, тъй като не е нужно да се сверяваме с базата данни на адресите и да избираме уникално адресно пространство за външната мрежа на всеки клиент. Освен това можем предварително да зададем външната мрежа и в момента на разгръщането просто да асоциираме външните адреси с клиентските машини.

Тук на помощ ни идва NAT — просто ще позволим на клиентите да излизат навън чрез default namespace с използването на NAT транслация. Но тук има малък проблем. Това е добре, ако клиентският сървър работи като клиент, а не като сървър — т.е. иницира, а не приема връзки. Но при нас ще е обратно. В такъв случай трябва да направим destination NAT, за да може контролният възел да разбере, че този трафик е предназначен за виртуалната машина на клиент А, а следователно трябва да направим NAT транслация от външния адрес, например 100.1.1.1 до вътрешния адрес 10.0.0.1. По този начин, въпреки че всички клиенти ще използват една и съща мрежа, вътрешната изолация напълно се запазва. Тоест, трябва да направим dNAT и sNAT на контролния възел. Използването на единна мрежа с выделение на плаващи адреси или външни мрежи, или и двете, зависи от това какво искате да привлечете в облака. Няма да добавяме плаващи адреси в схемата, а ще запазим вече добавените преди това външни мрежи — всеки клиент има своя собствена външна мрежа (в схемата обозначени като VLAN 100 и 200 на външния интерфейс).

В резултат получихме интересно и същевременно обмислено решение, което притежава определена гъвкавост, но все още не разполага с механизми за отказоустойчивост.

На първо място, имаме само един контролен възел — излизането му от строя ще доведе до провал на всички системи. За да отстраним този проблем, е необходимо да създадем поне кворум от 3 възела. Нека добавим това в схемата:

Въведение в мрежовата част на облачната инфраструктура

Естествено, всички възли се синхронизират и при излизането на активен възел, задълженията му ще поеме друг възел.

Следващият проблем са дисковете на виртуалните машини. В момента те се съхраняват на самите хипервизори и в случай на проблеми с хипервизора, губим всички данни — а наличието на RAID тук никак не помага, ако загубим не диск, а целия сървър. Затова ни е необходима услуга, която да бъде фронтенд за някакво хранилище. Какво точно ще бъде това хранилище, не е от особено значение, но то трябва да защити данните ни от повреди на диска, нодата или дори цялата ракла. Има няколко варианта — разбира се, съществуват SAN мрежи с Fiber Channel, но да бъдем честни — FC вече е реликва от миналото — аналог на E1 в транспорта — съгласен съм, все още се използва, но само там, където без него не може. Затова, доброволно да изградя FC мрежа през 2020 година, не бих се съгласил, знаейки за наличието на други, по-интересни алтернативи. Въпреки това, всеки има своето мнение и вероятно ще се намерят такива, които смятат, че FC с всичките си ограничения — е всичко, от което имаме нужда — няма да споря, всеки има своето мнение. Най-интересното решение според мен е използването на SDS, например Ceph.

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

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

Въведение в мрежовата част на облачната инфраструктура

Забележка: могат да се създават хиперконвергентни изчислителни възли — това е концепция за комбиниране на няколко функции на един възел — например съхранение + изчисление — без да се отделят специални възли за ceph storage. Ще получим такава съща отказоустойчива схема — тъй като SDS ще резервира данните с посочения от нас ниво на резервиране. Въпреки това, хиперконвергентните възли са винаги компромис — тъй като възелът за съхранение не просто загрява въздуха, както изглежда на пръв поглед (тъй като на него няма виртуални машини) — той изразходва ресурси на ЦП за поддръжка на SDS (в действителност, той в фонов режим извършва всички репликации, възстановявания след сривове на възли, дискове и т.н.). Тоест, ще загубите част от мощността на изчислителния възел, ако го комбинирате със съхранение.

Всички тези елементи трябва да се управляват — необходима е нещо, чрез което можем да създадем машина, мрежа, виртуален маршрутизатор и т.н. За целта на контролния възел ще добавим услуга, която ще играе роля на табло — клиентът ще може да се свърже с този портал чрез 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-сървърът всъщност е приложение, написано на Python, което се състои от две части:

  • REST услуга
  • Neutron плъгин (core/service)

REST услугата е предназначена да приема API повиквания от другите компоненти (например заявка за предоставяне на информация и т.н.)

Плъгините са свързани софтуерни компоненти/модули, които се извикват при API заявки — т.е. добавянето на определена услуга става чрез тях. Плъгините се делят на два вида — сервисен и коренов. Обикновено кореновият плъгин отговаря основно за управлението на адресното пространство и L2 връзките между VM, а сервисните плъгини осигуряват допълнителен функционал, например VPN или FW.

Списъкът на наличните в момента плъгини може да бъде видян например тук

Сервисните плъгини могат да бъдат няколко, но кореновият плъгин може да бъде само един.

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

RPC услуга (rabbitmq-server) — услуга, осигуряваща управлението на опашките и взаимодействие с другите услуги на OpenStack, както и взаимодействие между агентите на мрежовата услуга.

Мрежови агенти — агенти, които се намират на всяка възел и чрез които се извършва конфигуриране на мрежовите услуги.

Агентите са от няколко вида.

Основният агент — това е L2 агент. Тези агенти се стартират на всеки от хипервизорите, включително и контролни възли (по-точно казано на всички възли, които предоставят услуги за наемателите) и основната им функция е да свързват виртуални машини с обща L2 мрежа, както и да генерират уведомления при възникване на каквито и да било събития (напр. изключване/включване на порт).

Следващият, не по-малко важен агент е L3 агент. По подразбиране този агент се стартира изключително на мрежовия възел (често мрежовият възел е комбиниран с контролния възел) и осигурява маршрутизация между мрежите на наемателите (както между неговите мрежи и мрежите на други наематели, така и за достъп до външния свят, осигурявайки NAT, както и DHCP услуга). Въпреки това, при използване на DVR (разпределен маршрутизатор) необходимостта от L3 плъгин възниква и на изчислителните възли.

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

База данни — база данни на идентификатори на мрежи, подмрежи, портове, пулове и др.

Всъщност 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 плъгина.

Модулен слой 2

Както бе споменато по-горе, плъгинът е стандартният основен плъгин на OpenStack и разполага с модулна архитектура.

Предшественикът на ML2 плъгина имаше монолитна структура, което не позволяваше например да се използват различни технологии в една инсталация. Например, не можехте да използвате и openvswitch, и linuxbridge едновременно — или едното, или другото. Поради тази причина беше създаден ML2 плъгинът с неговата архитектура.

ML2 има две съставляващи — два типа драйвери: Type drivers и Mechanism drivers.

Type drivers определят технологиите, които ще бъдат използвани за организиране на мрежовите връзки, например VxLAN, VLAN, GRE. Тези драйвери позволяват използването на различни технологии. Стандартната технология е VxLAN инкапсулация за overlay мрежи и VLAN за външни мрежи.

Към Type drivers принадлежат следните типове мрежи:

Flat — мрежа без тагиране
VLAN — тагирана мрежа
Local — специален тип мрежа за инсталации тип all-in-one (такива инсталации са необходими или за разработчици, или за обучение)
GRE — overlay мрежа, използваща GRE тунели
VxLAN — overlay мрежа, използваща VxLAN тунели

Mechanism drivers определят средства, които осигуряват организацията на посочените в type 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 не е бил замислен като софтуерен комутатор за високо натоварени телеком функции и е бил повече адаптиран за по-малко изискващи по пропускна способност ИТ функции като уеб сървъри или пощенски сървъри. Въпреки това, OVS се подобрява и текущите реализации на OVS значително са подобрили производителността и възможностите му, което позволява на операторите да го използват с високо натоварени функции, например, съществува реализация на OVS с поддръжка на ускорение DPDK.

Съществуват три важни компонента на OVS, за които е необходимо да се знае:

  • Kernel module — компонент, разположен в пространството на ядрото, който извършва обработка на трафика на базата на получените от управляващия елемент правила;
  • vSwitch демон (ovs-vswitchd) — това е процес, който работи в потребителското пространство и отговаря за програмирането на ядрения модул — тоест представлява логиката на работа на комутатора.
  • Сървър на база данни — локална база данни, разположена на всеки хост, на който работи OVS, в която се съхранява конфигурацията. Чрез този модул SDN контролерите могат да комуникират по протокола OVSDB.

Към всичко това се добавя набор от диагностични и управляващи утилити, като ovs-vsctl, ovs-appctl, ovs-ofctl и т.н.

В момента Openstack се използва широко от телекомуникационни оператори за миграция на мрежови функции, като EPC, SBC, HLR и т.н. Част от функциите може да работят без проблеми с OVS в сегашния си вид, но например EPC обработва трафика на абонатите — тоест пропуска през себе си огромно количество трафик (в момента обемите достигат до няколко стотин гигабита в секунда). Естествено, пропускането на такъв трафик през ядрено пространство (тъй като по подразбиране форвардерът е разположен там) — не е най-добрата идея. Затова често OVS се разгръща изцяло в потребителското пространство, използвайки технологията за ускорение DPDK за пренос на трафик от NIC в потребителското пространство, заобикаляйки ядрото.

Забележка: за облак, разгръщан за телекомуникационни функции, е възможен вариант за извеждане на трафика от компютърния възел, заобикаляйки OVS и директно в комутационно оборудване. За тази цел се използват механизмите SR-IOV и Passthrough.

Как работи това на реален макет?

Сега да преминем към практическата част и да видим как всичко това работи на практика.

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

Тъй като трябва да видим само основната част, можем да не използваме няколко мрежи, а всичко да изградим с използването на само две мрежи, като втората мрежа в този макет ще се използва изключително за достъп до undercloud и DNS сървъра. Външните мрежи няма да засягаме засега — това е тема за отделна голяма статия.

Нека да започнем по реда. Първо малко теория. Ще инсталираме OpenStack с помощта на TripleO (OpenStack на OpenStack). Същността на TripleO е, че инсталираме OpenStack all-in-one (т.е. на една нода), наречен undercloud, и след това използваме възможностите на разгърнатия OpenStack, за да инсталираме OpenStack, предназначен за експлоатация, наречен overcloud. Undercloud ще използва вградени възможности за управление на физически сървъри (bare metal) - проект Ironic - за провизиране на хипервизори, които ще изпълняват роли на compute, control и storage нодове. Тоест, не използваме външни средства за разгръщане на OpenStack - разгръщаме OpenStack с усилията на OpenStack. По-нататък по време на инсталацията ще стане много по-ясно, затова няма да се спираме на това и ще продължим напред.

Забележка: В тази статия за опростяване не използвах мрежова изолация за вътрешните мрежи на OpenStack, а всичко беше разгръщано с помощта само на една мрежа. Въпреки това, наличието или отсъствието на изолация на мрежите не влияе на основната функционалност на решението - всичко ще работи точно така, както при използване на изолация, но трафикът ще минава в една мрежа. За търговски инсталации е естествено необходимо да се използва изолация с различни VLAN-ове и интерфейси. Например, управленският трафик на 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        

  ovs-network-1
  7a2e7de7-fc16-4e00-b1ed-4d190133af67

Тук са обявени три порт групи — две 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 няма да бъде достъпен, тъй като няма vlan тегло. За да се поправи това, трябва да изпълните командата sudo ovs-vsctl set port ovs-br1 tag=100. Обаче след рестартиране, това тегло ще изчезне (ако някой знае как да го запази — ще бъда много благодарен). Но това не е толкова важно, тъй като този адрес ще ни е необходим само по време на инсталацията и няма да ни е нужен, когато Openstack е напълно разположен.

След това създаваме подслон машина:


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 — провижининг мрежа

masquerade — използване на 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 е завършила.

Файлът, съдържащ паролите за тази инсталация, е на
/home/stack/undercloud-passwords.conf.

Има и файл stackrc на /home/stack/stackrc.

Тези файлове са необходими за взаимодействие със сървices на OpenStack и трябва да бъдат
осигурени.

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

Този изход означава, че успешно сте инсталирали undercloud и сега можете да проверите състоянието на undercloud и да преминете към инсталиране на overcloud.

Ако погледнете изхода на ifconfig, ще видите, че се е появил нов бридж интерфейс

[stack@undercloud ~]$ ifconfig
br-ctlplane: flags=4163 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
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 е отделен порт (или споделен порт, но това не е решаващо), то за виртуалните машини такива портове няма. Тук на помощ идва ‚костил‘ наречен vbmc — утилита, която позволява емулиране на IPMI порт. На този нюанс трябва да се обърне особено внимание, особено на тези, които искат да изградят такава лаборатория на хипервизор ESXI — честно казано, не зная дали в него има аналог на vbmc, затова си струва да се замислите за този въпрос, преди да разположите всичко.

Инсталираме vbmc:


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 файла. Трябва да посочим MAC адреса на порта, чрез който ще се извърши провижънинг, параметрите на възлите, да им зададем имена и да укажем как да се свържем с 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" беше качен.
+--------------------------------------+------------------------+-------------+---------+--------+
|                  ID                  |          Name          | Disk Format |   Size  | Status |
+--------------------------------------+------------------------+-------------+---------+--------+
| c2553770-3e0f-4750-b46b-138855b5c385 | overcloud-full-vmlinuz |     aki     | 6761064 | активен |
+--------------------------------------+------------------------+-------------+---------+--------+
Image "overcloud-full-initrd" беше качен.
+--------------------------------------+-----------------------+-------------+----------+--------+
|                  ID                  |          Name         | Disk Format |   Size   | Status |
+--------------------------------------+-----------------------+-------------+----------+--------+
| 949984e0-4932-4e71-af43-d67a38c3dc89 | overcloud-full-initrd |     ari     | 55183045 | активен |
+--------------------------------------+-----------------------+-------------+----------+--------+
Image "overcloud-full" беше качен.
+--------------------------------------+----------------+-------------+------------+--------+
|                  ID                  |      Name      | Disk Format |    Size    | Status |
+--------------------------------------+----------------+-------------+------------+--------+
| a2f2096d-c9d7-429a-b866-c7543c02a380 | overcloud-full |    qcow2    | 1487475712 | активен |
+--------------------------------------+----------------+-------------+------------+--------+
Image "bm-deploy-kernel" беше качен.
+--------------------------------------+------------------+-------------+---------+--------+
|                  ID                  |       Name       | Disk Format |   Size  | Status |
+--------------------------------------+------------------+-------------+---------+--------+
| e413aa78-e38f-404c-bbaf-93e582a8e67f | bm-deploy-kernel |     aki     | 6761064 | активен |
+--------------------------------------+------------------+-------------+---------+--------+
Image "bm-deploy-ramdisk" беше качен.
+--------------------------------------+-------------------+-------------+-----------+--------+
|                  ID                  |        Name       | Disk Format |    Size   | Status |
+--------------------------------------+-------------------+-------------+-----------+--------+
| 5cf3aba4-0e50-45d3-929f-27f025dd6ce3 | bm-deploy-ramdisk |     ari     | 461759376 | активен |
+--------------------------------------+-------------------+-------------+-----------+--------+
(undercloud) [stack@undercloud ~]$

Проверяваме, че всички изображения са качени


(undercloud) [stack@undercloud ~]$  openstack image list
+--------------------------------------+------------------------+--------+
| ID                                   | Name                   | Status |
+--------------------------------------+------------------------+--------+
| e413aa78-e38f-404c-bbaf-93e582a8e67f | bm-deploy-kernel       | активен |
| 5cf3aba4-0e50-45d3-929f-27f025dd6ce3 | bm-deploy-ramdisk      | активен |
| a2f2096d-c9d7-429a-b866-c7543c02a380 | overcloud-full         | активен |
| 949984e0-4932-4e71-af43-d67a38c3dc89 | overcloud-full-initrd  | активен |
| c2553770-3e0f-4750-b46b-138855b5c385 | overcloud-full-vmlinuz | активен |
+--------------------------------------+------------------------+--------+
(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 
Стартовал Mistral Workflow tripleo.baremetal.v1.register_or_update. ID выполнения: d57456a3-d8ed-479c-9a90-dff7c752d0ec
Ожидание сообщений в очереди 'tripleo' без таймаута.


5 узлов(а) успешно переведены в состояние "управляемый".
Успешно зарегистрирован узел UUID b4b2cf4a-b7ca-4095-af13-cc83be21c4f5
Успешно зарегистрирован узел UUID b89a72a3-6bb7-429a-93bc-48393d225838
Успешно зарегистрирован узел UUID 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e
Успешно зарегистрирован узел UUID bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8
Успешно зарегистрирован узел UUID 766ab623-464c-423d-a529-d9afb69d1167
Ожидание завершения интроспекции...
Запущен Mistral Workflow tripleo.baremetal.v1.introspect. ID выполнения: 6b4d08ae-94c3-4a10-ab63-7634ec198a79
Ожидание сообщений в очереди 'tripleo' без таймаута.
Интроспекция узла b89a72a3-6bb7-429a-93bc-48393d225838 завершена. Статус: УСПЕШНО. Ошибки: Нет
Интроспекция узла 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e завершена. Статус: УСПЕШНО. Ошибки: Нет
Интроспекция узла bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 завершена. Статус: УСПЕШНО. Ошибки: Нет
Интроспекция узла 766ab623-464c-423d-a529-d9afb69d1167 завершена. Статус: УСПЕШНО. Ошибки: Нет
Интроспекция узла b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 завершена. Статус: УСПЕШНО. Ошибки: Нет
Успешно проведена интроспекция 5 узлов(а).
Запущен Mistral Workflow tripleo.baremetal.v1.provide. ID выполнения: f5594736-edcf-4927-a8a0-2a7bf806a59a
Ожидание сообщений в очереди 'tripleo' без таймаута.
5 узлов(а) успешно переведены в состояние "доступный".
(undercloud) [stack@undercloud ~]$

Как видно из вывода, все завершилось без ошибок. Давайте проверим, что все узлы находятся в состоянии доступный:


(undercloud) [stack@undercloud ~]$ openstack baremetal node list
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
| UUID                                 | Name      | Instance UUID | Power State | Provisioning State | Maintenance |
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
| b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 | control-1 | None          | выключен    | доступный          | Ложь        |
| b89a72a3-6bb7-429a-93bc-48393d225838 | storage-1 | None          | выключен    | доступный          | Ложь        |
| 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e | storage-2 | None          | выключен    | доступный          | Ложь        |
| bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 | compute-1 | None          | выключен    | доступный          | Ложь        |
| 766ab623-464c-423d-a529-d9afb69d1167 | compute-2 | None          | выключен    | доступный          | Ложь        |
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
(undercloud) [stack@undercloud ~]$ 

Если узлы находятся в другом состоянии, например, управляемом, это может означать, что что-то пошло не так, и необходимо проверить журнал, чтобы выяснить причину. Учтите, что в данном сценарии мы используем виртуализацию, и могут быть ошибки, связанные с использованием виртуальных машин или 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 ~]$

Сега имате почти напълно функционираща версия на OpenStack, на която можете да учите, да провеждате експерименти и т.н.

Нека проверим дали всичко работи нормално. В домашната директория на потребителя 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 heat-admin@192.168.255.15         
Последний вход: Пт 14 авг 09:47:40 2020 с 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 сети
  • Две машины в разных сетях (маршрутизация между сетями)

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

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

Въведение в мрежовата част на облачната инфраструктура

У нас создано 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 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
	hether 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, ситуация изменится, но об этом поговорим в другой раз. При использовании изоляции сетей, например, с помощью VLAN, у вас будет не один L3 интерфейс в 0-ом VLAN, а несколько интерфейсов. Тем не менее, трафик VxLAN будет выходить с ноды также, но инкапсулированный еще в какой-то выделенный VLAN.

С 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 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
        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 тегов, этот порт является транковым портом, на котором разрешены все VLAN. В данный момент трафик выходит наружу без тега, о чем свидетельствует vlan-id 0 в выводе выше.

Въведение в мрежовата част на облачната инфраструктура

Все остальное в данный момент аналогично compute ноде — те же бриджи, те же тоннели, идущие на две compute ноды.

В тази статия няма да разглеждаме съхранителните нодове, но е необходимо да отбележим, че мрежовата част на тези нодове е крайно проста. В нашия случай там има само един физически порт (eth0) с назначен IP адрес и това е всичко. Няма VxLAN тунели, мостове и т.н. — там изобщо няма OVS, тъй като няма смисъл от него. При използване на изолация на мрежите — на този нод ще има два интерфейса (физически портове, bond или просто две VLAN — не е важно — зависи от това, какво искате) — един за управление, втори за трафик (запис на диск 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 — виртуален интерфейс, свързан към инстанс (VM)
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 patch-интерфейси, които свързват 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 сети

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


[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000001
Интерфейс  Тип       Източник   Модел       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
Интерфейс  Тип       Източник   Модел       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 
 порт  VLAN  MAC                Възраст
    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
Интерфейс  Тип       Източник   Модел       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 ~]$ 

MAC адресът е в таблицата за пренос в 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 има MAC адрес на целта:

[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. 0x16 — това е vni в шестнадесетична система. Преобразуваме това число в десетичната система:


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

Така vni отговаря на действителността.

Вторият ред показва обратния трафик, но не е необходимо да го обясняваме, там всичко е ясно.

Две машини в различни мрежи (маршрутизиране между мрежи)

Последният случай за днес — маршрутизиране между мрежи в рамките на един проект с използване на виртуален маршрутизатор. Обсъждаме случай без DVR (който ще разгледаме в друга статия), следователно маршрутизацията се извършва на network нода. В нашия случай 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

Тъй като в този случай пакетът трябва да отиде на шлюза и там да бъде маршрутизиран, трябва да разберем MAC адреса на шлюза, за което ще разгледаме 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 ~]$ 

Който гледа на контролния възел:

[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 ~]$ 

Трафикът стигна до контролния възел, така че трябва да преминем към него и да видим как ще се осъществява маршрутизацията.

Както помните, контролният възел изглеждаше точно така, както и компютърният възел — същите три бриджа, но br-ex имаше физически порт, през който възелът можеше да изпраща трафик навън. Създаването на инстанции промени конфигурацията на компютърните възли — добавиха се linux bridge, iptables и интерфейси във възлите. Създаването на мрежи и виртуален маршрутизатор също остави своя отпечатък върху конфигурацията на контролния възел.

И така, очевидно е, че mac адресът на шлюза трябва да бъде в таблицата за форвардинг на br-int на контролния възел. Нека да проверим дали е там и към какво сочи:

[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 ~]$ 

MAC адресът е видим от порта qr-0c52b15f-8f. Ако се върнем обратно към списъка на виртуалните портове в OpenStack, този тип порт се използва за свързване на OVS с различни виртуални устройства. По-точно qr — това е портът към виртуалния маршрутизатор, който е представен под формата на пространство namenamespace.

Да видим какви namespaces има на сървера:

[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. Нека проверим MAC адреса на порта 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  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
        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 ~]$ 

Всичко е логично, без изненади. Нека видим откъде може да се види MAC адреса на хоста 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, след което ще съберем дъмп на порта на контролния възел и ще се уверим, че трафикът преминава точно както е описано по-горе.
И така, тунелът до 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  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10
        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  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
        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 нода:

Въведение в мрежовата част на облачната инфраструктура

И имайте предвид, че това са само четири машини, две вътрешни мрежи и един виртуален рутер… В момента нямаме външни мрежи, множество различни проекти, всеки с неговите мрежи (които си пресичат), а разпределеният рутер е изключен. В края на краищата, в тестовата среда имаше само един контролен възел (за отказоустойчивост е нужен кворум от три възела). Логично е, че в търговската среда всичко е „малко“ по-сложно, но на този прост пример разбираме как трябва да работи — било то три или триста namespace, това е разбираемо, но от гледна точка на функционирането на цялата конструкция — нищо особено няма да се промени… освен ако не включите някакво вендорско SDN. Но това вече е съвсем друга история.

Надявам се да е било интересно. Ако имате коментари/допълнения или ако някъде съм излъгал откровено (аз съм човек и мнението ми винаги ще бъде субективно) — пишете какво трябва да поправим/добавим — всичко можем да оправим/добавим.

В заключение бих искал да кажа няколко думи за сравнение на Openstack (както ванилов, така и вендорски) с облачното решение на компания VMWare — твърде често ми задаваха този въпрос през последните две години и честно казано вече се уморих от него, но все пак. На мое мнение, много е трудно да се сравнят тези две решения, но може да се каже, че и двете имат недостатъци и при избора на едно от решенията трябва да се преценят всички „за“ и „против“.

Ако OpenStack е решение, ръководено от общността, то 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, иначе ще ви трябва още десетина такива машини — иначе производителността няма да стигне.

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

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster