Introduzione
Kubernetes è un potente sistema open-source, sviluppato inizialmente da Google e supportato dalla Cloud Native Computing Foundation (CNCF), per gestire applicazioni containerizzate in un ambiente clusterizzato. Ha lo scopo di fornire migliori modalità di gestione di componenti e servizi correlati e distribuiti su infrastrutture variegate. Per saperne di più su Kubernetes, esplora la guida qui sotto. Se stai cercando un servizio di hosting Kubernetes gestito, controlla il nostro semplice servizio Kubernetes gestito progettato per la crescita.
In questa guida, discuteremo cosa sia Kubernetes, alcuni dei concetti di base di Kubernetes. Parleremo dell’architettura del sistema, dei problemi che risolve e del modello che utilizza per gestire distribuzioni containerizzate e scalabilità.
Cos’è Kubernetes?
Kubernetes, al suo livello di base, è un sistema per eseguire e coordinare applicazioni containerizzate su un cluster di macchine. È una piattaforma progettata per gestire completamente il ciclo di vita di applicazioni e servizi containerizzati utilizzando metodi che forniscono prevedibilità, scalabilità e alta disponibilità.
Come utente di Kubernetes, puoi definire come devono funzionare le tue applicazioni e i modi in cui devono poter interagire con altre applicazioni o con il mondo esterno. Puoi scalare i tuoi servizi verso l’alto o verso il basso, eseguire aggiornamenti rolling in modo elegante e passare il traffico tra diverse versioni delle tue applicazioni per testare funzionalità o annullare distribuzioni problematiche. Kubernetes fornisce interfacce e primitive di piattaforma componibili che ti consentono di definire e gestire le tue applicazioni con elevati livelli di flessibilità, potenza e affidabilità.
Architettura di Kubernetes
Per capire come Kubernetes sia in grado di fornire queste capacità, è utile avere un’idea di come sia progettato e organizzato a un livello più alto. Kubernetes può essere visualizzato come un sistema costruito a strati, con ogni livello superiore che astrae la complessità trovata nei livelli inferiori.
Alla base, Kubernetes riunisce singole macchine fisiche o virtuali in un cluster utilizzando una rete condivisa per comunicare tra ogni server, nuovamente che siano macchine fisiche o virtuali. Questo cluster Kubernetes è la piattaforma fisica dove vengono configurati tutti i componenti, le capacità e i carichi di lavoro di Kubernetes.
I macchinari nel cluster Kubernetes vengono ciascuno assegnati a un ruolo all’interno dell’ecosistema Kubernetes. Un server (o un piccolo gruppo in distribuzioni altamente disponibili) funge da server master. Questo server agisce come gateway e cervello del cluster, esponendo un’API Kubernetes per utenti e client, controllando lo stato di salute degli altri server, decidendo come suddividere e assegnare il lavoro (noto come “scheduling”) e orchestrando la comunicazione tra gli altri componenti (a volte chiamato orchestratore di container). Il server master agisce come punto di contatto principale con il cluster ed è responsabile della maggior parte della logica centralizzata fornita da Kubernetes.
Gli altri macchinari nel cluster sono designati come nodi: server responsabili di accettare ed eseguire carichi di lavoro utilizzando risorse locali ed esterne. Per aiutare con l’isolamento, la gestione e la flessibilità, Kubernetes esegue applicazioni e servizi in container, quindi ogni nodo deve essere dotato di un runtime container (come Docker o rkt). Il nodo riceve istruzioni di lavoro dal server master e crea o distrugge container di conseguenza, adattando le regole di rete per instradare e inoltrare il traffico in modo appropriato.
Come già accennato, le applicazioni e i servizi stessi vengono eseguiti nel cluster all’interno di contenitori. I componenti sottostanti si assicurano che lo stato desiderato delle applicazioni corrisponda allo stato effettivo del cluster. Gli utenti interagiscono con il cluster comunicando con il server API principale di Kubernetes direttamente o tramite client e librerie. Per avviare un’applicazione o un servizio, viene inviato un piano dichiarativo in JSON o YAML che definisce cosa creare e come gestirlo. Il server principale prende quindi il piano e determina come eseguirlo sull’infrastruttura esaminando i requisiti e lo stato attuale del sistema. Questo gruppo di applicazioni definite dall’utente che vengono eseguite secondo un piano specificato rappresenta l’ultimo strato di Kubernetes.
Componenti del Server Principale
Come descritto in precedenza, il server principale funge da piano di controllo primario per i cluster di Kubernetes. Serve come punto di contatto principale per amministratori e utenti e fornisce anche molti sistemi su scala cluster per i nodi lavoratori relativamente poco sofisticati. Complessivamente, i componenti sul server principale lavorano insieme per accettare le richieste degli utenti, determinare i modi migliori per pianificare i contenitori di carico di lavoro, autenticare client e nodi, regolare la rete su scala cluster e gestire le responsabilità di scaling e controllo della salute.
Questi componenti possono essere installati su una singola macchina o distribuiti su più server. Esamineremo ciascuno dei componenti individuali associati ai server principali per i cluster Kubernetes in questa sezione.
etcd
Uno dei componenti fondamentali necessari affinché Kubernetes funzioni è uno store di configurazione globalmente disponibile. Il progetto etcd, sviluppato dal team di CoreOS (sistema operativo), è uno store chiave-valore distribuito e leggero che può essere configurato per estendersi su più nodi.
Kubernetes utilizza etcd
per memorizzare dati di configurazione che possono essere accessibili da ciascuno dei nodi nel cluster. Questo può essere utilizzato per la scoperta dei servizi e può aiutare i componenti a configurarsi o riconfigurarsi in base a informazioni aggiornate. Aiuta anche a mantenere lo stato del cluster con funzionalità come l’elezione del leader e il blocco distribuito. Fornendo una semplice API HTTP/JSON, l’interfaccia per impostare o recuperare i valori è molto diretta.
Come la maggior parte degli altri componenti nel piano di controllo, etcd
può essere configurato su un singolo server principale o, in scenari di produzione, distribuito tra diversi macchine. L’unico requisito è che sia accessibile tramite rete da ciascuna delle macchine Kubernetes.
kube-apiserver
Uno dei servizi principali del master è un server API. Questo è il punto principale di gestione dell’intero cluster poiché consente a un utente di configurare i carichi di lavoro e le unità organizzative di Kubernetes. È anche responsabile di garantire che il negozio etcd
e i dettagli del servizio dei contenitori distribuiti siano in accordo. Funge da ponte tra vari componenti per mantenere la salute del cluster e diffondere informazioni e comandi.
Il server API implementa un’interfaccia RESTful, il che significa che molti strumenti e librerie differenti possono comunicare facilmente con esso. Un client chiamato kubectl è disponibile come metodo predefinito per interagire con il cluster Kubernetes da un computer locale.
kube-controller-manager
Il controller manager è un servizio generale che ha molte responsabilità. Principalmente, gestisce diversi controller che regolano lo stato del cluster, gestiscono i cicli di vita del carico di lavoro e eseguono compiti di routine. Ad esempio, un controller di replica garantisce che il numero di repliche (copie identiche) definite per un pod corrisponda al numero attualmente distribuito sul cluster. I dettagli di queste operazioni vengono scritti su etcd
, dove il controller manager osserva le modifiche tramite il server API.
Quando viene rilevata una modifica, il controller legge le nuove informazioni ed esegue la procedura che soddisfa lo stato desiderato. Ciò può comportare la scalabilità di un’applicazione verso l’alto o verso il basso, l’aggiustamento degli endpoint, eccetera.
kube-scheduler
Il processo che effettivamente assegna i carichi di lavoro a nodi specifici nel cluster è lo scheduler. Questo servizio legge i requisiti operativi di un carico di lavoro, analizza l’ambiente infrastrutturale attuale e posiziona il lavoro su un nodo o nodi accettabili.
Lo scheduler è responsabile del monitoraggio della capacità disponibile su ciascun host per assicurarsi che i carichi di lavoro non siano pianificati in eccesso rispetto alle risorse disponibili. Lo scheduler deve conoscere la capacità totale così come le risorse già allocate ai carichi di lavoro esistenti su ciascun server.
cloud-controller-manager
Kubernetes può essere implementato in molti ambienti diversi e può interagire con vari provider di infrastrutture per comprendere e gestire lo stato delle risorse nel cluster. Mentre Kubernetes lavora con rappresentazioni generiche di risorse come storage collegabile e bilanciatori di carico, ha bisogno di un modo per mappare queste risorse effettive fornite da provider cloud non omogenei.
I controller dei cloud fungono da collante che permette a Kubernetes di interagire con fornitori con diverse capacità, funzionalità e API mantenendo internamente costrutti relativamente generici. Ciò consente a Kubernetes di aggiornare le informazioni sullo stato in base alle informazioni raccolte dal fornitore di cloud, adattare le risorse cloud secondo le modifiche necessarie nel sistema e creare e utilizzare servizi cloud aggiuntivi per soddisfare i requisiti di lavoro inviati al cluster.
Componenti del server dei nodi
In Kubernetes, i server che eseguono il lavoro eseguendo contenitori sono noti come nodi. I server dei nodi hanno alcuni requisiti necessari per comunicare con i componenti principali, configurare la rete dei container ed eseguire i carichi di lavoro effettivi assegnati loro.
A Container Runtime
Il primo componente che ogni nodo deve avere è un runtime dei container. Tipicamente, questo requisito viene soddisfatto installando e eseguendo Docker, ma alternative come rkt e runc sono anche disponibili.
Il runtime del contenitore è responsabile per l’avvio e la gestione dei contenitori, applicazioni racchiuse in un ambiente operativo relativamente isolato ma leggero. Ogni unità di lavoro nel cluster è, al suo livello di base, implementata come uno o più contenitori che devono essere distribuiti. Il runtime del contenitore su ciascun nodo è il componente che alla fine esegue i contenitori definiti nei carichi di lavoro inviati al cluster.
kubelet
Il principale punto di contatto di ciascun nodo con il gruppo del cluster è un piccolo servizio chiamato kubelet. Questo servizio è responsabile per trasmettere informazioni da e verso i servizi del piano di controllo, oltre che interagire con il negozio etcd
per leggere i dettagli di configurazione o scrivere nuovi valori.
Il servizio kubelet
comunica con i componenti principali per autenticarsi al cluster e ricevere comandi e lavoro. Il lavoro è ricevuto sotto forma di un manifest che definisce il carico di lavoro e i parametri operativi. Il processo kubelet
assume quindi la responsabilità di mantenere lo stato del lavoro sul server del nodo. Controlla il runtime del contenitore per avviare o distruggere i contenitori secondo necessità.
kube-proxy
Per gestire la suddivisione in subnet degli host individuali e rendere i servizi disponibili ad altri componenti, viene eseguito un piccolo servizio proxy chiamato kube-proxy su ciascun server nodo. Questo processo inoltra le richieste ai contenitori corretti, può eseguire un bilanciamento di carico primitivo ed è generalmente responsabile di garantire che l’ambiente di rete sia prevedibile e accessibile, ma isolato quando appropriato.
Oggetti e Carichi di Lavoro di Kubernetes
Sebbene i contenitori siano il meccanismo sottostante utilizzato per distribuire le applicazioni containerizzate, Kubernetes utilizza ulteriori livelli di astrazione sopra l’interfaccia del contenitore per fornire funzionalità di scalabilità, resilienza e gestione del ciclo di vita. Invece di gestire direttamente i contenitori, gli utenti definiscono e interagiscono con istanze composte da varie primitive fornite dal modello di oggetti di Kubernetes. Esamineremo i diversi tipi di oggetti che possono essere utilizzati per definire questi carichi di lavoro di seguito.
Pods
A pod is the most basic unit that Kubernetes deals with. Containers themselves are not assigned to hosts. Instead, one or more tightly coupled containers are encapsulated in an object called a pod.
A pod generally represents containers that should be controlled as a single application. Pods consist of containers that operate closely together, share a life cycle, and should always be scheduled on the same node. They are managed entirely as a unit and share their environment, volumes, and IP space. In spite of their containerized implementation, you should generally think of pods as a single, monolithic application to best conceptualize how the cluster will manage the pod’s resources and scheduling.
Di solito, i pod sono composti da un contenitore principale che soddisfa lo scopo generale del carico di lavoro e facoltativamente alcuni contenitori ausiliari che facilitano compiti strettamente correlati. Si tratta di programmi che traggono vantaggio dall’essere eseguiti e gestiti nei propri contenitori, ma sono strettamente legati all’applicazione principale. Ad esempio, un pod può avere un contenitore che esegue il server dell’applicazione primaria e un contenitore ausiliario che scarica file nel filesystem condiviso quando vengono rilevate modifiche in un repository esterno. Di solito, lo scaling orizzontale non è incoraggiato a livello di pod perché ci sono altri oggetti di livello superiore più adatti per il compito.
Di solito, gli utenti non dovrebbero gestire direttamente i pod, perché non forniscono alcune delle funzionalità tipicamente necessarie nelle applicazioni (come la gestione del ciclo di vita sofisticata e lo scaling). Invece, agli utenti viene consigliato di lavorare con oggetti di livello superiore che utilizzano pod o modelli di pod come componenti di base ma implementano funzionalità aggiuntive.
Controller di Replicazione e Set di Replicazione
Spesso, quando si lavora con Kubernetes, anziché lavorare con singoli pod, si gestiranno invece gruppi di pod identici e replicati. Questi sono creati da modelli di pod e possono essere scalati orizzontalmente da controller noti come controller di replicazione e set di replicazione.
A replication controller is an object that defines a pod template and control parameters to scale identical replicas of a pod horizontally by increasing or decreasing the number of running copies. This is an easy way to distribute load and increase availability natively within Kubernetes. The replication controller knows how to create new pods as needed because a template that closely resembles a pod definition is embedded within the replication controller configuration.
Il controller di replica è responsabile di garantire che il numero di pod distribuiti nel cluster corrisponda al numero di pod nella sua configurazione. Se un pod o l’host sottostante falliscono, il controller avvierà nuovi pod per compensare. Se il numero di repliche nella configurazione di un controller cambia, il controller avvierà o terminerà i contenitori per corrispondere al numero desiderato. I controller di replica possono anche eseguire aggiornamenti progressivi per passare un insieme di pod a una nuova versione uno per uno, riducendo al minimo l’impatto sulla disponibilità dell’applicazione.
I set di replica sono un’iterazione sul design del controller di replica con una maggiore flessibilità nel modo in cui il controller identifica i pod che deve gestire. I set di replica stanno iniziando a sostituire i controller di replica a causa delle loro maggiori capacità di selezione delle repliche, ma non sono in grado di eseguire aggiornamenti progressivi per ciclare i back-end a una nuova versione come possono fare i controller di replica. Invece, i set di replica sono destinati ad essere utilizzati all’interno di unità aggiuntive di livello superiore che forniscono tale funzionalità.
Come i pod, sia i controller di replica che i set di replica sono raramente le unità con cui si lavora direttamente. Sebbene si basino sul design del pod per aggiungere scaling orizzontale e garanzie di affidabilità, mancano alcune delle capacità di gestione del ciclo di vita dettagliate trovate in oggetti più complessi.
Le distribuzioni
Le distribuzioni sono uno dei carichi di lavoro più comuni da creare e gestire direttamente. Le distribuzioni utilizzano gli insiemi di replica come blocchi di costruzione, aggiungendo funzionalità flessibili di gestione del ciclo di vita al mix.
Anche se le distribuzioni costruite con insiemi di replica possono sembrare duplicare la funzionalità offerta dai controller di replica, le distribuzioni risolvono molti dei problemi che esistevano nell’implementazione degli aggiornamenti progressivi. Quando si aggiornano le applicazioni con i controller di replica, agli utenti viene richiesto di presentare un piano per un nuovo controller di replica che sostituirebbe il controller attuale. Quando si utilizzano i controller di replica, compiti come tracciare la cronologia, recuperare dai guasti di rete durante l’aggiornamento e annullare le modifiche errate sono o difficili o lasciati alla responsabilità dell’utente.
Le distribuzioni sono un oggetto di alto livello progettato per semplificare la gestione del ciclo di vita dei pod replicati. Le distribuzioni possono essere modificate facilmente modificando la configurazione e Kubernetes si adatterà agli insiemi di replica, gestirà le transizioni tra diverse versioni dell’applicazione e, facoltativamente, manterrà automaticamente la cronologia degli eventi e le capacità di annullamento. A causa di queste caratteristiche, le distribuzioni saranno probabilmente il tipo di oggetto Kubernetes con cui lavorerai più frequentemente.
Insiemi di stato
Set di stato sono controller di pod specializzati che offrono garanzie di ordinamento e unicità. Principalmente, questi sono utilizzati per avere un controllo più dettagliato quando si hanno requisiti speciali legati all’ordinamento del rilascio, ai dati persistenti o alla rete stabile. Ad esempio, i set di stato sono spesso associati ad applicazioni orientate ai dati, come database, che necessitano di accesso agli stessi volumi anche se riavviati su un nuovo nodo.
I set di stato forniscono un identificatore di rete stabile creando un nome univoco basato su numeri per ogni pod che persiste anche se il pod deve essere spostato su un altro nodo. Allo stesso modo, i volumi di archiviazione persistenti possono essere trasferiti con un pod quando è necessario riavviarlo. I volumi persistono anche dopo che il pod è stato eliminato per evitare la perdita accidentale di dati.
Quando si distribuiscono o si regolano le dimensioni, i set di stato eseguono operazioni in base all’identificatore numerico nel loro nome. Ciò offre una maggiore prevedibilità e controllo sull’ordine di esecuzione, che può essere utile in alcuni casi.
Daemon Sets
Daemon Sets sono un’altra forma specializzata di controller di pod che eseguono una copia di un pod su ogni nodo del cluster (o su un sottoinsieme, se specificato). Questo è più spesso utile quando si distribuiscono pod che aiutano a eseguire la manutenzione e forniscono servizi per i nodi Kubernetes stessi.
Ad esempio, raccogliere e inoltrare i log, aggregare le metriche ed eseguire servizi che aumentano le capacità del nodo stesso sono candidati popolari per i set di demoni. Poiché i set di demoni spesso forniscono servizi fondamentali e sono necessari in tutto il fleet, possono aggirare le restrizioni sulla programmazione dei pod che impediscono ad altri controller di assegnare pod a determinati host. Come esempio, a causa delle sue responsabilità uniche, il server principale è spesso configurato per essere non disponibile per la normale programmazione dei pod, ma i set di demoni hanno la capacità di annullare la restrizione su base pod per garantire che i servizi essenziali siano in esecuzione.
Lavori e Cron Lavori
Le carichi di lavoro descritti finora hanno tutti presupposto un ciclo di vita simile a un servizio a lungo termine. Kubernetes utilizza un carico di lavoro chiamato lavori per fornire un flusso di lavoro più orientato al compito in cui ci si aspetta che i container in esecuzione escano con successo dopo un certo tempo una volta completato il loro lavoro. I lavori sono utili se è necessario eseguire un’elaborazione singola o batch invece di eseguire un servizio continuo.
La costruzione su lavori sono lavori cron. Come i demòni cron convenzionali su sistemi Linux e simili a Unix che eseguono script su un programma, i lavori cron in Kubernetes forniscono un’interfaccia per eseguire lavori con un componente di pianificazione. I lavori cron possono essere utilizzati per pianificare un lavoro da eseguire in futuro o su base regolare e ricorrente. I lavori cron di Kubernetes sono essenzialmente una reimplementazione del comportamento cron classico, utilizzando il cluster come piattaforma anziché un singolo sistema operativo.
Altri Componenti di Kubernetes
Oltre ai carichi di lavoro che è possibile eseguire su un cluster, Kubernetes fornisce una serie di altre astrazioni che ti aiutano a gestire le tue applicazioni, controllare la rete e abilitare la persistenza. Discuteremo qui alcuni degli esempi più comuni.
Servizi Kubernetes
Fino ad ora, abbiamo usato il termine “servizio” nel senso convenzionale, simile a Unix: per indicare processi in esecuzione prolungata, spesso connessi in rete, in grado di rispondere a richieste. Tuttavia, in Kubernetes, un servizio è un componente che funge da bilanciatore di carico interno di base e ambasciatore per i pod. Un servizio raggruppa insieme raccolte logiche di pod che svolgono la stessa funzione per presentarli come un’unica entità.
Questo ti consente di distribuire un servizio che può tenere traccia e instradare tutti i contenitori di backend di un tipo particolare. Gli utenti interni devono solo conoscere il punto di accesso stabile fornito dal servizio. Nel frattempo, l’astrazione del servizio ti consente di scalare o sostituire le unità di lavoro di backend secondo necessità. L’indirizzo IP di un servizio rimane stabile indipendentemente dalle modifiche ai pod a cui è indirizzato. Deployando un servizio, ottieni facilmente una maggiore visibilità e puoi semplificare i tuoi progetti di contenitori.
Ogni volta che è necessario fornire l’accesso a uno o più pod a un’altra applicazione o a utenti esterni, è necessario configurare un servizio. Ad esempio, se hai un insieme di pod che eseguono server web che devono essere accessibili da Internet, un servizio fornirà l’astrazione necessaria. Allo stesso modo, se i tuoi server web devono archiviare e recuperare dati, vorresti configurare un servizio interno per consentire loro di accedere ai tuoi pod di database.
Anche se i servizi, per impostazione predefinita, sono disponibili solo utilizzando un indirizzo IP internamente instradabile, possono essere resi disponibili al di fuori del cluster scegliendo una delle varie strategie. La configurazione NodePort funziona aprendo una porta statica sull’interfaccia di rete esterna di ciascun nodo. Il traffico alla porta esterna verrà instradato automaticamente ai pod appropriati utilizzando un servizio IP di cluster interno.
Alternativamente, il tipo di servizio LoadBalancer crea un bilanciamento del carico esterno per instradare il servizio utilizzando l’integrazione del bilanciamento del carico di Kubernetes del provider cloud. Il gestore del controller cloud creerà la risorsa appropriata e la configurerà utilizzando gli indirizzi del servizio interno.
Volumi e Volumi Persistenti
Condividere in modo affidabile i dati e garantirne la disponibilità tra riavvii del contenitore è una sfida in molti ambienti containerizzati. Le runtime dei contenitori spesso forniscono un meccanismo per collegare uno storage a un contenitore che persiste oltre la durata del contenitore stesso, ma le implementazioni tipicamente mancano di flessibilità.
Per affrontare questo problema, Kubernetes utilizza la sua astrazione dei volumi che consente ai dati di essere condivisi da tutti i contenitori all’interno di una pod e rimanere disponibili fino alla terminazione della pod stessa. Ciò significa che le pod strettamente accoppiate possono condividere facilmente file senza meccanismi esterni complessi. I fallimenti del contenitore all’interno della pod non influenzeranno l’accesso ai file condivisi. Una volta terminata la pod, il volume condiviso viene distrutto, quindi non è una buona soluzione per dati veramente persistenti.
I volumi persistenti sono un meccanismo per astrarre uno storage più robusto che non è legato al ciclo di vita della pod. Invece, consentono agli amministratori di configurare risorse di storage per il cluster che gli utenti possono richiedere e reclamare per le pod che stanno eseguendo. Una volta che una pod ha finito con un volume persistente, la politica di riacquisizione del volume determina se il volume viene mantenuto fino alla cancellazione manuale o rimosso insieme ai dati immediatamente. I dati persistenti possono essere utilizzati per proteggere contro i fallimenti basati sul nodo e per allocare quantità di storage maggiori di quelle disponibili localmente.
Etichette e Annotazioni
A Kubernetes organizational abstraction related to, but outside of the other concepts, is labeling. A label in Kubernetes is a semantic tag that can be attached to Kubernetes objects to mark them as a part of a group. These can then be selected for when targeting different instances for management or routing. For instance, each of the controller-based objects use labels to identify the pods that they should operate on. Services use labels to understand the backend pods they should route requests to.
Le etichette sono fornite come semplici coppie chiave-valore. Ogni unità può avere più di una etichetta, ma ogni unità può avere solo una voce per ogni chiave. Di solito, una chiave “nome” viene utilizzata come identificatore a uso generale, ma è possibile classificare ulteriormente gli oggetti in base ad altri criteri come lo stadio di sviluppo, l’accessibilità pubblica, la versione dell’applicazione, ecc.
Le annotazioni sono un meccanismo simile che consente di allegare informazioni chiave-valore arbitrarie a un oggetto. Mentre le etichette dovrebbero essere utilizzate per informazioni semantiche utili per abbinare un pod con criteri di selezione, le annotazioni sono più libere e possono contenere dati meno strutturati. In generale, le annotazioni sono un modo per aggiungere metadati ricchi a un oggetto che non sono utili per scopi di selezione.
Conclusione
Source:
https://www.digitalocean.com/community/tutorials/an-introduction-to-kubernetes