Executive summary
Quando un'organizzazione gestisce centinaia o migliaia di applicazioni distribuite su infrastrutture eterogenee, il problema di allocare risorse, garantire la disponibilità dei servizi e reagire ai cambiamenti di carico diventa un ostacolo concreto alla velocità operativa. Questo articolo analizza in profondità i sistemi che automatizzano la distribuzione, il coordinamento e la gestione del ciclo di vita delle applicazioni eseguite in ambienti isolati, esaminando le scelte architetturali fondamentali, i meccanismi di posizionamento dei carichi di lavoro e le strategie di adattamento automatico della capacità. Dall'analisi emerge che l'efficacia di questi sistemi dipende dalla capacità di descrivere lo stato finale atteso anziché le operazioni da compiere, da un processo automatico che confronta continuamente la situazione reale con quella attesa correggendo le discrepanze, e dalla possibilità di aggiungere regole operative specifiche per ogni applicazione senza modificare il nucleo della piattaforma.
Background
L'orchestrazione di contenitori rappresenta il culmine di un percorso evolutivo iniziato con la virtualizzazione a livello di sistema operativo. I primi sistemi di isolamento a livello di processo (chroot nel 1979, FreeBSD Jails nel 2000, Linux VServer nel 2001) stabilirono il principio di partizionamento delle risorse senza il sovraccarico di una macchina virtuale completa. L'introduzione dei cgroups e dei namespace nel kernel Linux, tra il 2006 e il 2008, fornì le primitive necessarie per un isolamento più granulare di CPU, memoria, rete e filesystem, creando le condizioni tecniche per l'emergere dei contenitori moderni [1].
Il passaggio dalla gestione manuale dei contenitori all'orchestrazione automatizzata fu catalizzato dall'esperienza di Google con i sistemi Borg e Omega. Borg, descritto da Verma et al. nel 2015, gestiva centinaia di migliaia di job su cluster composti da decine di migliaia di macchine, combinando admission control, task-packing efficiente e over-commitment con isolamento a livello di processo [2]. Le lezioni apprese da oltre un decennio di operazione di Borg e Omega confluirono nella progettazione di Kubernetes, sistema reso open-source nel 2014 e donato alla Cloud Native Computing Foundation (CNCF) nel 2015 [3]. A differenza di Borg, che utilizzava un sistema centralizzato di gestione dello stato, Kubernetes adottò fin dall'inizio un'architettura dichiarativa fondata sul pattern di riconciliazione continua: ogni componente confronta lo stato osservato del cluster con lo stato desiderato espresso dall'utente, convergendo iterativamente verso la configurazione target.
L'adozione di Kubernetes ha raggiunto una penetrazione significativa nell'industria. Secondo il CNCF Annual Survey 2025, l'82% delle organizzazioni che utilizzano contenitori esegue Kubernetes in produzione, con un incremento rispetto al 66% registrato nel 2023 [4]. Il 59% delle organizzazioni intervistate dichiara che la maggior parte o la quasi totalità del proprio sviluppo e deployment è ormai cloud-native. Questa diffusione capillare rende l'analisi approfondita dell'architettura, dei meccanismi di scheduling e dei pattern di estensibilità di Kubernetes non un esercizio accademico, ma una necessità operativa per qualsiasi team di ingegneria che gestisca infrastrutture distribuite.
La domanda centrale a cui questo articolo risponde è la seguente: quali sono i principi architetturali, i meccanismi di scheduling e i pattern di estensibilità che determinano l'efficacia operativa di un sistema di container orchestration in scenari di produzione complessi? L'analisi esamina in sequenza l'architettura del control plane, i meccanismi di scheduling, i pattern di estensibilità tramite CRD e Operator, il packaging applicativo, le service mesh e i sistemi di autoscaling.
Architettura del control plane
Il modello dichiarativo e il loop di riconciliazione
Il principio architetturale fondante di Kubernetes è la separazione tra stato desiderato (desired state) e stato osservato (actual state). Ogni risorsa nel cluster (un Pod, un Deployment, un Service) è rappresentata come un oggetto dichiarativo che descrive la configurazione target. Il sistema non riceve istruzioni imperative su quali operazioni eseguire, ma converge autonomamente verso lo stato dichiarato attraverso un ciclo continuo di osservazione, confronto e correzione. Questo modello, derivato direttamente dall'esperienza con Borg [2, 3], conferisce al sistema proprietà di auto-riparazione (self-healing) e idempotenza: l'applicazione ripetuta della stessa dichiarazione produce sempre lo stesso risultato, indipendentemente dallo stato iniziale.
Componenti del control plane
Il control plane di Kubernetes è composto da quattro componenti principali che cooperano attraverso un'interfaccia API centralizzata [5].
kube-apiserver. Costituisce il punto di ingresso unico per tutte le interazioni con il cluster. Ogni operazione, dalla creazione di un Pod alla lettura dello stato di un nodo, transita attraverso l'API server, che implementa autenticazione, autorizzazione (RBAC), admission control e validazione dello schema. L'API server è progettato per lo scaling orizzontale: in ambienti di produzione ad alta disponibilità, è comune eseguire multiple istanze bilanciate tramite un load balancer esterno [5]. La scelta di centralizzare tutte le comunicazioni attraverso un unico componente stateless semplifica il modello di sicurezza e consente l'implementazione di policy trasversali (audit logging, rate limiting, admission webhook) in un punto singolo.
etcd. Il datastore distribuito che persiste l'intero stato del cluster. etcd implementa il protocollo di consenso Raft [6], che garantisce consistenza forte (linearizability) attraverso un meccanismo di leader election e log replication. Ogni scrittura deve essere confermata dalla maggioranza dei nodi etcd prima di essere considerata committed, il che fornisce tolleranza ai guasti fino a $\lfloor (n-1)/2 \rfloor$ nodi su un cluster di $n$ membri. La scelta di Raft rispetto ad alternative come Paxos fu motivata dalla maggiore comprensibilità dell'algoritmo, come dimostrato dallo studio utente condotto da Ongaro e Ousterhout [6]. In termini di limiti operativi, etcd impone un vincolo di 1.5 MB sulla dimensione massima di un singolo oggetto e la latenza delle scritture è direttamente influenzata dalla latenza del disco e della rete tra i nodi del cluster etcd.
kube-scheduler. Il componente responsabile dell'assegnazione dei Pod ai nodi del cluster. Il processo di scheduling opera in due fasi: una fase di filtering, che elimina i nodi che non soddisfano i vincoli del Pod (risorse insufficienti, node affinity/anti-affinity, taints e tolerations), e una fase di scoring, che classifica i nodi rimanenti in base a funzioni di priorità configurabili [5]. I fattori considerati includono requisiti di risorse individuali e aggregati, vincoli hardware e software, specifiche di affinità e anti-affinità, località dei dati e interferenza tra workload. Il scheduler opera in modalità watch sull'API server, reagendo alla creazione di Pod non ancora assegnati a un nodo.
kube-controller-manager. Esegue i controller che implementano la logica di riconciliazione per le risorse built-in di Kubernetes. Ogni controller è logicamente un processo separato, ma per ridurre la complessità operativa tutti i controller sono compilati in un singolo binario [5]. I controller principali includono il Node Controller (rileva e gestisce i guasti dei nodi), il Job Controller (crea Pod per l'esecuzione di task a completamento), l'EndpointSlice Controller (gestisce il collegamento tra Service e Pod) e il ServiceAccount Controller (crea i ServiceAccount predefiniti per i nuovi namespace).
Componenti dei nodi
Ogni nodo worker esegue tre componenti fondamentali. Il kubelet è l'agente che garantisce che i contenitori specificati nelle PodSpec siano in esecuzione e in stato di salute. Opera come il collegamento tra il control plane e il container runtime effettivo sul nodo. Il kube-proxy implementa le regole di rete che consentono la comunicazione tra Pod, utilizzando il layer di packet filtering del sistema operativo (iptables o IPVS) quando disponibile [5]. Il container runtime, tipicamente containerd o CRI-O, è responsabile dell'esecuzione effettiva dei contenitori, interagendo con il kubelet attraverso la Container Runtime Interface (CRI).
Implicazioni architetturali e single point of failure
L'architettura del control plane introduce una dipendenza critica da etcd: la perdita del quorum etcd rende il cluster incapace di accettare nuove modifiche allo stato, sebbene i workload in esecuzione continuino a funzionare. La letteratura recente evidenzia che questa dipendenza rappresenta una debolezza architetturale fondamentale, mitigabile attraverso il deployment di cluster etcd con un numero dispari di membri (tipicamente 3 o 5) distribuiti su failure domain distinti. L'API server, essendo stateless, tollera la perdita di istanze senza impatto sulla consistenza dei dati, a condizione che almeno un'istanza resti raggiungibile.
Meccanismi di scheduling
Il default scheduler e i suoi limiti
Lo scheduler predefinito di Kubernetes implementa un algoritmo best-effort che opera sulla base di informazioni statiche al momento della decisione di scheduling. La logica di base, filtraggio dei nodi idonei seguito dal punteggio e dalla selezione del nodo con il punteggio più alto, è efficace per workload omogenei ma presenta limiti significativi in scenari complessi. Come evidenziato dalla survey di Senjab et al. [7], che analizza 47 studi pubblicati tra il 2018 e il 2023, lo scheduler predefinito non considera fattori dinamici quali la latenza di rete, il consumo energetico, la località dei dati o le caratteristiche specifiche dei workload (batch vs. latency-sensitive).
Tassonomia degli approcci di scheduling
Senjab et al. [7] classificano gli algoritmi di scheduling per Kubernetes in quattro categorie principali:
-
Generic scheduling. Estensioni dello scheduler predefinito che aggiungono criteri di filtraggio o funzioni di scoring personalizzate, mantenendo la struttura algoritmica originale. Questi approcci operano tipicamente attraverso il meccanismo di scheduler extender o, a partire da Kubernetes 1.19, attraverso il scheduling framework basato su plugin.
-
Multi-objective optimization-based scheduling. Algoritmi che ottimizzano simultaneamente più obiettivi potenzialmente conflittuali, utilizzo delle risorse, bilanciamento del carico, consumo energetico, rispetto degli SLA. Le tecniche impiegate includono programmazione lineare intera, algoritmi genetici e ottimizzazione a sciame di particelle.
-
AI-focused scheduling. Approcci basati su machine learning, in particolare reinforcement learning, che apprendono politiche di scheduling dall'osservazione del comportamento del cluster. Studi recenti dimostrano che scheduler basati su Deep Q-Network (DQN) possono ridurre lo sbilanciamento di carico tra i nodi del 15-25% rispetto allo scheduler predefinito, considerando simultaneamente bilanciamento del carico, utilizzo delle risorse e consumo energetico [8].
-
Autoscaling-enabled scheduling. Strategie che integrano le decisioni di scheduling con quelle di autoscaling, considerando non solo dove posizionare un Pod ma anche quando e come adattare la capacità del cluster.
Scheduling e workload eterogenei
Un aspetto critico emerso dalla letteratura recente riguarda lo scheduling di workload eterogenei sullo stesso cluster. I workload di machine learning inference, ad esempio, richiedono accesso a GPU con caratteristiche specifiche (memoria VRAM, compute capability), latenza prevedibile e spesso co-locazione con i dati del modello. I workload batch tollerano latenze maggiori ma beneficiano di bin-packing aggressivo per massimizzare l'utilizzo delle risorse. Lo scheduler predefinito tratta entrambi i casi con la stessa logica, delegando la differenziazione ai vincoli dichiarati dall'utente (resource requests, node selectors, taints). Approcci più sofisticati, come quelli basati su scheduling multi-obiettivo, consentono di codificare queste differenze nelle funzioni obiettivo dell'ottimizzazione, ottenendo allocazioni più efficienti.
Estensibilità: Custom Resource Definition e Operator pattern
Il meccanismo di estensione dichiarativa
Una delle decisioni architetturali più consequenti nella progettazione di Kubernetes fu la creazione di un meccanismo di estensibilità nativo che consente di aggiungere nuovi tipi di risorse senza modificare il codice sorgente della piattaforma. Le Custom Resource Definition (CRD), stabilizzate nell'API apiextensions.k8s.io/v1, permettono di definire risorse personalizzate con schema OpenAPI v3, validazione tramite Common Expression Language (CEL) e supporto per il versioning semantico attraverso conversion webhook [5, 9]. Dal punto di vista dell'API server, una CRD è trattata come qualsiasi risorsa built-in: supporta operazioni CRUD, watch, field selectors e label selectors. Lo stato della risorsa è persistito in etcd con le stesse garanzie di consistenza delle risorse native.
L'Operator pattern
Una CRD da sola definisce solo un modello dati. L'Operator pattern completa il ciclo combinando una CRD con un controller personalizzato che implementa la logica di riconciliazione specifica del dominio [9, 10]. Il CNCF Operator White Paper definisce un Operator come un'estensione software di Kubernetes che codifica la conoscenza operativa in un controller automatizzato. Il ciclo di riconciliazione dell'Operator segue una sequenza invariante: (1) osservazione delle risorse personalizzate tramite meccanismo di watch sull'API server, (2) rilevamento di cambiamenti o derive dallo stato desiderato, (3) esecuzione delle azioni correttive necessarie, creazione, aggiornamento o eliminazione di risorse subordinate, e (4) aggiornamento dello status della risorsa personalizzata.
Questo pattern è particolarmente efficace per la gestione di applicazioni stateful complesse. Si consideri un Operator per un database distribuito: la CRD definisce lo schema della risorsa Database (numero di repliche, versione, configurazione dello storage), mentre il controller gestisce automaticamente la creazione dei StatefulSet, dei PersistentVolumeClaim, dei ConfigMap e dei Secret necessari, orchestrando operazioni complesse come upgrade rolling, backup schedulati e failover automatico. La logica operativa che tradizionalmente risiedeva in runbook manuali o script imperativi viene così codificata in un ciclo di riconciliazione dichiarativo, testabile e versionabile [10].
Maturità e limiti del pattern
Con Kubernetes 1.30+ e lo stack controller-runtime maturo, gli Operator sono diventati pervasivi: gestiscono database (CockroachDB, PostgreSQL via CloudNativePG), pipeline di ML (Kubeflow), policy di sicurezza (Kyverno, OPA Gatekeeper) e infrastruttura multi-cloud (Crossplane) [9]. Tuttavia, il pattern presenta limiti significativi. La complessità del ciclo di riconciliazione cresce rapidamente con il numero di risorse subordinate e con la necessità di gestire stati transitori e condizioni di errore. Ogni CRD aggiunge overhead all'API server, e etcd impone vincoli di dimensione (1.5 MB per oggetto) che limitano la quantità di stato gestibile in una singola risorsa. La progettazione di CRD stabili richiede disciplina nel versioning dell'API: una volta che una CRD è adottata dagli utenti, modifiche incompatibili al suo schema rompono il contratto implicito dell'API, rendendo necessari conversion webhook e strategie di migrazione pianificate.
Packaging applicativo: Helm e la gestione delle release
La complessità della configurazione dichiarativa di Kubernetes, dove una singola applicazione può richiedere decine di manifest YAML interdipendenti, ha generato la necessità di uno strumento di packaging e templating. Helm, il package manager ufficiale del progetto CNCF, affronta questo problema attraverso il concetto di chart: un archivio strutturato che contiene template YAML parametrizzabili, valori di default, dipendenze e metadati [11].
L'architettura di Helm ha subito un'evoluzione significativa tra la versione 2 e la versione 3. Helm v2 richiedeva Tiller, un componente server-side con privilegi elevati che operava all'interno del cluster, creando problemi di sicurezza in ambienti multi-tenant. Helm v3, rilasciato nel 2019, eliminò completamente Tiller adottando un'architettura client-only che interagisce direttamente con l'API server di Kubernetes tramite le credenziali dell'utente, allineando il modello di sicurezza con il RBAC nativo del cluster [11].
Helm 4.0.0, rilasciato nel novembre 2025 in occasione del decimo anniversario del progetto a KubeCon + CloudNativeCon North America, introduce il supporto nativo per Server-Side Apply (SSA). Con SSA, la logica di merge è delegata all'API server, che mantiene il concetto di field ownership e gestisce i conflitti in modo deterministico. Questo risolve una classe significativa di problemi che affliggevano le release Helm in scenari di modifica concorrente delle risorse, dove il three-way merge client-side di Helm 3 poteva produrre risultati imprevisti [11].
Il modello di Helm introduce tuttavia un trade-off architetturale. La parametrizzazione tramite template Go offre flessibilità ma sacrifica la validazione statica: un errore nel templating produce YAML malformato rilevabile solo al momento dell'installazione. Strumenti alternativi come Kustomize adottano un approccio diverso, basato sulla composizione e l'overlay di manifest YAML senza templating, preservando la validabilità statica a scapito della flessibilità parametrica. In pratica, molte organizzazioni combinano entrambi gli approcci: Helm per la distribuzione di chart complessi con valori environment-specific, Kustomize per gli overlay finali specifici di ciascun ambiente.
Service mesh: osservabilità e sicurezza del traffico inter-servizio
Il problema della comunicazione tra microservizi
In un'architettura a microservizi su Kubernetes, il traffico est-ovest (tra servizi interni al cluster) rappresenta la maggioranza delle comunicazioni di rete. Le funzionalità native di Kubernetes, Service, kube-proxy, DNS interno, forniscono discovery e load balancing di base, ma non offrono crittografia del traffico intra-cluster, osservabilità a livello di protocollo applicativo (HTTP/gRPC), circuit breaking, retry intelligenti o politiche di autorizzazione fine-grained tra servizi. Le service mesh colmano questa lacuna inserendo un layer di infrastruttura programmabile nella comunicazione tra servizi [12].
Architettura e varianti implementative
L'architettura tradizionale di una service mesh si basa sul pattern sidecar proxy: un proxy (tipicamente Envoy nel caso di Istio, linkerd2-proxy nel caso di Linkerd) viene iniettato in ogni Pod, intercettando trasparentemente tutto il traffico in ingresso e in uscita [12, 13]. Il control plane della mesh distribuisce configurazione, certificati e policy ai proxy, mentre il data plane esegue le operazioni di routing, crittografia e telemetria sul traffico effettivo.
Istio, progetto graduated dalla CNCF, ha consolidato il proprio control plane nel componente unificato Istiod, che gestisce configurazione, service discovery e certificate management. L'architettura ambient mesh, introdotta con Istio 1.22 e raggiunta la general availability con Istio 1.24, rappresenta un cambiamento paradigmatico: separa la funzionalità in due livelli distinti. Un overlay L4 leggero e sicuro (implementato da ztunnel, un proxy node-level) gestisce la crittografia mTLS e il routing di base, mentre proxy L7 dedicati (waypoint proxy) vengono attivati solo per i servizi che richiedono funzionalità avanzate come traffic splitting, header manipulation o autorizzazione fine-grained [13]. Questa separazione riduce drasticamente il footprint di risorse: i cluster che necessitano solo di mTLS possono evitare l'overhead dei proxy sidecar L7 per la maggior parte dei servizi.
Impatto sulle prestazioni
L'overhead introdotto dalla service mesh è stato quantificato empiricamente. Uno studio tecnico del 2024, pubblicato come preprint su arXiv, ha misurato l'incremento di latenza causato dall'enforcement di mTLS su quattro implementazioni: Istio tradizionale (+166%), Istio Ambient (+8%), Linkerd (+33%) e Cilium (+99%) [14]. I risultati evidenziano differenze di ordini di grandezza: la latenza di Istio in modalità sidecar è quasi quattro volte quella di Linkerd e oltre sei volte quella di Istio Ambient. In termini di consumo di risorse, Cilium e Istio Ambient hanno mostrato le migliori prestazioni rispettivamente per CPU e memoria, mentre Istio sidecar ha registrato il consumo più elevato su entrambe le dimensioni [14]. Un aspetto notevole emerso dallo studio riguarda Cilium, che disabilita per design la crittografia per il traffico intra-nodo, ottenendo un vantaggio prestazionale significativo ma con implicazioni di sicurezza che devono essere valutate esplicitamente.
Gateway API e convergenza architetturale
La Kubernetes Gateway API, raggiunta la stabilità nella versione 1.1, rappresenta il punto di convergenza tra ingress management e service mesh. Istio supporta nativamente la Gateway API come interfaccia unificata per la gestione del traffico sia nord-sud (ingress) che est-ovest (mesh) [13]. La combinazione di ambient mode e Gateway API consente un'adozione incrementale delle funzionalità mesh: un team può iniziare con un overlay L4 sicuro, aggiungere mTLS, applicare policy e osservare il traffico di base, per poi attivare le capacità L7 solo dove necessario. Questo approccio graduale riduce la barriera di adozione rispetto al deployment monolitico di una mesh completa.
Autoscaling: strategie di adattamento della capacità
Tassonomia dei meccanismi di autoscaling
Kubernetes supporta tre livelli distinti di autoscaling, ciascuno operante su una dimensione diversa del problema di capacity management [5, 15].
Horizontal Pod Autoscaler (HPA). Componente built-in che adatta il numero di repliche di un Deployment o ReplicaSet in base a metriche osservate. L'HPA opera attraverso un ciclo di controllo periodico (default: 15 secondi) che calcola il rapporto tra il valore corrente della metrica e il valore target configurato, determinando il numero di repliche necessarie secondo la formula:
$$\text{desiredReplicas} = \lceil \text{currentReplicas} \times \frac{\text{currentMetricValue}}{\text{desiredMetricValue}} \rceil$$
La metrica predefinita è l'utilizzo di CPU, ma l'HPA supporta metriche di memoria, metriche custom (esposte tramite l'API custom.metrics.k8s.io) e metriche esterne (tramite external.metrics.k8s.io). Il limite principale dell'HPA è la natura reattiva del meccanismo: la CPU è un indicatore lagging, quando l'utilizzo supera la soglia, il sistema di coda o la latenza percepita dall'utente potrebbero essere già degradati [15].
Vertical Pod Autoscaler (VPA). Add-on che adatta le resource request e i resource limit dei contenitori in base ai pattern di utilizzo osservati storicamente. Il VPA analizza il consumo effettivo di CPU e memoria nel tempo e raccomanda (o applica automaticamente) request più accurate, riducendo sia il sotto-provisioning (che causa throttling e OOM kill) sia il sovra-provisioning (che spreca risorse e aumenta i costi). A partire da Kubernetes 1.35, la funzionalità di in-place vertical scaling è stabile e abilitata per default, consentendo la modifica delle risorse di un contenitore senza riavviare il Pod [5]. Tuttavia, il VPA presenta un vincolo operativo significativo: il suo utilizzo simultaneo con l'HPA sulla stessa metrica (ad esempio CPU) genera conflitti, poiché entrambi i controller tentano di rispondere allo stesso segnale con azioni ortogonali.
Cluster-level autoscaling. Opera sulla dimensione infrastrutturale, aggiungendo o rimuovendo nodi dal cluster. Il Cluster Autoscaler tradizionale opera in modo reattivo: aggiunge nodi quando esistono Pod unschedulable e rimuove nodi sottoutilizzati dopo un periodo di grazia. Karpenter, progetto più recente della CNCF, adotta un approccio proattivo: effettua provisioning di nodi direttamente in base ai requisiti dei workload in attesa, senza dipendere da node group predefiniti. Test in produzione indicano che Karpenter riesce a rendere operativi i Pod CPU-bound in circa 55 secondi, rispetto ai 3-4 minuti del Cluster Autoscaler tradizionale, dove il collo di bottiglia è il tempo di spin-up dell'Auto Scaling Group del cloud provider [16].
Event-driven autoscaling con KEDA
KEDA (Kubernetes Event-Driven Autoscaling), progetto graduated dalla CNCF nell'agosto 2023, estende le capacità di autoscaling orizzontale di Kubernetes consentendo lo scaling basato su eventi provenienti da sorgenti esterne: lunghezza delle code di messaggi (Kafka, RabbitMQ, Azure Service Bus), metriche Prometheus, schedule cron, o qualsiasi sorgente custom [15, 17]. L'architettura di KEDA si compone di tre elementi: un operatore che gestisce le risorse ScaledObject e ScaledJob, un metrics server che espone le metriche degli scaler all'HPA nativo, e un catalogo di oltre 70 scaler built-in che si connettono a sorgenti di eventi esterne.
Il vantaggio architetturale fondamentale di KEDA risiede nella capacità di scalare a zero repliche quando non ci sono eventi da processare. L'HPA nativo richiede almeno una replica attiva per raccogliere metriche; KEDA supera questa limitazione monitorando direttamente la sorgente di eventi e attivando la prima replica quando un evento è disponibile. Una volta che il Pod è in esecuzione, KEDA alimenta le metriche dell'evento all'HPA nativo, che gestisce lo scaling da 1 a N repliche secondo la propria logica [17]. Questo pattern, scale-to-zero + HPA-driven scaling, risulta particolarmente efficace per workload event-driven con pattern di traffico bursty: gateway di pagamento, sistemi di elaborazione ordini, pipeline di data processing con carico variabile.
Composizione delle strategie di autoscaling
In scenari di produzione complessi, le strategie di autoscaling vengono combinate in modo complementare. Una configurazione tipica prevede KEDA per lo scaling orizzontale event-driven dei workload asincroni, HPA con metriche custom per i servizi sincroni, VPA per il right-sizing delle risorse dei workload con carico stabile, e Karpenter per il provisioning dinamico dei nodi. La sfida operativa principale risiede nell'orchestrazione di questi meccanismi: senza una progettazione attenta, i diversi autoscaler possono interferire tra loro, generando oscillazioni (flapping) o sovra-provisioning. La pratica consolidata prevede l'utilizzo di stabilization window nell'HPA, la separazione delle metriche tra HPA e VPA, e la configurazione di consolidation policy in Karpenter per evitare eviction premature.
Limiti e problemi aperti
Nonostante la maturità raggiunta, l'ecosistema Kubernetes presenta sfide significative che la ricerca e l'ingegneria stanno attivamente affrontando.
Complessità operativa. La superficie di configurazione di Kubernetes è vasta: un deployment di produzione richiede competenze in networking (CNI, network policy, service mesh), storage (CSI, PersistentVolume, storage classes), sicurezza (RBAC, Pod Security Standards, admission controller), e osservabilità (metriche, log, tracing distribuito). Il CNCF Annual Survey 2024 identifica la complessità come la barriera principale all'adozione in organizzazioni senza team di platform engineering dedicati [4].
Scheduling multi-obiettivo. Lo scheduler predefinito rimane inadeguato per scenari che richiedono ottimizzazione simultanea di latenza, costo, consumo energetico e affidabilità. Le ricerche emergenti su carbon-aware scheduling aggiungono una dimensione ulteriore: la possibilità di considerare l'intensità di carbonio dell'energia disponibile in ciascuna regione al momento della decisione di scheduling, un requisito che nessun scheduler commerciale soddisfa ancora in modo maturo [7].
Sicurezza del supply chain. L'estensibilità di Kubernetes tramite CRD, Operator, Helm chart e immagini container introduce una superficie di attacco significativa. La verifica dell'integrità dell'intera catena, dall'immagine base al chart Helm all'Operator, richiede strumenti e processi (Sigstore, SLSA, admission policy) che si trovano ancora in fase di consolidamento nell'ecosistema.
Gestione dello stato. Kubernetes è stato progettato per workload stateless. Sebbene StatefulSet, Operator e CSI abbiano migliorato significativamente il supporto per workload stateful, la gestione di database distribuiti, sistemi di caching e storage persistente in Kubernetes richiede ancora competenze specialistiche e comporta rischi operativi superiori rispetto al deployment su infrastruttura dedicata.
Riferimenti
[1] Linux Foundation, "Kernel Namespaces and Cgroups," Linux kernel documentation. https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
[2] A. Verma et al., "Large-scale cluster management at Google with Borg," in Proc. European Conference on Computer Systems (EuroSys), ACM, 2015. https://dl.acm.org/doi/10.1145/2741948.2741964
[3] B. Burns et al., "Borg, Omega, and Kubernetes," Communications of the ACM, vol. 59, no. 5, pp. 50-57, 2016. https://dl.acm.org/doi/10.1145/2890784
[4] Cloud Native Computing Foundation, "CNCF Annual Survey 2025," 2026. https://www.cncf.io/announcements/2026/01/20/kubernetes-established-as-the-de-facto-operating-system-for-ai-as-production-use-hits-82-in-2025-cncf-annual-cloud-native-survey/
[5] Kubernetes Project, "Cluster Architecture," official documentation, 2026. https://kubernetes.io/docs/concepts/architecture/
[6] D. Ongaro and J. Ousterhout, "In Search of an Understandable Consensus Algorithm," in Proc. USENIX Annual Technical Conference (ATC), 2014. https://raft.github.io/raft.pdf
[7] K. Senjab et al., "A survey of Kubernetes scheduling algorithms," Journal of Cloud Computing, vol. 12, no. 87, Springer, 2023. https://link.springer.com/article/10.1186/s13677-023-00471-1
[8] X. Li et al., "Adaptive container scheduling based on reinforcement learning in Kubernetes," CCF Transactions on High Performance Computing, Springer, 2025. https://link.springer.com/article/10.1007/s42514-025-00223-4
[9] Kubernetes Project, "Operator Pattern," official documentation, 2026. https://kubernetes.io/docs/concepts/extend-kubernetes/operator/
[10] CNCF TAG App Delivery, "CNCF Operator White Paper v1.0," 2022. https://github.com/cncf/tag-app-delivery/blob/163962c4b1cd70d085107fc579e3e04c2e14d59c/operator-wg/whitepaper/Operator-WhitePaper_v1-0.md
[11] Helm Project, "Helm Architecture," official documentation, 2026. https://helm.sh/docs/topics/architecture/
[12] Istio Project, "Istio Service Mesh," official documentation, 2026. https://istio.io/latest/docs/
[13] CNCF, "Istio Brings Future Ready Service Mesh to the AI Era with New Ambient Multicluster," 2026. https://www.cncf.io/announcements/2026/03/25/istio-brings-future-ready-service-mesh-to-the-ai-era-with-new-ambient-multicluster-gateway-api-inference-extension-and-more/
[14] F. Bonaventura et al., "Technical Report: Performance Comparison of Service Mesh Frameworks: the MTLS Test Case," arXiv:2411.02267, 2024. https://arxiv.org/abs/2411.02267
[15] Kubernetes Project, "Autoscaling Workloads," official documentation, 2026. https://kubernetes.io/docs/concepts/workloads/autoscaling/
[16] Kubernetes SIGs, "Karpenter — Just-in-time Nodes for Any Kubernetes Cluster," GitHub repository, 2025. https://github.com/kubernetes-sigs/karpenter
[17] KEDA Project, "KEDA — Kubernetes Event-driven Autoscaling," official documentation, 2026. https://keda.sh/