Introduzione alla parte di rete dell'infrastruttura cloud

Introduzione alla parte di rete dell'infrastruttura cloud

Il cloud computing sta penetrando sempre di più nella nostra vita e quasi sicuramente non c'è nessuna persona che non abbia mai utilizzato qualche servizio cloud. Ma cosa significa realmente "cloud" e come funziona? Molti lo sanno solo a livello concettuale. La tecnologia 5G diventa una realtà e l'infrastruttura telecomunicativa inizia a passare dalle soluzioni tradizionali a quelle cloud, proprio come avvenne in passato con l'evoluzione da soluzioni puramente hardware a pilastri virtualizzati.

Oggi parleremo del mondo interno dell'infrastruttura cloud, esaminando in particolare le basi della parte di rete.

Cosa significa "cloud"? È semplicemente la virtualizzazione vista da un'altra angolazione?

È una domanda più che logica. No, non è solo virtualizzazione, anche se è parte del processo. Consideriamo due definizioni:

Il cloud computing (d'ora in poi "Cloud") è un modello di fornitura di accesso user-friendly a risorse computazionali distribuite, che devono essere implementate e avviate su richiesta con la minima latenza possibile e i costi minimi per il fornitore di servizi.

Virtualizzazione — è la possibilità di suddividere un'unica entità fisica (ad esempio un server) in più entità virtuali, aumentando così l'utilizzo delle risorse (ad esempio, se avevi 3 server caricati al 25-30%, dopo la virtualizzazione ottieni 1 server caricato all'80-90%). Naturalmente, la virtualizzazione consuma una parte delle risorse — devi alimentare l'ipervisor, tuttavia, come ha dimostrato la pratica, ne vale la pena. Un esempio ideale di virtualizzazione è VMWare, che prepara ottimamente le macchine virtuali, oppure KVM, che preferisco, ma questo è una questione di gusto.

Utilizziamo la virtualizzazione senza nemmeno rendercene conto; anche i router hardware utilizzano già la virtualizzazione — ad esempio, nelle ultime versioni di JunOS il sistema operativo è installato come una macchina virtuale sopra una distribuzione di linux in tempo reale (Wind River 9). Ma la virtualizzazione non è il cloud, tuttavia il cloud non può esistere senza virtualizzazione.

La virtualizzazione è uno dei mattoni su cui si costruisce il cloud.

Creare un cloud semplicemente raccogliendo alcuni hypervisor in un unico dominio L2, aggiungendo un paio di playbook YAML per la configurazione automatica delle VLAN tramite Ansible e applicando sopra tutto un sistema di orchestrazione per la creazione automatica di macchine virtuali, non funzionerà. Anzi, funzionerà, ma il risultato sarà un Frankenstein che non è il cloud di cui abbiamo bisogno, anche se per alcuni potrebbe rappresentare il sogno ideale. Inoltre, se consideriamo OpenStack, esso stesso è un certo tipo di Frankenstein, ma per ora non approfondiamo.

Ma capisco che dalla definizione sopra non è chiaro cosa si possa realmente definire come cloud.

Perciò, nel documento del NIST (National Institute of Standards and Technology) sono indicate 5 caratteristiche fondamentali che deve possedere un'infrastruttura cloud:

Fornitura del servizio su richiesta. All'utente deve essere garantito un accesso libero alle risorse informatiche a lui dedicate (come reti, dischi virtuali, memoria, core dei processori, ecc.), e queste risorse devono essere fornite automaticamente, senza l'intervento del fornitore del servizio.

Ampia disponibilità del servizio. L'accesso alle risorse deve essere garantito tramite meccanismi standard, in modo da consentire l'uso sia di PC standard che di client leggeri e dispositivi mobili.

Unione delle risorse in pool. I pool di risorse devono garantire la fornitura simultanea di risorse a più clienti, assicurando l'isolamento dei clienti e l'assenza di influenze reciproche tra di loro e di competizione per le risorse. I pool includono anche le reti, il che indica la possibilità di utilizzare indirizzamento incrociato. I pool devono supportare la scalabilità a richiesta. L'uso dei pool consente di garantire il livello necessario di resilienza delle risorse e l'astrazione delle risorse fisiche e virtuali: al destinatario del servizio viene semplicemente fornito il set di risorse richiesto (dove queste risorse sono fisicamente situate, su quanti server e switch - non importa al cliente). Tuttavia, è importante tenere presente che il fornitore deve garantire un'adeguata riserva per queste risorse.

Flessibilità rapida per adattarsi a diverse condizioni. I servizi devono essere flessibili: fornire rapidamente risorse, ridistribuirle, aggiungere o ridurre risorse su richiesta del cliente, facendo sì che il cliente senta che le risorse del cloud siano infinite. Per semplificare, ad esempio, non ricevi avvisi su spazio su disco mancante in Apple iCloud a causa di un malfunzionamento del disco rigido sul server, e i dischi possono rompersi. Inoltre, le possibilità di questo servizio dall'altra parte sono praticamente illimitate: se hai bisogno di 2 TB, non è un problema, paghi e ottieni. Un esempio analogo può essere fatto con Google Drive o Yandex.Disk.

Possibilità di misurare il servizio fornito. I sistemi cloud devono monitorare e ottimizzare automaticamente le risorse consumate; tali meccanismi devono essere trasparenti sia per l'utente che per il fornitore di servizi. Ciò significa che puoi sempre verificare quante risorse tu e i tuoi clienti state consumando.

È importante considerare che questi requisiti sono per la maggior parte quelli del cloud pubblico; pertanto, per un cloud privato (cioè un cloud attivato per le esigenze interne dell'azienda) questi requisiti possono essere leggermente modificati. Tuttavia, devono comunque essere rispettati, altrimenti non otterremo tutti i vantaggi del cloud computing.

Perché abbiamo bisogno del cloud?

Tuttavia, ogni nuova tecnologia o protocollo esistente viene creato per uno scopo (tranne ovviamente RIP-ng). Un protocollo puramente per il protocollo non serve a nessuno (tranne ovviamente RIP-ng). È logico che il Cloud venga creato per fornire un servizio all'utente/cliente. Tutti noi siamo familiari con almeno un paio di servizi cloud, come Dropbox o Google.Docs, e suppongo che la maggior parte ne faccia uso con successo: ad esempio, questo articolo è stato scritto utilizzando il servizio cloud Google.Docs. Ma i noti servizi cloud rappresentano solo una parte delle possibilità del cloud: più precisamente, sono solo un tipo di servizio SaaS. Possiamo fornire un servizio cloud in tre modi: come SaaS, PaaS o IaaS. Quale servizio sia necessario per voi dipende dai vostri desideri e possibilità.

Esaminiamo ciascuno nel dettaglio:

Software as a Service (SaaS) — è un modello di fornitura di servizi completo per il cliente, come ad esempio il servizio di posta elettronica Yandex.Mail o Gmail. In questo modello, come cliente non devi preoccuparti di nulla, se non dell'uso del servizio: non devi pensare alla configurazione, all'affidabilità del servizio o al backup. L'importante è non compromettere la tua password; il provider del servizio si occuperà di tutto il resto. Dal punto di vista del fornitore, è responsabile completamente dell'intero servizio, partendo dall'hardware del server e dai sistemi operativi host, fino alla configurazione dei database e del software.

Platform as a Service (PaaS) — utilizzando questo modello, il fornitore di servizi fornisce al cliente un template per il servizio, ad esempio prendiamo un server Web. Il fornitore ha fornito al cliente un server virtuale (in realtà un insieme di risorse, come RAM/CPU/Storage/Nets, ecc.), e ha persino installato su questo server il sistema operativo e il software necessario, tuttavia la configurazione di tutto questo compito è a carico del cliente e la responsabilità per il corretto funzionamento del servizio ricade già sul cliente. Il fornitore, come nel caso precedente, è responsabile per il funzionamento dell'hardware fisico, degli ipervisor, della macchina virtuale stessa, della sua disponibilità in rete, ecc., ma il servizio stesso è già al di fuori della sua responsabilità.

Infrastructure as a Service (IaaS) — questo approccio è già più interessante, in quanto il fornitore di servizi offre al cliente un'intera infrastruttura virtualizzata, cioè un insieme (pool) di risorse come CPU Cores, RAM, Reti, ecc. Tutto il resto è compito del cliente: cosa vuole fare con queste risorse all'interno del pool a lui assegnato (quota) non è particolarmente rilevante per il fornitore. Se il cliente desidera creare il proprio vEPC o addirittura diventare un mini operatore e fornire servizi di telecomunicazione, nessun problema: può farlo. In questo scenario, il fornitore di servizi è responsabile della fornitura delle risorse, della loro resilienza e disponibilità, oltre che del sistema operativo che consente di aggregare queste risorse in pool e fornirle al cliente con la possibilità di aumentare o diminuire le risorse su richiesta. Tutte le macchine virtuali e altro sono configurate dal cliente tramite il portale di self-service e la console, inclusa la configurazione delle reti (eccetto le reti esterne).

Che cos'è OpenStack?

In tutte e tre le opzioni, il fornitore di servizi ha bisogno di un sistema operativo che consenta di creare un'infrastruttura cloud. Infatti, nel caso del SaaS, non è un solo reparto a gestire l'intero stack tecnologico: esiste un reparto che si occupa dell'infrastruttura, fornendo IaaS a un altro reparto, che a sua volta offre SaaS ai clienti. OpenStack è uno dei sistemi operativi cloud che consente di aggregare vari switch, server e sistemi di storage in un unico pool di risorse, dividere questo pool generale in sottopool (tenant) e fornire queste risorse ai clienti tramite la rete.

OpenStack è un sistema operativo cloud che consente di controllare grandi pool di risorse di calcolo, storage e risorse di rete, la cui provisioning e gestione avvengono tramite API utilizzando meccanismi di autenticazione standard.

In altre parole, si tratta di un insieme di progetti di software libero progettati per creare servizi cloud, sia pubblici che privati; un insieme di strumenti che consente di unire l'hardware server e di rete in un'unica risorsa, gestendo queste risorse e garantendo il necessario livello di tolleranza ai guasti.

Al momento della stesura di questo materiale, la struttura di OpenStack appare così:
Introduzione alla parte di rete dell'infrastruttura cloud
L'immagine è presa da openstack.org

Ogni componente che fa parte di OpenStack svolge una funzione specifica. Questa architettura distribuita consente di includere nel soluzionare il set di componenti funzionali di cui hai bisogno. Tuttavia, alcune componenti sono considerate componenti fondamentali e la loro rimozione porterà a un malfunzionamento totale o parziale della soluzione nel suo complesso. Componenti come questi sono comunemente referenziati come:

  • Dashboard — GUI basata sul web per gestire i servizi OpenStack
  • Keystone — servizio di identificazione centralizzato che fornisce funzionalità di autenticazione e autorizzazione per altri servizi, oltre a gestire le credenziali degli utenti e i loro ruoli.
  • Neutron — servizio di rete che garantisce connettività tra le interfacce dei vari servizi OpenStack (inclusa la connettività tra VM e il loro accesso al mondo esterno)
  • Cinder — fornisce accesso a storage a blocchi per le macchine virtuali
  • Nova — gestione del ciclo di vita delle macchine virtuali
  • Glance — repository di immagini di macchine virtuali e snapshot
  • Swift — fornisce accesso a storage oggetti
  • Ceilometer — servizio che offre la possibilità di raccogliere telemetria e misurare le risorse disponibili e consumate
  • Heat — orchestrazione basata su modelli per la creazione automatica e il provisioning delle risorse

Puoi visualizzare l'elenco completo di tutti i progetti e il loro scopo qui.

Ogni componente di OpenStack è un servizio che svolge una funzione specifica e fornisce API per gestire tale funzione e per l'interazione di questo servizio con altri servizi del sistema operativo cloud, al fine di creare un'infrastruttura unica. Ad esempio, Nova gestisce le risorse di calcolo e fornisce API per accedere alla configurazione di tali risorse; Glance gestisce le immagini e offre API per la loro gestione; Cinder si occupa dello storage a blocchi e fornisce API per la sua gestione, e così via. Tutte le funzioni sono strettamente collegate tra loro.

Tuttavia, se ci si riflette, tutti i servizi che girano in OpenStack rappresentano sostanzialmente una sorta di macchina virtuale (o contenitore) collegata alla rete. Si pone la domanda: perché abbiamo bisogno di così tanti elementi?

Esaminiamo l'algoritmo per la creazione di una macchina virtuale e il suo collegamento alla rete e allo storage persistente in OpenStack.

  1. Quando crei una richiesta per la creazione di una macchina, sia tramite Horizon (Dashboard) che tramite CLI, la prima cosa che avviene è l'autenticazione della tua richiesta su Keystone: puoi creare una macchina, hai il diritto di utilizzare questa rete, hai quota sufficiente per il tuo progetto, ecc.
  2. Keystone autentica la tua richiesta e genera in risposta un token auth, che sarà utilizzato in seguito. Dopo aver ricevuto la risposta da Keystone, la richiesta viene inviata a Nova (nova api).
  3. Nova-api verifica la validità della tua richiesta contattando Keystone, utilizzando il token auth precedentemente generato.
  4. Keystone esegue l'autenticazione e fornisce, sulla base di questo token auth, informazioni relative ai permessi e alle limitazioni.
  5. Nova-api crea un record nella nova-database per la nuova VM e invia la richiesta per la creazione della macchina a nova-scheduler.
  6. Nova-scheduler seleziona l'host (nodo computazionale) su cui la VM verrà implementata in base ai parametri forniti, ai pesi e alle zone. Record di questo e l'identificativo della VM vengono registrati nella nova-database.
  7. Successivamente, nova-scheduler richiede a nova-compute di avviare un'istanza. Nova-compute si rivolge a nova-conductor per ottenere informazioni sui parametri della macchina (nova-conductor è un elemento di nova che funge da server proxy tra nova-database e nova-compute, limitando il numero di richieste verso nova-database per evitare problemi di coerenza del database e ridurre il carico).
  8. Nova-conductor riceve le informazioni richieste da nova-database e le trasmette a nova-compute.
  9. Successivamente, nova-compute si rivolge a glance per ottenere l'ID dell'immagine. Glance valida la richiesta in Keystone e restituisce le informazioni richieste.
  10. Nova-compute si rivolge a neutron per ottenere informazioni sui parametri di rete. Analogamente a glance, neutron valida la richiesta in Keystone, quindi crea una registrazione nel database (ID della porta, ecc.), crea una richiesta per la creazione della porta e restituisce le informazioni richieste a nova-compute.
  11. Nova-compute richiede a cinder l'allocazione di un volume per la macchina virtuale. Analogamente a glance, cinder valida la richiesta in Keystone, crea una richiesta per la creazione del volume e restituisce le informazioni richieste.
  12. Nova-compute si rivolge a libvirt con una richiesta per il provisioning di una macchina virtuale con i parametri specificati.

A prima vista, sembra che l'operazione di creazione di una semplice macchina virtuale sia un processo piuttosto semplice, ma in realtà si trasforma in un vortice di chiamate API tra gli elementi della piattaforma cloud. Come potete vedere, anche i servizi precedentemente menzionati sono composti da componenti più piccole tra cui avviene l'interazione. Creare una macchina è solo una piccola parte di ciò che una piattaforma cloud può fare: ci sono servizi per il bilanciamento del carico, per lo storage a blocchi, per il DNS, per il provisioning dei server bare metal, ecc. Il cloud consente di considerare le vostre macchine virtuali come un branco di pecore (a differenza della virtualizzazione tradizionale). Se in un ambiente virtuale qualcosa accade a una macchina, la ripristinate dai backup, mentre le applicazioni cloud sono costruite in modo tale che le macchine virtuali non giochino un ruolo così cruciale: se una macchina virtuale "muore", non è un problema: semplicemente si crea una nuova macchina basata su un template e, come si suol dire, la squadra non nota la perdita di un soldato. Ovviamente, questo richiede l'esistenza di meccanismi di orchestrazione: utilizzando i template Heat, è possibile implementare senza problemi funzioni complesse composte da decine di reti e macchine virtuali.

È importante ricordare che l'infrastruttura cloud non esiste senza rete: ogni elemento interagisce in qualche modo con altri elementi attraverso la rete. Inoltre, la rete cloud non è affatto statica. Naturalmente, la rete di underlay è relativamente statica — non si aggiungono nuovi nodi e switch ogni giorno, tuttavia, la componente di overlay può e inevitabilmente cambierà costantemente: si aggiungeranno o rimuoveranno nuove reti, appariranno nuove macchine virtuali e altre smetteranno di esistere. Come ricorderete dalla definizione di cloud fornita all'inizio dell'articolo, le risorse devono essere allocate all'utente in modo automatico e con il minor intervento possibile (o meglio, senza intervento) da parte del fornitore di servizi. Quindi, il tipo di erogazione delle risorse di rete attualmente presente nel frontend del vostro pannello personale accessibile tramite http/https e l'ingegnere di rete di turno, Vasiliy, come backend — non è cloud, anche in presenza delle otto braccia di Vasiliy.

Neutron, essendo un servizio di rete, fornisce un'API per la gestione della parte di rete dell'infrastruttura cloud. Questo servizio garantisce il funzionamento e la gestione della rete di OpenStack, fornendo un livello di astrazione chiamato Network-as-a-Service (NaaS). In altre parole, la rete è un'unità virtuale misurabile proprio come i core virtuali della CPU o la quantità di RAM.

Prima di passare all'architettura della parte di rete di OpenStack, vediamo come questa rete funziona in OpenStack e perché la rete è una parte importante e indispensabile del cloud.

Quindi, abbiamo due macchine virtuali del cliente RED e due macchine virtuali del cliente GREEN. Supponiamo che queste macchine siano disposte su due hypervisor in questo modo:

Introduzione alla parte di rete dell'infrastruttura cloud

Al momento si tratta semplicemente della virtualizzazione di 4 server e non di più, poiché finora ciò che abbiamo fatto è virtualizzare 4 server, collocandoli su due server fisici. Inoltre, al momento non sono nemmeno collegati alla rete.

Per creare un cloud è necessario aggiungere alcuni componenti. Innanzitutto, dobbiamo virtualizzare la parte di rete: dobbiamo collegare queste 4 macchine a coppie, e i clienti vogliono esattamente una connessione L2. Si può utilizzare un commutatore e configurarlo per un trunk, gestendo il tutto tramite un bridge Linux, oppure per utenti più avanzati, openvswitch (di cui parleremo più avanti). Tuttavia, possono esserci molte reti e spingere continuamente L2 attraverso uno switch non è la soluzione migliore: comporta vari problemi, come le richieste dei reparti, il servizio clienti, i mesi di attesa per l'approvazione e le settimane di troubleshooting. Nel mondo moderno, questo approccio è obsoleto. Più presto un'azienda lo comprende, più facile sarà per essa progredire. Pertanto, tra i hypervisors dedicheremo una rete L3 attraverso la quale comunicheranno le nostre macchine virtuali, e costruiremo reti L2 sovrapposte (overlay) su questa rete L3, dove transiterà il traffico delle nostre macchine virtuali. Possiamo utilizzare GRE, Geneve o VxLAN per l'incapsulamento. Fermiamoci per ora sull'ultimo, anche se non è particolarmente importante.

Dobbiamo posizionare da qualche parte il VTEP (spero che tutti siano familiari con la terminologia VxLAN). Poiché dai server esce subito una rete L3, non abbiamo alcun problema a posizionare il VTEP sui server stessi, e OVS (OpenvSwitch) fa questo in modo eccellente. Alla fine abbiamo ottenuto una costruzione di questo tipo:

Introduzione alla parte di rete dell'infrastruttura cloud

Poiché il traffico tra le VM deve essere separato, le porte verso le macchine virtuali avranno numeri VLAN diversi. Il numero del tag ha importanza solo all'interno di uno stesso switch virtuale, in quanto durante l'incapsulamento in VxLAN possiamo rimuoverlo senza problemi, poiché avremo il VNI.

Introduzione alla parte di rete dell'infrastruttura cloud

Ora possiamo creare le nostre macchine e le reti virtuali per esse senza alcun problema.

Tuttavia, cosa succede se il cliente ha un'altra macchina, ma si trova in un'altra rete? Abbiamo bisogno di routing tra le reti. Esamineremo un'opzione semplice, quando si utilizza il routing centralizzato — cioè il traffico viene instradato attraverso nodi di rete dedicati (di solito sono anche collegati ai nodi di controllo, quindi avremo lo stesso).

Sembra semplice: creiamo un'interfaccia bridge sul nodo di controllo, instradando il traffico verso di essa e da lì lo reindirizziamo dove necessario. Tuttavia, il problema è che il cliente RED desidera utilizzare la rete 10.0.0.0/24, e il cliente GREEN vuole utilizzare la rete 10.0.0.0/24. Questo significa che ci sono sovrapposizioni negli spazi indirizzo. Inoltre, i clienti non vogliono che altri clienti possano interagire con le loro reti interne, il che è logico. Per separare le reti e il traffico dei dati dei clienti, assegneremo a ciascuno di essi un namespace separato. Un namespace è di fatto una copia dello stack di rete di Linux, quindi i clienti nel namespace RED sono completamente isolati dai clienti nel namespace GREEN (o la routing tra queste reti può essere autorizzata attraverso il namespace predefinito o sui dispositivi di trasporto superiori).

Dunque otteniamo questo schema:

Introduzione alla parte di rete dell'infrastruttura cloud

I tunnel L2 convergono da tutti i nodi di calcolo verso il nodo di controllo, dove si trova l'interfaccia L3 per queste reti, ciascuna in un namespace dedicato per l'isolamento.

Tuttavia, abbiamo dimenticato la cosa più importante. La macchina virtuale deve fornire un servizio al cliente, ossia deve avere almeno un'interfaccia esterna attraverso la quale è possibile accedervi. Dobbiamo quindi uscire nel mondo esterno. Ci sono diverse opzioni. Creiamo la soluzione più semplice. Aggiungiamo ai clienti una rete ciascuno, che sarà valida nella rete del fornitore e non si sovrapporrà con altre reti. Le reti possono anche sovrapporsi e puntare a diversi VRF nella rete del fornitore. Queste reti vivranno anche nel namespace di ciascun cliente. Tuttavia, usciranno comunque nel mondo esterno tramite un'unica interfaccia fisica (o un bond, che è più logico). Per separare il traffico dei clienti, il traffico in uscita sarà contrassegnato con un tag VLAN dedicato al cliente.

Di conseguenza, abbiamo ottenuto il seguente schema:

Introduzione alla parte di rete dell'infrastruttura cloud

Una domanda ragionevole è: perché non creare gateway direttamente sulle nodi compute? Non ci sono grandi problemi, anzi, con l'attivazione del router distribuito (DVR) funzionerà esattamente in questo modo. In questo scenario stiamo considerando la soluzione più semplice con un gateway centralizzato, che è utilizzato di default in Openstack. Per funzioni ad alto carico si utilizzeranno sia il router distribuito sia tecnologie di accelerazione come SR-IOV e Passthrough, ma come si suol dire, questa è un'altra storia. Iniziamo a esaminare la parte base e poi approfondiremo i dettagli.

La nostra schema è già funzionante, ma ci sono un paio di dettagli:

  • Dobbiamo in qualche modo proteggere le nostre macchine, ovvero applicare un filtro sull'interfaccia dello switch verso il cliente.
  • Consentire il recupero automatico dell'indirizzo IP da parte della macchina virtuale, in modo da non dover accedere ogni volta tramite la console per impostare l'indirizzo.

Iniziamo dalla protezione delle macchine. Possiamo utilizzare dei semplici iptables, perché no.

Quindi ora la nostra topologia è già un po' più complessa:

Introduzione alla parte di rete dell'infrastruttura cloud

Andiamo avanti. Dobbiamo aggiungere un server DHCP. Il posto ideale per collocare i server DHCP per ciascun cliente sarà il nodo di controllo sopra menzionato, dove sono situati gli spazi dei nomi:

Introduzione alla parte di rete dell'infrastruttura cloud

Tuttavia, c'è un piccolo problema. E se tutto si riavviasse e tutte le informazioni sul noleggio degli indirizzi sul DHCP venissero perse? È logico che alle macchine verranno assegnati nuovi indirizzi, il che non è molto comodo. Ci sono due soluzioni: o usare nomi di dominio e aggiungere un server DNS per ciascun cliente, in tal caso l'indirizzo non sarà particolarmente rilevante (in analogia con la parte di rete in k8s) — ma qui sorge un problema con le reti esterne, poiché anche in esse gli indirizzi possono essere assegnati tramite DHCP — è necessaria una sincronizzazione tra i server DNS della piattaforma cloud e il server DNS esterno, il che, a mio avviso, non è molto flessibile, ma è assolutamente possibile. Oppure, la seconda opzione — usare i metadati — cioè mantenere informazioni sull'indirizzo fornito alla macchina in modo che il server DHCP sappia quale indirizzo assegnare se la macchina ha già ricevuto un indirizzo. La seconda opzione è più semplice e flessibile, poiché consente di conservare informazioni aggiuntive sulla macchina. Ora aggiungiamo alla scheda l'agente dei metadati:

Introduzione alla parte di rete dell'infrastruttura cloud

Un altro aspetto da considerare è la possibilità di utilizzare una singola rete esterna per tutti i clienti. Poiché le reti esterne, se devono essere valide per tutta la rete, presentano delle complessità — è necessario continuamente allocare e controllare l'assegnazione di queste reti. L'uso di una rete preconfigurata unica per tutti i clienti sarebbe molto utile nella creazione di un cloud pubblico. Questo semplificherebbe il dispiegamento delle macchine, poiché non sarebbe necessario fare riferimento a un database degli indirizzi e selezionare uno spazio di indirizzi unico per la rete esterna di ciascun cliente. Inoltre, possiamo configurare in anticipo la rete esterna, e al momento del dispiegamento sarà sufficiente associare gli indirizzi esterni alle macchine dei clienti.

E qui entra in gioco il NAT: semplicemente consentiamo ai clienti di connettersi al mondo esterno tramite il namespace predefinito utilizzando la traduzione NAT. Tuttavia, qui c'è un piccolo problema. Va bene se il server del cliente agisce come client, e non come server — cioè, deve avviare e non accettare connessioni. Ma noi avremo il contrario. In quel caso, dobbiamo implementare il destination NAT, in modo che, al ricevimento del traffico, il nodo di controllo comprenda che tale traffico è destinato alla macchina virtuale A del cliente A, e di conseguenza dobbiamo realizzare una traduzione NAT dall'indirizzo esterno, ad esempio 100.1.1.1, all'indirizzo interno 10.0.0.1. In tal modo, pur utilizzando la stessa rete, l'isolamento interno rimane completamente preservato. Quindi, dobbiamo implementare dNAT e sNAT sul nodo di controllo. L'uso di una rete unica con indirizzi fluttuanti o reti esterne o entrambi contemporaneamente dipende da cosa volete portare nel cloud. Non andremo a segnare sulla mappa anche gli indirizzi fluttuanti, lasciando le reti esterne già aggiunte in precedenza — ogni cliente ha la propria rete esterna (indicate nello schema come VLAN 100 e 200 sull'interfaccia esterna).

Alla fine abbiamo ottenuto una soluzione interessante e ben congegnata, caratterizzata da una certa flessibilità ma priva di meccanismi di tolleranza agli errori.

Innanzitutto abbiamo solo un nodo di controllo: la sua uscita comporterebbe il fallimento di tutti i sistemi. Per risolvere questo problema, è necessario creare almeno un quorum di 3 nodi. Aggiungiamo questo allo schema:

Introduzione alla parte di rete dell'infrastruttura cloud

Naturalmente, tutti i nodi si sincronizzano e, in caso di uscita di un nodo attivo, le sue funzioni saranno assunte da un altro nodo.

Il problema successivo riguarda i dischi delle macchine virtuali. Attualmente, sono memorizzati sui hypervisor stessi e, in caso di problemi con l'hypervisor, perdiamo tutti i dati: avere un RAID qui non aiuta affatto se perdiamo non solo un disco, ma l'intero server. Per questo motivo, dobbiamo creare un servizio che agisca come front-end per qualche tipo di storage. Non ci interessa particolarmente quale sia questo storage, ma deve proteggere i nostri dati da guasti sia del disco che del nodo, e forse anche dell'intero armadio. Ci sono diverse opzioni: esistono naturalmente reti SAN con Fiber Channel, ma diciamolo chiaramente: FC è un retaggio del passato, analogo all'E1 nel trasporto; certo, è ancora utilizzato, ma solo dove è assolutamente indispensabile. Quindi, istituire volontariamente una rete FC nel 2020 non è qualcosa che farei, conoscendo l'esistenza di altre alternative più interessanti. Anche se ognuno ha le proprie opinioni e ci possono essere persone che credono che FC, con tutte le sue limitazioni, sia tutto ciò di cui abbiamo bisogno; non discuterò su questo, ognuno ha la propria idea. Tuttavia, la soluzione più interessante secondo me è l'uso di SDS, come ad esempio Ceph.

Ceph consente di costruire soluzioni di archiviazione ad alta disponibilità con una vasta gamma di opzioni di ripristino, a partire dai codici con controllo di parità (equivalente a RAID 5 o 6), fino alla replica completa dei dati su dischi diversi, considerando la posizione dei dischi nei server e dei server nei rack, e così via.

Per assemblare Ceph servono altre 3 nodi. L'interazione con lo storage avverrà tramite rete utilizzando servizi di archiviazione a blocchi, oggetti e file. Aggiungiamo allo schema di archiviazione:

Introduzione alla parte di rete dell'infrastruttura cloud

Nota: è possibile creare nodi compute iperconvergenti — è il concetto di unire più funzioni in un unico nodo — ad esempio storage + compute — senza dedicare nodi specifici per lo storage Ceph. Otterremo uno schema di alta disponibilità perché SDS riserverà i dati con il livello di ridondanza da noi specificato. Tuttavia, i nodi iperconvergenti comportano sempre un compromesso — poiché un nodo di storage non si limita a 'scaldare l'aria' come potrebbe sembrare a prima vista (dato che non ospita macchine virtuali) — consuma risorse CPU per gestire SDS (infatti, opera in background eseguendo tutte le replicazioni, i ripristini dopo guasti dei nodi, dei dischi, ecc.). Questo significa che perderai parte della potenza del nodo compute se lo combini con lo storage.

Tutti questi elementi devono essere gestiti in qualche modo — è necessario un sistema attraverso il quale possiamo creare macchine, reti, router virtuali, ecc. A tal fine, aggiungeremo un servizio al nodo di controllo che svolgerà la funzione di dashboard — il cliente potrà connettersi a questo portale tramite http/https e fare tutto ciò di cui ha bisogno (quasi).

Alla fine, ora abbiamo un sistema resistente ai guasti. È necessario gestire in qualche modo tutti gli elementi di questa infrastruttura. È stato precedentemente descritto che OpenStack è un insieme di progetti, ognuno dei quali fornisce una specifica funzione. Come possiamo vedere, ci sono più che abbastanza elementi da configurare e controllare. Oggi parleremo della parte di rete.

Architettura Neutron

In OpenStack, Neutron è responsabile della connessione delle porte delle macchine virtuali alla rete L2 comune, della gestione del routing del traffico tra VM situate in diverse reti L2 e del routing verso l'esterno, fornendo servizi come NAT, Floating IP, DHCP, ecc.

Possiamo descrivere a un livello alto il funzionamento del servizio di rete (parte di base) in questo modo.

Quando viene avviata una VM, il servizio di rete:

  1. Crea una porta per questa VM (o porte) e ne informa il servizio DHCP;
  2. Viene creato un nuovo dispositivo di rete virtuale (attraverso libvirt);
  3. La VM si connette alla porta (o alle porte) creata al passo 1;

Stranamente, alla base del funzionamento di Neutron ci sono meccanismi standard conosciuti da chiunque abbia mai esplorato Linux: namespaces, iptables, ponti Linux, openvswitch, conntrack, ecc.

È importante chiarire subito che Neutron non è un controller SDN.

Neutron è composto da diversi componenti interconnessi:

Introduzione alla parte di rete dell'infrastruttura cloud

openstack-neutron-server è un demone che lavora con le richieste degli utenti tramite API. Questo demone non si occupa di definire le connessioni di rete, ma fornisce le informazioni necessarie ai suoi plugin, che configurano quindi l'elemento di rete richiesto. Gli agenti Neutron sui nodi OpenStack si registrano sul server Neutron.

Neutron-server è in sostanza un'applicazione scritta in Python, composta da due parti:

  • Servizio REST
  • Plugin Neutron (core/service)

Il servizio REST è destinato a ricevere chiamate API dagli altri componenti (ad esempio, richieste per fornire determinate informazioni, ecc.)

I plugin sono componenti/moduli software collegabili che vengono richiamati durante le richieste API, quindi l'aggiunta di un servizio avviene tramite di essi. I plugin si suddividono in due categorie: plugin di servizio e plugin core. Di solito, il plugin core si occupa principalmente della gestione dello spazio indirizzi e delle connessioni L2 tra VM, mentre i plugin di servizio forniscono funzionalità aggiuntive, come VPN o FW.

È possibile visualizzare l'elenco dei plugin disponibili oggi, ad esempio qui

Possono esserci diversi plugin di servizio, ma ci può essere solo un plugin principale.

Openstack-neutron-ml2 è il plugin principale standard di Openstack. Questo plugin ha un'architettura modulare (a differenza del suo predecessore) e configura il servizio di rete attraverso i driver che vi si collegano. Esamineremo il plugin più avanti, poiché in effetti fornisce la flessibilità che OpenStack ha nella sua parte di rete. Il plugin principale può essere sostituito (ad esempio Contrail Networking effettua tale sostituzione).

Il servizio RPC (rabbitmq-server) è un servizio che gestisce le code e facilita l'interazione con altri servizi di OpenStack, nonché l'interazione tra gli agenti del servizio di rete.

Agenti di rete sono agenti localizzati in ciascun nodo, attraverso i quali viene configurato il servizio di rete.

Ci sono diversi tipi di agenti.

L'agente principale è l'agente L2. Questi agenti vengono avviati su ciascun hypervisor, comprese le nodi di controllo (più precisamente su tutti i nodi che offrono qualche servizio ai tenant), e la loro funzione principale è connettere le macchine virtuali alla rete L2 comune e generare avvisi in caso di eventi (ad esempio, disconnessione/riconnessione di una porta).

Un altro agente, altrettanto importante, è l'agente L3. Per impostazione predefinita, questo agente viene avviato esclusivamente sul nodo di rete (spesso il nodo di rete è combinato con il nodo di controllo) e gestisce il routing tra le reti dei tenant (sia tra le reti dei tenant e quelle di altri tenant, sia verso il mondo esterno, fornendo NAT e anche il servizio DHCP). Tuttavia, con l'uso di DVR (router distribuito), la necessità del plugin L3 si presenta anche sui nodi di calcolo.

L'agente L3 utilizza i namespace di Linux per fornire a ciascun tenant un insieme di reti isolate e la funzionalità di router virtuali, che instradano il traffico e forniscono servizi di gateway per le reti di Layer 2.

Database — un database di identificatori di reti, sottoreti, porte, pool, ecc.

In effetti, Neutron riceve richieste API per la creazione di entità di rete, autentica la richiesta e, tramite RPC (se si rivolge a un plugin o agente) o REST API (se comunica in SDN), trasmette agli agenti (tramite plugin) le istruzioni necessarie per organizzare il servizio richiesto.

Ora diamo un'occhiata all'installazione di prova (di come è stata implementata e quali componenti include parleremo più tardi nella parte pratica) e vediamo dove si trova ciascun componente:

(overcloud) [stack@undercloud ~]$ openstack network agent list  
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
| ID                                   | Tipo di Agente     | Host                                | Zona di disponibilità | Vivo  | Stato | Binario                  |
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
| 10495de9-ba4b-41fe-b30a-b90ec3f8728b | Agente Open vSwitch | overcloud-novacompute-1.localdomain | Nessuno            | :-)   | SU   | neutron-openvswitch-agent |
| 1515ad4a-5972-46c3-af5f-e5446dff7ac7 | Agente L3          | overcloud-controller-0.localdomain  | nova              | :-)   | SU   | neutron-l3-agent          |
| 322e62ca-1e5a-479e-9a96-4f26d09abdd7 | Agente DHCP        | overcloud-controller-0.localdomain  | nova              | :-)   | SU   | neutron-dhcp-agent        |
| 9c1de2f9-bac5-400e-998d-4360f04fc533 | Agente Open vSwitch | overcloud-novacompute-0.localdomain | Nessuno            | :-)   | SU   | neutron-openvswitch-agent |
| d99c5657-851e-4d3c-bef6-f1e3bb1acfb0 | Agente Open vSwitch | overcloud-controller-0.localdomain  | Nessuno            | :-)   | SU   | neutron-openvswitch-agent |
| ff85fae6-5543-45fb-a301-19c57b62d836 | Agente Metadata    | overcloud-controller-0.localdomain  | Nessuno            | :-)   | SU   | neutron-metadata-agent    |
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
(overcloud) [stack@undercloud ~]$ 

Introduzione alla parte di rete dell'infrastruttura cloud

Ecco qui tutta la struttura di Neutron. Ora è il momento di dedicare un po' di tempo al plugin ML2.

Modular Layer 2

Come già detto, il plugin è il plugin radice standard di OpenStack e ha un'architettura modulare.

Il predecessore del plugin ML2 aveva una struttura monolitica che non permetteva, ad esempio, di utilizzare un mix di diverse tecnologie in un'unica installazione. Ad esempio, non era possibile utilizzare sia openvswitch che linuxbridge contemporaneamente — solo uno dei due. Per questo motivo è stato creato il plugin ML2 con la sua architettura.

ML2 ha due componenti — due tipi di driver: Type drivers e Mechanism drivers.

Type drivers definiscono le tecnologie che verranno utilizzate per organizzare le connessioni di rete, come VxLAN, VLAN, GRE. Il driver consente l'uso di diverse tecnologie. La tecnologia standard è l'incapsulamento VxLAN per reti overlay e VLAN per reti esterne.

I seguenti tipi di reti appartengono ai Type drivers:

Flat — rete senza tagging
VLAN — rete taggata
Locale — tipo speciale di rete per installazioni all-in-one (queste installazioni sono necessarie per sviluppatori o per formazione)
GRE — rete overlay che utilizza tunnel GRE
VxLAN — rete overlay che utilizza tunnel VxLAN

Mechanism drivers definiscono i mezzi che garantiscono l'organizzazione delle tecnologie specificate nel type driver — ad esempio, openvswitch, sr-iov, opendaylight, OVN, ecc.

A seconda dell'implementazione di questo driver verranno utilizzati agenti gestiti da Neutron, oppure verranno stabilite connessioni con un controller SDN esterno, che si farà carico di tutte le questioni relative all'organizzazione delle reti L2, al routing, ecc.

Ad esempio, se utilizziamo ML2 insieme a OVS, un agente L2 è installato su ogni nodo di calcolo, che gestisce OVS. Tuttavia, se utilizziamo, ad esempio, OVN o OpenDayLight, la gestione di OVS passa sotto la loro giurisdizione — Neutron attraverso il plugin principale invia comandi al controller, e quest'ultimo esegue le istruzioni ricevute.

Rinfreschiamo la memoria su Open vSwitch

Attualmente, uno dei componenti chiave di OpenStack è Open vSwitch.
Quando si installa OpenStack senza alcuna SDN vendor come Juniper Contrail o Nokia Nuage, OVS è il principale componente di rete della rete cloud e, insieme a iptables, conntrack e namespaces, consente di organizzare reti overlay complete con multitenancy. Naturalmente, questo componente può essere sostituito, ad esempio, utilizzando soluzioni SDN proprietary di terze parti.

OVS è uno switch software con codice sorgente aperto, progettato per essere utilizzato in ambienti virtualizzati come un forwarder virtuale di traffico.

Attualmente, OVS ha un funzionale molto rispettabile, che include tecnologie come QoS, LACP, VLAN, VxLAN, GENEVE, OpenFlow, DPDK, ecc.

Nota: inizialmente OVS non era concepito come uno switch software per funzioni telecom ad alta capacità, ma era più orientato a funzioni IT meno esigenti in termini di larghezza di banda, come server WEB o server di posta. Tuttavia, OVS è stato migliorato, e le attuali implementazioni di OVS hanno notevolmente potenziato le sue prestazioni e capacità, permettendo il suo utilizzo da parte degli operatori di telecomunicazioni per funzioni ad alta richiesta, ad esempio, esiste un'implementazione di OVS con supporto per l'accelerazione DPDK.

Ci sono tre componenti importanti di OVS di cui è necessario essere a conoscenza:

  • Modulo del kernel — componente situato nello spazio del kernel che gestisce il traffico in base alle regole ricevute dall'elemento di controllo;
  • Daemon vSwitch (ovs-vswitchd) — è un processo in esecuzione nello spazio utente, responsabile della programmazione del modulo del kernel, ossia rappresenta direttamente la logica operativa dello switch. daemon (ovs-vswitchd) — è un processo in esecuzione nello spazio utente, responsabile della programmazione del modulo del kernel, ovvero rappresenta direttamente la logica di funzionamento dello switch.
  • Server di database — database locale situato su ogni host dove è in esecuzione OVS, che memorizza la configurazione. Attraverso questo modulo, possono comunicare i controller SDN tramite il protocollo OVSDB. — è un database locale presente su ogni host in cui è attivo OVS, dove viene memorizzata la configurazione. Attraverso questo modulo, i controller SDN possono comunicare tramite il protocollo OVSDB.

A tutto ciò si aggiunge un insieme di strumenti diagnostici e di gestione, come ovs-vsctl, ovs-appctl, ovs-ofctl e così via.

Attualmente, Openstack è ampiamente utilizzato dagli operatori di telecomunicazioni per migrare le funzioni di rete, come EPC, SBC, HLR e altro. Parte delle funzioni può convivere senza problemi con OVS nella sua forma attuale, ma ad esempio l'EPC gestisce il traffico degli utenti - ovvero, instrada un'enorme quantità di dati (attualmente il volume del traffico raggiunge diverse centinaia di gigabit al secondo). Naturalmente, gestire tale traffico attraverso lo spazio del kernel (poiché per impostazione predefinita il forwarder è collocato lì) non è l'idea migliore. Pertanto, spesso l'OVS viene implementato interamente nello spazio utente utilizzando la tecnologia di accelerazione DPDK per instradare il traffico dalla NIC allo spazio utente, bypassando il kernel.

Nota: per un cloud implementato per funzioni di telecomunicazioni è possibile una soluzione per instradare il traffico da un nodo di calcolo evitando OVS e collegandosi direttamente all'hardware di commutazione. A questo scopo si utilizzano meccanismi come SR-IOV e Passthrough.

Come funziona in un modello reale?

Bene, ora passiamo alla parte pratica e vediamo come tutto questo funziona nella pratica.

Iniziamo con una semplice installazione di OpenStack. Poiché non ho un set di server a disposizione per esperimenti, costruiremo il nostro modello su un unico server fisico utilizzando macchine virtuali. Certamente, una soluzione del genere non è adatta a scopi commerciali, ma è più che sufficiente per osservare come funziona la rete in un'installazione di OpenStack. Inoltre, tale installazione è persino più interessante per scopi didattici, poiché consente di catturare il traffico, e così via.

Poiché dobbiamo visualizzare solo la parte di base, possiamo evitare di utilizzare più reti e configurare tutto usando solo due reti. Inoltre, la seconda rete in questo modello sarà utilizzata esclusivamente per l'accesso al server undercloud e al server DNS. Al momento, non tratteremo le reti esterne: questo è un argomento per un'altra grande articolo.

Iniziamo dunque con ordine. Prima di tutto un po' di teoria. Installeremo Openstack utilizzando TripleO (Openstack on Openstack). L'idea di TripleO è che installiamo Openstack all-in-one (cioè su un'unica nodo), chiamato undercloud, e poi utilizziamo le capacità di Openstack già installato per realizzare Openstack destinato all'operatività, chiamato overcloud. L'undercloud utilizzerà la funzionalità integrata per gestire server fisici (bare metal) — il progetto Ironic — per il provisioning degli hypervisor, che assumeranno i ruoli di nodi compute, control e storage. In altre parole, non utilizziamo strumenti esterni per distribuire Openstack — stiamo distribuendo Openstack con le risorse di Openstack stesso. Procedendo con l'installazione, sarà molto più chiaro, quindi non ci fermiamo su questo e andiamo avanti.

Nota: In questo articolo, per semplificare, non ho utilizzato l'isolamento di rete per le reti interne di Openstack, ma ho implementato tutto utilizzando solo una rete. Tuttavia, la presenza o l'assenza di isolamento delle reti non influisce sulla funzionalità di base della soluzione: tutto funzionerà esattamente come nell'uso dell'isolamento, ma il traffico circolerà in una sola rete. Per un'installazione commerciale, è ovviamente necessario utilizzare l'isolamento con l'uso di VLAN e interfacce diverse. Ad esempio, il traffico di gestione dello storage Ceph e il traffico di dati (come le richieste delle macchine ai dischi, ecc.) utilizzano sottoreti diverse con isolamento (Storage management e Storage), il che rende la soluzione più resiliente, separando questo traffico, ad esempio, attraverso porte diverse, oppure utilizzando profili QoS differenti per diversi tipi di traffico, in modo che il traffico dati non soffochi il traffico di segnalazione. Nel nostro caso, invece, entrambi i tipi di traffico viaggeranno sulla stessa rete e questo non limita in alcun modo la nostra operazione.

Nota: Poiché stiamo per avviare macchine virtuali in un ambiente virtuale basato su macchine virtuali, è necessario attivare la virtualizzazione nidificata per prima cosa.

Per verificare se la virtualizzazione nidificata è attivata o meno, puoi procedere in questo modo:


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

Se vedi la lettera N, allora abilita il supporto per la virtualizzazione nidificata seguendo qualsiasi guida che puoi trovare in rete, ad esempio questo .

Dobbiamo costruire uno schema di questo tipo con le macchine virtuali:

Introduzione alla parte di rete dell'infrastruttura cloud

Nel mio caso, per la connettività delle macchine virtuali che compongono l'installazione futura (ne ho ottenute 7, ma si può fare con 4 se non hai molte risorse), ho utilizzato OpenvSwitch. Ho creato un ponte ovs e connesso le macchine virtuali tramite i gruppi di porte. Per fare ciò, ho creato un file xml di questo tipo:


[root@hp-gen9 ~]# virsh net-dumpxml ovs-network-1        

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

Qui sono dichiarati tre gruppi di porte: due access e uno trunk (l'ultimo era necessario per il server DNS, ma si può fare a meno di esso, oppure attivarlo sulla macchina host—come preferite). Successivamente, utilizziamo questo modello per dichiarare la nostra rete tramite virsh net-define:


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

Ora modifichiamo le configurazioni delle porte del hypervisor:


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

Nota: in questo scenario l'indirizzo sulla porta ovs-br1 non sarà disponibile poiché non ha un'etichetta VLAN. Per risolvere questo problema, bisogna dare il comando sudo ovs-vsctl set port ovs-br1 tag=100. Tuttavia, dopo il riavvio questo tag scomparirà (se qualcuno sa come farlo rimanere in posizione, sarei molto grato). Ma non è così importante, poiché questo indirizzo ci servirà solo durante l'installazione e non sarà necessario quando OpenStack sarà completamente distribuito.

Successivamente creiamo la macchina undercloud:


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

Durante l'installazione impostate tutti i parametri necessari, come il nome della macchina, le password, gli utenti, i server NTP ecc. È possibile configurare subito anche le porte, ma personalmente preferisco entrare nella macchina tramite la console dopo l'installazione e modificare i file necessari. Se avete già un'immagine pronta, potete usarla, oppure procedere come me: scaricare l'immagine minima di Centos 7 e utilizzarla per l'installazione della VM.

Dopo un'installazione riuscita, dovresti avere una macchina virtuale sulla quale installare undercloud


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

Iniziamo installando gli strumenti necessari per il processo di installazione:

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

Installazione di Undercloud

Creiamo l'utentente stack, impostiamo una password, lo aggiungiamo ai sudoer e gli diamo la possibilità di eseguire comandi root tramite sudo senza dover inserire la password:


useradd stack
passwd stack

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

Ora indichiamo nel file hosts il nome completo di undercloud:


vi /etc/hosts

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

Successivamente, aggiungiamo i repository e installiamo il software necessario:


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

Nota: se non hai intenzione di installare ceph, non è necessario inserire i comandi relativi a ceph. Ho usato la release Queens, ma puoi utilizzare qualsiasi altra che ti piaccia.

Successivamente, copiamo il file di configurazione undercloud nella home directory dell'utente stack:


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

Ora è necessario modificare questo file, adattandolo alla nostra installazione.

All'inizio del file è necessario aggiungere queste righe:

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

Quindi, esaminiamo le impostazioni:

undercloud_hostname — nome completo del server undercloud, deve corrispondere all'entry nel server DNS

local_ip — indirizzo locale di undercloud verso la rete di provisioning

network_gateway — stesso indirizzo locale, che fungerà da gateway per l'accesso al mondo esterno durante l'installazione dei nodi overcloud, corrisponde anche all'ip locale

undercloud_public_host — indirizzo dell'API esterno, può essere assegnato qualsiasi indirizzo libero dalla rete di provisioning

undercloud_admin_host indirizzo dell'API interno, può essere assegnato qualsiasi indirizzo libero dalla rete di provisioning

undercloud_nameservers — server DNS

generate_service_certificate — questa stringa è molto importante nel presente esempio, poiché se non è impostata su false si verificherà un errore durante l'installazione, problema descritto nel bug tracker di Red Hat

local_interface interfaccia nella rete di provisioning. Questa interfaccia verrà riconfigurata durante il deployment dell'undercloud, quindi l'undercloud deve avere due interfacce: una per l'accesso e l'altra per il provisioning

local_mtu — MTU. Poiché abbiamo un laboratorio di test e l'MTU è 1500 sulle porte dello switch OVS, è necessario impostarlo a 1450 affinché i pacchetti incapsulati in VxLAN possano passare

network_cidr — rete di provisioning

masquerade — utilizzo del NAT per l'accesso alla rete esterna

masquerade_network — rete che sarà NAT-izzata

dhcp_start — indirizzo iniziale del pool di indirizzi da cui saranno assegnati gli indirizzi ai nodi durante il deployment dell'overcloud

dhcp_end — indirizzo finale del pool di indirizzi da cui saranno assegnati gli indirizzi ai nodi durante il deployment dell'overcloud

inspection_iprange — pool di indirizzi necessario per l'ispettore (non deve sovrapporsi al pool sopra indicato)

scheduler_max_attempts — numero massimo di tentativi per l'installazione di overcloud (deve essere maggiore o uguale al numero di nodi)

Una volta che il file è descritto, puoi eseguire il comando per il deploy di undercloud:


openstack undercloud install

La procedura richiede da 10 a 30 minuti a seconda dell'hardware. Alla fine, dovresti vedere un output simile a questo:

vi undercloud.conf
2020-08-13 23:13:12,668 INFO: 
#############################################################################
Installazione di undercloud completata.

Il file contenente le password per questa installazione si trova in
/home/stack/undercloud-passwords.conf.

C'è anche un file stackrc in /home/stack/stackrc.

Questi file sono necessari per interagire con i servizi OpenStack e devono essere
protetti.

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

Questo output indica che hai installato correttamente undercloud e ora puoi controllare lo stato di undercloud e procedere all'installazione di overcloud.

Se guardi l'output di ifconfig, vedrai che è apparso un nuovo bridge interface

[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

Attraverso questo'interfaccia adesso verrà effettuato il lavoro di distribuzione dell'overcloud.

Dall'output qui sotto si può vedere che tutti i servizi sono su un'unica nodo:

(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     |
+--------------------------+-----------+----------+

Di seguito è mostrata la configurazione della parte di rete di 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 ~]$

Installazione overcloud

Al momento abbiamo solo undercloud e ci mancano i nodi da cui sarà composto l'overcloud. Pertanto, innanzitutto, procederemo a distribuire le macchine virtuali necessarie. Durante il deployment, l'undercloud installerà automaticamente il sistema operativo e il software necessari sulle macchine overcloud, quindi non è necessario configurare completamente la macchina, ma solo creare il disco (o i dischi) e definire i suoi parametri, ottenendo di fatto un server vuoto senza sistema operativo installato.

Accediamo alla cartella con i dischi delle nostre macchine virtuali e creiamo i dischi della dimensione necessaria:


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

Poiché stiamo agendo come root, dobbiamo cambiare il proprietario di questi dischi per evitare problemi di autorizzazioni:


[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]# 

Nota: se non prevedi di installare Ceph per scopi di apprendimento, non creare almeno 3 nodi con almeno due dischi, e nel template indica che verranno utilizzati dischi virtuali vda, vdb, ecc.

Ottimo, ora dobbiamo definire tutte queste macchine:


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 

Alla fine ci sono i comandi —print-xml > /tmp/storage-1.xml, che creano un file xml con la descrizione di ciascuna macchina nella cartella /tmp/, se non lo aggiungi, non potrai identificare le macchine virtuali.

Ora dobbiamo definire tutte queste macchine in 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 ~]#

Ora un piccolo dettaglio: tripleO utilizza IPMI per gestire i server durante l'installazione e l'introspezione.

L'introspezione è il processo di ispezione dell'hardware per ottenere i parametri necessari per il provisioning futuro delle nodi. L'introspezione avviene attraverso ironic, un servizio progettato per lavorare con server bare metal.

Ma qui c'è un problema: se i server fisici hanno IPMI su una porta separata (o su una porta condivisa, ma questo non è fondamentale), le macchine virtuali non hanno tali porte. Qui ci viene in aiuto un workaround chiamato vbmc, un'utilità che permette di emulare una porta IPMI. Questo aspetto è particolarmente importante per coloro che vogliono creare un laboratorio su un hypervisor ESXI — non so se esista un equivalente di vbmc in esso, quindi vale la pena considerare questa questione prima di effettuare il deployment.

Installiamo vbmc:


yum install python2-virtualbmc

Se il tuo sistema operativo non riesce a trovare il pacchetto, aggiungi il repository:

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

Ora configurando l'utilità. Qui tutto è incredibilmente semplice. È ragionevole che nell'elenco vbmc non ci siano server


[root@hp-gen9 ~]# vbmc list

[root@hp-gen9 ~]# 

Per farli comparire, è necessario dichiararli manualmente in questo modo:


[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
+-------------+--------+---------+------+
| Nome dominio | Stato  | Indirizzo | Porta |
+-------------+--------+---------+------+
| compute-1   | giù    | ::      | 7004 |
| compute-2   | giù    | ::      | 7005 |
| control-1   | giù    | ::      | 7001 |
| storage-1   | giù    | ::      | 7002 |
| storage-2   | giù    | ::      | 7003 |
+-------------+--------+---------+------+
[root@hp-gen9 ~]#

Penso che la sintassi del comando sia chiara senza spiegazioni. Tuttavia, al momento tutte le nostre sessioni sono nello stato DOWN. Per farle passare allo stato UP, è necessario accenderle:


[root@hp-gen9 ~]# vbmc start control-1
2020-08-14 03:15:57,826.826 13149 INFO VirtualBMC [-] Avviato l'istanza vBMC per il dominio control-1
[root@hp-gen9 ~]# vbmc start storage-1 
2020-08-14 03:15:58,316.316 13149 INFO VirtualBMC [-] Avviato l'istanza vBMC per il dominio storage-1
[root@hp-gen9 ~]# vbmc start storage-2
2020-08-14 03:15:58,851.851 13149 INFO VirtualBMC [-] Avviato l'istanza vBMC per il dominio storage-2
[root@hp-gen9 ~]# vbmc start compute-1
2020-08-14 03:15:59,307.307 13149 INFO VirtualBMC [-] Avviato l'istanza vBMC per il dominio compute-1
[root@hp-gen9 ~]# vbmc start compute-2
2020-08-14 03:15:59,712.712 13149 INFO VirtualBMC [-] Avviato l'istanza vBMC per il dominio compute-2
[root@hp-gen9 ~]# 
[root@hp-gen9 ~]# 
[root@hp-gen9 ~]# vbmc list
+-------------+---------+---------+------+
| Nome dominio | Stato   | Indirizzo | Porta |
+-------------+---------+---------+------+
| compute-1   | in esecuzione | ::      | 7004 |
| compute-2   | in esecuzione | ::      | 7005 |
| control-1   | in esecuzione | ::      | 7001 |
| storage-1   | in esecuzione | ::      | 7002 |
| storage-2   | in esecuzione | ::      | 7003 |
+-------------+---------+---------+------+
[root@hp-gen9 ~]#

L'ultimo passaggio è sistemare le regole del firewall (oppure disattivarlo completamente):


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

Ora accediamo a undercloud e verifichiamo che tutto funzioni. L'indirizzo della macchina host è 192.168.255.200; su undercloud abbiamo aggiunto il pacchetto necessario ipmitool durante la preparazione per il deploy:


[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power status          
Lo stato dell'alimentazione del chassis è spento
[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power on
Controllo dell'alimentazione del chassis: Acceso
[stack@undercloud ~]$ 

[root@hp-gen9 ~]# virsh list 
 Id    Nome                           Stato
----------------------------------------------------
 6     dns-server                     in esecuzione
 64    undercloud                     in esecuzione
 65    control-1                      in esecuzione

Come potete vedere, abbiamo avviato con successo il nodo di controllo tramite vbmc. Ora spegniamolo e procediamo:


[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power off
Controllo dell'alimentazione del chassis: Spento
[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power status
Lo stato dell'alimentazione del chassis è spento
[stack@undercloud ~]$ 

[root@hp-gen9 ~]# virsh list --all
 Id    Nome                           Stato
----------------------------------------------------
 6     dns-server                     in esecuzione
 64    undercloud                     in esecuzione
 -     compute-1                      spento
 -     compute-2                      spento
 -     control-1                      spento
 -     storage-1                      spento
 -     storage-2                      spento

[root@hp-gen9 ~]#

Il passo successivo è l'introspezione dei nodi sui quali sarà installato overcloud. Per questo, dobbiamo preparare un file json con la descrizione dei nostri nodi. Si prega di notare che, a differenza dell'installazione su server nudi, nel file è indicata la porta su cui vbmc è in esecuzione per ciascuna delle macchine.


[root@hp-gen9 ~]# virsh domiflist --domain control-1 
Interfaccia  Tipo       Sorgente     Modello       MAC
-------------------------------------------------------
-          rete    ovs-network-1 virtio      52:54:00:20:a2:2f
-          rete    ovs-network-1 virtio      52:54:00:3f:87:9f

[root@hp-gen9 ~]# virsh domiflist --domain compute-1
Interfaccia  Tipo       Sorgente     Modello       MAC
-------------------------------------------------------
-          rete    ovs-network-1 virtio      52:54:00:98:e9:d6

[root@hp-gen9 ~]# virsh domiflist --domain compute-2
Interfaccia  Tipo       Sorgente     Modello       MAC
-------------------------------------------------------
-          rete    ovs-network-1 virtio      52:54:00:6a:ea:be

[root@hp-gen9 ~]# virsh domiflist --domain storage-1
Interfaccia  Tipo       Sorgente     Modello       MAC
-------------------------------------------------------
-          rete    ovs-network-1 virtio      52:54:00:79:0b:cb

[root@hp-gen9 ~]# virsh domiflist --domain storage-2
Interfaccia  Tipo       Sorgente     Modello       MAC
-------------------------------------------------------
-          rete    ovs-network-1 virtio      52:54:00:a7:fe:27

Nota: sulla nodo di controllo ci sono due interfacce, ma in questo caso non è importante, in questa installazione ci basta anche una sola.

Ora prepariamo il file json. Dobbiamo specificare l'indirizzo MAC della porta attraverso la quale avverrà il provisioning, i parametri delle nodi, dare loro nomi e indicare come accedere a 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"
        }
    ]
}

Ora dobbiamo preparare le immagini per ironic. Per fare ciò, le scarichiamo tramite wget e le installiamo:

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

Carichiamo le immagini nell'undercloud:

(undercloud) [stack@undercloud ~]$ openstack overcloud image upload --image-path ~/images/
L'immagine "overcloud-full-vmlinuz" è stata caricata.
+--------------------------------------+------------------------+-------------+---------+--------+
|                  ID                  |          Nome          | Formato Disco |   Dimensione  | Stato |
+--------------------------------------+------------------------+-------------+---------+--------+
| c2553770-3e0f-4750-b46b-138855b5c385 | overcloud-full-vmlinuz |     aki     | 6761064 | attivo |
+--------------------------------------+------------------------+-------------+---------+--------+
L'immagine "overcloud-full-initrd" è stata caricata.
+--------------------------------------+-----------------------+-------------+----------+--------+
|                  ID                  |          Nome         | Formato Disco |   Dimensione   | Stato |
+--------------------------------------+-----------------------+-------------+----------+--------+
| 949984e0-4932-4e71-af43-d67a38c3dc89 | overcloud-full-initrd |     ari     | 55183045 | attivo |
+--------------------------------------+-----------------------+-------------+----------+--------+
L'immagine "overcloud-full" è stata caricata.
+--------------------------------------+----------------+-------------+------------+--------+
|                  ID                  |      Nome      | Formato Disco |    Dimensione    | Stato |
+--------------------------------------+----------------+-------------+------------+--------+
| a2f2096d-c9d7-429a-b866-c7543c02a380 | overcloud-full |    qcow2    | 1487475712 | attivo |
+--------------------------------------+----------------+-------------+------------+--------+
L'immagine "bm-deploy-kernel" è stata caricata.
+--------------------------------------+------------------+-------------+---------+--------+
|                  ID                  |       Nome       | Formato Disco |   Dimensione  | Stato |
+--------------------------------------+------------------+-------------+---------+--------+
| e413aa78-e38f-404c-bbaf-93e582a8e67f | bm-deploy-kernel |     aki     | 6761064 | attivo |
+--------------------------------------+------------------+-------------+---------+--------+
L'immagine "bm-deploy-ramdisk" è stata caricata.
+--------------------------------------+-------------------+-------------+-----------+--------+
|                  ID                  |        Nome       | Formato Disco |    Dimensione   | Stato |
+--------------------------------------+-------------------+-------------+-----------+--------+
| 5cf3aba4-0e50-45d3-929f-27f025dd6ce3 | bm-deploy-ramdisk |     ari     | 461759376 | attivo |
+--------------------------------------+-------------------+-------------+-----------+--------+
(undercloud) [stack@undercloud ~]$

Controlliamo che tutte le immagini siano state caricate


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

Un'ulteriore nota: è necessario aggiungere il server 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 ~]$

Ora possiamo dare il comando per l'introspezione:

(undercloud) [stack@undercloud ~]$ openstack overcloud node import --introspect --provide inspection.json 
Iniziato il flusso di lavoro Mistral tripleo.baremetal.v1.register_or_update. ID esecuzione: d57456a3-d8ed-479c-9a90-dff7c752d0ec
In attesa di messaggi nella coda 'tripleo' senza timeout.


5 nodi sono stati spostati con successo nello stato "gestibile".
Nodo registrato con successo UUID b4b2cf4a-b7ca-4095-af13-cc83be21c4f5
Nodo registrato con successo UUID b89a72a3-6bb7-429a-93bc-48393d225838
Nodo registrato con successo UUID 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e
Nodo registrato con successo UUID bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8
Nodo registrato con successo UUID 766ab623-464c-423d-a529-d9afb69d1167
In attesa che l'introspezione finisca...
Iniziato il flusso di lavoro Mistral tripleo.baremetal.v1.introspect. ID esecuzione: 6b4d08ae-94c3-4a10-ab63-7634ec198a79
In attesa di messaggi nella coda 'tripleo' senza timeout.
Introspezione del nodo b89a72a3-6bb7-429a-93bc-48393d225838 completata. Stato:SUCCESS. Errori:None
Introspezione del nodo 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e completata. Stato:SUCCESS. Errori:None
Introspezione del nodo bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 completata. Stato:SUCCESS. Errori:None
Introspezione del nodo 766ab623-464c-423d-a529-d9afb69d1167 completata. Stato:SUCCESS. Errori:None
Introspezione del nodo b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 completata. Stato:SUCCESS. Errori:None
5 nodi sono stati introspezionati con successo.
Iniziato il flusso di lavoro Mistral tripleo.baremetal.v1.provide. ID esecuzione: f5594736-edcf-4927-a8a0-2a7bf806a59a
In attesa di messaggi nella coda 'tripleo' senza timeout.
5 nodi sono stati spostati con successo nello stato "disponibile".
(undercloud) [stack@undercloud ~]$

Come si può vedere dall'output, tutto è stato completato senza errori. Verifichiamo che tutti i nodi siano in stato disponibile:


(undercloud) [stack@undercloud ~]$ openstack baremetal node list
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
| UUID                                 | Nome      | UUID dell'istanza | Stato di alimentazione | Stato di provisioning | Manutenzione |
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
| b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 | control-1 | Nessuno       | spento       | disponibile         | Falso       |
| b89a72a3-6bb7-429a-93bc-48393d225838 | storage-1 | Nessuno       | spento       | disponibile         | Falso       |
| 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e | storage-2 | Nessuno       | spento       | disponibile         | Falso       |
| bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 | compute-1 | Nessuno       | spento       | disponibile         | Falso       |
| 766ab623-464c-423d-a529-d9afb69d1167 | compute-2 | Nessuno       | spento       | disponibile         | Falso       |
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
(undercloud) [stack@undercloud ~]$ 

Se i nodi si trovano in uno stato diverso, solitamente gestibile, significa che c'è un problema e sarà necessario controllare i log per capire cosa è successo. Tieni presente che in questo scenario stiamo utilizzando la virtualizzazione e potrebbero esserci bug relativi all'uso di macchine virtuali o vbmc.

Successivamente, dobbiamo specificare quale nodo avrà quale funzione — cioè dobbiamo indicare il profilo con cui il nodo sarà distribuito:


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

Specifichiamo il profilo per ogni nodo:


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

Verifichiamo che abbiamo fatto tutto correttamente:


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

Se tutto è corretto, diamo il comando per il deployment dell'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

In un'installazione reale, naturalmente, si utilizzeranno template personalizzati; nel nostro caso questo complicherà molto il processo, poiché dovremo spiegare ogni modifica nel template. Come già detto, anche un'installazione semplice sarà sufficiente per vedere come funziona.

Nota: la variabile --libvirt-type qemu è necessaria in questo caso, poiché utilizzeremo la virtualizzazione annidata. In caso contrario, non potrete avviare le macchine virtuali.

Adesso avete circa un'ora, o forse di più (a seconda delle capacità dell'hardware), e non vi resta che sperare di vedere il seguente messaggio:


2020-08-14 08:39:21Z [overcloud]: CREATE_COMPLETE Stack CREATE completato con successo

 Stack overcloud CREATE_COMPLETE 

Host 192.168.255.21 non trovato in /home/stack/.ssh/known_hosts
Avviato il flusso di lavoro Mistral tripleo.deployment.v1.get_horizon_url. ID esecuzione: fcb996cd-6a19-482b-b755-2ca0c08069a9
Endpoint Overcloud: http://192.168.255.21:5000/
URL del dashboard di Overcloud Horizon: http://192.168.255.21:80/dashboard
File rc di Overcloud: /home/stack/overcloudrc
Overcloud distribuito
(undercloud) [stack@undercloud ~]$

Ora avete una versione quasi completa di OpenStack, sulla quale potete studiare, fare esperimenti, ecc.

Verifichiamo che tutto funzioni correttamente. Nella home directory dell'utente stack ci sono due file: uno è stackrc (per la gestione dell'undercloud) e l'altro è overcloudrc (per la gestione dell'overcloud). È necessario specificare questi file come source, poiché contengono le informazioni necessarie per l'autenticazione.


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

Nella mia installazione c'è ancora un piccolo ritocco da fare: aggiungere una route sul controller, poiché la macchina con cui lavoro si trova in un'altra rete. A tale scopo, accediamo a control-1 con l'account heat-admin e definiamo la route.


(undercloud) [stack@undercloud ~]$ ssh heat-admin@192.168.255.15         
Ultimo accesso: Ven 14 Ago 2020 09:47:40 da 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

E ora potete accedere all'orizzonte. Tutte le informazioni — indirizzi, login e password — si trovano nel file /home/stack/overcloudrc. Lo schema finale appare come segue:

Introduzione alla parte di rete dell'infrastruttura cloud

A proposito, nella nostra installazione gli indirizzi delle macchine vengono assegnati tramite DHCP e, come potete vedere, vengono assegnati "a caso". È possibile specificare rigidamente, nel template, quale indirizzo deve essere collegato a quale macchina durante il deployment, se necessario.

Come fluisce il traffico tra le macchine virtuali?

In questo articolo esamineremo tre opzioni per il passaggio del traffico.

  • Due macchine su un unico hypervisor nella stessa rete L2.
  • Due macchine su hypervisor diversi nella stessa rete L2.
  • Due macchine in reti diverse (routing tra reti).

I casi di connessione al mondo esterno attraverso la rete esterna, utilizzando indirizzi flottanti e una routing distribuita, verranno trattati la prossima volta; per ora ci concentreremo sul traffico interno.

Per il controllo, raccoglieremo uno schema del genere:

Introduzione alla parte di rete dell'infrastruttura cloud

Abbiamo creato 4 macchine virtuali: 3 in una rete L2 — net-1, e 1 nella rete 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 ~]$ 

Vediamo su quali hypervisor sono collocate le macchine create:

(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 ~]$
Le macchine vm-1 e vm-3 sono posizionate su compute-0, mentre le macchine vm-2 e vm-4 si trovano sul nodo compute-1.

Inoltre, è stato creato un router virtuale per consentire il routing tra le reti specificate:

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

Il router ha due porte virtuali che fungono da gateway per le reti:

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

Ma prima di vedere come si muove il traffico, esaminiamo cosa abbiamo attualmente sul nodo di controllo (che è anche un nodo di rete) e sul nodo di calcolo. Iniziamo dal nodo di calcolo.


[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: (interno)
    phy-br-ex 1/none: (patch: peer=int-br-ex)
  br-int:
    br-int 65534/2: (interno)
    int-br-ex 1/none: (patch: peer=phy-br-ex)
    patch-tun 2/none: (patch: peer=patch-int)
  br-tun:
    br-tun 65534/3: (interno)
    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 ~]$

Attualmente, ci sono tre bridge ovs sulla node: br-int, br-tun e br-ex. Tra di loro, come possiamo vedere, c'è un insieme di interfacce. Per semplificare la comprensione, rappresentiamo tutte queste interfacce in uno schema e vediamo cosa ne risulta.

Introduzione alla parte di rete dell'infrastruttura cloud

Dai indirizzi su cui sono attivati i tunnel VxLAN, è evidente che un tunnel è attivato su compute-1 (192.168.255.26) e il secondo tunnel punta a control-1 (192.168.255.15). Ma ciò che è particolarmente interessante è che br-ex non ha interfacce fisiche, e se guardiamo quali flussi sono configurati, si nota che questo bridge in questo momento può solo scartare il traffico.


[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
        ether 52:54:00:6a:ea:be  txqueuelen 1000  (Ethernet)
        RX packets 2909669  bytes 4608201000 (4.2 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1821057  bytes 349198520 (333.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

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

Come si può vedere dall'output, l'indirizzo è stato collegato direttamente alla porta fisica e non a un'interfaccia bridge virtuale.


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

Secondo la prima regola, tutto ciò che arriva dalla porta phy-br-ex deve essere scartato.
Pertanto, in questo bridge non ci sono altre fonti di traffico se non da questo'interfaccia (collegamento con br-int), e a giudicare dai pacchetti scartati nel bridge, era già presente traffico BUM.

Ciò significa che da questo nodo il traffico può uscire solo attraverso un tunnel VxLAN e in nessun altro modo. Tuttavia, se attiviamo DVR, la situazione cambierà, ma ne parleremo un'altra volta. Utilizzando l'isolamento delle reti, ad esempio tramite VLAN, avrete più di un'interfaccia L3 nella VLAN zero, ma il traffico VxLAN uscirà dal nodo esattamente nello stesso modo, incapsulato anche in una VLAN dedicata.

Abbiamo capito la nodi compute, passiamo al nodo control.


[heat-admin@overcloud-controller-0 ~]$ sudo ovs-appctl dpif/show
system@ovs-system: hit:930491 missed:825
  br-ex:
    br-ex 65534/1: (interno)
    eth0 1/2: (sistema)
    phy-br-ex 2/none: (patch: peer=int-br-ex)
  br-int:
    br-int 65534/3: (interno)
    int-br-ex 1/none: (patch: peer=phy-br-ex)
    patch-tun 2/none: (patch: peer=patch-int)
  br-tun:
    br-tun 65534/4: (interno)
    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 ~]$

Di fatto, si può dire che è tutto lo stesso, tuttavia l'indirizzo IP si trova non su un'interfaccia fisica ma su un bridge virtuale. Questo è fatto perché questa porta è il punto attraverso il quale il traffico uscirà verso il mondo esterno.


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

Questa porta è collegata al bridge br-ex e poiché non ci sono tag VLAN su di essa, questa porta è considerata una porta trunk dove tutte le VLAN sono consentite, attualmente il traffico esce senza tag, come indicato da vlan-id 0 nell'output sopra.

Introduzione alla parte di rete dell'infrastruttura cloud

Tutto il resto in questo momento è simile al nodo compute: gli stessi bridge, gli stessi tunnel che vanno verso i due nodi compute.

Non tratteremo i nodi di storage in questo articolo, ma è necessario menzionare che la parte di rete di questi nodi è sorprendentemente semplice. Nel nostro caso, c'è solo una porta fisica (eth0) con un indirizzo IP assegnato e basta. Non ci sono tunnel VxLAN, bridge tunnel e così via — non c'è nemmeno Open vSwitch, poiché non ha senso. Quando si utilizza l'isolamento delle reti, su questo nodo ci saranno due interfacce (porte fisiche, bond o semplicemente due VLAN — non importa, dipende da cosa si desidera) — una per la gestione, l'altra per il traffico (scrittura su disco VM, lettura da disco, ecc.).

Abbiamo chiarito quali elementi ci sono sui nodi in assenza di servizi. Ora avviamo 4 macchine virtuali e vediamo come cambia lo schema descritto sopra — dovremmo vedere comparire porte, router virtuali, ecc.

Fino ad ora, la nostra rete appare così:

Introduzione alla parte di rete dell'infrastruttura cloud

Abbiamo due macchine virtuali su ciascun nodo compute. Prendiamo come esempio compute-0 per vedere come è tutto connesso.


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

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

La macchina ha solo un'interfaccia virtuale — tap95d96a75-a0:

[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000001
Interfaccia  Tipo       Sorgente     Modello       MAC
-------------------------------------------------------
tap95d96a75-a0 bridge     qbr95d96a75-a0 virtio      fa:16:3e:44:98:20

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

Questa interfaccia è collegata al bridge linux:

[heat-admin@overcloud-novacompute-0 ~]$ sudo brctl show
nome del bridge     id del bridge               STP abilitato     interfacce
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 ~]$ 

Come si può vedere dall'output, nel bridge ci sono solo due interfacce — tap95d96a75-a0 e qvb95d96a75-a0.

Qui vale la pena soffermarsi sui tipi di dispositivi di rete virtuale in OpenStack:
vtap — interfaccia virtuale collegata all'istanza (VM)
qbr — bridge Linux
qvb e qvo — coppia vEth collegata al bridge Linux e al bridge Open vSwitch
br-int, br-tun, br-vlan — bridge di Open vSwitch
patch-, int-br-, phy-br- — interfacce patch di Open vSwitch che collegano i bridge
qg, qr, ha, fg, sg — porte di Open vSwitch utilizzate dai dispositivi virtuali per collegarsi a OVS

Come potete notare, se nella nostra bridge c'è la porta qvb95d96a75-a0, che è una coppia vEth, logicamente deve esserci un lato corrispondente, chiamato qvo95d96a75-a0. Vediamo quali porte sono presenti su 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: (interno)
    phy-br-ex 1/none: (patch: peer=int-br-ex)
  br-int:
    br-int 65534/2: (interno)
    int-br-ex 1/none: (patch: peer=phy-br-ex)
    patch-tun 2/none: (patch: peer=patch-int)
    qvo5bd37136-47 6/6: (sistema)
    qvo95d96a75-a0 3/5: (sistema)
  br-tun:
    br-tun 65534/3: (interno)
    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 ~]$ 

Come possiamo vedere, la porta si trova in br-int. Br-int funge da switch, terminando le porte delle macchine virtuali. Oltre a qvo95d96a75-a0, nel output è visibile anche la porta qvo5bd37136-47. Alla fine, il nostro schema ora appare così:

Introduzione alla parte di rete dell'infrastruttura cloud

Una domanda che dovrebbe subito catturare l'attenzione del lettore attento è: perché utilizzare un bridge Linux tra la porta di una macchina virtuale e la porta OVS? La questione è che per proteggere la macchina vengono utilizzati gruppi di sicurezza, che non sono altro che iptables. OVS non funziona con iptables, quindi è stata inventata questa "soluzione temporanea". Tuttavia, sta diventando obsoleta — sta per essere sostituita da conntrack nelle nuove versioni.

Quindi, alla fine, lo schema appare così:

Introduzione alla parte di rete dell'infrastruttura cloud

Due macchine su un unico hypervisor nella stessa rete L2.

Poiché le due VM si trovano nella stessa rete L2 e sullo stesso hypervisor, il traffico tra di esse passerà logicamente localmente attraverso br-int, dato che entrambe le macchine saranno nello stesso VLAN:


[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000001
Interfaccia  Tipo       Fonte     Modello       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
Interfaccia  Tipo       Fonte     Modello       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 
 porta  VLAN  MAC                Età
    6     1  fa:16:3e:83:ad:a4    0
    3     1  fa:16:3e:44:98:20    0
[heat-admin@overcloud-novacompute-0 ~]$ 

Due macchine su hypervisor diversi nella stessa rete L2.

Adesso vediamo come il traffico si comporta tra due macchine nella stessa rete L2, ma situate su hypervisor diversi. A dirla tutta, non cambierà molto, semplicemente il traffico tra gli hypervisor passerà attraverso un tunnel vxlan. Vediamo con un esempio.

Gli indirizzi delle macchine virtuali tra cui osserveremo il traffico:

[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000001
Interfaccia  Tipo       Sorgente     Modello       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
Interfaccia  Tipo       Origine     Modello       MAC
-------------------------------------------------------
tape7e23f1b-07 bridge     qbre7e23f1b-07 virtio      fa:16:3e:72:ad:53

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

Guardiamo la tabella di forwarding in br-int su 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 ~]

Il traffico deve andare alla porta 2 — vediamo quale porta è questa:

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

Questa è patch-tun — cioè l'interfaccia in br-tun. Vediamo cosa succede con il pacchetto su 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 ~]$ 

Il pacchetto viene incapsulato in VxLAN e inviato alla porta 2. Controlliamo dove porta 2 porta:

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

Questo è un tunnel vxlan su 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 ~]$

Andiamo su compute-1 e vediamo cosa succede al pacchetto:

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

Il MAC è presente nella tabella di forwarding di br-int su compute-1 e, come si può vedere dall'output sopra, è visibile attraverso la porta 2, che è la porta verso 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

E quindi, vediamo che in br-int su compute-1 c'è il mac di destinazione:

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

Ciò significa che il pacchetto ricevuto sarà inviato alla porta 3, dove si trova già la macchina virtuale instance-00000003.

La vera bellezza del deployment di Openstack per lo studio su un'infrastruttura virtuale è che possiamo facilmente monitorare il traffico tra gli hypervisor e vedere cosa succede. Adesso faremo proprio questo, avviando tcpdump sulla porta vnet verso compute-0:


[root@hp-gen9 bormoglotx]# tcpdump -vvv -i vnet3
tcpdump: ascoltando su vnet3, tipo di link EN10MB (Ethernet), dimensione di cattura 262144 bytes

*****************omesso*******************

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
	
*****************omesso*******************

La prima riga mostra che il pacchetto con indirizzo 10.0.1.85 sta andando all'indirizzo 10.0.1.88 (traffico ICMP), ed è incapsulato in un pacchetto VxLAN con vni 22, il pacchetto proviene dall'host 192.168.255.19 (compute-0) all'host 192.168.255.26 (compute-1). Possiamo verificare che il VNI corrisponda a quello specificato in ovs.

Torniamo a questa riga actions=load:0->NXM_OF_VLAN_TCI[],load:0x16->NXM_NX_TUN_ID[],output:2. 0x16 è il vni in sistema esadecimale. Convertiamo questo numero nel sistema decimale:


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

Quindi, il vni è corretto.

La seconda riga mostra il traffico inverso, ma non c'è bisogno di spiegarlo, è tutto chiaro.

Due macchine in reti diverse (instradamento tra reti)

L'ultimo caso per oggi è l'instradamento tra reti all'interno di un progetto utilizzando un router virtuale. Consideriamo il caso senza DVR (lo tratteremo in un altro articolo), quindi l'instradamento avviene sul nodo network. In questo caso, il nodo network non è stato separato in un'entità distinta ed è situato sul nodo di controllo.

Per iniziare, vediamo che l'instradamento funziona:

$ ping 10.0.2.8
PING 10.0.2.8 (10.0.2.8): 56 byte di dati
64 byte da 10.0.2.8: seq=0 ttl=63 time=7.727 ms
64 byte da 10.0.2.8: seq=1 ttl=63 time=3.832 ms
^C
--- statistiche ping 10.0.2.8 ---
2 pacchetti inviati, 2 pacchetti ricevuti, 0% perdita di pacchetti
round-trip min/avg/max = 3.832/5.779/7.727 ms

Poiché in questo caso il pacchetto deve andare al gateway e qui deve essere instradato, dobbiamo sapere l'indirizzo MAC del gateway. A questo scopo, guardiamo la tabella ARP nell'istanza:

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

Ora verifichiamo dove deve essere inviato il traffico destinato a (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 ~]$ 

Controlliamo dove porta la porta 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 ~]$ 

Tutto ha senso, il traffico va a br-tun. Vediamo in quale tunnel vxlan verrà incapsulato:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-ofctl dump-flows br-tun | grep fa:16:3e:c4:64:70
 cookie=0x8759a56536b67a8e, durata=3514.566s, tabella=20, n_pacchetti=3368, n_byte=317072, timeout_hard=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 ~]$ 

La terza porta è un tunnel 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 ~]$ 

Che osserva il nodo di controllo:

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

Il traffico è arrivato al nodo di controllo, quindi dobbiamo spostarci su di esso e osservare come avverrà il routing.

Come ricordate, il nodo di controllo appariva esattamente come il nodo di calcolo: gli stessi tre bridge, solo che br-ex aveva una porta fisica attraverso la quale il nodo poteva inviare traffico all'esterno. La creazione degli istanze ha modificato la configurazione sui nodi di calcolo: sono stati aggiunti linux bridge, iptables e interfacce ai nodi. La creazione di reti e di un router virtuale ha anche lasciato il suo segno sulla configurazione del nodo di controllo.

Quindi, è evidente che l'indirizzo MAC del gateway dovrebbe essere nella tabella di forwarding di br-int sul nodo di controllo. Controlliamo che ci sia e dove punta:

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

Il MAC è visibile dalla porta qr-0c52b15f-8f. Se torniamo indietro alla lista delle porte virtuali in Openstack, questo tipo di porta viene utilizzato per collegare vari dispositivi virtuali a OVS. Per essere precisi, qr è la porta verso il router virtuale, che è rappresentato come namespace.

Vediamo quali namespace ci sono sul server:

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

Tre istanze in totale. Ma a giudicare dai nomi, si può intuire la funzione di ciascuna di esse. Torneremo più tardi alle istanze con ID 0 e 1, ora siamo interessati al 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 ~]$ 

In questo namespace ci sono due interfacce interne che abbiamo creato in precedenza. Entrambe le porte virtuali sono state aggiunte a br-int. Controlliamo l'indirizzo MAC della porta qr-0c52b15f-8f, poiché il traffico, secondo l'indirizzo MAC di destinazione, è passato attraverso questa interfaccia.

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

Quindi, in questo caso, tutto funziona secondo le leggi della standard routing. Poiché il traffico è destinato all'host 10.0.2.8, deve passare attraverso la seconda interfaccia qr-92fa49b5-54 e attraversare il tunnel vxlan verso il nodo 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 ~]$ 

Tutto ha senso, nessuna sorpresa. Vediamo da dove è visibile l'indirizzo MAC dell'host 10.0.2.8 in 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 ~]$ 

Come previsto, il traffico passa attraverso br-tun, vediamo in quale tunnel il traffico proseguirà:

[heat-admin@overcloud-controller-0 ~]$ sudo ovs-ofctl dump-flows br-tun | grep fa:16:3e:6c:ad:9c
 cookie=0x2ab04bf27114410e, durata=5346.829s, tabella=20, n_pacchetti=5248, n_byte=498512, hard_timeout=300, idle_age=0, hard_age=0, priorità=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
 LOCALE(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 ~]$ 

Il traffico passa attraverso il tunnel verso compute-1. E su compute-1 è semplice: dal br-tun il pacchetto va al br-int e da lì all'interfaccia della macchina virtuale:

[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
 LOCALE(br-int): addr:e2:27:b2:ed:14:46
[heat-admin@overcloud-novacompute-1 ~]$ 

Controlliamo se questo è davvero l'interfaccia corretta:

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

Abbiamo esaminato l'intero percorso del pacchetto. Penso che abbiate notato che il traffico è passato attraverso diversi tunnel vxlan ed è uscito con VNI differenti. Controlliamo quali sono questi VNI, dopodiché raccoglieremo un dump sulla porta del nodo di controllo e ci assicureremo che il traffico circoli esattamente come descritto sopra.
Quindi, il tunnel verso compute-0 ha le seguenti actions=load:0->NXM_OF_VLAN_TCI[],load:0x16->NXM_NX_TUN_ID[],output:3. Convertiamo 0x16 nel sistema decimale:


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

Il tunnel verso compute-1 ha il seguente VNI: actions=load:0->NXM_OF_VLAN_TCI[],load:0x63->NXM_NX_TUN_ID[],output:2. Convertiamo 0x63 nel sistema decimale:


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

Ora diamo un'occhiata al dump:

[root@hp-gen9 bormoglotx]# tcpdump -vvv -i vnet4 
tcpdump: ascoltando su vnet4, tipo collegamento EN10MB (Ethernet), dimensione cattura 262144 byte

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

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

Il primo pacchetto è un pacchetto vxlan dal host 192.168.255.19 (compute-0) al host 192.168.255.15 (control-1) con vni 22, all'interno del quale è imballato un pacchetto ICMP dal host 10.0.1.85 al host 10.0.2.8. Come abbiamo calcolato sopra, il vni corrisponde a quanto visto negli output.

Il secondo pacchetto è un pacchetto vxlan dal host 192.168.255.15 (control-1) all'host 192.168.255.26 (compute-1) con vni 99, all'interno del quale è incapsulato un pacchetto ICMP dall'host 10.0.1.85 all'host 10.0.2.8. Come abbiamo calcolato sopra, il vni corrisponde a quanto abbiamo visto nelle uscite.

I due pacchetti successivi rappresentano il traffico inverso da 10.0.2.8 a 10.0.1.85.

Quindi alla fine abbiamo ottenuto questo schema della nodi di controllo:

Introduzione alla parte di rete dell'infrastruttura cloud

Sembra che sia tutto? Abbiamo dimenticato due 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 ~]$ 

Come abbiamo accennato riguardo all'architettura della piattaforma cloud — sarebbe utile che le macchine ricevessero gli indirizzi automaticamente dal server DHCP. Questi sono due server DHCP per le nostre due reti 10.0.1.0/24 e 10.0.2.0/24.

Verifichiamo se è così. In questo namespace c'è solo un indirizzo — 10.0.1.1 — l'indirizzo stesso del server DHCP, ed è anche incluso in 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

Vediamo se ci sono processi che contengono nel loro nome qdhcp-67a3798c-32c0-4c18-8502-2531247e3cc2 sul nodo di controllo:


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

Esiste un processo e, basandoci sulle informazioni fornite nell'output sopra, possiamo per esempio vedere quali sono attualmente assegnati:

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

In conclusione, otteniamo questo insieme di servizi sul nodo di controllo:

Introduzione alla parte di rete dell'infrastruttura cloud

E tenete presente che si tratta solo di 4 macchine, 2 reti interne e un router virtuale… Attualmente non abbiamo reti esterne, diversi progetti ognuno con le proprie reti (che si intersecano) e il router distribuito è spento. Dopotutto, nel banco di prova c'era solo una control node (per la resilienza è necessario avere un quorum di tre nodi). È logico che nella commercializzazione tutto sia 'un po' più complicato, ma in questo semplice esempio comprendiamo come dovrebbe funzionare: che tu abbia 3 o 300 namespace, è sicuramente importante, ma dal punto di vista del funzionamento dell'intera struttura non cambia molto… a meno che tu non introduca qualche SDN vendor. Ma questa è tutta un'altra storia.

Spero sia stato interessante. Se hai commenti/aggiunte o se ho mentito apertamente in qualche punto (sono umano e il mio parere sarà sempre soggettivo) – scrivi cosa deve essere corretto/aggiunto – correggeremo/aggiungeremo tutto.

In conclusione, vorrei dire qualche parola sul confronto tra OpenStack (sia nella sua versione base che in quella dei vendor) e la soluzione cloud offerta da VMWare. Questa domanda mi è stata posta spesso negli ultimi anni e, sinceramente, ne sono un po' stanco, ma tant'è. A mio avviso, è molto difficile confrontare queste due soluzioni, ma si può affermare senza dubbio che ci sono svantaggi in entrambe. Scegliendo una delle due soluzioni, è importante ponderare tutti i pro e i contro.

Se OpenStack è una soluzione guidata dalla community, VMWare può fare solo ciò che ritiene opportuno (leggi: ciò che le conviene), e questo ha senso, poiché è un'azienda commerciale abituata a guadagnare dai propri clienti. Tuttavia, c'è un grande e importante MA: puoi passare da OpenStack, ad esempio, di Nokia, e con poche difficoltà passare a una soluzione di, ad esempio, Juniper (Contrail Cloud), ma sarà difficile migrare via da VMWare. Per me queste due soluzioni si presentano così: OpenStack (versione venditore) è una semplice gabbia, in cui ti rinchiudono, ma hai la chiave e puoi uscire in qualsiasi momento. VMWare è una gabbia d'oro, la chiave è in possesso del padrone e ti costerà molto.

Non sto sostenendo né il primo prodotto né il secondo: siete voi a scegliere ciò di cui avete bisogno. Ma se dovessi fare una scelta, opterei per entrambe le soluzioni: VMWare per il cloud IT (carichi leggeri, gestione semplice) e OpenStack di qualche fornitore (Nokia e Juniper offrono soluzioni chiavi in mano piuttosto valide) per il cloud Telecom. Non utilizzerei OpenStack per il puro IT: è come usare un cannone per colpire un passero, ma non vedo controindicazioni nell'utilizzarlo, se non la questione della sovrabbondanza. Tuttavia, usare VMWare nel telecomunicazioni è come trasportare ghiaia su un Ford Raptor: è bello da vedere, ma il conducente deve fare 10 viaggi invece di uno.

A mio avviso, il principale svantaggio di VMWare è la sua completa chiusura: l'azienda non fornisce alcuna informazione su come funzioni, ad esempio, vSAN o cosa ci sia nel nucleo dell'hypervisor. Questo non le conviene, il che significa che non diventerai mai un esperto in VMWare: senza il supporto del fornitore, sei destinato a rimanere in difficoltà (incontro spesso esperti di VMWare che rimangono sconcertati da domande banali). Per me, VMWare è come acquistare un'auto con il cofano chiuso a chiave: sì, è possibile avere specialisti in grado di sostituire la cinghia di distribuzione, ma solo chi ti ha venduto questa soluzione può aprire il cofano. Personalmente, non mi piacciono le soluzioni in cui non posso mettere mano. Potreste dire che forse non avrete mai bisogno di guardare sotto il cofano. È possibile, ma vi osserverò quando dovrete assemblare in cloud una grande funzione con 20-30 macchine virtuali, 40-50 reti, metà delle quali vuole uscire verso l'esterno e l'altra metà richiede l'accelerazione SR-IOV; altrimenti vi serviranno almeno altre decine di queste macchine, altrimenti le prestazioni non basteranno.

Ci sono anche altre opinioni, quindi spetta solo a voi decidere cosa scegliere e, soprattutto, sarete voi a dover rispondere per la vostra scelta. Questa è solo la mia opinione, quella di una persona che ha visto e toccato con mano almeno 4 prodotti: Nokia, Juniper, Red Hat e VMWare. Insomma, ho dei termini di paragone.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster