Kubernetes o K8s è una piattaforma di orchestrazione di container open source, sviluppata originariamente da Google. È stata progettata per automatizzare il funzionamento dei container Linux, sia che vengano eseguiti su sistemi locali, centri dati o nel cloud.
Dal suo rilascio iniziale nel 2014, Kubernetes ha ottenuto una grande diffusione nelle aziende. Il suo grande punto di forza e la ragione della sua popolarità è la capacità di gestire un gran numero di container. In Kubernetes, l'orchestrazione comporta il monitoraggio, il roll out, la correzione, la copia e la migrazione automatica dei container.
Nonostante la sua popolarità, nemmeno gli esperti riescono a comprendere completamente Kubernetes. Pur avendo una gerarchia ben definita, è composto da molti oggetti e funzioni specifiche che interagiscono tra loro, rendendolo una tecnologia complessa e stratificata. In questo articolo cercheremo di offrire una panoramica semplificata dell’architettura e dei principali oggetti di Kubernetes. L’utilizzo di Kubernetes inizia sempre con la creazione di un cluster.
Che cos'è un cluster Kubernetes?
Utilizzare Kubernetes significa generalmente gestire uno o più cluster. In genere, un cluster è costituito da un piano di controllo, che controlla tutti gli oggetti del cluster, e da uno o più nodi worker che eseguono le applicazioni containerizzate. Per garantire la ridondanza dell'ambiente Kubernetes, la configurazione predefinita di un cluster consiste spesso in tre nodi del piano di controllo e tre nodi worker.
Per l'orchestrazione dei nodi worker, il piano di controllo in un cluster comprende i seguenti componenti:
- Server API: Il server API funge da front-end del piano di controllo di Kubernetes. Può essere utilizzato per leggere lo stato desiderato del cluster e determinare quali applicazioni K8 devono essere eseguite e come.
- Scheduler: Lo scheduler posiziona i container in base ai requisiti di risorse definiti e assegna i pod liberi a un nodo.
- Controller manager: Il controller manager confronta lo stato effettivo del cluster con le specifiche fornite.
- Etcd: Etcd è uno store coerente e altamente disponibile per la memorizzazione di tutti i dati critici del cluster, come la configurazione, lo stato e i metadati di Kubernetes.
I nodi worker eseguono i due componenti kubelet e kube-proxy, responsabili del controllo dei container e della comunicazione tra i nodi.
Un cluster è quindi composto da diversi nodi. Ma cosa fanno esattamente i nodi?
Cos'è un nodo Kubernetes?
I nodi sono gli elementi centrali di un cluster. Si distingue tra nodi del piano di controllo e nodi worker. Mentre il nodo master è responsabile dell'amministrazione del cluster, i nodi worker forniscono le risorse e i servizi necessari per il funzionamento dei carichi di lavoro.
Suggerimento pratico: Il ruolo di un nodo può essere riconosciuto dalle etichette "control-plane" o "master" utilizzando kubectl get nodes
.
Ospitando i pod, i nodi worker consentono l'esecuzione dei carichi di lavoro effettivi. In questo modo, i nodi agiscono come un pool di risorse CPU e RAM su cui Kubernetes esegue successivamente i carichi di lavoro containerizzati.
Anche se di solito devi comunque gestire direttamente le macchine fisiche o virtuali, Kubernetes ti solleva dalla decisione su quale nodo eseguirà l'applicazione e se su quel nodo ci sono risorse sufficienti.
In pratica, quando distribuisci un'applicazione in un cluster, Kubernetes suddivide il carico di lavoro tra i nodi. Può anche spostare i carichi tra i nodi in modo automatico.
In Kubernetes puoi utilizzare i cluster per separare applicazioni e risorse appartenenti a team diversi. Nelle infrastrutture IT tradizionali, questo veniva spesso realizzato tramite macchine virtuali, reti separate o ambienti distinti. In Kubernetes, invece, esiste uno strumento collaudato ed efficiente per suddividere i cluster in aree isolate: i namespace.
Cosa sono i namespace in Kubernetes?
I namespace consentono di dividere i cluster Kubernetes in aree logiche isolate. Ogni cluster supporta un numero qualsiasi di namespace, ma i namespace stessi non possono essere annidati.
Possono essere utilizzati, ad esempio, per organizzare le risorse dell'infrastruttura Kubernetes. Pertanto, uno spazio dei nomi può essere considerato come una sorta di sotto-cluster virtuale.
Quasi tutte le risorse di Kubernetes si trovano in uno spazio dei nomi predefinito o in uno spazio dei nomi creato manualmente. Tuttavia, i nodi e i volumi persistenti fanno eccezione. Entrambi sono cosiddetti risorse di basso livello ed esistono al di fuori degli spazi dei nomi, quindi sono sempre visibili a tutti gli spazi dei nomi del cluster.
Suggerimento pratico: tutti gli oggetti non legati a uno spazio dei nomi possono essere trovati da kubectl api-resources --namespaced=false
Perché è consigliabile usare i namespace?
Come già accennato, i namespace permettono a team diversi di lavorare insieme all’interno del proprio cluster virtuale, ad esempio nell’ambito di progetti. In questo modo, l’ambiente dei singoli team non viene influenzato. Allo stesso tempo, i namespace possono essere utilizzati per condividere le risorse di un cluster tra più team e utenti tramite le resource quotas.
I namespace possono anche essere impiegati per limitare l’accesso di utenti e carichi di lavoro a specifici namespace. Offrono un modo semplice per separare sviluppo, test e operazioni di un’applicazione – permettendo così di gestire l’intero ciclo di vita all’interno dello stesso cluster.
La comunicazione avviene tra i namespace?
I namespace sono separati gli uni dagli altri, ma possono comunicare facilmente tra loro. Il servizio DNS di Kubernetes è in grado di individuare qualsiasi servizio per nome, utilizzando una forma estesa di indirizzamento DNS (svc.cluster.local). L'aggiunta del nome del namespace al nome del servizio consente di accedere ai servizi in qualsiasi namespace del cluster.
Suggerimento pratico: Una query su service.namespace
è identica a service.namespace.svc.cluster.local
Facoltativamente, è possibile utilizzare le policy di rete per gestire l’accesso tra namespace, ad esempio per consentire o bloccare tutto il traffico proveniente da altri namespace.
Finora hai imparato cosa sono i cluster e i nodi, e come i namespace possano essere utilizzati per suddividere logicamente un cluster. Abbiamo anche visto che i nodi worker ospitano i pod, senza però approfondirli. Recupereremo questo aspetto nelle prossime sezioni.
Che cos'è un pod Kubernetes?
Un pod è un ambiente che viene distribuito su un nodo ed esegue un container. Sebbene sia possibile eseguire più container all’interno di un singolo pod, questa è solitamente un’eccezione.
I pod possono essere paragonati a computer indipendenti che svolgono un singolo compito. Se si modifica la configurazione di un pod, Kubernetes applica automaticamente le modifiche creando o rimuovendo nuovi pod.
Nel caso in cui un nodo vada in errore, Kubernetes distribuisce automaticamente i pod interessati su un altro nodo. Se un pod risulta non funzionante in base a un controllo di integrità (health check), Kubernetes lo riavvia. I pod vengono raramente definiti direttamente in Kubernetes. Di norma, vengono creati tramite meccanismi di livello superiore come deployments, DaemonSet e job. Se i pod dipendono dallo stato del sistema, la loro creazione avviene spesso tramite StatefulSet.
Suggerimento pratico: L'attributo "Controlled By" (controllato da) sull'output via kubectl describe pod [podname]
può essere usato per identificare come è stato creato un pod. Se il campo è vuoto, il pod è stato avviato senza meccanismi di livello superiore.
Cosa sono i deployment in Kubernetes?
I deployment sono uno dei primi meccanismi di creazione dei carichi di lavoro in Kubernetes. Nella definizione di un deployment puoi specificare quali immagini deve utilizzare l’applicazione, quanti pod sono necessari e come Kubernetes deve gestirne l’aggiornamento. Questo semplifica l’intero processo di aggiornamento e ne consente l’automazione e la ripetizione.
In concreto, i deployment consentono di eseguire il provisioning dei pod e di aggiornarli, di tornare alle versioni precedenti del deployment e di scalare, mettere in pausa o riprendere i deployment. Una volta creato un deployment, il control plane di Kubernetes si occupa automaticamente della pianificazione delle istanze applicative.
I deployment sono particolarmente adatti alle applicazioni stateless. Questo per motivi storici, dato che Kubernetes è stato inizialmente progettato proprio per gestire applicazioni stateless. Con il tempo, però, è emersa la necessità di supportare anche applicazioni stateful. Per questo motivo sono stati introdotti i cosiddetti StatefulSet.
Cosa sono gli StatefulSet?
Kubernetes utilizza StatefulSets per controllare l'esecuzione di applicazioni stateful che richiedono identità e nomi di host persistenti. In pratica, questo significa che gestisce il provisioning e lo scaling dei pod contenuti nell'insieme, garantendo al contempo l'ordine e l'unicità di tali pod.
Ad esempio, con StatefulSets per un database MySQL, scalato a tre repliche in un cluster Kubernetes, è possibile specificare che un'applicazione front-end acceda a tutti e tre i pod per i processi di lettura. Per i processi di scrittura, invece, si rivolge solo al primo pod, sincronizzando successivamente i dati con gli altri due pod.
Gli StatefulSet assegnano un'identità immutabile a ogni pod, a partire da 0 (0 -> n). Un nuovo pod viene creato clonando i dati del pod precedente. L'eliminazione o la terminazione avvengono in ordine inverso (n -> 0). Quindi, se si riduce il numero di repliche da quattro a tre, Kubernetes termina o elimina il pod con il numero 3 per primo.
Gli StatefulSet sono particolarmente adatti alle applicazioni che richiedono almeno uno dei seguenti elementi: identificatori di rete stabili e univoci, storage stabile e persistente, provisioning ordinato e regolamentato e aggiornamenti continui ordinati e automatici.
Uno StatefulSet creato assicura che il numero desiderato di pod sia in esecuzione e disponibile. Sostituisce automaticamente i pod falliti o rimossi dal nodo in base alle specifiche configurate nel set.
L'eliminazione di uno StatefulSet non comporta l'eliminazione automatica dei dati sui volumi associati, per motivi di sicurezza dei dati.
Oltre alle distribuzioni e agli StatefulSet, Kubernetes fornisce un altro meccanismo per l'avvio dei pod sotto forma di DaemonSet.
Cosa sono i DaemonSet?
Con i DaemonSet puoi avviare un pod specifico su ciascun nodo worker. Questo li rende ideali per applicazioni che devono essere eseguite su ogni singolo nodo. Un esempio tipico è un demone di logging che raccoglie i log da tutti i container e li invia a un server di log centralizzato.
Nel prossimo passaggio vedremo come i vari oggetti e funzioni in Kubernetes comunicano tra loro. Si distingue tra comunicazione interna ed esterna. Per la comunicazione tra oggetti all'interno di un cluster, Kubernetes utilizza i cosiddetti Service.
Cosa sono i servizi in Kubernetes?
I servizi in Kubernetes sono un'astrazione logica per un gruppo di pod in un cluster che svolgono la stessa funzione. Un servizio assegna un nome e un indirizzo IP univoco (clusterIP) a questo gruppo di pod in modo che sia raggiungibile dagli altri pod. Inoltre, imposta le politiche di accesso e gestisce il bilanciamento automatico del carico di tutte le richieste in arrivo.
Poiché un servizio gestisce la scoperta e l'instradamento tra pod dipendenti, come i componenti front-end e back-end, se un pod muore e viene replicato, l'applicazione non ne risente.
Per collegare i pod in un gruppo, i servizi utilizzano etichette e selettori.
Oltre alla comunicazione interna, tuttavia, le applicazioni devono essere in grado di comunicare con l'esterno. Questo avviene tramite Ingress.
Che cos'è Kubernetes Ingress?
Kubernetes Ingress è un'interfaccia che consente agli utenti esterni di accedere ai servizi di un cluster Kubernetes tramite HTTP/HTTPS. Ingress consente anche di creare regole per l'instradamento del traffico senza dover creare bilanciatori di carico o esporre tutti i servizi su un nodo.
Hai ora appreso i principali oggetti di Kubernetes. Ciò che ti manca adesso è sapere come distribuire un’applicazione su Kubernetes per la prima volta.
Come si fa il roll-out delle applicazioni in Kubernetes?
Per lanciare un’applicazione in Kubernetes, devi creare ed eseguire un manifesto. Un manifesto è un file JSON o YAML in cui specifichi quali oggetti - deployment, service, pod, ecc. - vuoi creare, come devono funzionare nel cluster, quale immagine del container utilizzare e quante repliche Kubernetes deve creare. Successivamente, distribuisci il manifesto nel cluster tramite la riga di comando (kubectl) o tramite una pipeline di integrazione continua (CI).
Per la sua facilità d’uso, la maggior parte dei nuovi utenti Kubernetes scrive i manifesti in YAML. Tuttavia, un manifesto ha lo svantaggio di essere molto statico e poco flessibile. Per questo motivo, a un certo punto gli utenti Kubernetes passano solitamente ai Helm chart. Helm è un package manager per Kubernetes che facilita in particolare la distribuzione di applicazioni altamente ripetibili. Un Helm chart è un pacchetto composto da uno o più manifesti rielaborati in template con variabili. Le variabili possono essere comodamente specificate tramite un altro file YAML, che viene fornito a Helm. Sfortunatamente, questo spesso rende i template quasi illeggibili.
Un altro metodo per distribuire applicazioni è il cosiddetto Kubernetes operator. Si tratta di un controller che automatizza ulteriormente questo processo. In pratica, significa codificare la conoscenza sul ciclo di vita di un’applicazione. Di conseguenza, gli operator permettono di gestire e scalare applicazioni stateless, come applicazioni web o servizi API, senza dover conoscere i dettagli del loro funzionamento. In questo modo, un operator riduce le operazioni manuali necessarie per gestire i carichi di lavoro su Kubernetes. Tuttavia, programmare un operator richiede competenze specifiche.
DOMANDE FREQUENTI
Per distribuire le applicazioni, di solito si usano i deployments o gli StatefulSets. La differenza tra deployments e StatefulSets può essere spiegata storicamente: Agli inizi, K8s era limitato alle applicazioni stateless. Col tempo, tuttavia, si è capito che le applicazioni statiche non potevano essere mappate con le distribuzioni. Di conseguenza, sono stati introdotti gli StatefulSet.
Le applicazioni stateful sono applicazioni che memorizzano e tengono traccia dei dati. Ad esempio, i database come MySQL, Oracle e PostgeSQL sono esempi di applicazioni di questo tipo. Le applicazioni stateless, invece, non memorizzano i dati, ma li elaborano di volta in volta con ogni richiesta, ad esempio passandoli a un'applicazione stateful.
Le distribuzioni possono essere create e gestite utilizzando YAML o JSON con kubectl. L'interfaccia a riga di comando comunica con l'API di Kubernetes per interagire con il cluster. Una volta creato un pod del deployment, un controller del deployment Kubernetes monitora continuamente le istanze. Se un nodo che esegue un'istanza si guasta, il controller sostituisce l'istanza con una nuova su un altro nodo del cluster. In questo modo, Kubernetes fornisce un processo di auto-riparazione progettato per evitare guasti al sistema.
Come suggerisce il nome, l'Horizontal Pod Autoscaler (HPA) scala automaticamente il numero di pod, ad esempio, da una distribuzione. Per l'autoscaling usa l'utilizzo medio della CPU del target assegnato o le metriche fornite dall'applicazione. In questo modo, l'HPA garantisce che vengano lanciati pod aggiuntivi durante i picchi di prestazioni e che l'applicazione continui a funzionare. L'HPA rende Kubernetes particolarmente efficace durante i picchi di carico di lavoro e fornisce una protezione contro i guasti del sistema.
Importante: è necessario specificare il valore al quale l'HPA deve avviare nuovi pod o eliminare quelli esistenti quando si crea l'installazione client.
Esistono diversi modi per monitorare Kubernetes. Lo stato delle applicazioni può essere facilmente controllato utilizzando gli health endpoint. Se si verifica un problema, Kubernetes offre, ad esempio, con kubectl, uno strumento di bordo per interrogare i log dei container per la risoluzione dei problemi tramite l'API.
Chi ha bisogno di una visione più approfondita sul consumo delle risorse deve integrare strumenti aggiuntivi. Ad esempio, con Kubernetes Dashboard è possibile visualizzare facilmente alcune metriche. Chi invece necessita di una panoramica completa su tutti gli aspetti dell’ambiente Kubernetes, insieme al rilevamento automatico di stati problematici e a un sistema di allerta intelligente, dovrebbe utilizzare una soluzione di monitoraggio per Kubernetes come Checkmk.