Risolvi i problemi dello scheduler Kubernetes

Queste pagine mostrano come risolvere i problemi relativi allo schedulatore Kubernetes (kube-scheduler) per Google Distributed Cloud.

Se hai bisogno di ulteriore assistenza, contatta Assistenza clienti Google Cloud.

Kubernetes pianifica sempre i pod nello stesso insieme di nodi

Questo errore può essere osservato in diversi modi:

  • Utilizzo non bilanciato del cluster. Puoi esaminare l'utilizzo del cluster ogni nodo con il comando kubectl top nodes. I seguenti esempi esagerati l'output di esempio 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%
    
  • Numero eccessivo di richieste. Se pianifichi molti pod contemporaneamente sullo stesso Il nodo e i pod effettuano richieste HTTP, è possibile che la frequenza limitato. L'errore comune restituito dal server in questo scenario è 429 Too Many Requests.

  • Servizio non disponibile. Un server web, ad esempio, ospitato su un nodo in un ambiente potrebbe rispondere a tutte le richieste con 503 Service Unavailable errori fino a quando è sottoposto a un carico più leggero.

Per verificare se hai pod sempre pianificati sugli stessi nodi, utilizza seguenti passaggi:

  1. Esegui il seguente comando kubectl per visualizzare lo stato dei pod:

    kubectl get pods -o wide -n default
    

    Per visualizzare la distribuzione dei pod tra i nodi, controlla la colonna NODE nell'output. Nell'esempio di output 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 varie funzionalità che ti consentono di ottimizzarne la pianificazione comportamento degli utenti. Queste funzionalità includono vincoli di diffusione della topologia e anti-affinità le regole del caso. Puoi utilizzare una di queste funzionalità o una loro combinazione. I requisiti che definisci sono uniti da AND per kube-scheduler.

I log del programmatore non vengono acquisiti al livello di dettaglio della registrazione predefinito. Se hai bisogno dei log del programmatore per la risoluzione dei problemi, segui questi passaggi per acquisirli:

  1. Aumenta il livello di dettaglio del logging:

    1. Modifica il deployment kube-scheduler:

      kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \
        -n USER_CLUSTER_NAMESPACE
      
    2. Aggiungi il flag --v=5 nella sezione spec.containers.command:

      containers:
      - command:
      - kube-scheduler
      - --profiling=false
      - --kubeconfig=/etc/kubernetes/scheduler.conf
      - --leader-elect=true
      - --v=5
      
  2. Al termine della risoluzione dei problemi, reimposta il livello di dettaglio al livello predefinito:

    1. Modifica il deployment kube-scheduler:

      kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \
        -n USER_CLUSTER_NAMESPACE
      
    2. Ripristina il livello di dettaglio 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 alla loro topologia zones,regions, node o altra topologia definita in base alle esigenze.

Il manifest di esempio seguente mostra un deployment che distribuisce le repliche in modo uniforme tra tutti i nodi pianificabili mediante vincoli di diffusione 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 diffusione della topologia, si applicano le seguenti considerazioni:

  • Il valore labels.app: myapp di un pod corrisponde al valore labelSelector del vincolo.
  • topologyKey specifica kubernetes.io/hostname. Questa etichetta viene collegata automaticamente a tutti i nodi e viene compilata con il nome host del nodo.
  • L'matchLabelKeys impedisce che le implementazioni di nuovi deployment prendano in considerazione Pod di vecchie revisioni per calcolare dove pianificare un pod. L'etichetta pod-template-hash viene compilata automaticamente da un deployment.

Anti-affinità dei pod

L'anti-affinità dei pod ti consente di definire i vincoli per i quali i pod possono essere posizionati insieme nello stesso nodo.

Il seguente esempio di manifest 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

In questo esempio il deployment specifica 30 repliche, ma si espande solo al numero di nodi disponibili nel tuo cluster.

Quando utilizzi l'anti-affinità dei pod, valgono le seguenti considerazioni:

  • Il valore labels.app: myapp di un pod corrisponde al valore labelSelector del vincolo.
  • Il topologyKey specifica kubernetes.io/hostname. Questa etichetta viene collegata automaticamente a tutti i nodi e viene compilata con il nome host del nodo. Puoi scegliere di utilizzare altre etichette se il tuo cluster le supporta, ad esempio region o zone.

Immagini container pre-pull

In assenza di altri vincoli, per impostazione predefinita kube-scheduler preferisce pianificare i pod sui nodi su cui è già stata scaricata l'immagine container che li rappresentano. Questo comportamento potrebbe essere interessante in 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 visto come l'ultima risorsa. R La soluzione migliore consiste nell'utilizzare nodeSelector, vincoli di distribuzione della topologia affinità / anti-affinità. Per ulteriori informazioni, vedi Assegnazione di pod ai nodi.

Se vuoi assicurarti che le immagini dei container vengano prelevate su tutti i nodi, puoi utilizzare un DaemonSet come nell'esempio seguente:

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

Quando il pod è Running su tutti i nodi, esegui nuovamente 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 Assistenza clienti Google Cloud.