Fehlerbehebung beim Kubernetes-Planer

Auf dieser Seite wird beschrieben, 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 in unterschiedlicher Weise auftreten:

  • Unausgeglichene Clusterauslastung. Mit dem Befehl kubectl top nodes können Sie die Clusternutzung für jeden Knoten prüfen. Die folgende übertriebene Beispielausgabe zeigt eine deutliche 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 stellen, kann es sein, dass der Knoten einer Ratenbegrenzung unterliegt. Der häufigste Fehler, der vom Server in diesem Fall zurückgegeben wird, ist 429 Too Many Requests.

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

So prüfen Sie, ob Sie Pods haben, die immer auf denselben Knoten geplant werden:

  1. 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 abstimmen können. Dazu gehören Topologie-Streuungseinschränkungen 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 dem standardmäßigen Logging-Ausführlichkeitsgrad erfasst. Wenn Sie die Scheduler-Logs zur Fehlerbehebung benötigen, gehen Sie so vor, um sie zu erfassen:

  1. Erhöhen Sie den Logging-Ausführlichkeitsgrad:

    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. Wenn Sie mit der Fehlerbehebung fertig sind, setzen Sie den Ausführlichkeitsgrad auf die Standardeinstellung 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 den Ausführlichkeitsgrad auf den Standardwert zurück:

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

Topologie-Streuungseinschränkungen

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 ein Deployment, bei dem Replikate mithilfe von Topologie-Streuungseinschränkungen 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:

  • Die labels.app: myapp eines Pods stimmt mit dem labelSelector der Einschränkung überein.
  • topologyKey gibt kubernetes.io/hostname an. Dieses Label wird automatisch allen Knoten angehängt und mit dem Hostnamen des Knotens ausgefüllt.
  • Mit dem matchLabelKeys wird verhindert, dass beim Roll-out neuer Deployments Pods alter Überarbeitungen berücksichtigt werden, wenn berechnet wird, wo ein Pod geplant werden soll. Das Label pod-template-hash wird automatisch durch ein Deployment eingefügt.

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 ein Deployment, bei dem 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.

Beachten Sie bei der Verwendung der Pod-Anti-Affinität Folgendes:

  • Die labels.app: myapp eines Pods stimmt mit dem labelSelector der Einschränkung überein.
  • topologyKey gibt kubernetes.io/hostname an. Dieses Label wird automatisch allen Knoten angehängt und mit dem Hostnamen des Knotens ausgefü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 vorliegen, plant kube-scheduler standardmäßig lieber Pods auf Knoten, auf die das Container-Image bereits heruntergeladen wurde. Dieses Verhalten kann in kleineren Clustern ohne andere Planungskonfigurationen von Interesse sein, bei denen die Images auf jedem Knoten heruntergeladen werden können. Sich auf dieses Konzept zu verlassen, sollte jedoch als letztes Mittel angesehen werden. 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 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

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. Weitere Informationen zu Supportressourcen finden Sie unter Support. Dazu gehören:

  • Anforderungen für das Eröffnen eines Supportfalls.
  • Tools zur Fehlerbehebung, z. B. Ihre Umgebungskonfiguration, Logs und Messwerte.
  • Unterstützte Komponenten.