PerfectScalePerfectScale

PerfectScale

NodeSelector in Kubernetes: sintassi, esempi e 5 best practice

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

Tania Duggal
By Tania Duggal
Oct 12, 202615 min read

Che cos'è NodeSelector in Kubernetes?

In Kubernetes, nodeSelector è il modo più semplice e consigliato per vincolare un Pod a essere schedulato solo su nodi con label specifiche. Agisce come un filtro rigido per il kube-scheduler: se un nodo non corrisponde a ogni singola label definita nel nodeSelector, il Pod non verrà posizionato su quel nodo.

Come funziona:

  • Etichettatura dei nodi di destinazione: assegnare ai nodi label chiave-valore in base a proprietà come tipo di storage, hardware, architettura o ruolo del workload.
  • Definizione del vincolo del pod: aggiungere un nodeSelector nella spec del pod con le label richieste per lo scheduling.
  • Corrispondenza con tutte le label specificate: lo scheduler considera solo i nodi che corrispondono a ogni coppia chiave-valore definita nel nodeSelector.
  • Valutazione degli altri requisiti di scheduling: i nodi corrispondenti devono comunque soddisfare requisiti di risorse, taint, regole di affinity e altri vincoli di scheduling.
  • Pod senza corrispondenza in stato Pending: se nessun nodo idoneo corrisponde, il pod resta in stato Pending finché le condizioni del cluster o i vincoli di scheduling non cambiano.

nodeSelector vs. node affinity: Se nodeSelector è ottimo per i deployment semplici, i requisiti di scheduling più complessi richiedono in genere la Node Affinity.

Caratteristica nodeSelector Node Affinity
Complessità Semplice e leggero Configurazione più complessa
Logica di matching Solo corrispondenze esatte chiave-valore Supporta operatori espressivi (In, NotIn, Exists, Gt, Lt)
Flessibilità delle regole Solo regole rigide (deve esserci corrispondenza, altrimenti il Pod resta in Pending) Regole rigide e soft (può "preferire" un nodo con fallback se non disponibile)
Targeting a livello di Pod No (solo label dei nodi) Sì (può schedulare rispetto ad altri Pod in esecuzione tramite Pod Affinity)

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

In questo articolo:

Come funziona NodeSelector in Kubernetes

Diagramma di come nodeSelector filtra i nodi: un pod con il selettore disktype: ssd può essere schedulato solo su node-1 e node-3, che hanno quella label, mentre node-2 e node-4 vengono esclusi

Il nodeSelector di Kubernetes funziona confrontando le label definite nella specifica di un pod con le label assegnate ai nodi. Lo scheduler considera solo i nodi che soddisfano ogni coppia chiave-valore presente nel nodeSelector del pod. Questo meccanismo offre un controllo di base sul posizionamento dei workloads senza richiedere regole di scheduling più avanzate.

1. Label dei nodi

Le label dei nodi sono coppie chiave-valore associate ai nodi Kubernetes. Descrivono proprietà del nodo che i workloads possono usare per lo scheduling, come tipo di hardware, configurazione dello storage o ruolo del workload. Kubernetes assegna automaticamente anche alcune label standard, tra cui quelle per architettura, sistema operativo e topologia.

È possibile aggiungere label personalizzate con kubectl label nodes. Ad esempio, kubectl label nodes node-1 disktype=ssd assegna la label disktype=ssd a node-1. I pod possono quindi fare riferimento a questa label tramite nodeSelector.

2. Vincoli di scheduling del pod

Un pod definisce nodeSelector nel campo spec. Ogni voce specifica una label del nodo che deve essere presente con il valore indicato. Ad esempio, nodeSelector: {disktype: ssd} limita il pod ai nodi etichettati disktype=ssd.

Quando vengono specificate più voci, un nodo deve corrisponderle tutte. nodeSelector supporta solo il matching esatto chiave-valore, senza operatori come In, NotIn o confronti numerici. Per condizioni più complesse, Kubernetes mette a disposizione la node affinity.

3. Come lo scheduler di Kubernetes valuta nodeSelector

Quando deve schedulare un pod, lo scheduler di Kubernetes identifica innanzitutto i nodi idonei a eseguirlo. Durante questa fase di filtraggio, confronta il nodeSelector del pod con le label di ciascun nodo candidato. I nodi che non corrispondono a tutte le label richieste vengono esclusi dalla valutazione.

Lo scheduler valuta quindi i nodi rimanenti in base agli altri criteri di scheduling e seleziona un nodo adatto. Un nodeSelector corrispondente rende un nodo idoneo, ma non ne garantisce la selezione, perché anche requisiti di risorse, taint, regole di affinity e altri vincoli possono influire sul posizionamento.

4. Cosa succede quando nessun nodo corrisponde

Se nessun nodo soddisfa il nodeSelector del pod e gli altri requisiti di scheduling, lo scheduler non può assegnare il pod a un nodo. Il pod resta nello stato Pending invece di essere posizionato su un nodo che viola il vincolo.

Kubernetes continua a tentare di schedulare il pod al variare delle condizioni del cluster. Lo scheduling può riuscire in un secondo momento se diventa disponibile un nodo corrispondente, se le sue label cambiano o se i vincoli del pod vengono modificati. Gli eventi dello scheduler, visibili con comandi come kubectl describe pod, aiutano a individuare il vincolo che impedisce il posizionamento.

Sintassi di NodeSelector in Kubernetes

Il campo nodeSelector si definisce sotto spec in un template di pod. Contiene una o più coppie chiave-valore di label dei nodi. Un nodo deve corrispondere a ogni coppia perché il pod sia idoneo allo scheduling su quel nodo.

apiVersion: v1
kind: Pod
metadata:
name: web-pod
spec:
nodeSelector:
workload: web
containers:
- name: nginx
image: nginx:latest

In questo esempio, Kubernetes può schedulare web-pod solo su nodi etichettati workload=web. È possibile applicare la label con:

Terminal window
kubectl label nodes node-1 workload=web

È possibile specificare più vincoli aggiungendo altre voci:

spec:
nodeSelector:
workload: web
environment: production

In questo caso, un nodo idoneo deve avere sia workload=web sia environment=production. nodeSelector esegue un matching esatto delle label; per espressioni come più valori accettabili o regole di esclusione, usare invece la node affinity.

Esempi di NodeSelector in Kubernetes

Schedulare pod su nodi ad alta memoria

È possibile etichettare i nodi in base al tipo di memoria e usare quella label per posizionare le applicazioni a uso intensivo di memoria su nodi adeguati. Ad esempio, etichettare un nodo appropriato con node-type=high-memory:

Terminal window
kubectl label nodes worker-2 node-type=high-memory

Quindi configurare il pod in modo che richieda quella label:

apiVersion: v1
kind: Pod
metadata:
name: memory-app
spec:
nodeSelector:
node-type: high-memory
containers:
- name: web-server
image: nginx:latest

Nel posizionare questo pod, lo scheduler considera solo i nodi con la label node-type=high-memory.

Schedulare pod in una zona di disponibilità specifica

Kubernetes espone comunemente la topologia dei nodi tramite la label topology.kubernetes.io/zone. È possibile usarla per vincolare un pod a una determinata zona di disponibilità:

apiVersion: v1
kind: Pod
metadata:
name: zone-pod
spec:
nodeSelector:
topology.kubernetes.io/zone: eu-west-1b
containers:
- name: app
image: nginx:latest

Il pod può essere eseguito solo su nodi la cui label di zona è eu-west-1b. I nomi effettivi delle zone dipendono dal cluster e dal provider dell'infrastruttura.

Schedulare i workloads per tipo di nodo

Le label personalizzate possono separare i nodi in base al workload previsto. Ad esempio, è possibile designare un gruppo di nodi per le applicazioni backend:

Terminal window
kubectl label nodes worker-3 role=backend

Fare riferimento alla stessa label nella specifica del pod:

apiVersion: v1
kind: Pod
metadata:
name: backend-pod
spec:
nodeSelector:
role: backend
containers:
- name: app
image: nginx

Questo approccio è utile quando un cluster contiene node pool con hardware, capacità o finalità operative diverse.

Schedulare workloads GPU su nodi GPU

I workloads GPU necessitano in genere sia di vincoli di posizionamento sui nodi sia di richieste di risorse GPU. Se i nodi GPU hanno una label adeguata, nodeSelector può limitare lo scheduling a quei nodi:

apiVersion: v1
kind: Pod
metadata:
name: gpu-workload
spec:
nodeSelector:
accelerator: nvidia-gpu
containers:
- name: inference-app
image: example/gpu-app:14.32
resources:
limits:
nvidia.com/gpu: 1

Il nodeSelector controlla l'idoneità dei nodi, mentre nvidia.com/gpu: 1 richiede una risorsa GPU al device plugin. Il nome della label è specifico del cluster, quindi usare una label effettivamente configurata sui propri nodi GPU.

NodeSelector vs. Node Affinity vs. nodeName in Kubernetes

Kubernetes offre diversi meccanismi per controllare su quale nodo viene eseguito un pod. nodeSelector, node affinity e nodeName possono tutti influire sul posizionamento, ma funzionano in modo diverso e si adattano a requisiti di scheduling differenti:

  • nodeSelector è l'opzione più semplice. Richiede che un nodo abbia esattamente le coppie chiave-valore di label specificate dal pod. Funziona bene quando i workloads hanno requisiti di posizionamento semplici, come l'esecuzione solo su nodi SSD o GPU.
  • Node affinity usa anch'essa le label dei nodi, ma supporta regole più espressive. Può effettuare matching su più valori, usare operatori come In, NotIn, Exists e DoesNotExist e definire regole di posizionamento sia obbligatorie sia preferenziali. Da usare quando la logica di scheduling non può essere rappresentata con corrispondenze esatte delle label.
  • nodeName funziona in modo diverso perché bypassa la normale selezione dei nodi da parte dello scheduler. Impostare spec.nodeName assegna il pod direttamente al nodo indicato. È utile in genere per casi specifici in cui il nodo di destinazione esatto è già noto, non per lo scheduling ordinario dei workloads.
Caratteristica nodeSelector Node Affinity nodeName
Metodo di posizionamento Confronta le label dei nodi Valuta espressioni basate sulle label Punta a un nodo specifico
Flessibilità di scheduling Bassa Alta Molto bassa
Matching esatto delle label Sì Sì No
Matching su più valori No Sì No
Regole obbligatorie Sì Sì Assegnazione diretta
Regole preferenziali No Sì No
Usa la normale selezione dei nodi dello scheduler Sì Sì No
Ideale per Posizionamento semplice basato sulle label Regole di posizionamento complesse o preferenziali Assegnare un pod a un nodo noto

Best practice per NodeSelector in Kubernetes

Ecco alcune pratiche utili da considerare quando si lavora con nodeSelector in Kubernetes.

1. Adottare convenzioni coerenti per le label dei nodi

Definire uno schema di denominazione standard per le label usate da nodeSelector. Ad esempio, label come workload=compute, storage=ssd e accelerator=gpu descrivono chiaramente perché un workload potrebbe selezionare un nodo. Per le label specifiche dell'organizzazione, usare un prefisso in stile DNS come example.com/node-pool=gpu.

Mantenere coerenti chiavi e valori delle label tra cluster e ambienti, dove possibile. Evitare che valori come gpu, GPU e gpu-node rappresentino la stessa proprietà. Piccole incoerenze possono lasciare i pod in stato Pending, perché nodeSelector richiede corrispondenze esatte.

Le label dovrebbero inoltre descrivere proprietà rilevanti per lo scheduling, non informazioni operative temporanee. Documentare le label di scheduling importanti, così che i team applicativi sappiano quali label sono disponibili e quali garanzie offre ciascuna.

2. Usare label stabili invece dei nomi dei nodi

Preferire label che descrivono un gruppo di nodi o una capacità, invece di legare i workloads a singoli nodi. I nodi sono spesso risorse temporanee e possono scomparire durante autoscaling, aggiornamenti, manutenzione o guasti dell'infrastruttura.

Ad esempio, node-pool=compute consente a un pod di essere eseguito su qualsiasi nodo adatto di un pool di compute. Puntare direttamente a un nodo come worker-03 crea una dipendenza da quella macchina e rende più difficile la sostituzione dei nodi.

Dove possibile, configurare le label dei nodi come parte del provisioning dei node pool o dell'infrastruttura. I nodi sostitutivi riceveranno così automaticamente le stesse label, consentendo alle regole nodeSelector esistenti di continuare a funzionare senza modifiche ai manifest dei workloads.

3. Combinare nodeSelector con request e limit delle risorse

nodeSelector determina se un nodo ha le label richieste, ma non indica se quel nodo dispone di CPU o memoria sufficienti. Configurare le request delle risorse insieme alle regole di posizionamento, così che lo scheduler possa tenere conto delle risorse necessarie a ciascun pod.

Ad esempio, un pod potrebbe selezionare nodi ad alta memoria richiedendo al contempo 8Gi di memoria. Lo scheduler considera solo i nodi corrispondenti e verifica poi se dispongono di capacità allocabile sufficiente per la request. Senza request adeguate, i workloads possono competere per le risorse anche quando vengono posizionati sul tipo di nodo previsto.

I limit delle risorse offrono controlli di runtime aggiuntivi sul consumo di risorse. Usare request e limit in base al comportamento del workload, senza presumere che la selezione di un nodo più grande o specializzato elimini la necessità di gestire le risorse.

4. Usare taint e toleration per i nodi dedicati

nodeSelector controlla dove può essere eseguito un determinato pod, ma non impedisce ad altri pod di usare gli stessi nodi. Questa distinzione è importante quando i nodi sono riservati a workloads che richiedono hardware costoso o specializzato.

Applicare un taint ai nodi dedicati e aggiungere una toleration corrispondente ai workloads autorizzati a usarli. Quindi usare nodeSelector per garantire che quei workloads selezionino attivamente il gruppo di nodi previsto. Ad esempio, è possibile applicare un taint ai nodi GPU in modo che le applicazioni ordinarie non vi vengano schedulate, mentre i workloads GPU tollerano il taint e selezionano la label GPU.

Taint, toleration e nodeSelector risolvono quindi problemi complementari. Il selector limita il posizionamento del workload, mentre il taint aiuta a proteggere la capacità dei nodi dedicati dai workloads che dovrebbero essere eseguiti altrove.

5. Usare label protette per l'isolamento dei nodi ai fini della sicurezza

Non considerare le normali label dei nodi un solido perimetro di sicurezza. A seconda della configurazione del cluster e dei permessi, un nodo compromesso o controllato in modo improprio potrebbe influenzare le label usate per determinare dove vengono eseguiti i workloads sensibili.

Per un isolamento rilevante ai fini della sicurezza, Kubernetes può usare l'admission plugin NodeRestriction insieme al Node authorizer. NodeRestriction impedisce ai kubelet di impostare o modificare label con il prefisso riservato node-restriction.kubernetes.io/ e nomi qualificati il cui prefisso termina con .node-restriction.kubernetes.io.

Un amministratore può quindi applicare una label come example.com.node-restriction.kubernetes.io/pci-dss=true e farvi riferimento nelle regole di scheduling. Poiché il kubelet non può assegnarsi quella label protetta, questa costituisce una base più solida per isolare i workloads che devono essere eseguiti solo su nodi designati dall'amministratore.

FAQ

Che cos'è nodeSelector in Kubernetes? nodeSelector è il modo più semplice e consigliato per vincolare un Pod a nodi con label specifiche. È un filtro rigido per il kube-scheduler: se un nodo non corrisponde a tutte le label definite nel nodeSelector, il Pod non viene posizionato su quel nodo.

Come si usa nodeSelector? Prima si assegna la label al nodo di destinazione con kubectl label nodes, ad esempio kubectl label nodes node-1 disktype=ssd. Poi si aggiunge un nodeSelector nella spec del Pod con la stessa chiave e lo stesso valore, ad esempio disktype: ssd. Lo scheduler considererà solo i nodi corrispondenti.

Cosa succede se nessun nodo corrisponde al nodeSelector? Il Pod resta nello stato Pending invece di essere posizionato su un nodo che viola il vincolo. Kubernetes continua a provare al variare delle condizioni, quindi lo scheduling può riuscire in seguito se compare un nodo corrispondente, se le label dei nodi cambiano o se i vincoli del Pod vengono modificati. Il comando kubectl describe pod mostra gli eventi dello scheduler che ne spiegano il motivo.

Qual è la differenza tra nodeSelector e node affinity? nodeSelector supporta solo corrispondenze esatte chiave-valore e regole rigide. La node affinity supporta operatori come In, NotIn, Exists, DoesNotExist, Gt e Lt e può esprimere sia regole di posizionamento obbligatorie sia preferenziali. Usare la node affinity quando le corrispondenze esatte delle label non sono sufficienti.

Qual è la differenza tra nodeSelector e nodeName? nodeSelector passa comunque attraverso lo scheduler, che filtra i nodi in base alle label e poi ne sceglie uno. Impostare nodeName bypassa la normale selezione dei nodi dello scheduler e assegna il Pod direttamente al nodo indicato, il che è utile soprattutto in casi specifici in cui il nodo di destinazione è già noto.

nodeSelector impedisce ad altri pod di usare gli stessi nodi? No. nodeSelector controlla dove può essere eseguito un determinato Pod, ma non riserva il nodo. Per tenere i workloads ordinari lontani dai nodi dedicati, applicare un taint a quei nodi e aggiungere una toleration corrispondente ai workloads autorizzati a utilizzarli.

Ottimizzare il posizionamento e l'utilizzo dei nodi Kubernetes con PerfectScale

PerfectScale è una piattaforma di ottimizzazione per Kubernetes che si installa con un singolo comando Helm e offre insight concreti e ottimizzazione autonoma su tutto lo stack K8s. Mentre nodeSelector controlla dove possono essere eseguiti i workloads, PerfectScale aiuta a garantire che quei workloads siano dimensionati correttamente e che i nodi su cui vengono eseguiti siano quelli giusti, così da ridurre la capacità sprecata senza compromettere prestazioni o affidabilità.

Funzionalità principali di PerfectScale:

  • Right-sizing autonomo dei workloads: Podfit offre una vista granulare su salute e costi del cluster, individua rapidamente risorse sprecate e problemi di resilienza e fornisce raccomandazioni basate sui dati o automazione per il right-sizing immediato dei workloads.
  • Visibilità sull'utilizzo dei nodi: Infrafit offre visibilità completa sull'utilizzo dei nodi, aiutando a individuare ed eliminare la capacità inattiva mantenendo prestazioni e affidabilità del cluster ai massimi livelli.
  • Selezione dei nodi basata sui dati: raccomandazioni che aiutano a scegliere i nodi giusti per i propri workloads, a supporto di decisioni migliori sui gruppi di nodi a cui puntano le label di scheduling.
  • Ottimizzazione degli autoscaler dei nodi: massimizza l'efficacia di autoscaler come Karpenter, con integrazioni per HPA, Cluster Autoscaler, EKS Auto Mode, Fargate, Node Auto Provisioning, Google Autopilot e altro ancora.
  • Avvisi in tempo reale con priorità: gli avvisi con priorità automatica, inviati a Slack, Datadog, MS Teams, PagerDuty e altri strumenti, consentono di affrontare per primi i rischi di resilienza e i picchi di costo più rilevanti.
  • Governance e previsioni: il report Trends offre visibilità nel tempo sulle metriche di costo, spreco e rischio tra cluster, gruppi di nodi, namespace e workloads, a supporto di una pianificazione accurata del budget e dell'analisi delle cause alla radice.
  • Supporto per qualsiasi ambiente: ottimizzazione dei cluster su cloud pubblici come EKS, GKE e AKS, cloud privati come OpenShift, ambienti on-premises e ibridi.

Vuole ottimizzare i Suoi nodi e workloads Kubernetes? Scopra di più sulla piattaforma PerfectScale.