
Облачните изчисления все повече навлизат в живота ни, и вероятно няма човек, който поне веднъж да не е използвал облачни услуги. Но какво точно е облакът и как работи, малко хора знаят дори на ниво идея. 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, изпълнява определена функция. Тази разпределена архитектура позволява включване в решението на необходимия набор от функционални компоненти. Въпреки това, част от компонентите са основни и тяхното изтриване ще доведе до пълна или частична неработоспособност на решението. Към такъв тип компоненти спадат:
- Дашборд — уеб базиран GUI за управление на OpenStack услугите
- Keystone — централизирана услуга за идентификация, която предоставя функционалност за аутентификация и авторизация за другите услуги, както и управление на потребителските данни и техните роли.
- Neutron е мрежова услуга, осигуряваща свързаност между интерфейсите на различните OpenStack услуги (включително свързаност между VM и достъп до външния свят)
- Cinder осигурява достъп до блочно хранилище за виртуални машини
- Nova — управление жизнения на виртуални машини
- Glance — хранилище на образи на виртуални машини и моментни снимки
- Swift — предоставя достъп до обектно хранилище
- Ceilometer — услуга, която предоставя възможност за събиране на телеметрични данни и измерване на наличните и потребяваните ресурси
- Heat — оркестрация на базата на шаблони за автоматично създаване и предоставяне на ресурси
Пълен списък на всички проекти и тяхното предназначение можете да видите .
Всяка от компонентите на OpenStack е услуга, която отговаря за определена функция и осигурява API за управление на тази функция и взаимодействие на тази услуга с други услуги в облачната операционна система с цел създаване на единна инфраструктура. Например, Nova осигурява управление на изчислителните ресурси и API за достъп до конфигуриране на тези ресурси, Glance – управление на образи и API за управление на тях, Cinder – блочно хранилище и API за управление на него и т.н. Всички функции са много тясно свързани помежду си.
Обаче, ако размислите, всички услуги, стартирани в OpenStack, в крайна сметка представляват някаква виртуална машина (или контейнер), свързана в мрежа. Изниква въпросът — защо ни е толкова много елементи?
Нека да прегледаме алгоритъма за създаване на виртуална машина и свързването ѝ към мрежата и постоянното хранилище в OpenStack.
- Когато подавате заявка за създаване на машина, независимо дали е чрез Horizon (табло) или чрез CLI, първото, което се случва — е удостоверяване на вашата заявка в Keystone — можете ли да създадете машина, имате ли право да използвате тази мрежа, достатъчни ли са квотите на вашия проект и т.н.
- Keystone удостоверява вашата заявка и генерира в отговор auth-токен, който ще бъде използван по-късно. След получаване на отговора от Keystone, заявката се изпраща към Nova (nova api).
- Nova-api проверява валидността на вашата заявка, като се обръща към Keystone, използвайки предварително сгенерирания auth-токен
- Keystone извършва удостоверяване и предоставя информация относно разрешенията и ограниченията на базата на този auth-токен.
- Nova-api създава запис за нова VM в nova-database и предава заявката за създаване на машина към nova-scheduler.
- Nova-scheduler избира хост (компютърна нода), на който VM ще бъде разположена на база зададените параметри, тежести и зони. Записът за това и идентификаторът на VM се записват в nova-database.
- След това nova-scheduler се свързва с nova-compute с искане за разполагане на инстанс. Nova-compute се свързва с nova-conductor за получаване на информация относно параметрите на машината (nova-conductor е елемент на nova, който изпълнява ролята на прокси сървър между nova-database и nova-compute, ограничавайки броя на исканията към nova-database, за да избегне проблеми с консистентността на базата данни и да намали натоварването).
- Nova-conductor получава исканата информация от nova-database и я предава на nova-compute.
- След това nova-compute се свързва с glance за получаване на ID на образа. Glance извършва проверка на валидността на искането в Keystone и връща исканата информация.
- Nova-compute се свързва с neutron за получаване информация относно параметрите на мрежата. Подобно на glance, neutron извършва проверка на валидността на искането в Keystone, след което създава запис в базата данни (идентификатор на порта и т.н.), създава искане за създаване на порт и връща исканата информация обратно на nova-compute.
- Nova-compute се свързва с cinder с искане за предоставяне на том на виртуалната машина. Подобно на glance, cinder извършва проверка на валидността на искането в Keystone, създава искане за създаване на том и връща исканата информация.
- 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 мрежовата служба:
- Създава порт за тази VM (или портове) и уведомява за това DHCP услугата;
- Създава се ново виртуално мрежово устройство (чрез libvirt);
- 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
