Distribuzione di applicazioni su VM, Nomad e Kubernetes

Ciao a tutti! Il mio nome è Pavel Agaletsky. Lavoro come team leader in un team che sviluppa il sistema di consegna Lamoda. Nel 2018 ho parlato alla conferenza HighLoad++ e oggi vorrei presentare una trascrizione della mia relazione.

Il mio argomento è dedicato all’esperienza della nostra azienda nella distribuzione di sistemi e servizi in ambienti diversi. A partire dalla nostra preistoria, quando abbiamo distribuito tutti i sistemi in normali server virtuali, per finire con la graduale transizione da Nomad alla distribuzione in Kubernetes. Ti dirò perché l'abbiamo fatto e quali problemi abbiamo avuto nel processo.

Distribuzione delle applicazioni sulla VM

Partiamo dal fatto che 3 anni fa tutti i sistemi e i servizi dell'azienda venivano distribuiti su normali server virtuali. Tecnicamente è stato organizzato in modo tale che tutto il codice per i nostri sistemi fosse archiviato e assemblato utilizzando strumenti di assemblaggio automatico, utilizzando Jenkins. Utilizzando Ansible, è stato implementato dal nostro sistema di controllo della versione ai server virtuali. Inoltre, ogni sistema di cui disponeva la nostra azienda era distribuito su almeno 2 server: uno in testa, il secondo in coda. Questi due sistemi erano assolutamente identici tra loro in tutte le loro impostazioni, potenza, configurazione, ecc. L'unica differenza tra loro era che head riceveva il traffico degli utenti, mentre tail non riceveva mai il traffico degli utenti.

Perché è stato fatto?

Quando abbiamo implementato le nuove versioni della nostra applicazione, volevamo garantire un'implementazione senza interruzioni, ovvero senza conseguenze evidenti per gli utenti. Ciò è stato ottenuto grazie al fatto che la successiva versione compilata utilizzando Ansible è stata implementata alla fine. Lì, le persone coinvolte nella distribuzione potevano controllare e assicurarsi che tutto andasse bene: tutte le metriche, le sezioni e le applicazioni funzionavano; vengono lanciati gli script necessari. Solo dopo essersi convinti che tutto andava bene, il traffico è stato invertito. Ha iniziato ad andare al server che in precedenza era tail. E quello che prima era il capo è rimasto senza traffico di utenti, pur mantenendo la versione precedente della nostra applicazione.

Quindi è stato semplice per gli utenti. Perché la commutazione è istantanea, poiché si tratta semplicemente di cambiare il bilanciatore. Puoi facilmente tornare alla versione precedente semplicemente ripristinando il bilanciatore. Abbiamo anche potuto verificare che l'applicazione fosse in grado di produrre anche prima di ricevere il traffico degli utenti, il che è stato abbastanza conveniente.

Quali vantaggi abbiamo visto in tutto questo?

  1. Prima di tutto basta funziona e basta. Tutti capiscono come funziona un simile schema di distribuzione, perché la maggior parte delle persone ha mai effettuato la distribuzione su normali server virtuali.
  2. È abbastanza affidabile, poiché la tecnologia di implementazione è semplice, testata da migliaia di aziende. Milioni di server vengono distribuiti in questo modo. È difficile rompere qualcosa.
  3. E finalmente potremmo ottenere schieramenti atomici. Distribuzioni che avvengono simultaneamente per gli utenti, senza una fase evidente di passaggio dalla vecchia versione a quella nuova.

Ma in tutto questo abbiamo riscontrato anche diverse carenze:

  1. Oltre all'ambiente di produzione, all'ambiente di sviluppo, esistono altri ambienti. Ad esempio, qa e preproduzione. A quel tempo avevamo molti server e circa 60 servizi. Per questo era necessario per ogni servizio, mantieni la versione più recente macchina virtuale. Inoltre, se desideri aggiornare le librerie o installare nuove dipendenze, devi farlo in tutti gli ambienti. Dovevi anche sincronizzare l'ora in cui distribuirai la prossima nuova versione della tua applicazione con l'ora in cui devops eseguirà le impostazioni dell'ambiente necessarie. In questo caso, è facile entrare in una situazione in cui il nostro ambiente sarà leggermente diverso in tutti gli ambienti contemporaneamente. Ad esempio, in un ambiente di QA ci saranno alcune versioni di librerie e in un ambiente di produzione ce ne saranno diverse, il che porterà a problemi.
  2. Difficoltà nell'aggiornamento delle dipendenze la tua applicazione. Non dipende da te, ma dall'altra squadra. Vale a dire, dal team devops che si occupa della manutenzione dei server. Devi dare loro un compito appropriato e una descrizione di ciò che vuoi fare.
  3. A quel tempo volevamo anche dividere i grandi monoliti che avevamo in piccoli servizi separati, poiché capivamo che ce ne sarebbero stati sempre di più. A quel tempo ne avevamo già più di 100. Per ogni nuovo servizio era necessario creare una nuova macchina virtuale separata, che doveva anche essere mantenuta e implementata. Inoltre, non è necessaria una macchina, ma almeno due. A tutto ciò si aggiunge l'ambiente di QA. Ciò causa problemi e rende più difficile la creazione e l'esecuzione di nuovi sistemi. processo complesso, costoso e lungo.

Pertanto, abbiamo deciso che sarebbe stato più conveniente passare dalla distribuzione di normali macchine virtuali alla distribuzione delle nostre applicazioni in un contenitore docker. Se disponi di una finestra mobile, hai bisogno di un sistema in grado di eseguire l'applicazione in un cluster, poiché non puoi semplicemente generare un contenitore. Di solito si desidera tenere traccia di quanti container vengono sollevati in modo che si sollevino automaticamente. Per questo motivo abbiamo dovuto selezionare un sistema di controllo.

Abbiamo pensato a lungo su quale avremmo potuto prendere. Il fatto è che a quel tempo questo stack di distribuzione sui normali server virtuali era in qualche modo obsoleto, poiché non disponevano delle versioni più recenti dei sistemi operativi. Ad un certo punto arrivò anche FreeBSD, che non era molto comodo da supportare. Abbiamo capito che dovevamo migrare alla finestra mobile il più rapidamente possibile. I nostri devop hanno esaminato la loro esperienza esistente con diverse soluzioni e hanno scelto un sistema come Nomad.

Passa a Nomade

Nomad è un prodotto di HashiCorp. Sono noti anche per le loro altre soluzioni:

Distribuzione di applicazioni su VM, Nomad e Kubernetes

"Console" è uno strumento per la scoperta dei servizi.

"Terraforma" - un sistema di gestione dei server che permette di configurarli tramite configurazione, la cosiddetta infrastruttura-as-a-code.

"Vagabondo" consente di distribuire macchine virtuali localmente o nel cloud tramite file di configurazione specifici.

Nomad a quel tempo sembrava una soluzione abbastanza semplice a cui si poteva passare rapidamente senza modificare l'intera infrastruttura. Inoltre, è abbastanza facile da imparare. Ecco perché lo abbiamo scelto come sistema di filtraggio per il nostro contenitore.

Di cosa hai bisogno per distribuire il tuo sistema su Nomad?

  1. Prima di tutto hai bisogno immagine mobile la tua applicazione. È necessario crearlo e inserirlo nel repository delle immagini docker. Nel nostro caso, questo è un artefatto, un sistema che ti consente di inserirvi vari artefatti di diverso tipo. Può archiviare archivi, immagini docker, pacchetti PHP del compositore, pacchetti NPM e così via.
  2. Anche necessario file di configurazione, che dirà a Nomad cosa, dove e in quale quantità vuoi distribuire.

Quando parliamo di Nomad, utilizza il linguaggio HCL come formato di file di informazioni, che sta per Linguaggio di configurazione HashiCorp. Questo è un superset di Yaml che ti consente di descrivere il tuo servizio in termini Nomad.

Distribuzione di applicazioni su VM, Nomad e Kubernetes

Ti consente di dire quanti contenitori vuoi distribuire, da quali immagini passare loro vari parametri durante la distribuzione. Pertanto, fornisci questo file a Nomad e in base ad esso avvia i contenitori in produzione.

Nel nostro caso, ci siamo resi conto che scrivere semplicemente file HCL assolutamente identici per ciascun servizio non sarebbe stato molto conveniente, perché i servizi sono molti e talvolta è necessario aggiornarli. Succede che un servizio non viene distribuito in un'istanza, ma in una varietà di istanze diverse. Ad esempio, uno dei sistemi che abbiamo in produzione ha più di 100 istanze in produzione. Vengono eseguiti dalle stesse immagini, ma differiscono nelle impostazioni di configurazione e nei file di configurazione.

Pertanto, abbiamo deciso che sarebbe stato conveniente per noi archiviare tutti i nostri file di configurazione per la distribuzione in un repository comune. In questo modo erano visibili: erano facili da manutenere e potevamo vedere quali sistemi avevamo. Se necessario, è anche facile aggiornare o modificare qualcosa. Anche aggiungere un nuovo sistema non è difficile: devi solo creare un file di configurazione all'interno della nuova directory. Al suo interno sono presenti i seguenti file: service.hcl, che contiene la descrizione del nostro servizio, ed alcuni file env che permettono di configurare proprio questo servizio, essendo distribuito in produzione.

Distribuzione di applicazioni su VM, Nomad e Kubernetes

Tuttavia, alcuni dei nostri sistemi vengono distribuiti in produzione non in una copia, ma in più copie contemporaneamente. Pertanto, abbiamo deciso che sarebbe stato conveniente per noi archiviare le configurazioni non nella loro forma pura, ma nella loro forma basata su modelli. E abbiamo scelto jinja 2. In questo formato, memorizziamo sia le configurazioni del servizio stesso che i file env necessari per esso.

Inoltre, abbiamo inserito nel repository uno script di distribuzione comune a tutti i progetti, che ti consente di avviare e distribuire il tuo servizio in produzione, nell'ambiente desiderato, nel target desiderato. Nel caso in cui abbiamo trasformato la nostra configurazione HCL in un modello, il file HCL, che prima era una normale configurazione Nomad, in questo caso ha iniziato ad apparire leggermente diverso.

Distribuzione di applicazioni su VM, Nomad e Kubernetes

Cioè, abbiamo sostituito alcune variabili di posizione della configurazione con variabili inserite prese da file env o altre fonti. Inoltre, abbiamo l'opportunità di raccogliere i file HCL in modo dinamico, ovvero possiamo utilizzare non solo i normali inserimenti di variabili. Poiché jinja supporta loop e condizioni, puoi anche creare lì file di configurazione, che cambiano a seconda di dove distribuisci esattamente le tue applicazioni.

Ad esempio, desideri distribuire il tuo servizio in pre-produzione e produzione. Diciamo che in pre-produzione non vuoi eseguire script cron, ma vuoi solo vedere il servizio su un dominio separato per assicurarti che funzioni. Per chiunque distribuisca il servizio, il processo sembra molto semplice e trasparente. Tutto quello che devi fare è eseguire il file deploy.sh, specificare quale servizio vuoi distribuire e su quale destinazione. Ad esempio, desideri implementare un determinato sistema in Russia, Bielorussia o Kazakistan. Per fare ciò è sufficiente modificare uno dei parametri e avrai il file di configurazione corretto.

Quando il servizio Nomad è già distribuito nel tuo cluster, appare così.

Distribuzione di applicazioni su VM, Nomad e Kubernetes

Innanzitutto, hai bisogno di una sorta di bilanciatore esterno, che riceverà tutto il traffico degli utenti. Lavorerà insieme a Consul e scoprirà da lui dove, su quale nodo, a quale indirizzo IP si trova un determinato servizio che corrisponde a un particolare nome di dominio. I servizi in Consul provengono dallo stesso Nomad. Poiché si tratta di prodotti della stessa azienda, sono abbastanza correlati tra loro. Possiamo dire che Nomad fuori dagli schemi può registrare tutti i servizi lanciati in esso all'interno di Consul.

Una volta che il sistema di bilanciamento del carico front-end sa a quale servizio inviare il traffico, lo inoltra al contenitore appropriato o a più contenitori che corrispondono alla tua applicazione. Naturalmente bisogna pensare anche alla sicurezza. Anche se tutti i servizi vengono eseguiti sulle stesse macchine virtuali in contenitori, ciò di solito richiede di impedire l'accesso gratuito da qualsiasi servizio a qualsiasi altro. Abbiamo raggiunto questo obiettivo attraverso la segmentazione. Ogni servizio veniva lanciato in una propria rete virtuale, sulla quale venivano prescritte regole di routing e regole per consentire/negare l'accesso ad altri sistemi e servizi. Potrebbero trovarsi sia all'interno che all'esterno di questo cluster. Ad esempio, se si desidera impedire a un servizio di connettersi a un database specifico, è possibile farlo tramite la segmentazione a livello di rete. Cioè, anche per errore, non è possibile connettersi accidentalmente dall'ambiente di test al database di produzione.

Quanto ci è costata la transizione in termini di risorse umane?

Il passaggio dell'intera azienda a Nomad è durato circa 5-6 mesi. Ci siamo mossi servizio per servizio, ma a un ritmo abbastanza veloce. Ogni squadra ha dovuto creare i propri contenitori per i servizi.

Abbiamo adottato un approccio tale che ogni team è responsabile delle immagini docker dei propri sistemi in modo indipendente. DevOps fornisce l'infrastruttura generale necessaria per la distribuzione, ovvero il supporto per il cluster stesso, il supporto per il sistema CI e così via. E a quel tempo avevamo più di 60 sistemi trasferiti su Nomad, per un totale di circa 2mila container.

Devops è responsabile dell'infrastruttura generale di tutto ciò che riguarda la distribuzione e i server. E ogni team di sviluppo, a sua volta, è responsabile dell'implementazione dei contenitori per il proprio sistema specifico, poiché è il team che sa di cosa ha generalmente bisogno in un particolare contenitore.

Motivi per abbandonare Nomad

Quali vantaggi abbiamo ottenuto passando alla distribuzione utilizzando Nomad e docker, tra gli altri?

  1. Noi purché a parità di condizioni per tutti gli ambienti. Nello sviluppo, nell'ambiente QA, nella pre-produzione, nella produzione, vengono utilizzate le stesse immagini del contenitore, con le stesse dipendenze. Di conseguenza, non hai praticamente alcuna possibilità che ciò che finirà in produzione non sia ciò che hai precedentemente testato localmente o nel tuo ambiente di test.
  2. Abbiamo anche scoperto che è sufficiente facile aggiungere un nuovo servizio. Dal punto di vista dell'implementazione, qualsiasi nuovo sistema viene lanciato in modo molto semplice. Basta andare al repository che memorizza le configurazioni, aggiungere lì un'altra configurazione per il tuo sistema e tutto è pronto. Puoi distribuire il tuo sistema in produzione senza alcuno sforzo aggiuntivo da parte di devops.
  3. tutto file di configurazione in un archivio comune si è rivelato in fase di revisione. Quando distribuivamo i nostri sistemi utilizzando server virtuali, utilizzavamo Ansible, in cui le configurazioni erano nello stesso repository. Tuttavia, per la maggior parte degli sviluppatori è stato un po’ più difficile lavorare con questo. Qui il volume di configurazioni e codice che devi aggiungere per distribuire il servizio è diventato molto inferiore. Inoltre, è molto facile per i devops correggerlo o modificarlo. In caso di transizione, ad esempio, a una nuova versione di Nomad, possono eseguire e aggiornare in blocco tutti i file operativi che si trovano nello stesso posto.

Ma abbiamo riscontrato anche diversi svantaggi:

Si è scoperto che noi non è stato possibile ottenere distribuzioni senza interruzioni nel caso di Nomad. Durante il lancio dei container in condizioni diverse, potrebbe risultare funzionante e Nomad lo percepisce come un container pronto a ricevere il traffico. Ciò è accaduto prima ancora che l'applicazione al suo interno avesse la possibilità di avviarsi. Per questo motivo il sistema ha iniziato a produrre 500 errori in un breve periodo di tempo, perché il traffico cominciava a dirigersi verso un container che non era ancora pronto ad accoglierlo.

Ne abbiamo incontrati alcuni dalle paludi. Il bug più significativo è che Nomad non gestisce molto bene un cluster di grandi dimensioni se si hanno molti sistemi e contenitori. Quando si desidera rimuovere uno dei server inclusi nel cluster Nomad per la manutenzione, è molto probabile che il cluster non si senta molto bene e vada in pezzi. Alcuni contenitori potrebbero, ad esempio, cadere e non sollevarsi: questo ti costerà molto in seguito se tutti i tuoi sistemi di produzione si trovano in un cluster gestito da Nomad.

Quindi abbiamo deciso di pensare a dove dovremmo andare dopo. A quel punto siamo diventati molto più consapevoli di ciò che volevamo ottenere. Vale a dire: vogliamo affidabilità, un po' più di funzioni rispetto a quelle fornite da Nomad e un sistema più maturo e più stabile.

A questo proposito, la nostra scelta è ricaduta su Kubernetes come piattaforma più popolare per il lancio di cluster. Soprattutto considerando che le dimensioni e il numero dei nostri container erano abbastanza grandi. Per tali scopi, Kubernetes sembrava essere il sistema più adatto a cui potessimo guardare.

Transizione a Kubernetes

Ti parlerò un po' dei concetti di base di Kubernetes e di come differiscono da Nomad.

Distribuzione di applicazioni su VM, Nomad e Kubernetes

Innanzitutto il concetto più basilare in Kubernetes è il concetto di pod. Baccello è un gruppo di uno o più contenitori che funzionano sempre insieme. E funzionano sempre come se fossero rigorosamente su una macchina virtuale. Sono accessibili tra loro tramite IP 127.0.0.1 su porte diverse.

Supponiamo che tu abbia un'applicazione PHP composta da nginx e php-fpm, lo schema classico. Molto probabilmente, vorrai tenere sempre insieme i contenitori nginx e php-fpm. Kubernetes ti consente di raggiungere questo obiettivo descrivendoli come un pod comune. Questo è esattamente ciò che non siamo riusciti a ottenere con Nomad.

Il secondo concetto è deployment. Il fatto è che la capsula stessa è una cosa effimera: inizia e scompare. Vuoi prima uccidere tutti i tuoi contenitori precedenti e poi lanciare subito le nuove versioni, o vuoi implementarli gradualmente? Questo è il processo di cui è responsabile il concetto di distribuzione. Descrive come distribuisci i tuoi pod, in quale quantità e come aggiornarli.

Il terzo concetto è servizio. Il tuo servizio è in realtà il tuo sistema, che riceve parte del traffico e poi lo inoltra a uno o più pod corrispondenti al tuo servizio. Cioè, ti permette di dire che tutto il traffico in entrata verso questo o quel servizio con questo o quel nome deve essere inviato a questi pod specifici. E allo stesso tempo ti fornisce il bilanciamento del traffico. Cioè, puoi avviare due pod della tua applicazione e tutto il traffico in entrata sarà equamente bilanciato tra i pod relativi a questo servizio.

E il quarto concetto fondamentale è Ingresso. Questo è un servizio che viene eseguito su un cluster Kubernetes. Funziona come un bilanciatore del carico esterno che si fa carico di tutte le richieste. Utilizzando l'API Kubernetes, Ingress può determinare dove inviare queste richieste. Inoltre, lo fa in modo molto flessibile. Puoi dire che tutte le richieste a questo host e tale e tale URL vengono inviate a questo servizio. E queste richieste che arrivano a questo host e ad un altro URL vengono inviate a un altro servizio.

La cosa più bella dal punto di vista di chi sviluppa un'applicazione è che puoi gestirla tutta da solo. Impostando la configurazione Ingress, puoi inviare tutto il traffico in arrivo a questa o quella API a contenitori separati scritti, ad esempio, in Go. Ma questo traffico, che arriva allo stesso dominio, ma a un URL diverso, dovrebbe essere inviato a contenitori scritti in PHP, dove c'è molta logica, ma non sono molto veloci.

Se confrontiamo tutti questi concetti con Nomad, possiamo dire che i primi tre concetti sono tutti insieme Servizio. E quest'ultimo concetto è assente nello stesso Nomad. Abbiamo utilizzato un bilanciatore esterno: potrebbe essere haproxy, nginx, nginx+ e così via. Nel caso di un cubo, non è necessario introdurre separatamente questo concetto aggiuntivo. Tuttavia, se guardi Ingress internamente, è nginx, haproxy o traefik, ma in qualche modo integrato in Kubernetes.

Tutti i concetti che ho descritto sono, infatti, risorse che esistono all'interno di un cluster Kubernetes. Per descriverli nel cubo viene utilizzato il formato yaml, che nel caso di Nomad è più leggibile e familiare dei file HCL. Ma strutturalmente descrivono la stessa cosa nel caso, ad esempio, del pod. Dicono: voglio distribuire tali e tali pod lì, con tali e tali immagini, in tali e tali quantità.

Distribuzione di applicazioni su VM, Nomad e Kubernetes

Inoltre, ci siamo resi conto che non volevamo creare manualmente ogni singola risorsa: distribuzione, servizi, Ingress, ecc. Volevamo invece descrivere ciascuno dei nostri sistemi in termini di Kubernetes durante la distribuzione, in modo da non dover ricreare manualmente tutte le dipendenze delle risorse necessarie nel giusto ordine. Helm è stato scelto come sistema che ci ha permesso di farlo.

Concetti di base in Helm

Il timone è gestore dei pacchetti per Kubernetes. È molto simile al funzionamento dei gestori di pacchetti nei linguaggi di programmazione. Ti consentono di archiviare un servizio costituito, ad esempio, da distribuzione nginx, distribuzione php-fpm, configurazione per Ingress, configmaps (questa è un'entità che ti consente di impostare env e altri parametri per il tuo sistema) sotto forma di so- chiamati grafici. Allo stesso tempo Timone funziona su Kubernetes. Cioè, questo non è una sorta di sistema da parte, ma solo un altro servizio lanciato all'interno del cubo. Interagisci con esso tramite la sua API tramite un comando della console. La sua comodità e bellezza è che anche se helm si rompe o lo rimuovi dal cluster, i tuoi servizi non scompariranno, poiché helm serve essenzialmente solo ad avviare il sistema. Kubernetes stesso è quindi responsabile delle prestazioni e dello stato dei servizi.

Ce ne siamo accorti anche noi modellizzazione, che in precedenza eravamo costretti a fare da soli introducendo jinja nelle nostre configurazioni, è una delle caratteristiche principali di helm. Tutte le configurazioni che crei per i tuoi sistemi sono archiviate in helm sotto forma di modelli, un po' simili a jinja, ma, in realtà, utilizzano i modelli del linguaggio Go, in cui è scritto helm, come Kubernetes.

Helm aggiunge alcuni altri concetti per noi.

Grafico - questa è una descrizione del tuo servizio. In altri gestori di pacchetti verrebbe chiamato pacchetto, bundle o qualcosa di simile. Qui si chiama grafico.

Valori sono le variabili che vuoi utilizzare per creare le tue configurazioni dai modelli.

Rilasciare. Ogni volta che un servizio distribuito utilizzando helm riceve una versione incrementale del rilascio. Helm ricorda qual era la configurazione del servizio nella versione precedente, nella versione precedente e così via. Pertanto, se è necessario eseguire il rollback, è sufficiente eseguire il comando helm callback, indirizzandolo alla versione di rilascio precedente. Anche se la configurazione corrispondente nel tuo repository non è disponibile al momento del rollback, helm ricorderà comunque qual era e riporterà il tuo sistema allo stato in cui si trovava nella versione precedente.

Nel caso in cui utilizziamo helm, le configurazioni regolari per Kubernetes si trasformano anche in modelli in cui è possibile utilizzare variabili, funzioni e applicare istruzioni condizionali. In questo modo puoi raccogliere la configurazione del tuo servizio a seconda dell'ambiente.

Distribuzione di applicazioni su VM, Nomad e Kubernetes

In pratica, abbiamo deciso di fare le cose in modo leggermente diverso rispetto a Nomad. Se in Nomad sia le configurazioni di distribuzione che le n-variabili necessarie per distribuire il nostro servizio erano archiviate in un unico repository, qui abbiamo deciso di dividerle in due repository separati. Il repository "deploy" memorizza solo le variabili n necessarie per la distribuzione, mentre il repository "helm" memorizza configurazioni o grafici.

Distribuzione di applicazioni su VM, Nomad e Kubernetes

Cosa ci ha dato questo?

Nonostante non memorizziamo dati veramente sensibili nei file di configurazione stessi. Ad esempio, le password per i database. Sono archiviati come segreti in Kubernetes, ma ci sono comunque alcune cose a cui non vogliamo dare accesso a tutti. Pertanto, l'accesso al repository "deploy" è più limitato e il repository "helm" contiene semplicemente una descrizione del servizio. Per questo motivo può accedervi in ​​tutta sicurezza da una fascia più ampia di persone.

Poiché non abbiamo solo la produzione, ma anche altri ambienti, grazie a questa separazione possiamo riutilizzare i nostri grafici timone per distribuire servizi non solo alla produzione, ma anche, ad esempio, a un ambiente di QA. Anche per distribuirli localmente utilizzando Minikube - questa è una cosa per eseguire Kubernetes localmente.

All'interno di ciascun repository, abbiamo lasciato una divisione in directory separate per ciascun servizio. Cioè, all'interno di ogni directory ci sono modelli relativi al grafico corrispondente e che descrivono le risorse che devono essere distribuite per avviare il nostro sistema. Abbiamo lasciato solo envs nel repository “deploy”. In questo caso, non abbiamo utilizzato il template utilizzando jinja, perché helm stesso fornisce template pronti all'uso: questa è una delle sue funzioni principali.

Abbiamo lasciato uno script di distribuzione, deploy.sh, che semplifica e standardizza l'avvio per la distribuzione utilizzando helm. Pertanto, per chiunque desideri eseguire la distribuzione, l'interfaccia di distribuzione appare esattamente identica a quella della distribuzione tramite Nomad. Lo stesso deploy.sh, il nome del tuo servizio e dove vuoi distribuirlo. Ciò provoca l'avvio interno del timone. A sua volta, raccoglie le configurazioni dai modelli, inserisce in essi i file dei valori necessari, quindi li distribuisce, avviandoli in Kubernetes.

risultati

Il servizio Kubernetes sembra essere più complesso di Nomad.

Distribuzione di applicazioni su VM, Nomad e Kubernetes

Qui il traffico in uscita arriva a Ingress. Si tratta semplicemente del front controller, che prende in carico tutte le richieste e successivamente le invia ai servizi corrispondenti ai dati della richiesta. Li determina in base alle configurazioni che fanno parte della descrizione della tua applicazione in helm e che gli sviluppatori impostano autonomamente. Il servizio invia richieste ai suoi pod, ovvero contenitori specifici, bilanciando il traffico in entrata tra tutti i contenitori che appartengono a questo servizio. E, naturalmente, non dovremmo dimenticare che non dovremmo allontanarci dalla sicurezza a livello di rete. Pertanto, la segmentazione funziona in un cluster Kubernetes, che si basa sul tagging. Tutti i servizi hanno determinati tag a cui sono associati i diritti di accesso dei servizi a determinate risorse esterne/interne all'interno o all'esterno del cluster.

Durante la transizione, abbiamo visto che Kubernetes aveva tutte le funzionalità di Nomad, che avevamo utilizzato in precedenza, e abbiamo anche aggiunto molte cose nuove. Può essere espanso tramite plugin e, di fatto, tramite tipi di risorse personalizzate. Cioè, hai l'opportunità non solo di utilizzare qualcosa fornito con Kubernetes immediatamente, ma di creare la tua risorsa e il tuo servizio che leggeranno la tua risorsa. Ciò ti offre opzioni aggiuntive per espandere il tuo sistema senza dover reinstallare Kubernetes e senza richiedere modifiche.

Un esempio di tale utilizzo è Prometheus, che viene eseguito all'interno del nostro cluster Kubernetes. Affinché possa iniziare a raccogliere parametri da un particolare servizio, dobbiamo aggiungere un ulteriore tipo di risorsa, il cosiddetto monitor del servizio, alla descrizione del servizio. Prometheus, poiché può leggere un tipo di risorsa personalizzato quando viene avviato in Kubernetes, inizia automaticamente a raccogliere parametri dal nuovo sistema. È abbastanza conveniente.

La prima distribuzione che abbiamo effettuato su Kubernetes è avvenuta a marzo 2018. E durante questo periodo non abbiamo mai avuto problemi con esso. Funziona in modo abbastanza stabile senza bug significativi. Inoltre, possiamo espanderlo ulteriormente. Oggi ne abbiamo abbastanza delle capacità di cui dispone e ci piace molto il ritmo di sviluppo di Kubernetes. Attualmente, più di 3000 contenitori si trovano in Kubernetes. Il cluster occupa diversi nodi. Allo stesso tempo, è utile, stabile e molto controllabile.

Fonte: habr.com

Aggiungi un commento