Fehlerbehebung beim Kubernetes-Planer

Auf dieser Seite wird beschrieben, wie Sie Probleme mit dem Kubernetes-Planer (kube-scheduler) für Google Distributed Cloud beheben.

Wenn Sie weitere Unterstützung benötigen, wenden Sie sich an den Cloud Customer Care.

Kubernetes plant Pods immer mit demselben Satz von Knoten.

Dieser Fehler kann auf verschiedene Arten auftreten:

  • Unausgeglichene Clusterauslastung. Mit dem Befehl kubectl top nodes können Sie die Clusterauslastung für jeden Knoten überprüfen. Die folgende übertriebene Beispielausgabe zeigt eine ausgesprochene 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, kann der Knoten die Rate begrenzt. Der häufig vom Server zurückgegebene Fehler in diesem Szenario ist 429 Too Many Requests.

  • Dienst nicht verfügbar: Ein Webserver, der beispielsweise auf einem Knoten unter hoher Last gehostet wird, kann auf alle Anfragen mit 503 Service Unavailable-Fehlern antworten, bis er geringer ist.

So prüfen Sie, ob Pods immer für dieselben Knoten geplant sind:

  1. Führen Sie den folgenden kubectl-Befehl aus, um den Status der Pods anzusehen:

    kubectl get pods -o wide -n default
    

    In der Spalte NODE in der Ausgabe sehen Sie die Verteilung der Pods auf Knoten. 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 Features gehören Streuungseinschränkungen für die Topologie und Anti-Affinitätsregeln. Sie können eine dieser Funktionen oder eine Kombination dieser Funktionen verwenden. Die von Ihnen definierten Anforderungen werden durch kube-scheduler miteinander verknüpft.

Die Planerlogs werden nicht auf der Ausführlichkeitsstufe des Standard-Loggings erfasst. Wenn Sie die Planerlogs zur Fehlerbehebung benötigen, führen Sie die folgenden Schritte aus, um die Planerlogs zu erfassen:

  1. Erhöhen Sie die Ausführlichkeitsstufe für das Logging:

    1. Bearbeiten Sie das Deployment kube-scheduler:

      kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \
        -n USER_CLUSTER_NAMESPACE
      
    2. Fügen Sie das Flag --v=5 im Abschnitt spec.containers.command hinzu:

      containers:
      - command:
      - kube-scheduler
      - --profiling=false
      - --kubeconfig=/etc/kubernetes/scheduler.conf
      - --leader-elect=true
      - --v=5
      
  2. Setzen Sie nach Abschluss der Fehlerbehebung die Ausführlichkeitsstufe wieder auf die Standardstufe zurück:

    1. Bearbeiten Sie das Deployment kube-scheduler:

      kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \
        -n USER_CLUSTER_NAMESPACE
      
    2. Setzen Sie die Ausführlichkeitsstufe auf den Standardwert zurück:

      containers:
      - command:
      - kube-scheduler
      - --profiling=false
      - --kubeconfig=/etc/kubernetes/scheduler.conf
      - --leader-elect=true
      

Streuungseinschränkungen für Topologien

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 Einschränkungen zur Topologieverteilung 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 gelten bei der Verwendung von Einschränkungen für die Topologieverteilung:

  • Der labels.app: myapp eines Pods entspricht dem labelSelector der Einschränkung.
  • topologyKey gibt kubernetes.io/hostname an. Dieses Label wird automatisch an alle Knoten angehängt und mit dem Hostnamen des Knotens gefüllt.
  • Der matchLabelKeys verhindert, dass Rollouts neuer Deployments Pods alter Überarbeitungen berücksichtigen, wenn sie berechnen, wo ein Pod geplant werden soll. Das Label pod-template-hash wird automatisch von einem Deployment 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 sind 30-Replikate angegeben, es wird jedoch nur auf so viele Knoten erweitert, die in Ihrem Cluster verfügbar sind.

Die folgenden Überlegungen gelten bei der Verwendung der Pod-Anti-Affinität:

  • Der labels.app: myapp eines Pods entspricht dem labelSelector der Einschränkung.
  • topologyKey gibt kubernetes.io/hostname an. Dieses Label wird automatisch an alle Knoten angehängt und mit dem Hostnamen des Knotens gefüllt. Sie können auch andere Labels verwenden, wenn Ihr Cluster sie unterstützt, z. B. region oder zone.

Container-Images vorab abrufen

Wenn keine anderen Einschränkungen vorhanden sind, plant kube-scheduler Pods standardmäßig auf Knoten, auf die bereits das Container-Image heruntergeladen wurde. Dieses Verhalten kann bei kleineren Clustern ohne andere Planungskonfigurationen von Interesse sein, bei denen die Images auf jedem Knoten heruntergeladen werden können. Sie sollten sich jedoch auf dieses Konzept als letztes Mittel verlassen. Eine bessere Lösung ist die Verwendung von nodeSelector, Topologieverteilungseinschränkungen oder Affinität / Anti-Affinität. Weitere Informationen finden Sie unter Pods zu Knoten zuweisen.

Wenn Sie dafür sorgen möchten, dass Container-Images vorab auf alle Knoten übertragen werden, können Sie einen 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.

Nächste Schritte

Wenn Sie weitere Unterstützung benötigen, wenden Sie sich an den Cloud Customer Care.