Una guía visual para solucionar problemas de Kubernetes
Nota. traducir: Este artículo es parte de los materiales del proyecto publicados en el dominio público. aprenderk8s, capacitando a empresas y administradores individuales para trabajar con Kubernetes. En él, Daniele Polencic, director del proyecto, comparte instrucciones visuales sobre los pasos a seguir en caso de problemas generales con las aplicaciones que se ejecutan en el clúster K8.
TL;DR: aquí hay un diagrama que le ayudará a depurar la implementación en Kubernetes:
Diagrama de flujo para buscar y corregir errores en un clúster. El original (en inglés) está disponible en (PDF) и como la imagen.
Al implementar una aplicación en Kubernetes, normalmente hay tres componentes que debes definir:
Despliegue - esta es una especie de receta para crear copias de la aplicación, llamadas pods;
Service — equilibrador de carga interno que distribuye el tráfico entre pods;
Ingreso — una descripción de cómo llegará el tráfico desde el mundo exterior al Servicio.
Aquí hay un resumen gráfico rápido:
1) En Kubernetes, las aplicaciones reciben tráfico del mundo exterior a través de dos capas de equilibradores de carga: interno y externo.
2) El equilibrador interno se llama Servicio, el externo se llama Ingreso.
3) La implementación crea pods y los monitorea (no se crean manualmente).
Supongamos que desea implementar una aplicación simple a la Hola Mundo. La configuración de YAML se verá así:
La definición es bastante larga y es fácil confundirse acerca de cómo se relacionan los componentes entre sí.
Por ejemplo:
¿Cuándo debería utilizar el puerto 80 y cuándo debería utilizar el 8080?
¿Debo crear un nuevo puerto para cada servicio para que no entren en conflicto?
¿Importan los nombres de las etiquetas? ¿Deberían ser iguales en todas partes?
Antes de centrarnos en la depuración, recordemos cómo se relacionan los tres componentes entre sí. Comencemos con Implementación y Servicio.
Relación entre Despliegue y Servicio
Se sorprenderá, pero la implementación y el servicio no están relacionados de ninguna manera. En cambio, el Servicio apunta directamente a los Pods, sin pasar por la Implementación.
Por lo tanto, nos interesa cómo se relacionan los Pods y los Servicios entre sí. Tres cosas para recordar:
Selector (selector) para el Servicio debe coincidir con al menos una etiqueta de Pod.
targetPort debe coincidir con containerPort contenedor dentro del Pod.
port El servicio puede ser cualquier cosa. Diferentes servicios pueden utilizar el mismo puerto porque tienen diferentes direcciones IP.
El siguiente diagrama representa todo lo anterior en forma gráfica:
1) Imagine que el servicio dirige el tráfico a un determinado módulo:
2) Al crear un pod, debes especificar containerPort por cada contenedor en vainas:
3) Al crear un servicio, debe especificar port и targetPort. ¿Pero cuál se utiliza para conectarse al contenedor?
4) Vía targetPort. debe coincidir containerPort.
5) Digamos que el puerto 3000 está abierto en el contenedor. Entonces el valor targetPort debería ser el mismo.
En el archivo YAML, etiquetas y ports / targetPort debe coincidir con:
¿Qué pasa con la etiqueta? track: canary en la parte superior de la sección Implementación? ¿Debería coincidir?
Esta etiqueta es específica de la implementación y el servicio no la utiliza para enrutar el tráfico. En otras palabras, se puede eliminar o asignar un valor diferente.
¿Qué pasa con el selector? matchLabels?
Siempre debe coincidir con las etiquetas del Pod., ya que la implementación lo utiliza para realizar un seguimiento de los pods.
Supongamos que realizó las ediciones correctas. ¿Cómo comprobarlos?
Puede verificar la etiqueta del pod con el siguiente comando:
kubectl get pods --show-labels
O, si los pods pertenecen a varias aplicaciones:
kubectl get pods --selector any-name=my-app --show-labels
Donde any-name=my-app es una etiqueta any-name: my-app.
¿Quedan dificultades?
¡Puedes conectarte al pod! Para hacer esto necesitas usar el comando. port-forward en kubectl. Le permite conectarse al servicio y verificar la conexión.
service/<service name> - Nombre del Servicio; en nuestro caso es my-service;
3000 es el puerto que debe abrirse en la computadora;
80 - puerto especificado en el campo port servicio.
Si se estableció la conexión, entonces la configuración es correcta.
Si la conexión falla, hay un problema con las etiquetas o los puertos no coinciden.
Relación entre servicio e ingreso
El siguiente paso para proporcionar acceso a la aplicación implica configurar Ingress. Ingress necesita saber cómo encontrar un servicio, luego encontrar pods y dirigir el tráfico hacia ellos. Ingress encuentra el servicio requerido por nombre y puerto abierto.
En la descripción de Ingress y Service deben coincidir dos parámetros:
servicePort en Ingress debe coincidir con el parámetro port en servicio;
serviceName en Ingress debe coincidir con el campo name en servicio.
El siguiente diagrama resume las conexiones de los puertos:
1) Como ya sabes, el Servicio escucha a un determinado port:
2) El ingreso tiene un parámetro llamado servicePort:
3) Este parámetro (servicePort) siempre debe coincidir port en la definición del Servicio:
4) Si se especifica el puerto 80 en Servicio, entonces es necesario que servicePort también era igual a 80:
En la práctica, debes prestar atención a las siguientes líneas:
Ahora, cada vez que envíe una solicitud al puerto 3000 de su computadora, se reenviará al puerto 80 del pod con el controlador de Ingress. Al ir a http://localhost:3000, debería ver la página generada por la aplicación.
Resumen de puertos
Recordemos una vez más qué puertos y etiquetas deben coincidir:
El selector en la definición del Servicio debe coincidir con la etiqueta del pod;
targetPort en la definición el Servicio debe coincidir containerPort contenedor dentro de una vaina;
port en la definición, Servicio puede ser cualquier cosa. Diferentes servicios pueden utilizar el mismo puerto porque tienen diferentes direcciones IP;
servicePort El ingreso debe coincidir port en la definición de Servicio;
El nombre del servicio debe coincidir con el campo. serviceName en ingreso.
Desafortunadamente, no basta con saber cómo estructurar correctamente una configuración YAML.
¿Qué pasa cuando las cosas van mal?
Es posible que el módulo no se inicie o que se bloquee.
Tres pasos para diagnosticar problemas de aplicaciones en Kubernetes
Antes de comenzar a depurar su implementación, debe comprender bien cómo funciona Kubernetes.
Dado que cada aplicación descargada en K8 tiene tres componentes, deben depurarse en un orden determinado, comenzando desde abajo.
Primero debes asegurarte de que las cápsulas estén funcionando, luego...
Compruebe si el servicio suministra tráfico a los pods y luego...
Compruebe si Ingress está configurado correctamente.
Representación visual:
1) Deberías empezar a buscar los problemas desde abajo. Primero verifique que los pods tengan estados Ready и Running:
2) Si las vainas están listas (Ready), deberías averiguar si el servicio distribuye el tráfico entre pods:
3) Finalmente, es necesario analizar la conexión entre el servicio y el Ingress:
1. Diagnóstico de vainas
En la mayoría de los casos el problema está relacionado con el pod. Asegúrese de que las vainas estén enumeradas como Ready и Running. Puedes verificar esto usando el comando:
kubectl get pods
NAME READY STATUS RESTARTS AGE
app1 0/1 ImagePullBackOff 0 47h
app2 0/1 Error 0 47h
app3-76f9fcd46b-xbv4k 1/1 Running 1 47h
En el resultado del comando anterior, el último pod aparece como Running и Ready, sin embargo, este no es el caso de los otros dos.
¿Cómo entender qué salió mal?
Hay cuatro comandos útiles para diagnosticar pods:
kubectl logs <имя pod'а> le permite extraer registros de contenedores en un pod;
kubectl describe pod <имя pod'а> le permite ver una lista de eventos asociados con el pod;
kubectl get pod <имя pod'а> le permite obtener la configuración YAML de un pod almacenado en Kubernetes;
kubectl exec -ti <имя pod'а> bash le permite iniciar un shell de comando interactivo en uno de los contenedores del pod
¿Cuál deberías elegir?
El hecho es que no existe un mandamiento universal. Se debe utilizar una combinación de estos.
Problemas típicos de las cápsulas
Hay dos tipos principales de errores de pod: errores de inicio y errores de tiempo de ejecución.
Errores de inicio:
ImagePullBackoff
ImageInspectError
ErrImagePull
ErrImageNeverPull
RegistryUnavailable
InvalidImageName
Errores de tiempo de ejecución:
CrashLoopBackOff
RunContainerError
KillContainerError
VerifyNonRootError
RunInitContainerError
CreatePodSandboxError
ConfigPodSandboxError
KillPodSandboxError
SetupNetworkError
TeardownNetworkError
Algunos errores son más comunes que otros. Estos son algunos de los errores más comunes y cómo solucionarlos.
ImagenPullBackOff
Este error ocurre cuando Kubernetes no puede obtener una imagen para uno de los contenedores del pod. Estas son las tres razones más comunes para esto:
El nombre de la imagen es incorrecto; por ejemplo, cometió un error o la imagen no existe;
Se especificó una etiqueta inexistente para la imagen;
La imagen se almacena en un registro privado y Kubernetes no tiene permiso para acceder a ella.
Las dos primeras razones son fáciles de eliminar: simplemente corrija el nombre de la imagen y la etiqueta. En el caso de este último, debe ingresar las credenciales para el registro cerrado en Secreto y agregarle enlaces en pods. En la documentación de Kubernetes hay un ejemplo Cómo se puede hacer esto.
Desactivación del bucle de bloqueo
Kubenetes arroja un error CrashLoopBackOff, si el contenedor no puede iniciarse. Esto suele suceder cuando:
Hay un error en la aplicación que impide que se inicie;
La prueba de Liveness ha fallado demasiadas veces.
Debe intentar acceder a los registros del contenedor para descubrir el motivo de su falla. Si resulta difícil acceder a los registros porque el contenedor se reinicia demasiado rápido, puede utilizar el siguiente comando:
kubectl logs <pod-name> --previous
Muestra mensajes de error de la encarnación anterior del contenedor.
EjecutarContenedorError
Este error ocurre cuando el contenedor no se inicia. Corresponde al momento previo al lanzamiento de la aplicación. Suele deberse a configuraciones incorrectas, por ejemplo:
intentar montar un volumen inexistente como ConfigMap o Secrets;
un intento de montar un volumen de solo lectura como lectura-escritura.
El equipo está bien preparado para analizar este tipo de errores. kubectl describe pod <pod-name>.
Los pods están en estado Pendiente
Una vez creado, el pod permanece en el estado Pending.
¿Por qué está pasando esto?
Estas son las posibles razones (supongo que el programador funciona bien):
El clúster no tiene suficientes recursos, como potencia de procesamiento y memoria, para ejecutar el pod.
El objeto se instala en el espacio de nombres apropiado. ResourceQuota y la creación de un pod hará que el espacio de nombres supere la cuota.
El pod está vinculado a Pendiente PersistentVolumeClaim.
En este caso, se recomienda utilizar el comando kubectl describe y revisa la sección Events:
kubectl describe pod <pod name>
En caso de errores relacionados con ResourceQuotas, se recomienda ver los registros del clúster usando el comando
kubectl get events --sort-by=.metadata.creationTimestamp
Las cápsulas no están listas
Si pod aparece como Running, pero no está en estado Ready, significa comprobar su preparación (sonda de preparación) falla.
Cuando esto sucede, el pod no se conecta al servicio y no fluye tráfico hacia él. El error en la prueba de preparación se debe a problemas en la aplicación. En este caso, para encontrar el error es necesario analizar la sección. Events en la salida del comando kubectl describe.
2. Diagnóstico de servicio
Si las vainas aparecen como Running и Ready, pero aún no hay respuesta de la aplicación, debes verificar la configuración del servicio.
Los servicios son responsables de enrutar el tráfico a los pods según sus etiquetas. Por tanto, lo primero que debes hacer es comprobar cuántos pods funcionan con el servicio. Para hacer esto, puede verificar los puntos finales en el servicio:
kubectl describe service <service-name> | grep Endpoints
El punto final es un par de valores de la forma <IP-адрес:порт>y al menos uno de esos pares debe estar presente en la salida (es decir, al menos un pod funciona con el servicio).
si seccion Endpoins vacío, son posibles dos opciones:
no hay pods con la etiqueta correcta (sugerencia: verifique si el espacio de nombres está seleccionado correctamente);
Hay un error en las etiquetas de servicios en el selector.
Si ve una lista de puntos finales pero aún no puede acceder a la aplicación, entonces el probable culpable es un error en targetPort en la descripción del servicio.
¿Cómo comprobar la funcionalidad del servicio?
Independientemente del tipo de servicio, puede utilizar el comando kubectl port-forward para conectarse a él:
el servicio distribuye con éxito el tráfico entre pods.
Sin embargo, todavía no puedes acceder a la aplicación.
Esto significa que lo más probable es que el controlador Ingress no esté configurado correctamente. Dado que el controlador de Ingress es un componente de terceros en el clúster, existen diferentes métodos de depuración según su tipo.
Pero antes de recurrir al uso de herramientas especiales para configurar Ingress, puedes hacer algo muy simple. Usos de ingreso serviceName и servicePort para conectarse al servicio. Debe verificar si están configurados correctamente. Puedes hacer esto usando el comando:
kubectl describe ingress <ingress-name>
Si columna Backend vacío, existe una alta probabilidad de que se produzca un error de configuración. Si los servidores están instalados, pero aún no se puede acceder a la aplicación, entonces el problema puede estar relacionado con:
Ingrese a la configuración de accesibilidad desde la Internet pública;
configuración de accesibilidad del clúster desde la Internet pública.
Puede identificar problemas con la infraestructura conectándose directamente al pod de Ingress. Para hacer esto, primero busque el pod del controlador de ingreso (puede estar en un espacio de nombres diferente):
Ahora todas las solicitudes al puerto 3000 de la computadora se redirigirán al puerto 80 del pod.
¿Funciona ahora?
En caso afirmativo, entonces el problema está en la infraestructura. Es necesario saber exactamente cómo se dirige el tráfico al clúster.
Si no, entonces el problema está en el controlador de Ingress.
Si no puedes hacer que el controlador Ingress funcione, tendrás que depurarlo.
Hay muchas variedades de controladores Ingress. Los más populares son Nginx, HAProxy, Traefik, etc. (para obtener más información sobre las soluciones existentes, consulte nuestra reseña - aprox. trad.) Debe consultar la guía de solución de problemas en la documentación del controlador correspondiente. Porque el Ingreso Nginx es el controlador Ingress más popular, hemos incluido algunos consejos en el artículo para resolver problemas relacionados con él.
Depuración del controlador Ingress Nginx
El proyecto Ingress-nginx tiene un oficial complemento para kubectl. Equipo kubectl ingress-nginx se puede usar para:
análisis de logs, backends, certificados, etc.;
conexiones con Ingress;
estudiando la configuración actual.
Los siguientes tres comandos te ayudarán con esto:
kubectl ingress-nginx lint - cheques nginx.conf;
kubectl ingress-nginx backend — explora el backend (similar a kubectl describe ingress <ingress-name>);
kubectl ingress-nginx logs — revisa los registros.
Tenga en cuenta que en algunos casos es posible que necesite especificar el espacio de nombres correcto para el controlador de Ingress usando la bandera --namespace <name>.
Resumen
Solucionar problemas de Kubernetes puede ser un desafío si no sabes por dónde empezar. Siempre debes abordar el problema desde abajo hacia arriba: comenzar con los pods y luego pasar al servicio e Ingress. Las técnicas de depuración descritas en este artículo se pueden aplicar a otros objetos, como: