Kubernetes su più continenti: k3s e k8s ad alta disponibilità tra data center di tutto il mondo

Pubblicato il 15 min di lettura

Kubernetes tra USA, Europa e Asia, capace di reggere la caduta di un intero continente: perché etcd non sopporta le lunghe distanze, un cluster k3s per regione, GitOps con Flux, failover via Geo-DNS, dati tra le regioni e le differenze con kubeadm.

Kubernetes è lo standard quando le applicazioni devono girare in modo resistente ai guasti e scalare automaticamente. L'idea più ovvia, cioè estendere un unico cluster Kubernetes su server negli USA, in Europa e in Asia, si scontra però con un dettaglio: etcd, il database in cui Kubernetes salva tutto il proprio stato. Questo articolo mostra come far funzionare comunque Kubernetes su più continenti, e in modo che possa venire a mancare anche un intero continente: con un cluster per regione, un deploy comune tramite GitOps e un Geo-DNS che manda gli utenti alla regione sana più vicina.

Costruiamo l'architettura con k3s, la distribuzione Kubernetes leggera e pienamente certificata che si installa in pochi minuti, e alla fine mostriamo cosa cambia con un Kubernetes classico installato con kubeadm. Le basi su disponibilità, quorum e failover tra più sedi sono spiegate in dettaglio nell'articolo Docker Swarm su tre continenti; qui ci occupiamo di ciò che con Kubernetes è diverso.

Un cluster su tutti i continenti o un cluster per regione?

Per Kubernetes su più continenti l'architettura giusta è un cluster per regione, non un unico cluster esteso su tutti i continenti. Ogni cluster funziona in modo autonomo, tutti vengono distribuiti dallo stesso repository Git e un Geo-DNS con health check smista gli utenti. Se una regione cade, subentrano le altre, senza dover sincronizzare uno stato comune del cluster attraverso l'oceano.

Perché etcd non sopporta le lunghe distanze

Kubernetes salva ogni stato, ogni configurazione e ogni modifica in etcd, un archivio chiave-valore basato sul consenso Raft. Ogni scrittura richiede la conferma della maggioranza di tutti i membri di etcd. Per impostazione predefinita etcd lavora con un heartbeat di 100 millisecondi e un timeout di elezione di un secondo; tra Europa, Nord America e Asia la latenza dei pacchetti va da 80 a 250 millisecondi. Si possono aumentare questi tempi, ma allora ogni scrittura nel cluster diventa lenta, dalla schedulazione di un Pod al salvataggio di un Secret. Su questo punto la documentazione di k3s è chiara: l'etcd integrato non è supportato nei cluster distribuiti su più reti, tutti i server dovrebbero trovarsi nella stessa sede. Anche Kubernetes in sé è progettato perché un cluster copra più zone all'interno di una stessa regione, non continenti diversi.

I tre modelli a confronto

ModelloCome funzionaValutazione
Un cluster su tutti i continentiControl plane ed etcd distribuiti su più continentiSconsigliato: scritture lente, etcd instabile, con k3s ed etcd integrato non supportato
Control plane in una regione, worker in tutto il mondoServer in una sede, agent su altri continentiTecnicamente funziona, ma se cade la regione del control plane, in tutto il mondo non si può più rischedulare nulla
Un cluster per regioneTre cluster indipendenti, distribuiti insieme via GitOps, con un Geo-DNS davantiConsigliato: ogni regione sopravvive alla caduta delle altre, gli errori restano confinati a una regione

L'approccio «un cluster per regione» ha un secondo vantaggio, spesso sottovalutato: un errore nel control plane, una modifica sbagliata al cluster o un upgrade andato storto colpisce sempre una sola regione. Gli utenti delle altre regioni non se ne accorgono.

k3s o k8s?

Entrambi sono Kubernetes a tutti gli effetti, con la stessa API, gli stessi manifest e gli stessi strumenti. La differenza sta nella struttura e nell'impegno richiesto:

Caratteristicak3sk8s con kubeadm
InstallazioneUn comando, un file binarioRuntime dei container, kubeadm, kubelet e plugin di rete da configurare singolarmente
Risorse per un nodo serverAlmeno 2 core e 2 GB di RAMMolte di più, a seconda dei componenti
In dotazioneIngress controller (Traefik), rete (Flannel), provisioner di storage, load balancer per i ServiceSolo il nucleo, tutto il resto lo scegli tu
Alta disponibilitàetcd integrato con tre serverTre nodi control plane con un load balancer davanti all'API
Adatto aLa maggior parte delle applicazioni, team piccoli, un solo nodo per regioneTeam che vogliono scegliere da sé ogni componente

Per l'architettura con un cluster per regione consigliamo k3s: gestire tre cluster è comodo solo se ciascuno di essi è semplice. Chi ha già esperienza con kubeadm può adottare l'architettura senza modifiche; la sezione su kubeadm più avanti mostra le differenze.

L'architettura: tre regioni, tre cluster, un unico punto di accesso

ComponenteCompitoQuale guasto copre
Un cluster k3s per regioneEsegue l'applicazione vicino agli utentiCaduta di un'intera regione
Tre server per regione (fase di espansione)Mantiene etcd e il control plane ad alta disponibilità all'interno della regioneGuasto di singoli server in una regione
Repository Git e Flux in ogni clusterOgni cluster preleva da solo da Git il proprio stato desideratoNessun server di deploy centrale che faccia da punto di guasto
Ingress con certificati tramite challenge DNSRiceve le richieste degli utentiI certificati funzionano indipendentemente dalla commutazione DNS
Geo-DNS con health checkManda gli utenti alla regione sana più vicinaRegioni non raggiungibili
Dati replicati e backupConserva i dati in più regioniPerdita di dati in caso di caduta di una regione

Punto di partenza ed espansione

Si parte con tre server, uno negli USA, uno in Europa e uno in Asia, ciascuno come cluster autonomo a nodo singolo. Se un server cade, cade la sua regione e il Geo-DNS ne manda gli utenti nella regione vicina. Questo livello è già progettato per reggere la caduta di un intero continente. Nella fase di espansione ogni regione riceve tre server nella stessa sede: a quel punto anche ogni singola regione sopravvive da sola al guasto di un server, senza che gli utenti debbano essere reindirizzati.

Quali sedi KernelHost sono adatte

KernelHost gestisce server nel data center maincubes di Francoforte sul Meno e offre server virtuali in altre sedi in Europa, Nord America e Asia-Pacifico, tra cui tre sedi negli USA, Canada, Londra, Strasburgo, Varsavia, Helsinki, Singapore, Giappone, Sydney e Mumbai. L'elenco completo si trova nella pagina Sedi dei server. L'esempio di questo articolo usa Francoforte sul Meno per l'Europa, la costa est degli USA per il Nord America e Singapore per l'Asia.

Guida: Kubernetes con k3s in tre regioni

L'esempio usa tre server con Debian 12 o 13: k3s-eu, k3s-us e k3s-asia. Gli indirizzi pubblici provengono dalla rete di documentazione 203.0.113.0/24, il dominio è example.com. Sostituisci entrambi con i tuoi valori.

Passo 1: preparare i server in tre regioni

Ordina tre server in tre regioni, con almeno 2 vCPU e 4 GB di RAM, così che oltre a k3s ci sia spazio anche per la tua applicazione. Applica l'hardening di base della checklist per nuovi server root e assegna hostname descrittivi. etcd trae un vantaggio tangibile da SSD veloci, e lo storage NVMe dei server KernelHost soddisfa questo requisito.

Passo 2: installare k3s

Su ciascuno dei tre server installi k3s con un solo comando. Ogni server diventa così un cluster Kubernetes completo con un nodo:

curl -sfL https://get.k3s.io | sh -
kubectl get nodes

Dopo circa un minuto kubectl get nodes riporta il nodo come Ready. Sono inclusi Traefik come Ingress controller, Flannel per la rete e un provisioner per i volumi locali.

Passo 3: espansione a tre server per regione

Se vuoi che una regione sia di per sé ad alta disponibilità, metti tre server nella stessa sede. Il primo server avvia l'etcd integrato, gli altri due si uniscono con un token comune. etcd richiede un numero dispari di server; con tre server la regione regge il guasto di uno di essi:

curl -sfL https://get.k3s.io | K3S_TOKEN=TOKEN_SEGRETO sh -s - server \
    --cluster-init \
    --tls-san=api.eu.example.com
curl -sfL https://get.k3s.io | K3S_TOKEN=TOKEN_SEGRETO sh -s - server \
    --server https://203.0.113.21:6443 \
    --tls-san=api.eu.example.com

Tutti i server di una regione hanno bisogno delle stesse impostazioni per range di rete e funzionalità. Tra di loro devono essere aperte le porte da 2379 a 2380/TCP per etcd, 6443/TCP per l'API, 10250/TCP per il kubelet e 8472/UDP per la rete Flannel; verso l'esterno restano chiuse. Il token è un segreto: chi lo conosce può aggiungere server propri al cluster.

Passo 4: configurare l'accesso a tutti e tre i cluster

k3s salva le credenziali di accesso in /etc/rancher/k3s/k3s.yaml. Copia il file di ogni cluster sul tuo computer di lavoro, sostituisci al suo interno 127.0.0.1 con l'indirizzo del server e dai ai contesti il nome della regione:

kubectl config rename-context default eu
kubectl config use-context eu
kubectl --context us get nodes

L'API sulla porta 6443 è l'accesso più potente al cluster. Consenti questo accesso nel firewall solo dal tuo indirizzo o da una VPN, mai a tutta Internet. Il file k3s.yaml contiene un certificato di amministratore e va custodito con la stessa cura di una password di root.

Passo 5: GitOps con Flux in ogni cluster

Perché tutte e tre le regioni facciano girare la stessa applicazione nella stessa versione, lo stato desiderato si trova in un repository Git e in ogni cluster gira Flux, che realizza questo stato in modo autonomo. Ogni cluster, quindi, si procura da solo la propria configurazione; non esiste un server di deploy centrale che potrebbe guastarsi. Una struttura collaudata del repository:

apps/
  web/            manifest comuni dell'applicazione
clusters/
  eu/             impostazioni e versione per l'Europa
  us/             impostazioni e versione per il Nord America
  asia/           impostazioni e versione per l'Asia
flux bootstrap git --url=ssh://git@git.example.com/infra/fleet.git --branch=main --path=clusters/eu

Esegui lo stesso comando con --path=clusters/us e --path=clusters/asia nel rispettivo contesto. Poiché ogni regione ha la propria directory, puoi distribuire una nuova versione prima in una regione e solo dopo nelle altre.

Passo 6: descrivere l'applicazione in modo resistente ai guasti

All'interno di una regione tre elementi fanno sì che l'applicazione superi manutenzioni e guasti dei server: più repliche distribuite su nodi diversi, controlli che riconoscono i Pod malati e un budget che impedisce a una manutenzione di rimuovere tutti i Pod contemporaneamente:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: web
      containers:
        - name: web
          image: registry.example.com/web:1.0
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            periodSeconds: 10
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web
spec:
  minAvailable: 1
  selector:
    matchLabels:
      app: web

La readiness probe toglie un Pod dal traffico finché non risponde, la liveness probe lo riavvia quando si blocca. In un cluster a nodo singolo la distribuzione su più nodi non ha ancora effetto; entra in funzione automaticamente non appena la regione ha tre server.

Passo 7: Ingress e certificati

Il punto di ingresso è gestito da Traefik, già incluso. Poiché tutte e tre le regioni servono lo stesso dominio, ottieni i certificati TLS con cert-manager tramite la challenge DNS: funziona in ogni regione, indipendentemente da dove punti in quel momento il record DNS. La challenge HTTP, invece, fallisce in ogni regione verso cui il record non punta in quel momento. Chi lavora senza Ingress di Kubernetes trova le basi nell'articolo Configurare nginx come reverse proxy.

Passo 8: configurare il Geo-DNS con failover

Un servizio DNS con geo-routing e health check manda gli utenti dall'Europa a Francoforte sul Meno, dall'America alla costa est degli USA e dall'Asia a Singapore, e controlla a intervalli da 30 a 60 secondi se il punto di ingresso di ogni regione risponde. Se una regione cade, il servizio smette di restituirne l'indirizzo. Imposta il TTL dei record a 60 secondi: così di solito una commutazione è completata dopo uno o due minuti. Se vuoi gestire i record direttamente dal cluster, puoi usare external-dns.

Passo 9: distribuire regione per regione e testare il guasto

Inserisci una nuova versione prima nella directory di una regione, osserva la regione per qualche minuto e solo dopo adotta la versione anche per le altre. In questo modo un errore che nessun controllo rileva raggiunge al massimo una regione. Per simulare la caduta di una regione fermi k3s sul suo server e verifichi che il Geo-DNS tolga la regione dalle risposte e che la regione vicina regga il carico:

systemctl stop k3s
systemctl start k3s

In una regione con tre server simuli inoltre la manutenzione di un singolo server. kubectl drain sposta i Pod rispettando il budget del passo 6, kubectl uncordon rimette in servizio il server:

kubectl drain k3s-eu-2 --ignore-daemonsets --delete-emptydir-data
kubectl uncordon k3s-eu-2

Dati tra le regioni

Kubernetes distribuisce Pod, non dati. Un PersistentVolume del provisioner incluso risiede su un solo nodo, e di serie tra i cluster non c'è alcuna archiviazione condivisa dei dati. Per tutto ciò che contiene dati vale quindi lo stesso che per qualsiasi cluster su più sedi:

  • I database si replicano da soli. Una soluzione collaudata è un'istanza primaria in una regione con repliche nelle altre; operator di database come CloudNativePG per PostgreSQL supportano queste repliche anche tra cluster diversi. Tra continenti la replica è asincrona: in caso di emergenza possono mancare gli ultimi secondi di scritture. Per scritture senza perdite a livello mondiale esistono database pensati per più regioni, come CockroachDB o YugabyteDB.
  • File e upload vanno in un object storage compatibile S3 con replica in una seconda regione.
  • Le sessioni risiedono in un database o in una cache replicati, oppure l'applicazione usa token firmati.
  • I backup restano obbligatori, perché la replica distribuisce gli errori esattamente come i dati buoni. Per gli oggetti e i volumi di Kubernetes è adatto Velero; per le basi consulta la strategia di backup per server.

Kubernetes con kubeadm invece di k3s

Con kubeadm l'architettura resta la stessa: un cluster per regione, GitOps, Geo-DNS. Cambia invece la costruzione di ogni cluster. Su tutti i nodi installi un runtime dei container come containerd, oltre a kubeadm, kubelet e kubectl, metti davanti all'API della regione un load balancer o un indirizzo virtuale, per esempio con kube-vip, e inizializzi il primo nodo control plane:

kubeadm init --control-plane-endpoint "api.eu.example.com:6443" --upload-certs

L'output contiene due comandi di join: uno con --control-plane --certificate-key per gli altri due nodi control plane e uno per i worker. Poi installi un plugin di rete come Calico o Cilium e un Ingress controller, che k3s include già di serie. Lo sforzo in più ne vale la pena se devi scegliere in modo mirato i singoli componenti o restare allineato alla versione upstream.

Perché KernelHost per Kubernetes su più continenti

RequisitoPerché contaCon KernelHost
Sedi su più continentiUn cluster per regione richiede server in ogni regioneFrancoforte sul Meno più sedi in Europa, Nord America e Asia-Pacifico da un unico fornitore
Traffico illimitatoDownload delle immagini, replica dei database e backup generano traffico costanteVPS a traffico illimitato senza limiti di volume
Storage veloceetcd è sensibile ai dischi lentiSSD NVMe in RAID
Protezione DDoSOgni Ingress è raggiungibile pubblicamenteInclusa in ogni sede, nella sede principale di Francoforte sul Meno con filtraggio Arbor in tempo reale da 3,2 Tbps, senza null-routing
Accesso root completok3s, firewall e impostazioni del kernel richiedono il pieno controlloSu ogni server root KVM e server dedicato
Nessun vincolo contrattualeNodi e cluster di test vanno e vengonoPrePaid, senza durata minima, senza costi di attivazione
AutomazioneI nuovi nodi devono poter essere creati via scriptOrdine e gestione tramite la KernelHost API

Una panoramica di tutti i piani cloud e un confronto dei costi con i grandi provider cloud li trovi nella pagina Noleggio server cloud.

Errori frequenti e come evitarli

  • etcd esteso su più continenti. Le conseguenze sono scritture lente ed elezioni instabili; con k3s ed etcd integrato non è supportato. Soluzione: un cluster per regione.
  • Due server in una regione. etcd ha bisogno di una maggioranza, due server non reggono nemmeno un guasto. Soluzione: uno o tre.
  • API aperta a tutta Internet. La porta 6443 è il passe-partout del cluster. Soluzione: solo dal proprio indirizzo o tramite VPN.
  • Server di deploy centrale. Se si guasta, non si può più distribuire nulla. Soluzione: Flux in ogni cluster, che attinge da solo a Git.
  • Aggiornamento in tutte le regioni contemporaneamente. Un errore colpisce allora tutti gli utenti. Soluzione: regione per regione tramite le directory del repository.
  • Certificati tramite challenge HTTP. Nelle regioni verso cui il record DNS non punta in quel momento il rinnovo fallisce. Soluzione: challenge DNS.
  • Database su un volume locale senza replica. Se il nodo si guasta, i dati non sono raggiungibili. Soluzione: replica tramite un operator di database.
  • Nessuna probe e nessun budget. I Pod malati continuano a ricevere traffico e le manutenzioni tolgono dalla rete tutti i Pod insieme. Soluzione: readiness e liveness probe più un PodDisruptionBudget.

In sintesi

  • Per Kubernetes su più continenti la scelta giusta è un cluster per regione; un unico cluster su tutti i continenti fallisce a causa della latenza di etcd.
  • Si parte con tre server, uno negli USA, uno in Europa e uno in Asia; già questo livello sopravvive alla caduta di un intero continente.
  • Nella fase di espansione ogni regione riceve tre server nella stessa sede; così ogni regione regge anche il guasto di singoli server.
  • Flux in ogni cluster distribuisce l'applicazione dallo stesso repository Git, regione per regione.
  • Il Geo-DNS con health check e TTL breve manda gli utenti alla regione sana più vicina, i certificati arrivano tramite challenge DNS.
  • Kubernetes distribuisce Pod, non dati: i database hanno bisogno di una replica propria, i backup restano obbligatori.
  • Per questa architettura k3s è di solito una scelta migliore di kubeadm, perché tre cluster semplici si gestiscono più facilmente di tre cluster complessi.

Domande frequenti

Un cluster Kubernetes può estendersi su più continenti?
Tecnicamente il control plane si può distribuire, ma non è consigliabile. Kubernetes salva il proprio stato in etcd e ogni scrittura richiede la conferma di una maggioranza di tutti i membri di etcd. Tra un continente e l'altro la latenza va da 80 a 250 millisecondi, mentre etcd lavora per impostazione predefinita con un heartbeat di 100 millisecondi. Secondo la propria documentazione, k3s non supporta l'etcd integrato su reti distribuite. La soluzione giusta è un cluster per regione.
Come si costruisce Kubernetes ad alta disponibilità su più regioni?
Con un cluster separato per ogni regione, per esempio un cluster k3s negli USA, uno in Europa e uno in Asia. Tutti i cluster vengono distribuiti via GitOps dallo stesso repository Git, per esempio con Flux in ogni cluster, e un Geo-DNS con health check manda gli utenti alla regione sana più vicina. Se una regione cade, subentrano le altre, senza dover sincronizzare uno stato comune attraverso l'oceano.
Qual è la differenza tra k3s e k8s?
Entrambi sono Kubernetes completo, con la stessa API e gli stessi manifest. k3s è una distribuzione leggera e certificata in un unico file binario, che si installa con un solo comando e include Ingress controller, rete e provisioner di storage; un server richiede almeno 2 core e 2 GB di RAM. Un cluster k8s con kubeadm si compone di singoli componenti, offre più libertà di scelta e richiede più lavoro.
Quanti server servono per un cluster k3s ad alta disponibilità?
Tre nodi server con etcd integrato, nella stessa sede. etcd ha bisogno di una maggioranza, quindi tre server reggono il guasto di un server. Due server non portano alcun vantaggio, perché il guasto di uno dei due fa perdere la maggioranza. Per Kubernetes su più continenti, per iniziare bastano tre cluster a nodo singolo, uno per regione, perché il Geo-DNS assorbe la caduta di un'intera regione.
Di quali porte ha bisogno k3s?
L'API di Kubernetes e il supervisor di k3s usano la porta 6443/TCP, il kubelet la 10250/TCP, la rete Flannel con VXLAN la 8472/UDP e con WireGuard la 51820/UDP. Con più server ed etcd integrato si aggiungono tra i server le porte da 2379 a 2380/TCP. Nessuna di queste porte deve essere aperta verso Internet: consenti l'API solo dal tuo indirizzo o tramite VPN.
Come si distribuiscono le applicazioni su più cluster Kubernetes?
Con GitOps: lo stato desiderato di tutti i cluster si trova in un repository Git e in ogni cluster gira uno strumento come Flux, che realizza questo stato in modo autonomo. Ogni regione ha la propria directory, così una nuova versione si può distribuire prima in una regione e, dopo un periodo di osservazione, nelle altre. Non esiste un server di deploy centrale che potrebbe guastarsi.
Come funziona il failover tra le regioni Kubernetes?
Tramite un servizio DNS con geo-routing e health check. Il servizio manda gli utenti alla regione più vicina e controlla a intervalli da 30 a 60 secondi se l'Ingress di quella regione risponde. Se una regione cade, smette di restituirne l'indirizzo e manda gli utenti alla regione sana più vicina. Con un TTL di 60 secondi la commutazione è di solito completata dopo uno o due minuti.
Come si conservano i dati quando cade una regione?
Kubernetes distribuisce Pod, non dati. Per questo i database si replicano da soli, per esempio PostgreSQL con l'operator CloudNativePG, che gestisce repliche anche tra cluster diversi. Tra continenti la replica è asincrona: in caso di emergenza possono mancare gli ultimi secondi di scritture. I file vanno in un object storage replicato, e i backup regolari, per esempio con Velero, restano obbligatori.
Kubernetes o Docker Swarm per più continenti?
Docker Swarm si può estendere come un unico cluster su tre continenti ed è molto più semplice da gestire. Kubernetes offre più automazione e un ecosistema più ampio, ma su più continenti si gestisce con un cluster per regione, riunendo il tutto tramite GitOps. Per team piccoli con applicazioni di dimensioni contenute Swarm è spesso la scelta pragmatica, per piattaforme complesse lo è Kubernetes.
Quali sedi KernelHost sono adatte a Kubernetes su più continenti?
KernelHost offre server a Francoforte sul Meno e in altre sedi in Europa, Nord America e Asia-Pacifico, tra cui tre sedi negli USA, Canada, Londra, Strasburgo, Varsavia, Helsinki, Singapore, Giappone, Sydney e Mumbai. Una combinazione collaudata è Francoforte sul Meno, la costa est degli USA e Singapore, con uno o tre server per regione nella stessa sede.
Quanto costa Kubernetes su tre continenti?
All'inizio tre server, uno per regione, nella fase di espansione nove, più un servizio DNS con health check. k3s in sé è gratuito. Poiché replica, backup e download delle immagini generano traffico costante, sono decisivi i piani con traffico illimitato. Con KernelHost i VPS a traffico illimitato funzionano senza limiti di volume, in PrePaid, senza durata minima e senza costi di attivazione, così i cluster si possono ingrandire o ridurre secondo necessità.

Kubernetes k3s k8s kubeadm Alta disponibilità Multi-region GitOps Flux Geo-DNS Cloud