PerfectScalePerfectScale

PerfectScale

Guida completa alla node affinity: esempi, casi d'uso e consigli pratici

Questa pagina è disponibile anche in English, Deutsch, Español, Français, 日本語 e Português.

Aug 30, 202612 min read
Josh Palmer

About Josh Palmer

Head of Content

I'm Josh Palmer, Head of Content at DoiT, where I split my time across multiple business units including DoiT Cloud Intelligence, PerfectScale (Kubernetes cost optimization), and SELECT (Snowflake, Databricks, and BigQuery cost optimization). Before DoiT, I spent four and a half years at OnBoard building content for a board intelligence platform used by 6,000+ organizations, and before that, two years as Content Marketing Manager at Zylo, a SaaS management platform.

My personal page

TLDR: La node affinity permette di vincolare i nodi su cui un pod può essere schedulato in base alle label dei nodi, tramite regole hard (requiredDuringSchedulingIgnoredDuringExecution) o soft (preferredDuringSchedulingIgnoredDuringExecution). È più espressiva di nodeSelector e viene usata tipicamente per indirizzare i pod verso nodi con GPU o SSD, mantenere i workloads in una zona specifica o separare produzione e sviluppo. Standardizzare le label dei nodi, privilegiare le regole soft quando il posizionamento non è obbligatorio e allineare l'affinity con l'autoscaling e il dimensionamento dei workloads aiuta a evitare pod bloccati in stato Pending.

In questo articolo:

Che cos'è la node affinity in Kubernetes?

La node affinity in Kubernetes è un insieme di regole utilizzate per vincolare i nodi su cui un pod può essere schedulato, in base alle label assegnate ai nodi. Offre una logica di scheduling più espressiva e articolata rispetto a nodeSelector, supportando sia regole soft sia regole hard per posizionare i pod su hardware specifico ed etichettato, come SSD o GPU.

Questa funzionalità è particolarmente utile nei cluster Kubernetes multi-tenant, ibridi o eterogenei, dove i workloads possono avere requisiti diversi in termini di hardware o di localizzazione. La node affinity consente di ottimizzare l'utilizzo delle risorse, isolare i workloads sensibili e migliorare le prestazioni delle applicazioni, abbinando i workloads ai nodi con le caratteristiche più adatte.

Principali tipi di node affinity:

  • Regole hard (requiredDuringSchedulingIgnoredDuringExecution): lo scheduler deve trovare un nodo corrispondente su cui collocare il pod; in caso contrario, il pod resta in stato Pending.
  • Regole soft (preferredDuringSchedulingIgnoredDuringExecution): lo scheduler tenta di trovare un nodo corrispondente, ma se non ce ne sono di disponibili schedula comunque il pod altrove.

Esempio di utilizzo (YAML):

spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd

Questo articolo fa parte di una serie dedicata allo scheduling in Kubernetes.

Come funziona la node affinity in Kubernetes

Ecco gli elementi tecnici chiave alla base della node affinity.

Label dei nodi

Le label dei nodi sono coppie chiave-valore associate ai nodi Kubernetes per descriverne gli attributi. Le label sono arbitrarie e possono rappresentare caratteristiche come il tipo di istanza, la regione, la zona di disponibilità o metadati personalizzati rilevanti per lo scheduling dei workloads. Ad esempio, è possibile etichettare i nodi con disktype=ssd o gpu=true per identificare i nodi dotati di storage SSD o accelerazione GPU.

Le label vengono impostate dagli amministratori del cluster o da script di automazione, al momento dell'aggiunta dei nodi al cluster oppure dinamicamente al variare dell'infrastruttura. Un'etichettatura coerente e significativa è essenziale per una node affinity efficace, perché le regole di affinity si basano su queste label per selezionare i nodi appropriati per il posizionamento dei pod. Una corretta etichettatura garantisce che lo scheduler possa interpretare e applicare correttamente le politiche di posizionamento.

Operatori di node affinity

Le regole di node affinity utilizzano operatori per definire come i pod devono corrispondere alle label dei nodi. Gli operatori più comuni sono In, NotIn, Exists e DoesNotExist. Gli operatori In e NotIn permettono di specificare i valori accettabili o non accettabili per una determinata label, mentre Exists e DoesNotExist verificano la presenza o l'assenza di una chiave, indipendentemente dal suo valore.

Questi operatori offrono flessibilità nell'esprimere requisiti di scheduling complessi. Ad esempio, è possibile imporre che i pod vengano eseguiti solo su nodi con environment=production o evitare i nodi con dedicated=backup. Combinando operatori e selettori di label diversi, è possibile perfezionare il posizionamento dei pod in base ai requisiti dei workloads e alle politiche aziendali.

Comportamento dello scheduler

Lo scheduler di Kubernetes valuta le regole di node affinity nel decidere dove collocare un pod. Confronta le label dei nodi disponibili con i criteri di affinity definiti nella specifica del pod. Se un nodo soddisfa le regole di affinity richieste, diventa idoneo allo scheduling del pod; in caso contrario, il pod resta non schedulato finché non è disponibile un nodo adatto.

Esistono due tipi di node affinity: required (hard) e preferred (soft). Le regole required devono essere soddisfatte perché il pod venga schedulato, mentre le regole preferred influenzano la scelta dello scheduler ma non impediscono lo scheduling se nessun nodo preferito è disponibile. Questa distinzione consente strategie di posizionamento sia rigide sia flessibili, bilanciando esigenze operative e disponibilità delle risorse.

Sintassi YAML della node affinity: regole hard e soft

1. RequiredDuringSchedulingIgnoredDuringExecution

requiredDuringSchedulingIgnoredDuringExecution definisce regole di node affinity hard che devono essere soddisfatte prima che un pod possa essere schedulato su un nodo. Lo scheduler considera solo i nodi le cui label corrispondono a tutte le condizioni specificate. Se non è disponibile alcun nodo corrispondente, il pod resta in stato Pending finché non compare un nodo adatto.

Questo tipo di affinity viene usato comunemente per i workloads con requisiti infrastrutturali stringenti. Ad esempio, un'applicazione di machine learning può richiedere nodi con GPU, oppure un workload soggetto a requisiti di conformità può dover essere eseguito solo in una regione o zona di disponibilità specifica.

La parte IgnoredDuringExecution indica che Kubernetes non effettua l'eviction del pod se le label del nodo cambiano dopo lo scheduling. Se una label viene rimossa o modificata in un secondo momento, il pod in esecuzione continua a operare su quel nodo, a meno che un altro meccanismo non ne attivi il rescheduling.

Esempio di codice:

affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd

In questo esempio, il pod può essere eseguito solo su nodi etichettati con disktype=ssd.

2. PreferredDuringSchedulingIgnoredDuringExecution

preferredDuringSchedulingIgnoredDuringExecution definisce regole di affinity soft che influenzano le decisioni di scheduling senza renderle vincolanti. Lo scheduler cerca di collocare i pod su nodi che soddisfano le condizioni preferite, ma può comunque schedulare il pod su altri nodi se necessario.

Le regole di affinity preferred utilizzano un sistema di pesi. A ogni preferenza viene assegnato un peso compreso tra 1 e 100. I nodi che soddisfano le preferenze con peso maggiore ricevono punteggi più alti durante lo scheduling, aumentando la probabilità di essere selezionati.

Questo approccio è utile quando le preferenze di posizionamento migliorano le prestazioni o l'efficienza in termini di costi, ma non sono strettamente necessarie. Ad esempio, si può preferire che i workloads vengano eseguiti su nodi con SSD o in una determinata zona per ridurre la latenza, consentendo comunque lo scheduling altrove in caso di scarsità di risorse.

Esempio di codice:

affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 50
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd

In questo esempio, Kubernetes privilegia i nodi etichettati con disktype=ssd, ma il pod può comunque essere eseguito su altri nodi se non sono disponibili nodi con SSD.

Casi d'uso comuni della node affinity

Eseguire i workloads GPU su nodi GPU

La node affinity viene utilizzata per l'esecuzione di workloads GPU in un cluster Kubernetes. Etichettando i nodi dotati di GPU con una chiave come gpu=true, è possibile garantire che i pod che richiedono risorse GPU vengano schedulati solo su hardware compatibile. Questo previene la contesa delle risorse per i workloads dipendenti dalla GPU.

L'affinity soft può essere utilizzata se il fallback su nodi CPU è accettabile in scenari non critici.

Schedulare i database su nodi SSD

I database richiedono spesso prestazioni di I/O elevate, che i nodi con SSD possono garantire. Etichettando i nodi con disktype=ssd e impostando una node affinity required sui pod dei database, si assicurano prestazioni di storage elevate e una latenza ridotta per i workloads stateful.

Man mano che nuovi nodi SSD vengono aggiunti ed etichettati, i pod dei database diventano idonei a esservi schedulati.

Mantenere i workloads in una zona di disponibilità specifica

Eseguire i workloads in una zona di disponibilità specifica può ridurre la latenza, migliorare la tolleranza ai guasti o soddisfare requisiti normativi. Etichettando i nodi con un identificatore di zona come zone=us-west1-b e specificando la node affinity nelle specifiche dei pod, è possibile controllare la distribuzione dei pod tra le zone.

Con l'affinity preferred, è possibile indirizzare lo scheduler a collocare i pod nella zona desiderata, consentendo comunque il fallback su altre zone in caso di risorse limitate.

Separare i workloads di produzione e di sviluppo

Separare gli ambienti di produzione e di sviluppo in un cluster condiviso è un caso d'uso comune della node affinity. Etichettando i nodi come env=prod o env=dev, è possibile applicare politiche di posizionamento che impediscono ai workloads di sviluppo di essere eseguiti su nodi di produzione e viceversa.

Con la node affinity required si impone una separazione rigorosa, mentre l'affinity preferred offre flessibilità nelle situazioni con risorse limitate.

Node affinity vs. node selector vs. pod affinity

La node affinity, i node selector e la pod affinity sono tutti meccanismi di scheduling di Kubernetes, ma risolvono problemi di posizionamento diversi e offrono livelli di flessibilità differenti.

Il node selector è l'opzione più semplice. Consente a un pod di essere eseguito solo su nodi con label specifiche. La configurazione è immediata e si basa su corrispondenze esatte chiave-valore, come disktype=ssd. Tuttavia, nodeSelector supporta solo semplici controlli di uguaglianza e non può esprimere condizioni più avanzate, come valori multipli o regole di esclusione.

La node affinity estende le capacità di nodeSelector supportando operatori di corrispondenza avanzati come In, NotIn, Exists e DoesNotExist. Supporta inoltre sia regole di scheduling required sia preferred, offrendo agli amministratori un maggiore controllo sul posizionamento dei pod. La node affinity viene tipicamente utilizzata quando i workloads devono essere indirizzati verso nodi con hardware, regioni o ruoli operativi specifici.

La pod affinity funziona diversamente, perché si concentra sulle relazioni tra pod anziché sulle label dei nodi. Consente di schedulare i pod vicino ad altri pod con label specifiche, in genere sullo stesso nodo o nella stessa zona di disponibilità. È utile per ridurre la latenza di rete tra servizi strettamente accoppiati. Kubernetes supporta anche la pod anti-affinity, che distribuisce i pod su nodi diversi per migliorare disponibilità e tolleranza ai guasti.

La tabella seguente riassume le principali differenze:

Caratteristica Node Selector Node Affinity Pod Affinity
Target Label dei nodi Label dei nodi Altri pod
Complessità Semplice Avanzata Avanzata
Operatori supportati Solo uguaglianza Operatori multipli Selettori di label
Regole hard e soft No Sì Sì
Caso d'uso principale Selezione di base dei nodi Posizionamento flessibile sui nodi Co-locazione o separazione dei pod

Consigli pratici per usare la node affinity in modo efficace

1. Standardizzare le label dei nodi prima di scrivere le regole di affinity

La node affinity dipende dalle label dei nodi, quindi un'etichettatura incoerente può causare errori di scheduling o un posizionamento imprevedibile dei pod. Definire una strategia di etichettatura chiara prima di creare le politiche di affinity. Utilizzare convenzioni di denominazione coerenti per label come ambiente, tipo di hardware, regione, ruolo del workload o classe di storage.

Ad esempio, standardizzare label come env=prod, disktype=ssd o workload=batch. Evitare di creare più label che rappresentano lo stesso concetto, come gpu=true e accelerator=gpu.

Automatizzare la gestione delle label dove possibile. I cloud provider e gli strumenti di provisioning dei cluster supportano spesso l'etichettatura automatica per tipi di istanza, zone e node pool. L'automazione riduce gli errori di configurazione manuale e garantisce che i nuovi nodi siano compatibili con le politiche di affinity esistenti.

2. Privilegiare le regole soft se il posizionamento non è obbligatorio

Le regole di affinity hard possono rendere i workloads non schedulabili se i nodi corrispondenti non sono disponibili. Un uso eccessivo di requiredDuringSchedulingIgnoredDuringExecution può ridurre la flessibilità del cluster durante eventi di scaling, finestre di manutenzione o guasti dei nodi.

Le regole di affinity preferred garantiscono un comportamento di scheduling più resiliente. Consentono a Kubernetes di dare priorità ai nodi ideali, collocando comunque i workloads altrove quando necessario.

Utilizzare l'affinity hard solo quando il posizionamento è obbligatorio, ad esempio per applicazioni dipendenti dalla GPU, workloads con vincoli di licenza, sistemi soggetti a requisiti di conformità o applicazioni che richiedono funzionalità hardware specifiche.

3. Allineare la node affinity con l'autoscaling dei nodi

La node affinity deve essere allineata alle politiche di autoscaling del cluster. Se i workloads richiedono nodi con label specifiche, l'autoscaler deve poter effettuare il provisioning di node group corrispondenti. In caso contrario, i pod possono restare bloccati in stato Pending anche con l'autoscaling attivo.

Ad esempio, i workloads GPU dovrebbero essere indirizzati verso node pool dedicati alle istanze GPU, mentre i workloads a uso intensivo di storage dovrebbero essere allineati a node group con SSD.

Verificare che i limiti dell'autoscaler supportino la crescita prevista dei workloads. Se l'autoscaler non può creare ulteriori nodi corrispondenti a causa di limiti di quota o vincoli di configurazione, le regole di affinity possono bloccare i deployment.

4. Combinare l'affinity con il right-sizing dei workloads

La node affinity è più efficace quando i workloads sono dimensionati correttamente. Richieste di CPU o memoria sovradimensionate possono limitare le opzioni di scheduling, anche se esistono nodi adatti che soddisfano le regole di affinity.

Ad esempio, un pod con requisiti di affinity rigidi e richieste di memoria eccessive può restare non schedulato anche in presenza di nodi corrispondenti.

Esaminare le richieste e i limiti di risorse dei workloads insieme alle politiche di affinity. Gli strumenti di monitoraggio e le metriche di Kubernetes possono aiutare a identificare i workloads che consumano costantemente meno risorse di quelle richieste.

5. Rivedere le politiche di affinity man mano che i workloads evolvono

I requisiti dell'infrastruttura e delle applicazioni cambiano nel tempo, quindi le politiche di node affinity vanno riviste regolarmente. Label un tempo significative possono diventare obsolete dopo aggiornamenti del cluster, migrazioni o cambiamenti architetturali.

Revisioni periodiche aiutano a individuare vincoli non necessari, label inutilizzate o politiche di scheduling che riducono l'efficienza del cluster.

Le revisioni operative dovrebbero coinvolgere sia i team di piattaforma sia quelli applicativi, per garantire che le regole di affinity continuino a corrispondere ai requisiti dei workloads senza aggiungere complessità di scheduling superflua.

Ottimizzare il posizionamento sui nodi e l'efficienza delle risorse con PerfectScale

La node affinity permette di controllare dove vengono eseguiti i workloads, ma anche i pod posizionati correttamente possono sprecare capacità o attivare uno scaling dei nodi non necessario se le richieste e i limiti di risorse non sono calibrati. I container sovradimensionati costringono l'autoscaler ad avviare più nodi del necessario, quelli sottodimensionati causano OOM kill ed eviction proprio sui nodi selezionati con cura dalle regole di affinity, e un bin-packing inefficiente lascia sottoutilizzati i nodi etichettati. PerfectScale migliora l'efficienza di Kubernetes con il right-sizing autonomo dei workloads e una visibilità approfondita a livello di nodo, così le politiche di affinity portano i pod su nodi già configurati per la massima efficienza.

Funzionalità chiave di PerfectScale:

  • Right-sizing autonomo dei workloads: analizza continuamente i workloads e adegua le richieste e i limiti di CPU e memoria in base all'utilizzo effettivo, garantendo che i pod schedulati tramite regole di affinity usino le risorse in modo efficiente.
  • Visibilità e ottimizzazione a livello di nodo: offre una visibilità completa su nodi e node pool, convalida node affinity e taint rispetto ai pattern di scheduling effettivi dei workloads e aiuta a selezionare i tipi di nodo ottimali per ciascun workload.
  • Correzioni proattive della configurazione: identifica errori di configurazione — come CPU Request Not Set, Memory Request Not Set e Memory Limit Not Set — che causano eviction, over-commitment dei nodi e scheduling inefficiente sui nodi accuratamente etichettati.
  • Efficienza dell'autoscaling: perfeziona le configurazioni dei workloads affinché autoscaler come Karpenter e Cluster Autoscaler effettuino il provisioning dei tipi e delle dimensioni di nodo corretti, mantenendo il posizionamento basato sull'affinity prevedibile ed efficiente in termini di costi.

Vuole assicurarsi che lo scheduling basato sull'affinity porti i pod su nodi efficienti e dimensionati correttamente? Scopra di più su PerfectScale.

FAQ

Qual è la differenza tra node affinity hard e soft? Le regole hard (requiredDuringSchedulingIgnoredDuringExecution) devono essere soddisfatte, altrimenti il pod resta in stato Pending. Le regole soft (preferredDuringSchedulingIgnoredDuringExecution) sono una preferenza: lo scheduler cerca di rispettarle, ma se necessario colloca il pod altrove.

In cosa la node affinity differisce da nodeSelector? nodeSelector supporta solo semplici regole di corrispondenza esatta sulle label. La node affinity supporta operatori più ricchi (In, NotIn, Exists, DoesNotExist), oltre a logiche di scheduling sia required sia preferred.

In cosa la node affinity differisce dalla pod affinity? La node affinity abbina i pod alle label dei nodi. La pod affinity (e l'anti-affinity) abbina i pod al posizionamento di altri pod, tipicamente per co-locare o distribuire workloads correlati.

Perché il mio pod è bloccato in Pending con la node affinity impostata? Di solito perché nessun nodo soddisfa una regola hard (required): controllare le label dei nodi, verificare che l'autoscaler possa effettuare il provisioning di nodi corrispondenti e assicurarsi che le richieste di risorse del pod non siano sovradimensionate rispetto ai nodi corrispondenti.

Quando conviene usare regole hard invece di regole soft? Solo quando il posizionamento è davvero obbligatorio: workloads dipendenti dalla GPU, vincoli di licenza o requisiti di conformità e residenza dei dati. In caso contrario, meglio privilegiare le regole soft per mantenere flessibile lo scheduling.

Modificare le label di un nodo influisce sui pod già in esecuzione? No. Poiché le regole sono "IgnoredDuringExecution", un pod in esecuzione non subisce l'eviction se le label del nodo cambiano dopo lo scheduling.