Questa pagina mostra come risolvere i problemi relativi allo scheduler Kubernetes
(kube-scheduler
) per Google Distributed Cloud Virtual for Bare Metal.
Kubernetes pianifica sempre i pod sullo stesso insieme di nodi
Questo errore può essere osservato in diversi modi:
Utilizzo del cluster non bilanciato. Puoi controllare l'utilizzo del cluster per ciascun nodo con il comando
kubectl top nodes
. Il seguente output di esempio esagerato mostra l'utilizzo pronunciato su determinati nodi:NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% XXX.gke.internal 222m 101% 3237Mi 61% YYY.gke.internal 91m 0% 2217Mi 0% ZZZ.gke.internal 512m 0% 8214Mi 0%
Troppe richieste. Se pianifichi molti pod contemporaneamente sullo stesso nodo e questi pod effettuano richieste HTTP, la frequenza del nodo potrebbe essere limitata. L'errore comune restituito dal server in questo scenario è
429 Too Many Requests
.Servizio non disponibile. Un server web, ad esempio, ospitato su un nodo sottoposto a carico elevato, potrebbe rispondere a tutte le richieste con errori
503 Service Unavailable
finché non viene sottoposto a un carico più leggero.
Per verificare se disponi di pod sempre pianificati per gli stessi nodi, segui questi passaggi:
Esegui questo comando
kubectl
per visualizzare lo stato dei pod:kubectl get pods -o wide -n default
Per visualizzare la distribuzione dei pod tra i nodi, controlla la colonna
NODE
nell'output. Nell'output di esempio seguente, tutti i pod sono pianificati sullo stesso nodo:NAME READY STATUS RESTARTS AGE IP NODE nginx-deployment-84c6674589-cxp55 1/1 Running 0 55s 10.20.152.138 10.128.224.44 nginx-deployment-84c6674589-hzmnn 1/1 Running 0 55s 10.20.155.70 10.128.226.44 nginx-deployment-84c6674589-vq4l2 1/1 Running 0 55s 10.20.225.7 10.128.226.44
I pod hanno una serie di funzionalità che consentono di perfezionare il loro comportamento di pianificazione. Queste funzionalità includono vincoli di diffusione della topologia e regole di anti-affinità. Puoi utilizzarne una sola o una combinazione di queste. I requisiti
definiti sono collegati tra loro tramite AND da kube-scheduler
.
I log dello scheduler non vengono acquisiti al livello di dettaglio di logging predefinito. Se hai bisogno dei log dello scheduler per la risoluzione dei problemi, segui questi passaggi per acquisire i log dello scheduler:
Aumenta il livello di dettaglio del logging:
Modifica il deployment
kube-scheduler
:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
Aggiungi il flag
--v=5
nella sezionespec.containers.command
:containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true - --v=5
Al termine della risoluzione dei problemi, reimposta il livello di dettaglio al livello predefinito:
Modifica il deployment
kube-scheduler
:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
Ripristina il livello di dettaglio sul valore predefinito:
containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true
Vincoli di diffusione della topologia
I vincoli disseminati della topologia
possono essere utilizzati per distribuire i pod in modo uniforme tra i nodi in base a zones
,
regions
, node
o altra topologia definita dall'utente.
Il manifest di esempio seguente mostra un deployment che distribuisce le repliche in modo uniforme tra tutti i nodi pianificabili utilizzando vincoli di distribuzione della topologia:
apiVersion: apps/v1
kind: Deployment
metadata:
name: topology-spread-deployment
labels:
app: myapp
spec:
replicas: 30
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
topologySpreadConstraints:
- maxSkew: 1 # Default. Spreads evenly. Maximum difference in scheduled Pods per Node.
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule # Default. Alternatively can be ScheduleAnyway
labelSelector:
matchLabels:
app: myapp
matchLabelKeys: # beta in 1.27
- pod-template-hash
containers:
# pause is a lightweight container that simply sleeps
- name: pause
image: registry.k8s.io/pause:3.2
Quando si utilizzano vincoli di diffusione della topologia, si applicano le seguenti considerazioni:
- Il valore
labels.app: myapp
di un pod corrisponde al valorelabelSelector
del vincolo. - Il parametro
topologyKey
specificakubernetes.io/hostname
. Questa etichetta viene collegata automaticamente a tutti i nodi e viene compilata con il nome host del nodo. - L'istruzione
matchLabelKeys
impedisce alle implementazioni di nuovi deployment di considerare i pod di revisioni precedenti al momento di calcolare dove pianificare un pod. L'etichettapod-template-hash
viene completata automaticamente da un deployment.
Anti-affinità dei pod
L'anti-affinità dei pod consente di definire i vincoli per cui i pod possono essere co-locati sullo stesso nodo.
Il manifest di esempio seguente mostra un deployment che utilizza l'anti-affinità per limitare le repliche a un pod per nodo:
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-affinity-deployment
labels:
app: myapp
spec:
replicas: 30
selector:
matchLabels:
app: myapp
template:
metadata:
name: with-pod-affinity
labels:
app: myapp
spec:
affinity:
podAntiAffinity:
# requiredDuringSchedulingIgnoredDuringExecution
# prevents Pod from being scheduled on a Node if it
# does not meet criteria.
# Alternatively can use 'preferred' with a weight
# rather than 'required'.
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
# Your nodes might be configured with other keys
# to use as `topologyKey`. `kubernetes.io/region`
# and `kubernetes.io/zone` are common.
topologyKey: kubernetes.io/hostname
containers:
# pause is a lightweight container that simply sleeps
- name: pause
image: registry.k8s.io/pause:3.2
Questo deployment di esempio specifica 30
repliche, ma si espande solo al numero di nodi disponibili nel tuo cluster.
Quando si utilizza l'anti-affinità dei pod, si applicano le seguenti considerazioni:
- Il valore
labels.app: myapp
di un pod corrisponde al valorelabelSelector
del vincolo. - Il parametro
topologyKey
specificakubernetes.io/hostname
. Questa etichetta viene collegata automaticamente a tutti i nodi e viene compilata con il nome host del nodo. Puoi scegliere di utilizzare altre etichette se il cluster le supporta, ad esempioregion
ozone
.
Pre-pull delle immagini container
In assenza di altri vincoli, per impostazione predefinita kube-scheduler
preferisce pianificare i pod sui nodi su cui è già stata scaricata l'immagine del container. Questo comportamento potrebbe essere interessante per i cluster più piccoli senza altre configurazioni di pianificazione in cui sarebbe possibile scaricare le immagini su ogni nodo. Tuttavia, basarsi su questo concetto dovrebbe essere visto come l'ultima risorsa. Una
soluzione migliore è utilizzare nodeSelector
, vincoli di diffusione della topologia o
affinità / anti-affinità. Per maggiori informazioni, consulta
Assegnare pod ai nodi.
Se vuoi assicurarti che le immagini container siano precaricate su tutti i nodi, puoi utilizzare un elemento DaemonSet
come nell'esempio seguente:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: prepulled-images
spec:
selector:
matchLabels:
name: prepulled-images
template:
metadata:
labels:
name: prepulled-images
spec:
initContainers:
- name: prepulled-image
image: IMAGE
# Use a command the terminates immediately
command: ["sh", "-c", "'true'"]
containers:
# pause is a lightweight container that simply sleeps
- name: pause
image: registry.k8s.io/pause:3.2
Quando il pod è Running
su tutti i nodi, esegui nuovamente il deployment dei pod per vedere se i container sono ora distribuiti uniformemente tra i nodi.