Questa pagina mostra come risolvere i problemi con lo scheduler di Kubernetes (kube-scheduler) per Google Distributed Cloud.
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 ogni nodo con il comando
kubectl top nodes. Il seguente output di esempio esagerato mostra un 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, è possibile che il nodo sia soggetto a limitazione della frequenza. L'errore comune restituito dal server in questo scenario è
429 Too Many Requests.Servizio non disponibile. Un web server, ad esempio, ospitato su un nodo con un carico elevato potrebbe rispondere a tutte le richieste con errori
503 Service Unavailablefinché il carico non è più leggero.
Per verificare se hai pod che vengono sempre pianificati sugli stessi nodi, segui questi passaggi:
Esegui il seguente comando
kubectlper visualizzare lo stato dei pod:kubectl get pods -o wide -n defaultPer visualizzare la distribuzione dei pod tra i nodi, controlla la colonna
NODEnell'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 ottimizzare il loro comportamento di pianificazione. Queste funzionalità includono vincoli di distribuzione della topologia e regole di anti-affinità. Puoi utilizzare una o una combinazione di queste funzionalità. I requisiti definiti vengono combinati con l'operatore AND da kube-scheduler.
I log dello scheduler non vengono acquisiti al livello di verbosità di logging predefinito. Se hai bisogno dei log dello scheduler per la risoluzione dei problemi, segui questi passaggi per acquisirli:
Aumenta il livello di verbosità di logging:
Modifica il deployment
kube-scheduler:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACEAggiungi il flag
--v=5nella 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 verbosità al livello predefinito:
Modifica il deployment
kube-scheduler:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACEImposta di nuovo il livello di verbosità 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 a zones,
regions, node, o ad altre topologie definite personalizzate.
Il seguente manifest di esempio mostra un deployment che distribuisce uniformemente le repliche 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 i vincoli di distribuzione della topologia, tieni presenti le seguenti considerazioni:
- L'attributo
labels.app: myappdi un pod corrisponde alabelSelectordel vincolo. topologyKeyspecificakubernetes.io/hostname. Questa etichetta viene collegata automaticamente a tutti i nodi e viene compilata con il nome host del nodo.matchLabelKeysimpedisce ai rollout dei nuovi deployment di considerare i pod delle revisioni precedenti quando si calcola dove pianificare un pod. L'etichettapod-template-hashviene compilata automaticamente da un deployment.
Anti-affinità dei pod
L'anti-affinità dei pod consente di definire i vincoli per i pod che possono essere collocati sullo stesso nodo.
Il seguente manifest di esempio 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 cluster.
Quando utilizzi l'anti-affinità dei pod, tieni presenti le seguenti considerazioni:
- L'attributo
labels.app: myappdi un pod corrisponde alabelSelectordel vincolo. topologyKeyspecificakubernetes.io/hostname. Questa etichetta viene collegata automaticamente a tutti i nodi e viene compilata con il nome host del nodo. Se il cluster le supporta, puoi scegliere di utilizzare altre etichette, ad esempioregionozone.
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 container. Questo comportamento potrebbe essere interessante nei cluster più piccoli senza altre configurazioni di pianificazione in cui sarebbe possibile scaricare le immagini su ogni nodo. Tuttavia, affidarsi a questo concetto dovrebbe essere considerato come ultima risorsa. Una soluzione migliore è utilizzare nodeSelector, i vincoli di distribuzione della topologia o l'affinità / anti-affinità. Per ulteriori informazioni, consulta
Assegnare pod ai nodi.
Se vuoi assicurarti che le immagini container vengano pre-pull su tutti i nodi, puoi utilizzare un DaemonSet come il seguente esempio:
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
Dopo che il pod è Running su tutti i nodi, esegui di nuovo il deployment dei pod per verificare se i container sono ora distribuiti uniformemente tra i nodi.
Passaggi successivi
Se hai bisogno di ulteriore assistenza, contatta l'assistenza clienti Google Cloud. Per ulteriori informazioni sulle risorse di assistenza, inclusi i seguenti, consulta anche Richiedere assistenza:
- Requisiti per l'apertura di una richiesta di assistenza.
- Strumenti per la risoluzione dei problemi, come la configurazione dell'ambiente, i log e le metriche.
- Componenti supportati.