Auf dieser Seite erfahren Sie, wie Sie Probleme mit dem Kubernetes-Planer (kube-scheduler
) für Google Distributed Cloud beheben.
Kubernetes plant Pods immer für dieselben Knoten
Dieser Fehler kann auf unterschiedliche Weise auftreten:
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 ausgeprägte Auslastung auf bestimmten 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 senden, ist es möglich, dass der Knoten eine Ratenbegrenzung erhält. Der häufigste Fehler, der in diesem Szenario vom Server zurückgegeben wird, ist
429 Too Many Requests
.Der Dienst ist nicht verfügbar. Ein Webserver, der beispielsweise auf einem Knoten unter hoher Last gehostet wird, reagiert möglicherweise auf alle Anfragen mit
503 Service Unavailable
-Fehlern, bis er weniger ausgelastet ist.
So prüfen Sie, ob Pods immer für dieselben Knoten geplant sind:
Führen Sie den folgenden
kubectl
-Befehl aus, um den Status der Pods anzusehen:kubectl get pods -o wide -n default
Die Verteilung der Pods auf Knoten sehen Sie in der Spalte
NODE
in der Ausgabe. In der folgenden Beispielausgabe sind 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 Features, mit denen Sie ihr Planungsverhalten optimieren können. Zu diesen Funktionen gehören Streuungsbeschränkungen der Topologie und Anti-Affinitätsregeln. Sie können eine dieser Funktionen oder eine Kombination davon verwenden. Die von Ihnen definierten Anforderungen werden durch eine UND-Verbindung durch kube-scheduler
verknüpft.
Die Planerlogs werden nicht mit der standardmäßigen Ausführlichkeitsstufe für Logging erfasst. Wenn Sie die Planerlogs zur Fehlerbehebung benötigen, führen Sie die folgenden Schritte aus, um die Planerlogs zu erfassen:
Erhöhen Sie den Logging-Ausführlichkeitsgrad:
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 den Ausführlichkeitsgrad auf die Standardstufe zurück:
Bearbeiten Sie das Deployment
kube-scheduler
:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
Setzen Sie die Ausführlichkeit auf den Standardwert zurück:
containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true
Streuungseinschränkungen der Topologie
Topologie-Streuungseinschränkungen können verwendet werden, um Pods gemäß ihrer zones
, regions
, node
oder einer anderen benutzerdefinierten Topologie gleichmäßig auf Knoten zu verteilen.
Das folgende Beispielmanifest zeigt ein Deployment, das Replikate mithilfe von Topologie-Streuungseinschränkungen gleichmäßig auf alle planbaren Knoten verteilt:
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
Die folgenden Überlegungen sind bei der Verwendung von Topologie-Streuungseinschränkungen zu beachten:
- Der
labels.app: myapp
eines Pods stimmt mit demlabelSelector
der Einschränkung überein. topologyKey
gibtkubernetes.io/hostname
an. Dieses Label wird automatisch an alle Knoten angehängt und mit dem Hostnamen des Knotens gefüllt.- Das
matchLabelKeys
verhindert, dass bei Roll-outs neuer Deployments Pods aus alten Überarbeitungen bei der Berechnung berücksichtigt werden, wo ein Pod geplant werden soll. Das Labelpod-template-hash
wird von einem Deployment automatisch ausgefüllt.
Pod-Anti-Affinität
Mit der Pod-Anti-Affinität können Sie Einschränkungen definieren, für die sich Pods auf demselben Knoten befinden können.
Das folgende Beispielmanifest zeigt ein Deployment, das Anti-Affinität verwendet, um Replikate auf einen Pod pro Knoten zu beschränken:
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 werden jedoch nur so viele Knoten in Ihrem Cluster verfügbar, dass sie verfügbar sind.
Die folgenden Überlegungen gelten bei Verwendung der Pod-Anti-Affinität:
- Der
labels.app: myapp
eines Pods stimmt mit demlabelSelector
der Einschränkung überein. topologyKey
gibtkubernetes.io/hostname
an. Dieses Label wird automatisch an alle Knoten angehängt und mit dem Hostnamen des Knotens gefüllt. Sie können andere Labels verwenden, wenn Ihr Cluster diese unterstützt, z. B.region
oderzone
.
Container-Images vorab per Pull abrufen
Wenn keine anderen Einschränkungen vorhanden sind, bevorzugt kube-scheduler
standardmäßig das Planen von Pods auf Knoten, auf die bereits das Container-Image heruntergeladen wurde. Dieses Verhalten kann bei kleineren Clustern ohne andere Planungskonfigurationen von Interesse sein, bei denen es möglich wäre, die Images auf jeden Knoten herunterzuladen. Dieses Konzept sollte jedoch als letztes Mittel angesehen werden. Eine bessere Lösung ist die Verwendung von nodeSelector
, Einschränkungen der Topologie-Streuung 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 geladen werden, können Sie ein 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
Nachdem der Pod auf allen Knoten den Status Running
hat, stellen Sie die Pods noch einmal bereit, um zu prüfen, ob die Container jetzt gleichmäßig auf die Knoten verteilt sind.