Resolva problemas do programador do Kubernetes

Estas páginas mostram como resolver problemas com o programador do Kubernetes (kube-scheduler) para o Google Distributed Cloud.

O Kubernetes agenda sempre os pods para o mesmo conjunto de nós

Este erro pode ser observado de várias formas:

  • Utilização desequilibrada do cluster. Pode inspecionar a utilização do cluster para cada nó com o comando kubectl top nodes. O exemplo de saída exagerado seguinte mostra uma utilização pronunciada em determinados nós:

    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%
    
  • Demasiados pedidos. Se agendar muitos pods em simultâneo no mesmo nó e esses pods fizerem pedidos HTTP, é possível que o nó seja limitado pela taxa. O erro comum devolvido pelo servidor neste cenário é 429 Too Many Requests.

  • Serviço indisponível. Por exemplo, um servidor Web alojado num nó sob carga elevada pode responder a todos os pedidos com erros 503 Service Unavailable até estar sob carga mais baixa.

Para verificar se tem pods sempre agendados para os mesmos nós, use os seguintes passos:

  1. Execute o seguinte comando kubectl para ver o estado dos pods:

    kubectl get pods -o wide -n default
    

    Para ver a distribuição de pods nos nós, verifique a coluna NODE na saída. No exemplo de saída seguinte, todos os pods estão agendados no mesmo nó:

    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
    

Os grupos de anúncios têm várias funcionalidades que lhe permitem otimizar o respetivo comportamento de agendamento. Estas funcionalidades incluem restrições de dispersão de topologia e regras de antiafinidade. Pode usar uma ou uma combinação destas funcionalidades. Os requisitos que definir são cumulativos através do operador kube-scheduler.

Os registos do programador não são capturados no nível de detalhe de registo predefinido. Se precisar dos registos do agendador para a resolução de problemas, siga os passos abaixo para capturar os registos do agendador:

  1. Aumente o nível de detalhe do registo:

    1. Edite a implementação de kube-scheduler:

      kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \
        -n USER_CLUSTER_NAMESPACE
      
    2. Adicione a flag --v=5 na secção spec.containers.command:

      containers:
      - command:
      - kube-scheduler
      - --profiling=false
      - --kubeconfig=/etc/kubernetes/scheduler.conf
      - --leader-elect=true
      - --v=5
      
  2. Quando terminar a resolução de problemas, reponha o nível de detalhe para o nível predefinido:

    1. Edite a implementação de kube-scheduler:

      kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \
        -n USER_CLUSTER_NAMESPACE
      
    2. Defina o nível de detalhe novamente para o valor predefinido:

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

Restrições de dispersão da topologia

As restrições de propagação da topologia podem ser usadas para distribuir uniformemente os pods entre os nós de acordo com o respetivo zones, regions, node ou outra topologia definida pelo utilizador.

O manifesto de exemplo seguinte mostra uma implementação que distribui as réplicas uniformemente entre todos os nós agendáveis através de restrições de distribuição de 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

As seguintes considerações aplicam-se quando usa restrições de dispersão de topologia:

  • O labels.app: myapp de um pod corresponde ao labelSelector da restrição.
  • O elemento topologyKey especifica kubernetes.io/hostname. Esta etiqueta é anexada automaticamente a todos os nós e é preenchida com o nome de anfitrião do nó.
  • O matchLabelKeys impede que as implementações de novas implementações considerem os pods de revisões antigas ao calcular onde agendar um pod. A etiqueta pod-template-hash é preenchida automaticamente por uma implementação.

Antiafinidade de agrupamentos

A antiafinidade de agrupamentos permite-lhe definir restrições para os agrupamentos que podem ser colocados em conjunto no mesmo nó.

O manifesto de exemplo seguinte mostra uma implementação que usa a antiafinidade para limitar as réplicas a um pod por nó:

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

Esta implementação de exemplo especifica 30 réplicas, mas só se expande até ao número de nós disponíveis no seu cluster.

As seguintes considerações aplicam-se quando usa a antiafinidade de pods:

  • O labels.app: myapp de um pod corresponde ao labelSelector da restrição.
  • O elemento topologyKey especifica kubernetes.io/hostname. Esta etiqueta é anexada automaticamente a todos os nós e é preenchida com o nome de anfitrião do nó. Pode optar por usar outras etiquetas se o seu cluster as suportar, como region ou zone.

Extraia previamente imagens de contentores

Na ausência de outras restrições, por predefinição, o kube-scheduler prefere agendar pods em nós que já tenham a imagem do contentor transferida para os mesmos. Este comportamento pode ser interessante em clusters mais pequenos sem outras configurações de agendamento, onde seria possível transferir as imagens em todos os nós. No entanto, a utilização deste conceito deve ser vista como último recurso. Uma solução melhor é usar nodeSelector, restrições de dispersão da topologia ou afinidade / antiafinidade. Para mais informações, consulte o artigo Atribuir pods a nós.

Se quiser certificar-se de que as imagens de contentores são pré-extraídas para todos os nós, pode usar um DaemonSet como no exemplo seguinte:

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

Depois de o pod estar Running em todos os nós, volte a implementar os pods para ver se os contentores estão agora distribuídos uniformemente pelos nós.

O que se segue?

Se precisar de assistência adicional, contacte o apoio ao cliente do Google Cloud.

Também pode consultar o artigo Receber apoio técnico para mais informações sobre recursos de apoio técnico, incluindo o seguinte: