Auf dieser Seite wird beschrieben, wie Sie Probleme mit dem Kubernetes-Planer (kube-scheduler
) für Google Distributed Cloud beheben.
Kubernetes plant Pods immer auf denselben Knoten
Dieser Fehler kann sich auf unterschiedliche Weise äußern:
Unausgeglichene Clusterauslastung. Mit dem Befehl
kubectl top nodes
können Sie die Clusterauslastung für jeden Knoten prüfen. Die folgende übertriebene Beispielausgabe zeigt eine starke Auslastung bestimmter Knoten: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%
Zu viele Anfragen: Wenn Sie viele Pods gleichzeitig auf demselben Knoten planen und diese Pods HTTP-Anfragen stellen, kann die Rate des Knotens begrenzt werden. In diesem Fall wird vom Server häufig der Fehler
429 Too Many Requests
zurückgegeben.Dienst nicht verfügbar: Ein Webserver, der beispielsweise auf einem Knoten mit hoher Auslastung gehostet wird, antwortet möglicherweise auf alle Anfragen mit
503 Service Unavailable
-Fehlern, bis die Auslastung sinkt.
So prüfen Sie, ob Pods immer auf denselben Knoten geplant werden:
Führen Sie den folgenden
kubectl
-Befehl aus, um den Status der Pods aufzurufen:kubectl get pods -o wide -n default
Die Verteilung der Pods auf die Knoten sehen Sie in der Spalte
NODE
in der Ausgabe. In der folgenden Beispielausgabe werden alle Pods auf demselben Knoten geplant: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
Pods haben eine Reihe von Funktionen, mit denen Sie das Planungsverhalten optimieren können. Dazu gehören Einschränkungen für die Topologieverteilung und Anti-Affinitätsregeln. Sie können eine oder mehrere dieser Funktionen verwenden. Die von Ihnen definierten Anforderungen werden mit AND durch kube-scheduler
verbunden.
Die Scheduler-Logs werden nicht mit der standardmäßigen Logging-Ausführlichkeit erfasst. Wenn Sie die Scheduler-Protokolle zur Fehlerbehebung benötigen, gehen Sie so vor, um sie zu erfassen:
Erhöhen Sie die Ausführlichkeitsstufe für Protokolle:
Bearbeiten Sie das Deployment
kube-scheduler
:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
Fügen Sie das Flag
--v=5
im Abschnittspec.containers.command
hinzu:containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true - --v=5
Wenn Sie mit der Fehlerbehebung fertig sind, setzen Sie die Detailebene auf die Standardeinstellung zurück:
Bearbeiten Sie das Deployment
kube-scheduler
:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
Setzen Sie die Detailebene auf den Standardwert zurück:
containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true
Einschränkungen für die Topologieverteilung
Mit Topologie-Streuungseinschränkungen können Pods gemäß ihrer zones
-, regions
-, node
- oder einer anderen benutzerdefinierten Topologie gleichmäßig auf Knoten verteilt werden.
Das folgende Beispielmanifest zeigt eine Bereitstellung, bei der Replikats mithilfe von Einschränkungen für die Topologieverteilung gleichmäßig auf alle planbaren Knoten verteilt werden:
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
Beachten Sie bei der Verwendung von Topologie-Streuungseinschränkungen Folgendes:
- Der
labels.app: myapp
eines Pods stimmt mit demlabelSelector
der Einschränkung überein. topologyKey
gibtkubernetes.io/hostname
an. Dieses Label wird automatisch allen Knoten hinzugefügt und mit dem Hostnamen des Knotens ausgefüllt.- Mit dem
matchLabelKeys
wird verhindert, dass beim Roll-out neuer Bereitstellungen Pods alter Versionen berücksichtigt werden, wenn berechnet wird, wo ein Pod geplant werden soll. Das Labelpod-template-hash
wird automatisch durch ein Deployment ausgefüllt.
Pod-Anti-Affinität
Mit der Pod-Anti-Affinität können Sie Einschränkungen dafür definieren, welche Pods sich auf demselben Knoten befinden dürfen.
Das folgende Beispielmanifest zeigt eine Bereitstellung, bei der Replikate mithilfe von Anti-Affinität auf einen Pod pro Knoten beschränkt werden:
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
In diesem Beispiel-Deployment werden 30
Replikate angegeben, es wird jedoch nur auf so viele Knoten erweitert, wie in Ihrem Cluster verfügbar sind.
Bei der Verwendung der Pod-Anti-Affinität gilt Folgendes:
- Der
labels.app: myapp
eines Pods stimmt mit demlabelSelector
der Einschränkung überein. topologyKey
gibtkubernetes.io/hostname
an. Dieses Label wird automatisch allen Knoten hinzugefügt und mit dem Hostnamen des Knotens ausgefüllt. Sie können auch andere Labels verwenden, wenn Ihr Cluster sie unterstützt, z. B.region
oderzone
.
Container-Images vorab abrufen
Wenn keine anderen Einschränkungen vorliegen, plant kube-scheduler
standardmäßig Pods auf Knoten, auf die das Container-Image bereits heruntergeladen wurde. Dieses Verhalten kann in kleineren Clustern ohne andere Planungskonfigurationen von Interesse sein, in denen die Images auf jedem Knoten heruntergeladen werden können. Sie sollten sich jedoch nur im Notfall auf dieses Konzept verlassen. Eine bessere Lösung ist die Verwendung von nodeSelector
, Topologie-Streuungseinschränkungen oder Affinität / Anti-Affinität. Weitere Informationen finden Sie unter Pods zu Knoten zuweisen.
Wenn Sie sicherstellen möchten, dass Container-Images vorab auf alle Knoten gezogen werden, können Sie eine DaemonSet
wie im folgenden Beispiel verwenden:
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
Wenn sich der Pod auf allen Knoten im Status Running
befindet, stellen Sie die Pods noch einmal bereit, um zu prüfen, ob die Container jetzt gleichmäßig auf Knoten verteilt sind.