Ciao a tutti! Mi chiamo Pavel Agaletsky. Lavoro come team leader in un gruppo che sviluppa il sistema di consegna di Lamoda. Nel 2018 ho parlato alla conferenza HighLoad++, e oggi voglio presentarvi la trascrizione della mia presentazione.
Il mio tema riguarda l'esperienza della nostra azienda nel deployare sistemi e servizi in diversi ambienti. Partendo dai nostri tempi preistorici, quando deployavamo tutti i sistemi su normali server virtuali, fino al graduale passaggio da Nomad al deploy in Kubernetes. Parlerò di perché lo abbiamo fatto e quali problemi abbiamo incontrato nel processo.

Deploy di applicazioni su VM
Iniziamo col dire che 3 anni fa tutti i sistemi e i servizi dell'azienda venivano deployati su normali server virtuali. Tecnologicamente, era organizzato in modo che tutto il codice dei nostri sistemi fosse archiviato e compilato tramite strumenti di build automatizzati, tramite jenkins. Con Ansible, veniva distribuito dalla nostra sistema di controllo versioni ai server virtuali. Ogni sistema presentava almeno 2 server: uno – il head, e l'altro – il tail. Questi due sistemi erano assolutamente identici tra loro per quanto riguardava configurazioni, potenza, impostazioni e altro. L'unica differenza era che il head riceveva traffico utente, mentre il tail non riceveva mai traffico degli utenti.
Perché è stato fatto?
Quando deployavamo nuove versioni della nostra applicazione, volevamo garantire un rollout senza interruzioni, ovvero senza conseguenze visibili per gli utenti. Ciò si otteneva distribuendo la versione appena compilata tramite Ansible sul tail. Qui le persone responsabili del deploy potevano controllare e assicurarsi che tutto funzionasse bene: tutte le metriche, i moduli e le applicazioni erano operativi; venivano eseguiti gli script necessari. Solo dopo aver confermato che tutto andava bene, il traffico veniva indirizzato. Cominciava a fluire verso il server che in precedenza era il tail. E quello che prima era il head rimaneva senza traffico utente, mantenendo la versione precedente della nostra applicazione.
In questo modo, per gli utenti è stato fluido. Perché il passaggio è istantaneo, poiché si tratta semplicemente di cambiare il bilanciatore. È molto facile tornare alla versione precedente, semplicemente ripristinando il bilanciatore. Inoltre, abbiamo potuto verificare la capacità dell'applicazione in produzione prima ancora che il traffico degli utenti vi passasse, il che è stato piuttosto comodo.
Quali vantaggi abbiamo riscontrato in tutto questo?
- Prima di tutto, è abbastanza facile e funziona. È chiaro a tutti come funziona uno schema di distribuzione del genere, poiché la maggior parte delle persone ha distribuito su normali server virtuali.
- È abbastanza affidabile, poiché la tecnologia di distribuzione è semplice, collaudata da migliaia di aziende. Milioni di server vengono distribuiti in questo modo. È difficile rompere qualcosa.
- E infine, abbiamo potuto ottenere distribuzioni atomiche. Distribuzioni che per gli utenti avvengono istantaneamente, senza un passaggio evidente tra la vecchia e la nuova versione.
Ma in tutto questo abbiamo visto anche alcuni svantaggi:
- Oltre all'ambiente di produzione, ci sono anche ambienti di sviluppo e altri ambienti. Ad esempio, QA e preproduzione. A quel tempo avevamo molti server e circa 60 servizi. Per questa ragione, era necessario mantenere per ogni servizio la versione attuale della macchina virtuale. Inoltre, se si desidera aggiornare le librerie o installare nuove dipendenze, è necessario farlo in tutti gli ambienti. Era anche necessario sincronizzare il momento in cui si intende distribuire la nuova versione della vostra applicazione con il momento in cui il devops eseguirà le necessarie configurazioni ambientali. In tal caso è facile trovarsi in una situazione in cui l'ambiente differisce in modo significativo tra tutti gli ambienti consecutivamente. Ad esempio, nell'ambiente QA ci saranno versioni di librerie diverse rispetto a quelle in produzione, il che porterà a problemi.
- La complessità nell'aggiornamento delle dipendenze della vostra applicazione. Questo dipende da un'altra squadra. Cioè, dal team devops, che gestisce i server. È necessario fornire loro il compito corrispondente e dare una descrizione di cosa si desidera fare.
- In quel periodo volevamo anche suddividere i grandi monoliti che avevamo in servizi più piccoli, poiché comprendevamo che ne sarebbero diventati sempre di più. Avevamo già più di 100 di questi. Era necessario creare una nuova macchina virtuale per ogni nuovo servizio, che doveva essere anche gestita e distribuita. Inoltre, non serviva una sola macchina, ma almeno due. A tutto ciò si aggiungeva l'ambiente QA. Questo causava problemi e rendeva la creazione e il lancio di nuovi sistemi più complesso, costoso e lungo.
Pertanto, abbiamo deciso che sarebbe stato più conveniente passare dalla distribuzione di macchine virtuali classiche alla distribuzione delle nostre applicazioni in contenitori Docker. Con Docker c'è bisogno di un sistema in grado di avviare l'applicazione in cluster, poiché non è possibile avviare semplicemente un contenitore. Di solito si desidera tenere traccia di quanti contenitori siano stati avviati, affinché si alzino automaticamente. Per questo motivo, era necessario scegliere un sistema di gestione.
Abbiamo riflettuto a lungo su quale di essi potessimo utilizzare. Il fatto è che a quel tempo il nostro stack di distribuzione su normali server virtuali era piuttosto obsoleto, poiché conteneva versioni non aggiornate dei sistemi operativi. A un certo punto vi era persino FreeBSD, che non era molto conveniente da mantenere. Comprendevamo che era necessario migrare il prima possibile a Docker. I nostri DevOps hanno analizzato la loro esperienza con diverse soluzioni e hanno scelto un sistema come Nomad.
Transizione a Nomad
Nomad è un prodotto dell'azienda “HashiCorp”. Sono anche noti per le loro altre soluzioni:

«Consul» è uno strumento per la scoperta dei servizi.
«Terraform» è un sistema di gestione dei server che ti consente di configurarli tramite configurazione, nota come infrastructure-as-a-code.
«Vagrant» ti consente di avviare macchine virtuali localmente o nel cloud tramite file di configurazione specifici.
A quel tempo, Nomad ci è sembrato una soluzione abbastanza semplice, che consente una transizione rapida senza modificare l'intera infrastruttura. Inoltre, è relativamente facile da apprendere. Perciò, lo abbiamo scelto come sistema per la gestione del nostro contenitore.
Cosa serve per distribuire il tuo sistema in Nomad?
- Prima di tutto, è necessario un'immagine Docker della tua applicazione. È necessario raccoglierlo e posizionarlo nello storage delle immagini docker. Nel nostro caso si tratta di artifactory: un sistema che consente di caricare diversi artefatti di vario tipo. È in grado di memorizzare archivi, immagini docker, pacchetti composer PHP, pacchetti NPM e così via.
- È inoltre necessario un file di configurazione, che dirà a Nomad cosa, dove e in quale quantità vuoi implementare.
Quando parliamo di Nomad, usa il linguaggio HCL come formato del file informativo, che si decodifica come HashiCorp Configuration Language. Questo è un superinsieme di Yaml, che ti consente di descrivere il tuo servizio in termini di Nomad.

Ti permette di specificare quanti contenitori desideri implementare, quali immagini utilizzare e di passare loro vari parametri durante l'implementazione. In questo modo, fornisci questo file a Nomad, che avvia i contenitori in produzione in base a quanto specificato.
Nel nostro caso, ci siamo resi conto che scrivere file HCL identici per ogni servizio sarebbe stato poco pratico, poiché ci sono molti servizi e a volte si desidera aggiornarli. Può capitare che un servizio sia implementato in più istanze. Ad esempio, uno dei sistemi che abbiamo in produzione ha oltre 100 istanze operative. Vengono eseguiti dalle stesse immagini, ma differiscono per le impostazioni di configurazione e i file di configurazione.
Pertanto, abbiamo deciso che sarebbe stato comodo mantenere tutti i nostri file di configurazione per l'implementazione in un unico repository comune. In questo modo, diventano facilmente consultabili: è semplice mantenerli e vedere quali sistemi abbiamo. Inoltre, in caso di necessità, non è complicato aggiornare o modificare qualcosa. Aggiungere un nuovo sistema non richiede nemmeno troppa fatica: è sufficiente creare un file di configurazione all'interno di una nuova directory. All'interno troverai i file: service.hcl, che contiene la descrizione del nostro servizio, e alcuni file .env, che consentono di configurare il servizio stesso una volta implementato in produzione.

Tuttavia, alcuni dei nostri sistemi non sono implementati in produzione in un'unica istanza, ma in più. Pertanto, abbiamo ritenuto conveniente conservare non le configurazioni in forma pura, ma la loro versione templated. E come linguaggio di templating abbiamo scelto jinja 2. In questo formato, conserviamo sia le configurazioni del servizio stesso che i file env necessari per esso.
Inoltre, abbiamo inserito nel repository uno script di deployment condiviso per tutti i progetti, che consente di avviare e distribuire il tuo servizio in produzione, nell'ambiente richiesto, nel target desiderato. Quando abbiamo trasformato la nostra configurazione HCL in un modello, il file HCL, che era prima una configurazione normale di Nomad, è apparso un po' diverso.

Cioè, abbiamo sostituito alcune variabili della configurazione con inserzioni di variabili, che vengono prelevate dai file env o da altre fonti. Inoltre, abbiamo acquisito la possibilità di generare file HCL dinamicamente, il che significa che possiamo applicare non solo le normali inserzioni di variabili. Poiché jinja supporta cicli e condizioni, è possibile creare file di configurazione che cambiano in base a dove stai distribuendo le tue applicazioni.
Ad esempio, vuoi distribuire il tuo servizio in pre-produzione e in produzione. Supponiamo che in pre-produzione tu non voglia avviare script cron, ma voglia semplicemente vedere il servizio su un dominio separato per assicurarti che funzioni. Per chiunque distribuisca un servizio, il processo appare molto semplice e trasparente. È sufficiente eseguire il file deploy.sh, specificare quale servizio vuoi distribuire e in quale target. Ad esempio, vuoi distribuire un certo sistema in Russia, Bielorussia o Kazakistan. Per farlo, basta cambiare uno dei parametri e ti verrà generato il file di configurazione corretto.
Quando il servizio Nomad è già stato distribuito nel tuo cluster, appare come segue.

Per iniziare, hai bisogno di un bilanciatore all'esterno, che riceverà tutto il traffico degli utenti. Funzionerà insieme a Consul e gli chiederà dove, su quale nodo, si trova il indirizzo IP servizio specifico corrispondente a un certo nome di dominio. I servizi in Consul sorgono da Nomad stesso. Poiché sono prodotti della stessa azienda, sono ben integrati tra loro. Si può dire che Nomad è in grado di registrare automaticamente tutti i servizi avviati in esso all'interno di Consul.
Dopo che il vostro bilanciatore esterno ha appreso a quale servizio deve inviare il traffico, lo reindirizza nel contenitore corrispondente o in più contenitori che si adattano alla vostra applicazione. È naturale che in questo si debba considerare anche la sicurezza. Anche se tutti i servizi vengono eseguiti sulle stesse macchine virtuali nei contenitori, di solito è necessario vietare l'accesso libero da qualsiasi servizio a qualsiasi altro. Abbiamo raggiunto questo obiettivo attraverso la segmentazione. Ogni servizio veniva eseguito nella propria rete virtuale, sulla quale erano definite le regole di routing e le regole di autorizzazione/divieto di accesso ad altri sistemi e servizi. Questi potevano trovarsi sia all'interno di questo cluster che all'esterno. Ad esempio, se desiderate vietare a un servizio di connettersi a un determinato database, è possibile farlo tramite segmentazione a livello di rete. Cioè, anche per errore, non potete accidentalmente collegarvi dal vostro ambiente di test al vostro database di produzione.
Quanto ci è costato il processo di transizione in termini di risorse umane?
La transizione di tutta l'azienda a Nomad ha impiegato circa 5-6 mesi. Ci siamo spostati servizio per servizio, ma a un ritmo abbastanza veloce. Ogni team doveva creare i propri contenitori per i servizi.
Abbiamo adottato un approccio in cui ogni team è responsabile autonomamente delle immagini docker dei propri sistemi. I DevOps, invece, forniscono l'infrastruttura generale necessaria per il deployment, ovvero il supporto per il cluster stesso, il supporto per il sistema CI e così via. E a quel tempo oltre 60 sistemi si erano trasferiti in Nomad, con circa 2000 contenitori.
I DevOps sono responsabili per l'infrastruttura generale di tutto ciò che riguarda il deployment e i server. Ogni team di sviluppo, a sua volta, è responsabile dell'implementazione dei contenitori per il proprio sistema specifico, poiché è proprio il team a sapere cosa necessita esattamente in quel particolare contenitore.
Motivi per cui ci siamo allontanati da Nomad
Quali vantaggi abbiamo ottenuto passando al deployment con Nomad e Docker?
- Noi abbiamo garantito condizioni uniformi per tutti i mezzi. Nel development, nell'ambiente QA, nella pre-produzione e nella produzione si utilizzano le stesse immagini dei container, con le stesse dipendenze. Ne consegue che avete praticamente zero probabilità che in produzione arrivi qualcosa che non avete già testato localmente o nell'ambiente di test.
- Abbiamo anche scoperto che è sufficiente aggiungere un nuovo servizio. Qualsiasi nuovo sistema dal punto di vista del deploy può essere avviato molto facilmente. È sufficiente andare nel repository che contiene le configurazioni, aggiungere una nuova configurazione per il vostro sistema e il gioco è fatto. Potete distribuire il vostro sistema in produzione senza ulteriori sforzi da parte dei DevOps.
- Tutti file di configurazione in un unico repository generale sono risultati consultabili. Nel momento in cui distribuivamo i nostri sistemi utilizzando server virtuali, utilizzavamo Ansible, dove le configurazioni erano tutte nello stesso repository. Tuttavia, per la maggior parte degli sviluppatori lavorare con questo era un po' più complicato. Qui il numero di configurazioni e codice che dovete aggiungere per distribuire un servizio è diventato molto più ridotto. Inoltre, per i DevOps è molto facile correggerlo o modificarlo. Nel caso di transizioni, ad esempio, su una nuova versione di Nomad, possono prendere e aggiornare in massa tutti i file operativi che si trovano nello stesso posto.
Ma ci siamo anche imbattuti in alcuni svantaggi:
Si è rivelato che non siamo riusciti a raggiungere la continuità dei deploy nel caso di Nomad. Durante il roll-out dei container in diverse condizioni, può succedere che un container venga avviato e Nomad lo riconosca come pronto a ricevere traffico. Questo accadeva ancora prima che l'applicazione al suo interno riuscisse ad avviarsi. Per questo motivo, il sistema in breve tempo iniziava a restituire errori 500, poiché il traffico iniziava a fluire verso un container che non era ancora pronto ad accoglierlo.
Ci siamo imbattuti in alcuni bug. Il bug più significativo è che Nomad non gestisce bene i grandi cluster, specialmente se hai molti sistemi e contenitori. Quando vuoi mettere in manutenzione uno dei server inclusi nel cluster Nomad, c'è una buona possibilità che il cluster non stia bene e si scomponga. Alcuni contenitori potrebbero, ad esempio, bloccarsi e non ripartire — questo ti costerà molto, soprattutto se tutti i tuoi sistemi in produzione sono nel cluster gestito da Nomad.
Perciò abbiamo deciso di riflettere su quale direzione prendere. A quel punto eravamo molto più consapevoli di ciò che volevamo ottenere. Vale a dire: desideriamo affidabilità, un po' più di funzionalità rispetto a quelle offerte da Nomad e un sistema più maturo e stabile.
In questo senso, abbiamo scelto Kubernetes come la piattaforma più popolare per eseguire i cluster. Soprattutto considerando che le dimensioni e il numero dei nostri contenitori erano abbastanza grandi. Per tali scopi, Kubernetes sembrava il sistema più adatto tra quelli che abbiamo preso in considerazione.
Transizione a Kubernetes
Voglio raccontarvi quali sono i concetti principali di Kubernetes e come si differenziano da Nomad.

Prima di tutto, il concetto più basilare in Kubernetes è il pod. Pod – è un gruppo di uno o più contenitori che vengono sempre eseguiti insieme. E lavorano come se fossero sempre rigorosamente su una macchina virtuale. Sono accessibili tra loro all'indirizzo IP 127.0.0.1 su porte diverse.
Supponiamo che tu abbia un'applicazione PHP che consiste in nginx e php-fpm – uno schema classico. Probabilmente vorrai che i contenitori nginx e php-fpm siano sempre insieme. Kubernetes consente di farlo descrivendoli come un unico pod comune. Esattamente questo non era possibile farlo con Nomad.
Il secondo concetto è deployment. Infatti, il pod di per sé è una cosa effimera, viene avviato e poi scompare. Vuoi uccidere prima tutti i tuoi contenitori precedenti e poi avviare subito nuove versioni, o vuoi distribuirli gradualmente – proprio di questo processo si occupa il concetto di deployment. Descrive come distribuisci i tuoi pod, in quale quantità e come aggiornarli.
Il terzo concetto è service. Il tuo service è praticamente il tuo sistema che accoglie un certo traffico e poi lo indirizza verso uno o più pod che corrispondono al tuo servizio. In altre parole, ti consente di dire che tutto il traffico in ingresso per un determinato servizio con un certo nome deve essere inviato a questi pod specifici. Inoltre, ti offre bilanciamento del traffico. Puoi avviare due pod della tua applicazione e tutto il traffico in ingresso verrà bilanciato uniformemente tra i pod associati a questo servizio.
E il quarto concetto principale — Ingress. Questo è un servizio che viene avviato nel cluster Kubernetes. Funziona come un bilanciatore di carico esterno che raccoglie tutte le richieste. Grazie all'API di Kubernetes, Ingress può determinare dove devono essere inviate queste richieste. Inoltre, lo fa in modo molto flessibile. Puoi specificare che tutte le richieste su questo host e su un certo URL devono essere inviate a questo servizio. E queste richieste, che arrivano su questo host e su un altro URL, devono essere indirizzate a un altro servizio.
La cosa più interessante per chi sviluppa un'applicazione è che sei in grado di gestire tutto questo autonomamente. Stabilendo la configurazione di Ingress, puoi inviare tutto il traffico che arriva su un certo API a contenitori specifici, ad esempio scritti in Go. E questo traffico, che entra nello stesso dominio, ma su un altro URL, deve 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 costituiscono insieme il Service. L'ultimo concetto è assente in Nomad. Per questo abbiamo usato un bilanciatore di carico esterno: potrebbe essere haproxy, nginx, nginx+ e così via. Nel caso di Kubernetes, non è necessario introdurre questo concetto separatamente. Tuttavia, se si guarda all'Ingress internamente, si tratta di nginx, haproxy o traefik, ma incorporato in Kubernetes.
Tutti i concetti che ho descritto sono, in sostanza, risorse che esistono all'interno del cluster Kubernetes. Per descriverle nel cluster viene utilizzato il formato yaml, più leggibile e familiare rispetto ai file HCL nel caso di Nomad. Ma strutturalmente descrivono, nel caso di un pod, la stessa cosa. Dicono – voglio distribuire questi pod in questo luogo, con queste immagini, in questa quantità.

Inoltre, abbiamo capito che non vogliamo creare manualmente ogni singola risorsa: deployment, servizi, Ingress, e altro ancora. Invece, volevamo descrivere ogni nostro sistema durante il deployment in termini di Kubernetes, in modo da non dover ricreare manualmente tutte le dipendenze necessarie in ordine. Per questo scopo, abbiamo scelto Helm come sistema che ci ha permesso di farlo.
Concetti fondamentali in Helm
Helm è un gestore di pacchetti per Kubernetes. È molto simile a come funzionano i gestori di pacchetti nei linguaggi di programmazione. Permettono di memorizzare un servizio che consiste, ad esempio, in deployment nginx, deployment php-fpm, configurazioni per Ingress, configmaps (questo è un'entità che consente di definire env e altri parametri per il sistema) sotto forma di cosiddetti chart. Helm funziona sopra Kubernetes. Cioè, non è un sistema esterno, ma semplicemente un altro servizio eseguito all'interno del cluster. Interagisci con esso tramite la sua API attraverso un comando da console. La sua comodità e bellezza stanno nel fatto che anche se Helm si rompe o lo rimuovi dal cluster, i tuoi servizi non scompariranno, poiché Helm serve sostanzialmente solo per avviare il sistema. La funzionalità e lo stato dei servizi sono poi gestiti da Kubernetes stesso.
Abbiamo anche capito che la templating, che in precedenza eravamo costretti a fare manualmente implementando jinja nelle nostre configurazioni, è una delle principali funzionalità di Helm. Tutte le configurazioni che crei per i tuoi sistemi sono conservate in Helm come modelli, simili a jinja, ma in realtà usano la templating del linguaggio Go, sul quale è scritto Helm, proprio come Kubernetes.
Helm ci aggiunge anche alcuni concetti aggiuntivi.
Chart — è la descrizione del tuo servizio. Negli altri gestori di pacchetti sarebbe stata chiamata pacchetto, bundle o qualcosa di simile. Qui è chiamata chart.
Values sono le variabili che desideri utilizzare per costruire le tue configurazioni dai modelli.
Release. Ogni volta che un servizio viene implementato tramite helm, riceve una versione incrementale della release. Helm ricorda quale fosse la configurazione del servizio nella release precedente, in quella prima e così via. Pertanto, se è necessario tornare indietro, basta eseguire il comando helm callback, specificando la versione precedente della release. Anche se al momento del rollback la configurazione corrispondente non è disponibile nel tuo repository, helm ricorda comunque quale fosse e riporterà il sistema allo stato in cui si trovava nella release precedente.
Nel caso in cui utilizziamo helm, le configurazioni standard per Kubernetes si trasformano anch'esse in modelli, nei quali è possibile utilizzare variabili, funzioni e applicare operatori condizionali. In questo modo, puoi costruire la configurazione del tuo servizio in base all'ambiente.

In pratica abbiamo deciso di procedere in modo leggermente diverso rispetto a quanto fatto con Nomad. Se in Nomad le configurazioni per l'implementazione e le variabili necessarie per distribuire il nostro servizio erano memorizzate nello stesso repository, qui abbiamo deciso di separarle in due repository distinti. Nel repository "deploy" vengono memorizzate solo le variabili necessarie per l'implementazione, mentre nel repository "helm" si trovano le configurazioni o i chart.

Cosa ci ha dato questo?
Nonostante nei file di configurazione non memorizziamo dati altamente sensibili, come le password dei database, che sono conservate sotto forma di secrets in Kubernetes, ci sono comunque elementi specifici ai quali non vogliamo dare accesso indiscriminato. Pertanto, l'accesso al repository "deploy" è più limitato, mentre il repository "helm" contiene semplicemente una descrizione del servizio. Per questo motivo, si può concedere l'accesso in modo sicuro a un numero maggiore di persone.
Poiché abbiamo non solo l'ambiente di produzione, ma anche altri ambienti, grazie a questa separazione possiamo riutilizzare i nostri helm chart per distribuire servizi non solo in produzione, ma anche, ad esempio, nell'ambiente QA. Anche per svilupparli localmente, utilizzando Minikube — è uno strumento per avviare Kubernetes localmente.
All'interno di ciascun repository, abbiamo lasciato una suddivisione in directory separate per ciascun servizio. Cioè, all'interno di ogni directory si trovano i modelli relativi al corrispondente chart e che descrivono le risorse da deployare per avviare il nostro sistema. Nel repository "deploy" abbiamo lasciato solo le env. In questo caso non abbiamo utilizzato la templating con jinja, perché helm fornisce già la templating out of the box – è una delle sue funzioni principali.
Abbiamo lasciato uno script per il deployment – deploy.sh, che semplifica e standardizza l'avvio del deployment tramite helm. Così, per chiunque voglia effettuare il deployment, l'interfaccia di deployment appare esattamente come nel caso del deployment tramite Nomad. Lo stesso deploy.sh, il nome del tuo servizio, e dove desideri deployarlo. Questo fa sì che si avvii helm. Quest'ultimo raccoglie le configurazioni dai modelli, sostituisce i file values necessari, quindi deploya, lanciandoli in Kubernetes.
Conclusioni
Il servizio Kubernetes appare più complesso rispetto a Nomad.

Qui il traffico in uscita arriva in Ingress. Questo è il front-controller che gestisce tutte le richieste e le invia successivamente ai servizi corrispondenti ai dati della richiesta. Li identifica in base alle configurazioni che fanno parte della descrizione della tua applicazione in helm e che gli sviluppatori impostano autonomamente. Il servizio poi invia le richieste ai propri pod, cioè container specifici, bilanciando il traffico in entrata tra tutti i container appartenenti a quel servizio. E, naturalmente, non dobbiamo dimenticare che in termini di sicurezza a livello di rete, non dobbiamo allontanarci. Pertanto, nel cluster Kubernetes opera la segmentazione basata sul tagging. Tutti i servizi hanno tag specifici a cui sono associati i diritti di accesso ai vari risorse esterni o interni nel cluster.
Effettuando il passaggio, abbiamo notato che Kubernetes offre tutte le funzionalità di Nomad, che avevamo utilizzato in precedenza, e aggiunge molte novità. Può essere esteso tramite plugin e, in effetti, tramite tipi di risorse personalizzati. Questo significa che avete la possibilità non solo di utilizzare ciò che viene fornito con Kubernetes di default, ma di creare la vostra risorsa e servizio che leggeranno la vostra risorsa. Ciò offre ulteriori opportunità di espansione del vostro sistema senza la necessità di reinstallare Kubernetes e senza la necessità di modifiche.
Un esempio di tale utilizzo è Prometheus, che eseguiamo all'interno del nostro cluster Kubernetes. Affinché inizi a raccogliere metriche da un servizio specifico, dobbiamo aggiungere alla descrizione del servizio un ulteriore tipo di risorsa, il cosiddetto servizio-monitor. Grazie al fatto che Prometheus può leggere, essendo in esecuzione su Kubernetes, tipi di risorse personalizzati, inizia automaticamente a raccogliere metriche dal nuovo sistema. È piuttosto comodo.
Il primo deployment che abbiamo fatto in Kubernetes è avvenuto a marzo 2018. E in tutto questo tempo non abbiamo mai riscontrato problemi. Funziona in modo abbastanza stabile senza bug significativi. Inoltre, possiamo espanderlo ulteriormente. Ad oggi, abbiamo sufficienti possibilità di cui disporre, e ci piacciono molto i tassi di sviluppo di Kubernetes. Attualmente, ci sono più di 3000 contenitori in Kubernetes. Il cluster occupa diversi Node. È gestito, stabile e molto controllato.
Fonte: habr.com
