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 di cui prevedi di scalare su larga scala. Le best practice sono destinate agli amministratori responsabili del provisioning dell'infrastruttura e agli sviluppatori che preparano componenti e carichi di lavoro Kubernetes.
Che cos'è la scalabilità?
In un cluster Kubernetes, per scalabilità si intende la capacità del cluster di crescere mantenendosi all'interno obiettivi del livello di servizio (SLO). Kubernetes ha anche il suo insieme di SLO
Kubernetes è un sistema complesso e la sua scalabilità è determinata più fattori. Alcuni di questi fattori includono il tipo e il numero di nodi un pool di nodi, i tipi e il numero di pool di nodi, 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 piano di controllo regionale o zonale
A causa delle differenze di architettura, i cluster a livello di regione sono più adatti per la disponibilità elevata. I cluster a livello di regione hanno più piani di controllo su più zone di computing in una regione, mentre i cluster di zona hanno un piano di controllo in una singola zona di computing.
Se viene eseguito l'upgrade di un cluster zonale, la VM del piano di controllo presenta un tempo di riposo durante il quale l'API Kubernetes non è disponibile fino al completamento dell'upgrade.
Nei cluster regionali, il piano di controllo rimane disponibile durante la manutenzione del cluster, ad esempio la rotazione degli IP, l'upgrade delle VM del piano di controllo o il ridimensionamento dei cluster o dei pool di nodi. Quando esegui l'upgrade di un cluster a livello di regione, due piani di controllo su tre Le VM sono sempre in esecuzione durante l'upgrade in sequenza, quindi l'API Kubernetes ancora disponibili. Analogamente, un'interruzione in una singola zona non causerà tempi di inattività a livello di regione.
Tuttavia, i cluster a livello di regione con disponibilità più elevata includono compromessi:
Le modifiche alla configurazione del cluster richiedono più tempo perché devono essere propagate a tutti i control plane in un cluster a livello di regione anziché al singolo control plane nei 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, per mancanza di capacità o per altri problemi temporanei, non è possibile creare o eseguire l'upgrade dei cluster.
A causa di questi compromessi, i cluster a livello di zona e di regione hanno casi d'uso diversi:
- Utilizza i cluster di zona per creare o eseguire l'upgrade dei cluster rapidamente in base alla disponibilità non è un problema.
- Utilizza i cluster a livello di regione quando la disponibilità è più importante della flessibilità.
Seleziona attentamente il tipo di cluster quando lo crei, perché non potrai modificarlo dopo la creazione. Devi invece creare un nuovo cluster e poi migrarvi il traffico. La migrazione del traffico di produzione tra i cluster è possibile, ma difficile su larga scala.
Scelta di pool di nodi multi-zona o a zona singola
Per ottenere un'alta disponibilità, il piano di controllo di Kubernetes e i relativi nodi devono essere distribuiti in zone diverse. GKE offre due tipi di nodi pool: a zona singola e multi-zona.
Per eseguire il deployment di un'applicazione ad alta disponibilità, distribuisci il carico di lavoro su più zone di calcolo in una regione utilizzando pool di nodi multizonali 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 diventa irraggiungibile. L'uso di pool di nodi multi-zona prevede alcune compromessi:
Le GPU sono disponibili solo in zone specifiche. 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 di una singola zona. La differenza dovrebbe essere irrilevante per la maggior parte dei carichi di lavoro.
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, computing e archiviazione. Devi fornire CPU e memoria sufficienti per eseguire i pod. Tuttavia, esistono altri parametri dell'infrastruttura di base che possono influire sul rendimento e sulla scalabilità di un cluster GKE.
Networking per il cluster
L'utilizzo di un cluster nativo di VPC è l'impostazione predefinita di networking scelta consigliata per la configurazione nei nuovi cluster GKE. I cluster nativi VPC 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 i pod e gli indirizzi IP esterni. A ogni nodo viene quindi assegnato un segmento dell'intervallo secondario per i suoi indirizzi IP del pod. In questo modo, la rete VPC può comprendere in modo nativo come instradare il traffico ai pod senza fare affidamento su route personalizzate. R una singola rete VPC può avere fino a 15.000 VM.
Un altro approccio, deprecato e che non supporta più di 1500 nodi, consiste nell'utilizzare un cluster basato su route. Un cluster basato su route non è adatto per carichi di lavoro di grandi dimensioni. Utilizza la quota di route VPC e non presenta altri vantaggi il networking nativo di VPC. Funziona aggiungendo una nuova route personalizzata alla tabella di routing nel rete VPC per ogni nuovo nodo.
Cluster privati
Nei cluster GKE standard, tutti i nodi hanno indirizzi IP pubblici. Nei cluster privati, i nodi hanno solo indirizzi IP interni per isolarli dalla connettività di rete in entrata e in uscita con internet. GKE utilizza il peering di rete VPC per connettere le VM che eseguono il server API Kubernetes con il resto del cluster. Ciò consente di ottenere tra piani di controllo e nodi di GKE, poiché il traffico viene instradato tramite indirizzi IP privati.
L'uso dei cluster privati presenta il vantaggio di sicurezza aggiuntivo, che i nodi non sono esposte a internet.
Bilanciamento del carico del cluster
GKE Ingress e Cloud Load Balancing configurano ed eseguono il deployment di bilanciatori del carico per esporre i carichi di lavoro Kubernetes all'esterno del cluster e anche all'internet pubblico. I controller GKE Ingress e di servizio eseguono il deployment oggetti come regole di forwarding, mappe URL, servizi di backend, endpoint di rete gruppi e altro ancora per conto dei carichi di lavoro GKE. Ciascuno di questi di risorse hanno quote e limiti intrinsechi, questi limiti si applicano anche in GKE. Quando un particolare La risorsa di Cloud Load Balancing ha raggiunto la quota, ciò impedirà un correttamente il deployment di Ingress o di servizio e gli errori verranno visualizzati nella e gli 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 hai bisogno di scalare ulteriormente, contatta il team di vendita di Google Cloud per aumentare questo limite.
DNS
Il Service Discovery in GKE viene fornito kube-dns, che è un risorsa centralizzata per fornire risoluzione DNS ai pod in esecuzione all'interno in un cluster Kubernetes. Questo può diventare un collo di bottiglia su cluster molto grandi o per i carichi di lavoro che hanno un carico di richieste elevato. GKE scala automaticamente kube-dns in base alle dimensioni del cluster per aumentarne la capacità. Se questa capacità non è ancora sufficiente, GKE offre la risoluzione localizzata e distribuita delle query DNS su ogni nodo con NodeLocal DNSCache. Questo fornisce una cache DNS locale su ciascun nodo GKE che risponde alle query localmente, distribuendo il carico e fornendo tempi di risposta più rapidi.
Gestione degli indirizzi IP nei cluster nativi di VPC
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 del pod: il valore predefinito è /14 (262.144 indirizzi IP). Tuttavia, puoi configurare la subnet del pod.
- Intervallo secondario per la subnet di servizio: il valore predefinito è /20 (4096 indirizzi). Tuttavia, non puoi modificare questo intervallo dopo aver creato la sottorete di servizio.
Per saperne di più, consulta Intervalli di indirizzi IP per i cluster VPC-native.
Limitazioni e suggerimenti relativi agli indirizzi IP:
- Limite di nodi: il limite di nodi è determinato sia dagli indirizzi IP primari sia da quelli dei pod per nodo. Negli intervalli di indirizzi IP dei nodi e dei pod devono essere presenti indirizzi sufficienti per eseguire il provisioning di un nuovo nodo. Per impostazione predefinita, puoi creare solo 1024 nodi a causa delle limitazioni degli indirizzi IP dei pod.
- Numero massimo di pod per nodo: per impostazione predefinita, il numero massimo di pod per nodo è 110. Tuttavia, puoi configurare pod più piccoli CIDR per un uso efficiente con meno pod per nodo.
- Escalabilità oltre RFC 1918: se hai bisogno di più indirizzi IP di quelli disponibili all'interno dello 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 servizio e pod: per impostazione predefinita, puoi e configurare i servizi 4096. Tuttavia, puoi configurare altri servizi scegliendo l'intervallo di subnet del servizio. Non puoi modificare gli intervalli secondari dopo la creazione. Quando crei un assicurati di scegliere intervalli sufficientemente grandi da soddisfare le previsioni la crescita di Kubernetes. Tuttavia, puoi aggiungere altri indirizzi IP per i pod in un secondo momento utilizzando CID multi-pod discontinuo. Per saperne di più, vedi Spazio indirizzi IP libero insufficiente per i pod.
Per ulteriori informazioni, consulta la sezione sulla limitazione dei nodi intervalli IP e Pianifica IP indirizzi IP durante la migrazione con GKE.
Configurazione dei nodi per migliorare le prestazioni
I nodi GKE sono normali macchine virtuali Google Cloud. Alcuni di questi parametri, ad esempio il numero di core o le dimensioni del disco, possono influire sul rendimento dei cluster GKE.
Riduzione dei tempi di inizializzazione del pod
Puoi utilizzare Image streaming per eseguire lo streaming di dati dalle immagini container idonee man mano che i carichi di lavoro li richiedono, il che porta a tempi di inizializzazione più rapidi.
Traffico in uscita
In Google Cloud, il tipo di macchina e il numero di core allocati a determinare la capacità di rete. La larghezza di banda massima in uscita varia da 1 a 32 Gbps, mentre la larghezza di banda in uscita massima per le macchine e2-medium-2 predefinite è di 2 Gbit/s. Per informazioni dettagliate sui limiti di larghezza di banda, consulta Tipi di macchine con core in comune.
IOPS e velocità effettiva del disco
In Google Cloud, la dimensione dei dischi permanenti determina il numero di IOPS e della velocità effettiva del disco. In genere, GKE utilizza i dischi permanenti come dischi di avvio e per eseguire il backup dei volumi permanenti di Kubernetes. Aumento delle dimensioni del disco aumenta sia le IOPS sia la velocità effettiva, fino determinati limiti.
Ogni operazione di scrittura su disco permanente contribuisce alle prestazioni il limite cumulativo di traffico in uscita dalla rete dell'istanza. Pertanto, Le prestazioni IOPS dei dischi, in particolare delle unità 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 dei limiti di traffico in uscita della rete sulla velocità effettiva di scrittura.
Se l'istanza di macchina virtuale ha CPU insufficienti, l'applicazione non riuscire ad avvicinarsi a Limite IOPS. Come regola generale, dovresti avere una CPU disponibile per ogni 2000-2500 IOPS di previsto.
I carichi di lavoro che richiedono una grande capacità o un numero elevato di dischi devono tenere conto dei limiti del numero di PD che possono essere collegati a una singola VM. Per le VM normali, il limite è di 128 dischi con una dimensione complessiva di 64 TB, mentre le VM con core condivisi hanno un limite di 16 DP con una dimensione complessiva di 3 TB. Questo limite viene applicato da Google Cloud, non da Kubernetes.
Monitora le metriche del piano di controllo
Utilizza le opzioni disponibili metriche del piano di controllo per configurare le dashboard di monitoraggio. Puoi usare le metriche del piano di controllo osservare l'integrità del cluster, osservare i risultati della configurazione del cluster modifiche (ad esempio, deployment di carichi di lavoro aggiuntivi o componenti di terze parti) durante la risoluzione dei problemi.
Una delle metriche più importanti da monitorare è la latenza dell'API Kubernetes. Quando la latenza aumenta, significa che il sistema è sovraccaricato. 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ò essere causata anche dalla lentezza della reattività delle terza parte Webhook di ammissione. Puoi utilizzare le metriche per misurare la latenza dei webhook in modo da rilevare questi che le applicazioni presentino problemi di prestazioni.
Best practice per gli sviluppatori Kubernetes
Utilizza il modello di elenco e visualizzazione anziché la scheda periodica
In qualità di sviluppatore Kubernetes, potresti dover creare un componente con i seguenti requisiti:
- Il componente deve recuperare l'elenco di alcuni oggetti Kubernetes periodicamente.
- Il componente deve essere eseguito in più istanze (in 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, si tratta di un un approccio inefficiente e costoso sia per il chiamante che per il server perché tutti gli oggetti devono essere caricati nella memoria, serializzati e trasferiti ogni volta. L'uso eccessivo delle richieste LIST potrebbe sovraccaricare il piano di controllo o generare un'elevata limitazione di queste richieste.
Puoi migliorare il tuo componente impostando Parametro resourceVersion=0 per le chiamate LIST. Ciò consente a kube-apiserver di utilizzare la cache di oggetti in memoria riduce il numero di interazioni interne tra kube-apiserver e etcd e la relativa elaborazione.
Ti consigliamo vivamente di evitare le chiamate LIST ripetibili e di sostituirle con il pattern list e watch. Elenca gli oggetti una volta, quindi utilizza l'API Watch per ottenere modifiche incrementali dello stato. Questo approccio riduce i tempi di elaborazione e riduce al minimo 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 osservatori richiedono molto meno risorse rispetto alle chiamate LIST periodiche, l'elaborazione degli osservatori in cluster di grandi dimensioni può richiedere una parte significativa delle risorse del cluster e influire sul rendimento del cluster. L'impatto negativo maggiore viene generato dalla creazione di smartwatch che osservare oggetti che cambiano frequentemente da più posizioni. Ad esempio, per osservando i dati su tutti i pod di un componente in esecuzione su tutti i nodi. Se installi codice o estensioni di terze parti nel tuo cluster, queste possono creare questi monitor sotto il cofano.
Consigliamo le seguenti best practice:
- Riduci le elaborazioni non necessarie e il traffico generato dagli orologi e da LIST chiamate.
- Evita di creare monitor che osservano oggetti in continua evoluzione da più posizioni (ad esempio i DaemonSet).
- (Molto consigliato) Crea un controller centrale che monitora ed elabora i dati richiesti su un singolo nodo.
- Monitora solo un sottoinsieme di oggetti, ad esempio kubelet su ogni nodo osserva solo i pod pianificati sullo stesso nodo.
- Evita di eseguire il deployment di componenti o estensioni di terze parti che potrebbero avere un impatto raggruppa le prestazioni effettuando un volume elevato di visualizzazioni o chiamate LIST.
Limita la dimensione del manifest degli oggetti Kubernetes
Se hai bisogno di operazioni veloci che richiedono un'elevata velocità effettiva dei pod, come ridimensionando o aggiornando carichi di lavoro di grandi dimensioni, assicurati che le dimensioni del manifest dei pod minimo, idealmente inferiore a 10 KiB.
Kubernetes memorizza i manifest delle risorse in etcd. L'intero manifest viene inviato ogni volta che la risorsa viene recuperata, ad esempio quando utilizzi l'elenco e il pattern di visualizzazione.
Le dimensioni del file manifest presentano le seguenti limitazioni:
- Dimensione massima per ogni oggetto in etcd: circa 1,5 MB.
- Quota totale per tutti gli oggetti etcd nel cluster: quota preconfigurata è di 6 GiB. Ciò include un log delle modifiche con tutti gli aggiornamenti a tutti gli oggetti negli ultimi 150 secondi di cronologia del cluster.
- Rendimento del piano di controllo durante i periodi di traffico elevato: manifest più grande. aumentano il carico sul server API.
Per oggetti singoli elaborati raramente, le dimensioni del file manifest di solito non sono un problema, purché non superino 1,5 MB. Tuttavia, dimensioni dei manifest superiori a 10 KiB per numerosi oggetti elaborati di frequente, come i pod in carichi di lavoro molto grandi, possono causare un aumento della latenza delle chiamate API e una diminuzione delle prestazioni complessive. Gli elenchi e le visualizzazioni, in particolare, possono essere influenzati in modo significativo da di file manifest di grandi dimensioni. Potresti anche riscontrare problemi con la quota etcd, perché la quantità di revisioni negli ultimi 150 secondi può accumularsi rapidamente durante periodi di elevato traffico del server API.
Per ridurre le dimensioni del file manifest di un pod, puoi utilizzare i ConfigMap di Kubernetes per memorizzare parte della configurazione, in particolare la parte condivisa da più pod nel cluster. Ad esempio, le variabili di ambiente sono spesso condivise da tutti i pod in un carico di lavoro.
Tieni presente che è anche possibile riscontrare problemi simili con gli oggetti ConfigMap se sono numerosi, di grandi dimensioni ed elaborati con la stessa frequenza dei pod. L'estrazione di parte della configurazione è più utile quando diminuisce nel complesso per via del traffico.
Disabilita il montaggio automatico dell'account di servizio predefinito
Se la logica in esecuzione nei tuoi pod non ha bisogno di accedere all'API Kubernetes, devi disabilita il montaggio automatico predefinito dell'account di servizio per evitare la creazione di secret e smartwatch correlati.
Quando crei un pod senza specificare un account di servizio, Kubernetes esegue automaticamente le seguenti azioni:
- Assegna il service account predefinito al pod.
- Monta le credenziali dell'account di servizio come secret per il pod.
- Per ogni secret montato, il kubelet crea un orologio per osservare le modifiche quel secret su ogni nodo.
In cluster di grandi dimensioni, queste azioni rappresentano migliaia di monitoraggi non necessari che potrebbero comportare un carico significativo su kube-apiserver.
Utilizza i buffer di protocollo anziché JSON per le richieste API
Utilizza i protocol buffer per implementare componenti altamente scalabili come descritto in Concetti di base dell'API Kubernetes.
L'API REST di Kubernetes supporta JSON e protocol buffer come formato di serializzazione per gli oggetti. Per impostazione predefinita viene utilizzato JSON, ma i buffer di protocollo sono più efficienti su larga scala perché richiede un'elaborazione che richiede meno CPU e invia meno dati sulla rete. Il sovraccarico relativo all'elaborazione di JSON può causare timeout durante l'elenco di dati di grandi dimensioni.