Queste pagine mostrano come risolvere i problemi relativi allo schedulatore Kubernetes
(kube-scheduler
) per Google Distributed Cloud.
Kubernetes pianifica sempre i pod nello stesso insieme di nodi
Questo errore può essere osservato in diversi modi:
Utilizzo non bilanciato del cluster. Puoi controllare l'utilizzo del cluster per ciascun nodo con il comando
kubectl top nodes
. L'esempio seguente mostra un output esagerato che indica un utilizzo elevato su alcuni 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%
Numero eccessivo di richieste. Se pianifichi molti pod contemporaneamente sullo stesso Nodo e questi pod inviano richieste HTTP, è possibile che il Nodo sia soggetto a un limite di velocità. L'errore comune restituito dal server in questo scenario è
429 Too Many Requests
.Servizio non disponibile. Ad esempio, un web server ospitato su un Nodo con un carico elevato potrebbe rispondere a tutte le richieste con errori
503 Service Unavailable
finché il carico non sarà inferiore.
Per verificare se hai pod pianificati sempre sugli stessi nodi, segui i seguenti passaggi:
Esegui il seguente 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'esempio di output 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 dispongono di una serie di funzionalità che consentono di ottimizzare il loro comportamento di pianificazione. Queste funzionalità includono vincoli di distribuzione della topologia e regole anti-affinità. Puoi utilizzare una o più di queste funzionalità. I requisiti
che definisci sono uniti da AND per kube-scheduler
.
I log del programmatore non vengono acquisiti al livello di dettaglio della registrazione predefinito. Se hai bisogno dei log del programmatore per la risoluzione dei problemi, segui questi passaggi per acquisizione dei log del programmatore:
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 sul 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 distribuzione della topologia
I vincoli di distribuzione della topologia
possono essere utilizzati per distribuire uniformemente i pod tra i nodi in base alla loro topologia zones
,regions
, node
o altra topologia definita in base alle esigenze.
Il manifest di esempio seguente mostra un deployment che distribuisce le repliche in modo uniforme tra tutti i nodi pianificabili utilizzando i 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 utilizzi le limitazioni di distribuzione della topologia, si applicano le seguenti considerazioni:
- Il
labels.app: myapp
di un pod corrisponde allabelSelector
della limitazione. topologyKey
specificakubernetes.io/hostname
. Questa etichetta viene collegata automaticamente a tutti i nodi e viene compilata con il nome host del nodo.matchLabelKeys
impedisce che i rollout dei nuovi deployment tengano conto dei pod delle vecchie revisioni durante il calcolo di dove pianificare un pod. L'etichettapod-template-hash
viene compilata automaticamente da un deployment.
Anti-affinità dei pod
L'anti-affinità dei pod ti consente di definire i vincoli per i quali i pod possono essere posizionati insieme nello stesso nodo.
Il seguente esempio di manifest 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 esempio di deployment specifica 30
repliche, ma si espande solo fino al numero di nodi disponibili nel cluster.
Le seguenti considerazioni si applicano quando utilizzi l'anti-affinità dei pod:
- Il
labels.app: myapp
di un pod corrisponde allabelSelector
della limitazione. 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 tuo cluster le supporta, ad esempioregion
ozone
.
Immagini container pre-pull
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 in cluster più piccoli senza altre configurazioni di pianificazione in cui sarebbe possibile scaricare le immagini su ogni nodo. Tuttavia, fare affidamento su questo concetto dovrebbe essere visto come ultima risorsa. Una
soluzione migliore è utilizzare nodeSelector
, vincoli di distribuzione della topologia o
affinità / anti-affinità. Per ulteriori informazioni, consulta
Assegnazione dei pod ai nodi.
Se vuoi assicurarti che le immagini dei container vengano prelevate su tutti i nodi, puoi utilizzare un 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
Una volta che il pod è Running
su tutti i nodi, esegui nuovamente il deployment dei pod per verificare se i container sono ora distribuiti uniformemente tra i nodi.