The Ops Community ⚙️

jose luis pujol
jose luis pujol

Posted on

Debug nodos kubernetes

Los nodos son un componente vital de un clúster de Kubernetes y son responsables de ejecutar las pods. Dependiendo de la configuración de tu clúster, un nodo puede ser una máquina física o virtual.
Un clúster típicamente tiene uno o varios nodos, los cuales son gestionados por el control plane.
Debido a que los nodos realizan la mayor parte del trabajo de la gestión de carga, es importante asegurarse de que todos tus nodos estén funcionando correctamente. El comando kubectl get nodes se utiliza para verificar el estado de tus nodos.

NAME           STATUS   ROLES           AGE     VERSION
controlplane   Ready    control-plane   2d11h   v1.29.0
node01         Ready    <none>          2d10h   v1.29.0
Enter fullscreen mode Exit fullscreen mode

Un nodo con un estado NotReady significa que no se puede utilizar para ejecutar una pod debido a un problema interno.
Posibles razones por las cuales un nodo puede entrar en el estado NotReady y cómo depurarlo.

Estados

Antes de programar un pod en un nodo, Kubernetes verifica si el nodo es capaz de ejecutar la pod o no. La columna STATUS en la salida de kubectl get nodes representa el estado.

NAME           STATUS   ROLES           AGE     VERSION
controlplane   Ready    control-plane   2d10h   v1.29.0
node01         Ready    <none>          2d10h   v1.29.0
Enter fullscreen mode Exit fullscreen mode

Los posibles valores en STATUS son:

  • Ready: El nodo está listo para aceptar pods.
  • NotReady: El nodo ha encontrado algún problema y no se puede programar un pod en él.
  • SchedulingDisabled: El nodo está marcado como no programable. Esta marca se puede realizar mediante el comando kubectl cordon.
  • Unknown: El nodo no es alcanzable por el control plane.

Tener un nodo en estado NotReady significa que el nodo está sin usar y sin participar en la ejecución de pods.

Posibles causas del estado NotReady:

  • Escasez de recursos. Para operar normalmente, un nodo debe tener suficiente espacio en disco, memoria y capacidad de procesamiento. Si un nodo tiene poco espacio en disco o la memoria disponible es baja, entrará en el estado NotReady. Si hay demasiados procesos ejecutándose en el nodo, también cambiará al estado "NotReady".
  • Configuración de red incorrecta. Si la red no se ha configurado correctamente en el nodo, el nodo no podrá comunicarse con el nodo maestro y se mostrará como NotReady.
  • Problemas con el proceso kubelet. Kubelet es un componente esencial de Kubernetes y opera en cada nodo del clúster como un agente. Su papel principal es servir de enlace entre el nodo y la API de Kubernetes. Kubelet informa a la API de Kubernetes sobre el estado del nodo, incluyendo detalles como los recursos disponibles y la salud general del nodo. Además, Kubelet registra el nodo en el clúster de Kubernetes, permitiendo que el nodo sea reconocido y utilizado para desplegar aplicaciones. Si Kubelet se bloquea o se detiene por alguna razón, su comunicación con la API de Kubernetes se interrumpe. Esto impide que el nodo informe de su estado y reciba instrucciones de la API. Como resultado, el nodo se marca con el estado NotReady, lo que indica que NO está preparado para recibir nuevas cargas de trabajo hasta que se resuelva el problema de Kubelet.
  • Problemas con Kube-proxy. Kube-proxy es un componente de Kubernetes y opera en cada nodo como un proxy. Mantiene las reglas de red que facilitan la comunicación con los pods, tanto interna como externamente. Si kube-proxy se bloquea o se detiene, el nodo se marca como NotReady.
  • Problemas específicos del proveedor cloud. Supongamos que estás utilizando una solución alojada en la nube como GKE, EKS, AKS, .... En ese caso, algunos problemas específicos del proveedor pueden estar impidiendo que tus nodos funcionen normalmente y se comuniquen con el control plane. Estos problemas podrían ser por una configuración incorrecta de IAM, por reglas de red mal configuradas, etc.

Debug del estado NotReady mas detallado

El estado NotReady puede ser causado por una multitud de problemas. Es esencial entender que la forma de solucionar estos problemas depende de la causa exacta y de la configuración del clúster.
No hay soluciones universales. Pero, una vez que identifiques la causa raíz, debería ser más fácil resolverla.

Problemas Kube-Proxy

Asegúrate que cada nodo tenga un pod kube-proxy y esté en el estado "Running".

kubectl get pods -n kube-system -o wide
Enter fullscreen mode Exit fullscreen mode

resultado:

NAME                                      READY   STATUS    RESTARTS        AGE     IP            NODE           NOMINATED NODE   READINESS GATES
calico-kube-controllers-9d57d8f49-8smt7   1/1     Running   3 (4h30m ago)   2d10h   192.168.0.2   controlplane   <none>           <none>
canal-mpvd7                               2/2     Running   2 (4h30m ago)   2d10h   172.30.2.2    node01         <none>           <none>
canal-t59ms                               2/2     Running   2 (4h30m ago)   2d10h   172.30.1.2    controlplane   <none>           <none>
coredns-86b698fbb6-7dhfx                  1/1     Running   1 (4h30m ago)   2d10h   192.168.1.2   node01         <none>           <none>
coredns-86b698fbb6-c7h4v                  1/1     Running   1 (4h30m ago)   2d10h   192.168.1.3   node01         <none>           <none>
etcd-controlplane                         1/1     Running   2 (4h30m ago)   2d10h   172.30.1.2    controlplane   <none>           <none>
kube-apiserver-controlplane               1/1     Running   2 (4h30m ago)   2d10h   172.30.1.2    controlplane   <none>           <none>
kube-controller-manager-controlplane      1/1     Running   2 (4h30m ago)   2d10h   172.30.1.2    controlplane   <none>           <none>
kube-proxy-4rlmh                          1/1     Running   2 (4h30m ago)   2d10h   172.30.1.2    controlplane   <none>           <none>
kube-proxy-8whxf                          1/1     Running   1 (4h30m ago)   2d10h   172.30.2.2    node01         <none>           <none>
kube-scheduler-controlplane               1/1     Running   2 (4h30m ago)   2d10h   172.30.1.2    controlplane   <none>           <none>
Enter fullscreen mode Exit fullscreen mode

o más especifico para todos los kubeproxy:

kubectl get pods -n kube-system -o wide | grep kube-proxy
Enter fullscreen mode Exit fullscreen mode
NAME                                      READY   STATUS    RESTARTS        AGE     IP            NODE           NOMINATED NODE   READINESS GATES
kube-proxy-4rlmh                          1/1     Running   2 (4h31m ago)   2d10h   172.30.1.2    controlplane   <none>           <none>
kube-proxy-8whxf                          1/1     Running   1 (4h31m ago)   2d10h   172.30.2.2    node01         <none>           <none>
Enter fullscreen mode Exit fullscreen mode

Si alguno de los pods kube-proxy se encuentra en un estado diferente a Running, utiliza el siguiente comando para obtener más información:

kubectl describe pod POD_KUBEPROXY_EN_ESTADO_NO_RUNNING -n kube-system
Enter fullscreen mode Exit fullscreen mode

La sección de "Events" registra diversos eventos en el pod, y podría ser un excelente lugar para comenzar a buscar cualquier inconveniente.

Puedes acceder a los logs del pod ejecutando el siguiente comando:

kubectl logs POD_KUBEPROXY_EN_ESTADO_NO_RUNNING -n kube-system
Enter fullscreen mode Exit fullscreen mode

Si el nodo que no esta Ready NO tiene pod kube-proxy, entonces debes inspeccionar el daemonset kube-proxy.
Un daemonset es una forma de asegurar que todos los nodos en un clúster tengan una copia de un pod corriendo, el daemonset se encarga automáticamente de asegurar que haya una copia de ese pod en cada nodo del clúster.

kubectl describe daemonset kube-proxy -n kube-system
Enter fullscreen mode Exit fullscreen mode

resultado:

Name:           kube-proxy
Selector:       k8s-app=kube-proxy
Node-Selector:  kubernetes.io/os=linux
Labels:         k8s-app=kube-proxy
Annotations:    deprecated.daemonset.template.generation: 1
Desired Number of Nodes Scheduled: 2
Current Number of Nodes Scheduled: 2
Number of Nodes Scheduled with Up-to-date Pods: 2
Number of Nodes Scheduled with Available Pods: 2
Number of Nodes Misscheduled: 0
Pods Status:  2 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:           k8s-app=kube-proxy
  Service Account:  kube-proxy
  Containers:
   kube-proxy:
    Image:      registry.k8s.io/kube-proxy:v1.29.0
    Port:       <none>
    Host Port:  <none>
    Command:
      /usr/local/bin/kube-proxy
      --config=/var/lib/kube-proxy/config.conf
      --hostname-override=$(NODE_NAME)
    Environment:
      NODE_NAME:   (v1:spec.nodeName)
    Mounts:
      /lib/modules from lib-modules (ro)
      /run/xtables.lock from xtables-lock (rw)
      /var/lib/kube-proxy from kube-proxy (rw)
  Volumes:
   kube-proxy:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      kube-proxy
    Optional:  false
   xtables-lock:
    Type:          HostPath (bare host directory volume)
    Path:          /run/xtables.lock
    HostPathType:  FileOrCreate
   lib-modules:
    Type:               HostPath (bare host directory volume)
    Path:               /lib/modules
    HostPathType:       
  Priority Class Name:  system-node-critical
Events:                 <none>
Enter fullscreen mode Exit fullscreen mode

Problemas Recursos

El siguiente comando sirve para obtener información detallada sobre un nodo:

kubectl describe node NODO_NOT_READY
Enter fullscreen mode Exit fullscreen mode

resultado:

Name:               node01
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=node01
                    kubernetes.io/os=linux
Annotations:        flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"f6:5a:70:e7:20:39"}
                    flannel.alpha.coreos.com/backend-type: vxlan
                    flannel.alpha.coreos.com/kube-subnet-manager: true
                    flannel.alpha.coreos.com/public-ip: 172.30.2.2
                    kubeadm.alpha.kubernetes.io/cri-socket: unix:///var/run/containerd/containerd.sock
                    node.alpha.kubernetes.io/ttl: 0
                    projectcalico.org/IPv4Address: 172.30.2.2/24
                    projectcalico.org/IPv4IPIPTunnelAddr: 192.168.1.1
                    volumes.kubernetes.io/controller-managed-attach-detach: true
[...]
Conditions:
  Type                 Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----                 ------  -----------------                 ------------------                ------                       -------
  NetworkUnavailable   False   Sun, 31 Dec 2023 18:57:52 +0000   Sun, 31 Dec 2023 18:57:52 +0000   FlannelIsUp                  Flannel is running on this node
  MemoryPressure       False   Sun, 31 Dec 2023 23:37:39 +0000   Fri, 29 Dec 2023 13:10:41 +0000   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure         False   Sun, 31 Dec 2023 23:37:39 +0000   Fri, 29 Dec 2023 13:10:41 +0000   KubeletHasNoDiskPressure     kubelet has no disk pressure
  PIDPressure          False   Sun, 31 Dec 2023 23:37:39 +0000   Fri, 29 Dec 2023 13:10:41 +0000   KubeletHasSufficientPID      kubelet has sufficient PID available
  Ready                True    Sun, 31 Dec 2023 23:37:39 +0000   Fri, 29 Dec 2023 13:10:50 +0000   KubeletReady                 kubelet is posting ready status. AppArmor enabled
Addresses:
  InternalIP:  172.30.2.2
  Hostname:    node01
Capacity:
  cpu:                1
  ephemeral-storage:  20134592Ki
  hugepages-2Mi:      0
  memory:             2030940Ki
  pods:               110
Allocatable:
  cpu:                1
  ephemeral-storage:  19586931083
  hugepages-2Mi:      0
  memory:             1928540Ki
  pods:               110
System Info:
  Machine ID:                 388a2d0f867a4404bc12a0093bd9ed8d
  System UUID:                1d3e87e7-ec41-400e-9e8a-9fbba2d3adc8
  Boot ID:                    0f813b78-e5d3-4cca-b969-763745e13991
  Kernel Version:             5.4.0-131-generic
  OS Image:                   Ubuntu 20.04.5 LTS
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  containerd://1.6.12
  Kubelet Version:            v1.29.0
  Kube-Proxy Version:         v1.29.0
PodCIDR:                      192.168.1.0/24
PodCIDRs:                     192.168.1.0/24
Non-terminated Pods:          (4 in total)
  Namespace                   Name                        CPU Requests  CPU Limits  Memory Requests  Memory Limits  Age
  ---------                   ----                        ------------  ----------  ---------------  -------------  ---
  kube-system                 canal-mpvd7                 25m (2%)      0 (0%)      0 (0%)           0 (0%)         2d10h
  kube-system                 coredns-86b698fbb6-7dhfx    50m (5%)      0 (0%)      50Mi (2%)        170Mi (9%)     2d10h
  kube-system                 coredns-86b698fbb6-c7h4v    50m (5%)      0 (0%)      50Mi (2%)        170Mi (9%)     2d10h
  kube-system                 kube-proxy-8whxf            0 (0%)        0 (0%)      0 (0%)           0 (0%)         2d10h
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests    Limits
  --------           --------    ------
  cpu                125m (12%)  0 (0%)
  memory             100Mi (5%)  340Mi (18%)
  ephemeral-storage  0 (0%)      0 (0%)
  hugepages-2Mi      0 (0%)      0 (0%)
Events:              <none>
Enter fullscreen mode Exit fullscreen mode

En la sección Conditions muestra si el nodo se está quedando sin recursos o no. Posibles estados:

  • MemoryPressure: Si es Verdadero, indica que el nodo se está quedando sin memoria.
  • DiskPressure: Si es Verdadero, indica que al nodo le falta espacio.
  • PIDPressure: Si es Verdadero, indica que hay demasiados procesos en ejecución en el nodo.
  • NetworkUnavailable: Si es Verdadero, indica que la red del nodo no está configurada correctamente.
  • Ready: Un valor Falso en este campo es equivalente al estado NotReady. Si el controlador del nodo no ha tenido noticias del node-monitor-grace-period (por defecto, 40 segundos), el valor será Unknown.

Si alguna de las primeras cuatro condiciones es Verdadera, habrás identificado el problema.

Problemas Kubelet

Si todos los campos de Conditions estan en Unknown, podría indicar que kubelet esta caido.

Para realizar debug, primero accede por SSH al nodo y verifica el estado del proceso kubelet.
Si se está ejecutando como un servicio de systemd, utiliza el siguiente comando:

systemctl status kubelet
Enter fullscreen mode Exit fullscreen mode

resultado:

● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: active (running) since Sun 2023-12-31 18:56:43 UTC; 4h 48min ago
       Docs: https://kubernetes.io/docs/
   Main PID: 1650 (kubelet)
      Tasks: 11 (limit: 2338)
     Memory: 61.6M
     CGroup: /system.slice/kubelet.service
             └─1650 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/>
Enter fullscreen mode Exit fullscreen mode

Si el campo Active muestra "inactive (dead)", significa que el proceso kubelet se ha detenido.

Para descubrir la posible razón del fallo, verifica los logs con el siguiente comando:

journalctl -u kubelet
Enter fullscreen mode Exit fullscreen mode

Una vez que has realizado fix, reinicia el kubelet con:

systemctl restart kubelet
Enter fullscreen mode Exit fullscreen mode

Problemas conectividad

Si Conditions muestra NetworkUnavailable, indica un problema en la comunicación de red entre el nodo y la API Kubernetes.

Algunas posibles soluciones:

  • Si el nodo está configurado para usar un proxy, verifica que el proxy permita el acceso a los endpoints de la API Kubernetes.
  • Asegúrate de que las tablas de enrutamiento estén configuradas adecuadamente para evitar bloquear la comunicación con la API Kubernetes.

Para obtener la dirección de la API, ejecuta:

kubectl cluster-info
Enter fullscreen mode Exit fullscreen mode

resultado:

Kubernetes control plane is running at https://172.30.1.2:6443
CoreDNS is running at https://172.30.1.2:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Enter fullscreen mode Exit fullscreen mode

Puedes ejecutar el siguiente comando desde dentro del nodo para verificar que pueda alcanzar el servidor API:

nc -vz IP_CONTROL_PLANE_O_ENDPOINT PUERTO
Enter fullscreen mode Exit fullscreen mode

resultado:

Connection to 172.30.1.2 6443 port [tcp/*] succeeded!
Enter fullscreen mode Exit fullscreen mode

Si el resultado es succeeded, la comunicacion de red funciona correctamente.

Top comments (0)