Pianifica la scalabilità


Questa pagina descrive le best practice generali per la progettazione di cluster GKE scalabili. Puoi applicare questi consigli a tutti i cluster e i carichi di lavoro per ottenere un rendimento ottimale. Questi consigli sono particolarmente importanti per i cluster che prevedi di scalare in modo significativo. Le best practice sono destinate agli amministratori responsabili del provisioning dell'infrastruttura e agli sviluppatori che preparano i componenti e i carichi di lavoro Kubernetes.

Che cos'è la scalabilità?

In un cluster Kubernetes, la scalabilità si riferisce alla capacità del cluster di crescere rimanendo entro i suoi obiettivi del livello di servizio (SLO). Kubernetes ha anche un proprio insieme di SLO

Kubernetes è un sistema complesso e la sua capacità di scalabilità è determinata da più fattori. Alcuni di questi fattori includono il tipo e il numero di nodi in un pool di nodi, i tipi e i numeri di node pool, il numero di pod disponibili, il modo in cui le risorse vengono allocate ai pod e il numero di servizi o backend dietro un servizio.

Best practice per la disponibilità

Scegliere un control plane regionale o zonale

A causa delle differenze architetturali, i cluster regionali sono più adatti all'alta disponibilità. I cluster regionali hanno più control plane in più zone di calcolo in una regione, mentre i cluster zonali hanno un control plane in una singola zona di computing.

Se viene eseguito l'upgrade di un cluster zonale, la VM del control plane subisce tempi di inattività durante i quali l'API Kubernetes non è disponibile finché l'upgrade non viene completato.

Nei cluster regionali, il control plane rimane disponibile durante la manutenzione del cluster, ad esempio la rotazione degli IP, l'upgrade delle VM del control plane o il ridimensionamento dei cluster o dei node pool. Quando esegui l'upgrade di un cluster regionale, almeno una delle più VM del control plane è sempre in esecuzione durante l'upgrade in sequenza, quindi l'API Kubernetes è ancora disponibile. Allo stesso modo, un'interruzione del servizio in una singola zona non causerà tempi di inattività nel control plane regionale.

Tuttavia, i cluster regionali con maggiore disponibilità presentano alcuni compromessi:

  • Le modifiche alla configurazione del cluster richiedono più tempo perché devono propagarsi a tutti i control plane di un cluster regionale anziché al singolo control plane dei cluster di zona.

  • Potresti non essere in grado di creare o eseguire l'upgrade dei cluster regionali con la stessa frequenza dei cluster zonali. Se non è possibile creare VM in una delle zone, a causa di una mancanza di capacità o di un altro problema temporaneo, non è possibile creare o aggiornare i cluster.

A causa di questi compromessi, i cluster zonali e regionali hanno casi d'uso diversi:

  • Utilizza i cluster di zona per creare o eseguire l'upgrade dei cluster rapidamente quando la disponibilità non è un problema.
  • Utilizza i cluster regionali quando la disponibilità è più importante della flessibilità.

Seleziona con attenzione il tipo di cluster quando ne crei uno, perché non potrai modificarlo dopo la creazione. Devi invece creare un nuovo cluster e poi migrare il traffico. La migrazione del traffico di produzione tra i cluster è possibile, ma difficile da scalare.

Scelta di pool di nodi multizona o a zona singola

Per ottenere un'alta disponibilità, il control plane Kubernetes e i relativi nodi devono essere distribuiti su zone diverse. GKE offre due tipi di pool di nodi: a zona singola e multi-zona.

Per eseguire il deployment di un'applicazione ad alta disponibilità, distribuisci il carico di lavoro in più zone di calcolo di una regione utilizzando pool di nodi multizona che distribuiscono i nodi in modo uniforme tra le zone.

Se tutti i nodi si trovano nella stessa zona, non potrai pianificare i pod se la zona non è più raggiungibile. L'utilizzo di node pool multizona comporta alcuni compromessi:

  • Le GPU sono disponibili solo in determinate zone. Potrebbe non essere possibile ottenerli in tutte le zone della regione.

  • La latenza di andata e ritorno tra le zone all'interno di una singola regione potrebbe essere superiore a quella tra le risorse in una singola zona. La differenza dovrebbe essere irrilevante per la maggior parte dei workload.

  • Il prezzo del traffico in uscita tra zone nella stessa regione è disponibile nella pagina dei prezzi di Compute Engine.

Best practice per la scalabilità

Infrastruttura di base

I carichi di lavoro Kubernetes richiedono networking, calcolo e archiviazione. Devi fornire CPU e memoria sufficienti per eseguire i pod. Tuttavia, esistono altri parametri dell'infrastruttura sottostante che possono influenzare le prestazioni e la scalabilità di un cluster GKE.

Networking per il cluster

L'utilizzo di un cluster nativo di VPC è l'impostazione predefinita di networking e la scelta consigliata per la configurazione di nuovi cluster GKE. I cluster VPC nativi consentono carichi di lavoro più grandi, un numero maggiore di nodi e altri vantaggi.

In questa modalità, la rete VPC ha un intervallo secondario per tutti gli indirizzi IP del pod. A ogni nodo viene quindi assegnata una parte dell'intervallo secondario per i propri indirizzi IP del pod. In questo modo, la rete VPC può comprendere in modo nativo come instradare il traffico verso i pod senza fare affidamento su route personalizzate. Una singola rete VPC può avere fino a 15.000 VM.

Un altro approccio, deprecato e che supporta non più di 1500 nodi, consiste nell'utilizzare un cluster basato su route. Un cluster basato su route non è adatto a carichi di lavoro di grandi dimensioni. Consuma la quota di route VPC e non offre altri vantaggi del networking VPC nativo. Aggiunge una nuova route personalizzata alla tabella di routing nella rete VPC per ogni nuovo nodo.

Dimensione cluster

I cluster con più di 5000 nodi devono utilizzare Private Service Connect. Private Service Connect collega privatamente i nodi e il control plane e offre una migliore sicurezza e prestazioni di rete.

Bilanciamento del carico del cluster

GKE Ingress e Cloud Load Balancing configurano ed eseguono il deployment dei bilanciatori del carico per esporre i workload Kubernetes all'esterno del cluster e anche a internet pubblico. I controller Ingress e Service di GKE eseguono il deployment di oggetti come regole di forwarding, mappe URL, servizi di backend, gruppi di endpoint di rete e altro ancora per conto dei carichi di lavoro GKE. Ognuna di queste risorse ha quote e limiti intrinseci e questi limiti si applicano anche in GKE. Quando una determinata risorsa Cloud Load Balancing ha raggiunto la quota, impedirà il deployment corretto di un determinato Ingress o Service e verranno visualizzati errori negli eventi della risorsa.

La tabella seguente descrive i limiti di scalabilità quando utilizzi GKE Ingress e Services:

Bilanciatore del carico Limite di nodi per cluster
Bilanciatore del carico di rete passthrough interno
Bilanciatore del carico di rete passthrough esterno 1000 nodi per zona
Application Load Balancer esterno
Bilanciatore del carico delle applicazioni interno Nessun limite di nodi

Se devi eseguire un ulteriore scalabilità, contatta il team di vendita Trusted Cloud by S3NS per aumentare questo limite.

DNS

La Service Discovery in GKE viene fornita tramite kube-dns, una risorsa centralizzata per fornire la risoluzione DNS ai pod in esecuzione all'interno del cluster. Questo può diventare un collo di bottiglia su cluster molto grandi o per carichi di lavoro con un carico di richieste elevato. GKE esegue automaticamente la scalabilità automatica di kube-dns in base alle dimensioni del cluster per aumentarne la capacità. Quando questa capacità non è ancora sufficiente, GKE offre la risoluzione distribuita e locale delle query DNS su ogni nodo con NodeLocal DNSCache. In questo modo viene fornita una cache DNS locale su ogni nodo GKE che risponde alle query localmente, distribuendo il carico e fornendo tempi di risposta più rapidi.

Gestione degli indirizzi IP nei cluster VPC nativi

Un cluster nativo di VPC utilizza tre intervalli di indirizzi IP:

  • Intervallo principale per la subnet del nodo: il valore predefinito è /20 (4092 indirizzi IP).
  • Intervallo secondario per la subnet dei pod: il valore predefinito è /14 (262.144 indirizzi IP). Tuttavia, puoi configurare la subnet dei pod.
  • Intervallo secondario per la subnet di servizio: il valore predefinito è /20 (4096 indirizzi). Tuttavia, non puoi modificare questo intervallo dopo aver creato questa subnet di servizio.

Per maggiori informazioni, vedi Intervalli IP per cluster VPC nativi.

Limitazioni e consigli per gli indirizzi IP:

  • Limite di nodi: il limite di nodi è determinato sia dall'IP primario sia dall'IP pod per nodo. Devono essere presenti indirizzi sufficienti negli intervalli di indirizzi IP di nodi e pod per eseguire il provisioning di un nuovo nodo. Per impostazione predefinita, puoi creare solo 1024 nodi a causa delle limitazioni dell'indirizzo IP del pod.
  • Limite di pod per nodo: per impostazione predefinita, il limite di pod per nodo è 110 pod. Tuttavia, puoi configurare CIDR pod più piccoli per un utilizzo efficiente con meno pod per nodo.
  • Scalabilità oltre RFC 1918: se hai bisogno di più indirizzi IP di quelli disponibili nello spazio privato definito da RFC 1918, ti consigliamo di utilizzare indirizzi privati non RFC 1918 o PUPI per una maggiore flessibilità.
  • Intervallo di indirizzi IP secondari per servizi e pod: per impostazione predefinita, puoi configurare 4096 servizi. Tuttavia, puoi configurare più servizi scegliendo l'intervallo di subnet del servizio. Non puoi modificare gli intervalli secondari dopo la creazione. Quando crei un cluster, assicurati di scegliere intervalli sufficientemente grandi da ospitare la crescita prevista. Tuttavia, puoi aggiungere altri indirizzi IP per i pod in un secondo momento utilizzando il CIDR multi-pod non contiguo.

Per ulteriori informazioni, consulta le seguenti risorse:

Configurazione dei nodi per un rendimento migliore

I nodi GKE sono normali macchine virtuali. Trusted Cloud Alcuni dei suoi parametri, ad esempio il numero di core o le dimensioni del disco, possono influire sul rendimento dei cluster GKE.

Riduzione dei tempi di inizializzazione dei pod

Puoi utilizzare il flusso dell'immagine per trasmettere i dati dalle immagini container idonee man mano che i carichi di lavoro li richiedono, il che comporta tempi di inizializzazione più rapidi.

Traffico in uscita

In Trusted Cloud, il tipo di macchina e il numero di core allocati all'istanza determinano la capacità di rete. La larghezza di banda in uscita massima varia da 1 a 32 Gbps, mentre la larghezza di banda in uscita massima per le macchine e2-medium-2 predefinite è 2 Gbps. Per informazioni dettagliate sui limiti di larghezza di banda, vedi Tipi di macchine con core condivisi.

IOPS e throughput del disco

In Trusted Cloud, le dimensioni dei dischi permanenti determinano le IOPS e il throughput del disco. GKE utilizza in genere i dischi permanenti come dischi di avvio e per il backup dei volumi permanenti di Kubernetes. L'aumento delle dimensioni del disco aumenta sia le IOPS sia il throughput, fino a determinati limiti.

Ogni operazione di scrittura su disco permanente contribuisce al limite di uscita di rete cumulativo dell'istanza di macchina virtuale. Pertanto, le prestazioni IOPS dei dischi, in particolare degli SSD, dipendono anche dal numero di vCPU nell'istanza, oltre alle dimensioni del disco. Le VM con meno core hanno limiti di IOPS di scrittura inferiori a causa delle limitazioni del traffico in uscita della rete sulla velocità effettiva di scrittura.

Se la tua istanza di macchina virtuale ha CPU insufficienti, la tua applicazione non sarà in grado di avvicinarsi al limite IOPS. Come regola generale, dovresti avere una CPU disponibile per ogni 2000-2500 IOPS di traffico previsto.

I carichi di lavoro che richiedono una capacità elevata o un numero elevato di dischi devono considerare i limiti del numero di PD che possono essere collegati a una singola VM. Per le VM regolari, questo limite è di 128 dischi con una dimensione totale di 64 TB, mentre le VM condivise hanno un limite di 16 dischi permanenti con una dimensione totale di 3 TB. Trusted Cloud impone questo limite, non Kubernetes.

Monitora le metriche del control plane

Utilizza le metriche del piano di controllo disponibili per configurare le dashboard di monitoraggio. Puoi utilizzare le metriche del control plane per osservare l'integrità del cluster, i risultati delle modifiche alla configurazione del cluster (ad esempio, il deployment di workload aggiuntivi o componenti di terze parti) o durante la risoluzione dei problemi.

Una delle metriche più importanti da monitorare è la latenza dell'API Kubernetes. Gli aumenti di latenza indicano che il sistema è sovraccarico. Tieni presente che le chiamate LIST che trasferiscono grandi quantità di dati dovrebbero avere una latenza molto più elevata rispetto alle richieste più piccole.

L'aumento della latenza dell'API Kubernetes può anche essere causato da risposte lente da parte di webhook di ammissione di terze parti. Puoi utilizzare le metriche per misurare la latenza dei webhook e rilevare questi problemi comuni.

Il limite superiore suggerito per una chiamata a una singola risorsa come GET, POST o PATCH è di un secondo. Il limite superiore suggerito per le chiamate LIST con ambito spazio dei nomi e cluster è di 30 secondi. Le aspettative del limite superiore sono stabilite dagli SLO definiti dalla community open source di Kubernetes. Per ulteriori informazioni, consulta Dettagli degli indicatori/obiettivi di livello di servizio della latenza delle chiamate API.

Best practice per gli sviluppatori Kubernetes

Utilizzare il modello di elenco e visualizzazione anziché la pubblicazione periodica

In qualità di sviluppatore Kubernetes, potresti dover creare un componente con i seguenti requisiti:

  • Il componente deve recuperare periodicamente l'elenco di alcuni oggetti Kubernetes.
  • Il componente deve essere eseguito in più istanze (nel caso di DaemonSet, anche su ogni nodo).

Un componente di questo tipo può generare picchi di carico su kube-apiserver, anche se lo stato degli oggetti recuperati periodicamente non cambia.

L'approccio più semplice consiste nell'utilizzare chiamate LIST periodiche. Tuttavia, questo è un approccio inefficiente e costoso sia per il chiamante che per il server perché tutti gli oggetti devono essere caricati in memoria, serializzati e trasferiti ogni volta. L'uso eccessivo di richieste LIST potrebbe sovraccaricare il piano di controllo o generare una forte limitazione di queste richieste.

Puoi migliorare il componente impostando il parametro resourceVersion=0 nelle chiamate LIST. Ciò consente a kube-apiserver di utilizzare la cache degli oggetti in memoria e riduce la frequenza con cui il server API Kubernetes interagisce con l'API etcd, il che riduce anche l'elaborazione correlata.

Ti consigliamo vivamente di evitare chiamate LIST ripetibili e di sostituirle con il pattern list and watch. Elenca gli oggetti una sola volta e poi utilizza l'API Watch per ottenere le modifiche incrementali dello stato. Questo approccio riduce i tempi di elaborazione e minimizza il traffico rispetto alle chiamate LIST periodiche. Quando gli oggetti non cambiano, non viene generato alcun carico aggiuntivo.

Se utilizzi il linguaggio Go, controlla SharedInformer e SharedInformerFactory per i pacchetti Go che implementano questo pattern.

Limitare il traffico non necessario generato da visualizzazioni ed elenchi

Kubernetes utilizza internamente watch per inviare notifiche sugli aggiornamenti degli oggetti. Anche se gli orologi richiedono molte meno risorse rispetto alle chiamate LIST periodiche, l'elaborazione degli orologi in cluster di grandi dimensioni può richiedere una parte significativa delle risorse del cluster e influire sulle prestazioni del cluster. L'impatto negativo maggiore si verifica quando si creano orologi che osservano oggetti che cambiano frequentemente da più luoghi. Ad esempio, osservando i dati di tutti i pod di un componente in esecuzione su tutti i nodi. Se installi codice o estensioni di terze parti sul tuo cluster, questi possono creare tali controlli in background.

Consigliamo le seguenti best practice:

  • Ridurre l'elaborazione e il traffico non necessari generati da orologi e chiamate LIST.
  • Evita di creare osservatori che osservano oggetti che cambiano frequentemente da più posizioni (ad esempio DaemonSet).
  • (Consigliato) Crea un controller centrale che monitori ed elabori i dati richiesti su un singolo nodo.
  • Osserva solo un sottoinsieme degli oggetti, ad esempio kubelet su ogni nodo osserva solo i pod pianificati sullo stesso nodo.
  • Evita di implementare componenti o estensioni di terze parti che potrebbero influire sul rendimento del cluster effettuando un volume elevato di chiamate WATCH o LIST.

Utilizza gli aggiornamenti in sequenza con i DaemonSet per evitare aumenti improvvisi del traffico

Quando viene creato un DaemonSet in un cluster, pianifica immediatamente un nuovo pod in ogni nodo. Se tutti questi nuovi pod si connettono allo stesso endpoint di rete, le richieste vengono eseguite simultaneamente, il che comporta un carico elevato sull'host di destinazione. Per evitare questo, configura i DaemonSet con aggiornamenti in sequenza con pod maxSurge limitati.

Limita le dimensioni del manifest dell'oggetto Kubernetes

Se hai bisogno di operazioni rapide che richiedono un'elevata velocità effettiva dei pod, come il ridimensionamento o l'aggiornamento di carichi di lavoro di grandi dimensioni, assicurati di ridurre al minimo le dimensioni dei manifest dei pod, idealmente inferiori a 10 KiB.

Kubernetes archivia i manifest delle risorse in un database che è un archivio chiave-valore. L'intero manifest viene inviato ogni volta che la risorsa viene recuperata, anche quando utilizzi il pattern di elenco e visualizzazione.

Le dimensioni del file manifest presentano le seguenti limitazioni:

  • Dimensione massima per ogni manifest dell'oggetto: circa 1,5 MiB.
  • Quota totale per tutti gli oggetti API di Kubernetes nel cluster: le dimensioni della quota preconfigurata sono 6 GiB. Ciò include un log delle modifiche con tutti gli aggiornamenti a tutti gli oggetti negli ultimi 150 secondi della cronologia del cluster.
  • Prestazioni del control plane durante i periodi di traffico elevato: le dimensioni maggiori del manifest aumentano il carico sul server API.

Per gli oggetti singoli e raramente elaborati, la dimensione del manifest di solito non è un problema purché sia inferiore a 1, 5 MiB. Tuttavia, dimensioni del manifest superiori a 10 KiB per numerosi oggetti elaborati di frequente, come i pod in workload molto grandi, possono causare un aumento della latenza delle chiamate API e una diminuzione delle prestazioni complessive. In particolare, gli elenchi e gli orologi possono essere influenzati in modo significativo dalle dimensioni elevate del file manifest. Potresti anche avere problemi con la quota del database dello stato del cluster, perché la quantità di revisioni negli ultimi 150 secondi può accumularsi rapidamente durante i periodi di traffico elevato del server API.

Per ridurre le dimensioni del manifest di un pod, è possibile utilizzare ConfigMap di Kubernetes per archiviare parte della configurazione, in particolare la parte condivisa da più pod nel cluster. Ad esempio, le variabili di ambiente vengono spesso condivise da tutti i pod in un workload.

Tieni presente che è anche possibile riscontrare problemi simili con gli oggetti ConfigMap se sono numerosi, grandi e vengono elaborati con la stessa frequenza dei pod. L'estrazione di una parte della configurazione è più utile quando riduce il traffico complessivo.

Disabilita il montaggio automatico del account di servizio predefinito

Se la logica in esecuzione nei pod non deve accedere all'API Kubernetes, devi disabilitare il montaggio automatico predefinito del service account per evitare la creazione di secret e monitoraggi correlati.

Quando crei un pod senza specificare un account di servizio, Kubernetes esegue automaticamente le seguenti azioni:

  • Assegna il account di servizio predefinito al pod.
  • Monta le credenziali del account di servizio come secret per il pod.
  • Per ogni secret montato, kubelet crea un'osservazione per monitorare le modifiche apportate a questo secret su ogni nodo.

Nei cluster di grandi dimensioni, queste azioni rappresentano migliaia di osservazioni non necessarie che potrebbero sovraccaricare in modo significativo kube-apiserver.

Utilizzare i buffer di protocollo anziché JSON per le richieste API

Utilizza i buffer di protocollo quando implementi componenti altamente scalabili, come descritto in Concetti dell'API Kubernetes.

L'API REST di Kubernetes supporta JSON e i buffer di protocollo come formato di serializzazione per gli oggetti. JSON viene utilizzato per impostazione predefinita, ma i buffer del protocollo sono più efficienti per le prestazioni su larga scala perché richiedono un'elaborazione meno intensiva della CPU e inviano meno dati sulla rete. L'overhead relativo all'elaborazione di JSON può causare timeout durante l'elenco di dati di grandi dimensioni.

Passaggi successivi