Kubernetes su Hetzner Cloud: setup economico per startup e PMI italiane

Kubernetes su Hetzner Cloud: setup economico per startup e PMI italiane

A marzo 2025 un cliente del settore SaaS - una startup italiana con un prodotto di gestione documentale per studi professionali, 400 utenti attivi e un'architettura a microservizi con sei container Docker - mi ha chiesto di costruire un cluster Kubernetes di produzione. Il budget mensile per l'infrastruttura era rigido: massimo 50 euro al mese, tutto incluso. Il preventivo che aveva ricevuto per un cluster EKS su AWS con tre nodi t3.medium, load balancer ALB e storage EBS era di 380 euro al mese - senza contare i costi di trasferimento dati. Il preventivo per un GKE su Google Cloud era comparabile: 340 euro al mese con tre nodi e2-standard-2. Per una startup che fattura 8.000 euro al mese di abbonamenti, dedicare il 4-5% del fatturato alla sola infrastruttura Kubernetes è insostenibile. Su Hetzner Cloud, con k3s e il CSI driver ufficiale Hetzner, ho costruito un cluster produttivo con tre nodi da 4 vCPU e 8 GB RAM ciascuno (CPX31) per 36,51 euro al mese totali. Lo stesso cluster, con le stesse prestazioni, a un decimo del costo dei managed Kubernetes dei grandi cloud provider.

Kubernetes non è per tutti - lo dico subito per evitare fraintendimenti. Se hai un singolo applicativo Laravel su un VPS con 200 utenti, Kubernetes è un over-engineering colossale che aggiunge complessità senza valore. Ma se hai tre o più servizi containerizzati che devono essere deployati indipendentemente, scalati in base al carico, e riavviati automaticamente in caso di crash, allora Kubernetes diventa lo strumento giusto - e su Hetzner Cloud diventa anche economicamente accessibile.

Quanto costa davvero un cluster Kubernetes per una PMI?

La risposta dipende interamente da dove lo esegui. Ecco il confronto reale che ho presentato al cliente, basato sui prezzi pubblici di aprile 2025:

ComponenteAWS EKSGoogle GKEHetzner k3s
Control plane73€/mese (EKS fee)73€/mese (standard)0€ (k3s sul primo nodo)
3 nodi (4 vCPU, 8 GB)210€/mese (t3.medium)195€/mese (e2-standard-2)36,51€/mese (CPX31)
Load balancer25€/mese (ALB)20€/mese (TCP LB)5,83€/mese (Hetzner LB11)
Storage 100 GB12€/mese (gp3)8€/mese (standard)4,40€/mese (Hetzner Volume)
Totale mensile~320€~296€~47€
Totale annuo~3.840€~3.552€~564€

Il risparmio annuo è di circa 3.000 euro rispetto ai cloud provider americani. Per una PMI o una startup italiana, quel delta è significativo - equivale al costo di un consulente senior per una settimana di lavoro, o a sei mesi di abbonamento a una suite di monitoring. Il trade-off è operativo: su EKS e GKE il control plane è gestito dal provider, su Hetzner con k3s lo gestisci tu. Ma k3s è stato progettato esattamente per questo scenario: un Kubernetes ridotto all'osso, certificato CNCF, che gira in 512 MB di RAM e si aggiorna con un singolo binario.

Per nuovi clienti Hetzner, puoi ottenere €20.00 di credito gratuito utilizzando questo link con codice sconto - una scelta ideale per aziende europee che necessitano conformità GDPR.

k3s: Kubernetes ridotto all'osso senza sacrificare la produzione

k3s è una distribuzione Kubernetes leggera sviluppata da Rancher (ora parte di SUSE), certificata CNCF come distribuzione conforme e progettata per ambienti con risorse limitate: edge computing, IoT, CI/CD, e VPS con budget contenuti. La differenza con un Kubernetes vanilla sta in ciò che k3s rimuove e in ciò che sostituisce: usa SQLite (o etcd embedded) invece di un etcd cluster separato, include Traefik come ingress controller di default, include Flannel come CNI di default, e comprime l'intero control plane in un singolo binario di circa 70 MB.

L'installazione del primo nodo (server) su un VPS Hetzner Debian 12 è un singolo comando:

# Installazione k3s server sul primo nodo (control plane + worker)
# Il token generato servirà per aggiungere i nodi worker
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server \
  --disable=traefik \
  --tls-san=$(hostname -I | awk '{print $1}') \
  --write-kubeconfig-mode=644" sh -

# Recupera il token per i nodi worker
cat /var/lib/rancher/k3s/server/node-token

# Verifica che il nodo sia pronto
kubectl get nodes

Ho disabilitato Traefik di default perché in produzione uso Nginx Ingress Controller, che offre più controllo sulla configurazione e supporta annotazioni per rate limiting, proxy buffer e header personalizzati. L'aggiunta dei due nodi worker è altrettanto semplice:

# Eseguire su ogni nodo worker (sostituire IP e TOKEN)
curl -sfL https://get.k3s.io | K3S_URL="https://10.0.0.1:6443" \
  K3S_TOKEN="<token-dal-server>" sh -

In meno di cinque minuti dall'inizio, hai un cluster Kubernetes a tre nodi con networking funzionante, DNS interno (CoreDNS), e kubectl configurato. Il mio profilo professionale documenta l'esperienza che ho maturato nella gestione di cluster k3s in produzione su Hetzner per diversi clienti SaaS e PMI - la competenza operativa sul day-2 (aggiornamenti, backup etcd, monitoring) è ciò che distingue un cluster che "funziona in demo" da uno che regge in produzione per anni.

Storage persistente e load balancer con i driver ufficiali Hetzner

Un cluster Kubernetes senza storage persistente è utile solo per applicazioni stateless. Per database, file upload, cache persistenti e qualsiasi dato che deve sopravvivere al restart di un pod, serve un driver CSI (Container Storage Interface) che permetta a Kubernetes di creare e montare volumi automaticamente. Hetzner mantiene un CSI driver ufficiale che si integra con Hetzner Cloud Volumes - storage a blocchi basato su Ceph, replicato e ad alta disponibilità.

L'installazione del CSI driver e del Cloud Controller Manager richiede un token API Hetzner Cloud e due manifest:

# Crea il secret con il token API Hetzner
kubectl -n kube-system create secret generic hcloud \
  --from-literal=token="<hetzner-api-token>" \
  --from-literal=network="<network-id>"

# Installa il Cloud Controller Manager
kubectl apply -f https://github.com/hetznercloud/hcloud-cloud-controller-manager/releases/latest/download/ccm-networks.yaml

# Installa il CSI driver
kubectl apply -f https://raw.githubusercontent.com/hetznercloud/csi-driver/main/deploy/kubernetes/hcloud-csi.yml

# Verifica che la storage class sia disponibile
kubectl get storageclass
# Output: hcloud-volumes (default)

Da questo momento, qualsiasi PersistentVolumeClaim con storage class hcloud-volumes crea automaticamente un volume Hetzner Cloud e lo monta nel pod. Il volume minimo è 10 GB (limitazione Hetzner), il costo è 0,044€/GB/mese. Per il cliente SaaS, un volume da 50 GB per PostgreSQL costa 2,20€/mese - un centesimo del costo equivalente su AWS EBS gp3.

Il load balancer si configura con un'annotazione sul Service Kubernetes:

apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress
  annotations:
    # Hetzner LB: tipo, location, nome
    load-balancer.hetzner.cloud/type: "lb11"
    load-balancer.hetzner.cloud/location: "fsn1"
    load-balancer.hetzner.cloud/name: "k3s-lb"
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80
    - port: 443
      targetPort: 443
  selector:
    app: nginx-ingress

Kubernetes crea il load balancer Hetzner LB11 (5,83€/mese, 25 target, certificato SSL incluso) e lo collega automaticamente ai nodi worker. Il traffico HTTPS arriva al load balancer, viene terminato e inoltrato all'Nginx Ingress Controller, che lo smista ai pod corretti in base alle regole di ingress. L'intero stack - dal DNS alla risposta del container - è gestito da Kubernetes senza intervento manuale.

Un aspetto che molti tutorial trascurano è la configurazione della rete privata tra i nodi. Su Hetzner Cloud, i nodi k3s comunicano attraverso la rete pubblica di default - il che significa che tutto il traffico inter-nodo (inclusi i dati di etcd, le comunicazioni kubelet-apiserver e il traffico tra pod su nodi diversi) transita su Internet senza cifratura aggiuntiva. La soluzione è creare una rete privata Hetzner Cloud (vSwitch o Cloud Network) e configurare k3s per usarla come interfaccia di comunicazione interna. Il costo di una Cloud Network su Hetzner è zero - è una funzionalità inclusa. La configurazione richiede l'aggiunta del flag --flannel-iface=ens10 (l'interfaccia della rete privata) al comando di installazione k3s e l'assegnazione di IP privati ai nodi tramite il pannello Hetzner o la CLI hcloud. Senza questa configurazione, il traffico del cluster è esposto sulla rete pubblica - un rischio di sicurezza che in produzione è inaccettabile, specialmente per applicazioni che gestiscono dati sensibili di utenti europei sotto regime GDPR.

Il Cloud Controller Manager di Hetzner, oltre a gestire il provisioning automatico dei load balancer, ha un'altra funzione critica: il lifecycle management dei nodi. Se un nodo Hetzner Cloud viene distrutto (per un failure hardware o per un'operazione di manutenzione del provider), il CCM lo rileva e notifica Kubernetes, che rischedula automaticamente i pod su un nodo sano. Senza il CCM, Kubernetes continuerebbe a credere che il nodo esista e i pod rimarrebbero in stato Terminating per il timeout di default (5 minuti), causando un'interruzione del servizio evitabile. Per il cliente SaaS, ho configurato un Cluster Autoscaler che aggiunge automaticamente un nodo worker quando l'utilizzo CPU medio supera il 70% e lo rimuove quando scende sotto il 30% per più di 10 minuti - un'elasticità che su Hetzner Cloud costa 12,17€/mese per nodo aggiuntivo (CPX31), attivato solo quando serve.

Day-2 operations: backup, aggiornamenti e monitoring

Il cluster è in piedi, ma il lavoro vero comincia il giorno dopo il deploy. Le tre operazioni che determinano se un cluster k3s sopravvive in produzione sono: backup del datastore, aggiornamenti del cluster e monitoring dei nodi - gli stessi principi che applico a qualsiasi infrastruttura critica, come ho descritto nel mio articolo sul piano di disaster recovery per applicazioni PHP e infrastrutture PMI.

Il backup del datastore k3s (SQLite o etcd embedded) si fa con un cronjob che esegue lo snapshot di etcd e lo carica su uno storage esterno. Con k3s il comando è integrato:

# Snapshot manuale del datastore k3s
k3s etcd-snapshot save --name backup-$(date +%Y%m%d)

# Cronjob per snapshot giornaliero automatico
# (k3s supporta snapshot schedulati nativamente)
# In /etc/rancher/k3s/config.yaml:
# etcd-snapshot-schedule-cron: "0 2 * * *"
# etcd-snapshot-retention: 7

L'aggiornamento di k3s è il punto dove la semplicità del progetto brilla: aggiorni il binario e riavvii il servizio. Su un cluster di tre nodi, aggiorni prima i worker (uno alla volta, con kubectl drain e kubectl uncordon per evitare downtime), poi il server. L'intero processo richiede meno di 15 minuti e non causa interruzione di servizio se il tuo deployment ha almeno 2 repliche per pod.

Il monitoring minimo che installo su ogni cluster k3s in produzione è kube-prometheus-stack: Prometheus per le metriche, Grafana per le dashboard, e AlertManager per le notifiche. Si installa con Helm in un comando e fornisce out-of-the-box dashboard per stato dei nodi, utilizzo risorse dei pod, stato dei deployment e alerting su condizioni critiche (nodo NotReady, pod in CrashLoopBackOff, disco pieno). Per il cliente SaaS, le alert vanno su un canale Telegram dedicato - il team riceve una notifica in 30 secondi se un pod crasha o se un nodo diventa irraggiungibile.

Il cluster k3s su Hetzner del cliente SaaS è in produzione da undici mesi al momento in cui scrivo. Ha servito oltre 2 milioni di richieste HTTP, ha gestito zero downtime non pianificati, e ha ricevuto quattro aggiornamenti di versione k3s senza alcuna interruzione di servizio. Il costo mensile medio, inclusi i tre nodi CPX31, un load balancer LB11, un volume da 50 GB e il traffico di rete, è stato di 46,74 euro - confermando la stima iniziale e dimostrando che un cluster Kubernetes di produzione per una PMI non deve costare centinaia di euro al mese. La documentazione ufficiale di Kubernetes rimane il riferimento per capire i concetti architetturali, ma per l'implementazione pratica su Hetzner, k3s e gli strumenti della community rendono il percorso molto più diretto di quanto la reputazione di Kubernetes lasci intendere. Se stai valutando Kubernetes per i tuoi servizi containerizzati e il budget dei grandi cloud provider è fuori portata, contattami per una valutazione architetturale: in una sessione di due ore analizziamo i tuoi requisiti, dimensioniamo il cluster e definiamo un piano di deployment con tempi e costi certi.

Ultima modifica: