Le migliori pratiche di Kubernetes. Creazione di piccoli container

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Il primo passo per il deployment su Kubernetes è posizionare la tua applicazione in un container. In questa serie esploreremo come creare un'immagine di un container piccolo e sicuro.
Grazie a Docker, la creazione di immagini di container non è mai stata così semplice. Specifica un'immagine di base, aggiungi le tue modifiche e crea il container.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Anche se questo approccio è ottimo per cominciare, l'uso delle immagini di base predefinite può portare a un funzionamento non sicuro con grandi immagini piene di vulnerabilità.

Inoltre, la maggior parte delle immagini Docker utilizza come immagine di base Debian o Ubuntu, e anche se questo garantisce un'ottima compatibilità e una facile adattabilità (il file Docker richiede solo due righe di codice), le immagini di base possono aggiungere centinaia di megabyte di carico aggiuntivo al tuo container. Ad esempio, un semplice file di un'applicazione Node.js 'hello-world' occupa circa 700 megabyte, mentre la dimensione vera e propria della tua applicazione è solo di pochi megabyte.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Quindi, tutto questo carico aggiuntivo è una perdita di spazio digitale e un ottimo nascondiglio per vulnerabilità e errori di sicurezza. Perciò, consideriamo due modi per ridurre le dimensioni dell'immagine del container.

Il primo consiste nell'uso di immagini di base di dimensioni ridotte, il secondo nell'uso del pattern di progettazione Builder Pattern. Utilizzare immagini di base più piccole è probabilmente il modo più semplice per ridurre le dimensioni del tuo container. È probabile che il linguaggio o lo stack che utilizzi fornisca un'immagine originale dell'applicazione di dimensioni molto più piccole rispetto all'immagine predefinita. Diamo un'occhiata al nostro container Node.js.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Per impostazione predefinita, la dimensione dell'immagine di base node:8 in Docker è di 670 MB, mentre la dimensione di node:8-alpine è di soli 65 MB, ovvero 10 volte inferiore. Utilizzando un'immagine di base più piccola come Alpine, ridurrai notevolmente la dimensione del tuo contenitore. Alpine è una distribuzione Linux leggera e piccola, molto popolare tra gli utenti di Docker, poiché è compatibile con molte applicazioni pur mantenendo dimensioni contenitoriali ridotte. A differenza dell'immagine standard di Docker "node", "node:alpine" rimuove molti file di servizio e programmi, lasciando solo quelli necessari per eseguire la tua applicazione.

Per passare a un'immagine di base più piccola, aggiorna semplicemente il file Docker per iniziare a utilizzare la nuova immagine di base:

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Ora, a differenza della vecchia immagine onbuild, dovrai copiare il tuo codice nel contenitore e installare tutte le dipendenze. Nel nuovo file Docker, il contenitore inizia con l'immagine node:alpine, crea quindi una directory per il codice, installa le dipendenze tramite il gestore pacchetti NPM e infine esegue server.js.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Con questo aggiornamento ottieni un contenitore di dimensioni dieci volte inferiori. Se il tuo linguaggio di programmazione o stack non dispone della funzione di riduzione dell'immagine di base, usa Alpine Linux. Ti offrirà anche la possibilità di gestire completamente il contenuto del contenitore. Utilizzare immagini di base di piccole dimensioni è un ottimo modo per creare rapidamente contenitori piccoli. Ma è possibile ottenere ulteriori riduzioni utilizzando il Builder Pattern.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Nei linguaggi interpretati, il codice sorgente viene prima passato all'interprete e poi eseguito direttamente. Nei linguaggi compilati, il codice sorgente viene prima convertito in codice compilato. Durante questo processo, la compilazione utilizza spesso strumenti che in realtà non sono necessari per eseguire il codice. Ciò significa che puoi rimuovere completamente questi strumenti dal contenitore finale. Per fare ciò, puoi utilizzare il Builder Pattern.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Il codice viene creato nel primo contenitore e compilato. Quindi, il codice compilato viene confezionato nel contenitore finale senza compilatori e strumenti necessari per compilare questo codice. Passiamo attraverso questo processo con un'applicazione Go. Prima di tutto, passeremo dall'immagine onbuild a Alpine Linux.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Nel nuovo file Docker, il contenitore inizia con l'immagine golang:alpine. Poi crea una directory per il codice, copia il codice sorgente, compila il sorgente e avvia l'applicazione. Questo contenitore è molto più piccolo rispetto al contenitore onbuild, ma contiene ancora il compilatore e altri strumenti Go che in realtà non ci servono. Quindi, estraiamo semplicemente il programma compilato e mettiamolo nel nostro contenitore.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Potresti notare qualcosa di strano in questo file Docker: contiene due righe FROM. La prima sezione, di 4 righe, appare esattamente come nel precedente file Docker, tranne per il fatto che utilizza la parola chiave AS per dare un nome a questa fase. Nella sezione successiva c'è una nuova riga FROM, permettendo di iniziare una nuova immagine, mentre invece di utilizzare l'immagine golang:alpine come immagine di base utilizzeremo Raw alpine.

Raw Alpine Linux non ha certificati SSL installati, il che porterà al fallimento della maggior parte delle chiamate API via HTTPS, quindi installiamo alcuni certificati CA radice.

E ora la parte interessante: per copiare il codice compilato dal primo contenitore al secondo, puoi semplicemente utilizzare il comando COPY, che si trova nella 5ª riga della seconda sezione. Copierà solo un file dell'applicazione e non toccherà gli strumenti di servizio Go. Il nuovo file Docker multistadio conterrà una immagine del contenitore di soli 12 megabyte, mentre l'immagine di base era di 700 megabyte, il che fa una grande differenza!
Pertanto, utilizzare immagini di base più piccole e il modello Builder è un ottimo modo per creare contenitori di dimensioni molto inferiori senza molto lavoro.
È possibile che, a seconda del stack dell'applicazione, ci siano modi aggiuntivi per ridurre le dimensioni dell'immagine e del contenitore, ma i contenitori piccoli hanno davvero un vantaggio misurabile? Esaminiamo due aspetti in cui i contenitori piccoli sono estremamente efficienti: sono le prestazioni e la sicurezza.

Per valutare l'aumento della produttività, consideriamo la durata del processo di creazione del contenitore, l'inserimento nel registro (push) e l'estrazione successiva da esso (pull). Puoi vedere che un contenitore di dimensioni più piccole ha un indiscutibile vantaggio rispetto a un contenitore di dimensioni maggiori.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Docker memorizzerà nella cache i layer, quindi le costruzioni successive verranno eseguite molto rapidamente. Tuttavia, in molti sistemi CI utilizzati per costruire e testare contenitori, i layer non vengono memorizzati nella cache, quindi c'è un notevole risparmio di tempo. Come puoi vedere, il tempo di costruzione di un contenitore di grandi dimensioni, a seconda della potenza della tua macchina, varia da 34 a 54 secondi, mentre per un contenitore ridotto tramite il Builder Pattern è compreso tra 23 e 28 secondi. Per operazioni di questo tipo, l'incremento della produttività sarà del 40-50%. Pertanto, pensa a quante volte crei e test di codice.

Dopo che il contenitore è stato costruito, devi inserire la sua immagine (push container image) nel registro dei contenitori per poi usarla nel tuo cluster Kubernetes. Ti consiglio di utilizzare il registro dei contenitori di Google.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Utilizzando Google Container Registry (GCR), paghi solo per lo storage 'grezzo' e per la rete, mentre non ci sono costi aggiuntivi per la gestione dei contenitori. È riservato, sicuro e molto veloce. GCR utilizza molti accorgimenti per accelerare l'operazione di pull. Come puoi vedere, l'inserimento dell'immagine del contenitore Docker Container Image utilizzando go:onbuild, a seconda della potenza del computer, richiederà dai 15 ai 48 secondi, mentre la stessa operazione con un contenitore di dimensioni minori richiederà da 14 a 16 secondi, e per macchine meno potenti, il vantaggio in termini di velocità aumenta di 3 volte. Per macchine di grandi dimensioni, il tempo è comunque simile, poiché GCR utilizza una cache globale per la base di immagini condivisa, il che significa che non è necessario caricarle affatto. Nei computer di bassa potenza, la CPU rappresenta il collo di bottiglia, quindi il vantaggio di utilizzare piccoli contenitori è molto più evidente.

Se utilizzi GCR, ti consiglio vivamente di utilizzare Google Container Builder (GCB) come parte del tuo sistema di costruzione.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Come potete vedere, il suo utilizzo consente di ottenere risultati significativamente migliori nella riduzione della durata dell'operazione Build+Push, rispetto anche a una macchina potente: in questo caso, il processo di costruzione e invio dei contenitori al host è quasi raddoppiato in velocità. Inoltre, ogni giorno ricevete 120 minuti di compilazione gratuitamente, il che nella maggior parte dei casi soddisfa le esigenze di creazione dei contenitori.

Successivamente, arriva la metrica prestazionale più importante: la velocità di estrazione o download dei contenitori Pull. E se non vi preoccupa molto il tempo impiegato per l'operazione push, la durata del processo pull influisce gravemente sulle prestazioni complessive del sistema. Supponiamo che abbiate un cluster di tre nodi e che uno di essi abbia un guasto. Se utilizzate un sistema di gestione, come Google Kubernetes Engine, esso sostituirà automaticamente il nodo non funzionante con uno nuovo. Tuttavia, questo nuovo nodo sarà completamente vuoto, e dovrete trasferirvi tutti i vostri contenitori affinché inizi a funzionare. Se l'operazione pull richiede troppo tempo, il vostro cluster lavorerà con una minore produttività per tutto quel tempo.

Ci sono molti casi in cui può verificarsi una situazione simile: aggiunta di un nuovo nodo al cluster, aggiornamento dei nodi o anche passaggio a un nuovo contenitore per il deployment. Pertanto, la minimizzazione del tempo di estrazione pull diventa un fattore cruciale. È innegabile che un piccolo contenitore si scarichi molto più rapidamente di uno grande. Se utilizzate più contenitori in un cluster Kubernetes, il risparmio di tempo può essere molto significativo.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

Date un'occhiata al confronto riportato: l'operazione pull con piccoli contenitori richiede da 4 a 9 volte meno tempo a seconda della potenza della macchina, rispetto alla stessa operazione utilizzando go:onbuild. Utilizzare immagini di base condivise di piccole dimensioni accelera notevolmente il tempo e la velocità con cui i nuovi nodi Kubernetes possono essere distribuiti e connessi a Internet.

Esaminiamo la questione della sicurezza. Si ritiene che i contenitori di dimensioni più piccole siano molto più sicuri rispetto a quelli più grandi, poiché hanno una superficie di attacco minore. È veramente così? Una delle funzionalità più utili di Google Container Registry è la possibilità di scansionare automaticamente i tuoi contenitori alla ricerca di vulnerabilità. Qualche mese fa, ho creato sia contenitori onbuild che multi-stadio, quindi vediamo se ci sono punti vulnerabili.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

I risultati sono sbalorditivi: nel contenitore piccolo sono state trovate solo 3 vulnerabilità medie, mentre nel grande ci sono 16 vulnerabilità critiche e 376 altre vulnerabilità. Se si esamina il contenuto del grande contenitore, si può notare che la maggior parte dei problemi di sicurezza non ha nulla a che fare con la nostra applicazione, ma è correlata a programmi che nemmeno utilizziamo. Pertanto, quando le persone parlano di una grande superficie di attacco, si riferiscono a questo.

Le migliori pratiche di Kubernetes. Creazione di piccoli container

La conclusione è chiara: crea contenitori piccoli, poiché offrono reali vantaggi in termini di prestazioni e sicurezza per il tuo sistema.

Le migliori pratiche di Kubernetes. Organizzazione di Kubernetes con spazi dei nomi

Guarda il video

Un po' di pubblicità 🙂

Grazie per rimanere con noi. Ti piacciono i nostri articoli? Vuoi vedere più contenuti interessanti? Supportaci effettuando un ordine o raccomandandoci a qualcuno. VPS cloud per sviluppatori a partire da $4.99., unica alternativa ai server entry-level, concepita da noi per te: Tutta la verità sui VPS (KVM) E5-2697 v3 (6 Core) 10GB DDR4 480GB SSD 1Gbps a partire da $19 o come dividere correttamente un server? (sono disponibili opzioni con RAID1 e RAID10, fino a 24 core e fino a 40GB DDR4).

Dell R730xd a metà prezzo nel data center Equinix Tier IV ad Amsterdam? Solo da noi 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TB a partire da $199 nei Paesi Bassi! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — a partire da $99! Leggi di Come costruire un'infrastruttura di livello enterprise utilizzando server Dell R730xd E5-2650 v4 del valore di 9000 euro a pochi spiccioli?

Fonte: habr.com

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