docker: el contenedor Nginx no se reinicia después del apagado en Kubernetes

CorePress2024-01-24  11

Recientemente hemos encontrado un problema con nuestra implementación en Kubernetes que se ejecuta en GKE. Parecería que, aleatoriamente, nuestros contenedores front-end NGINX, que sirven a nuestra aplicación Front End, aparentemente mueren. Esto ha causado bastante conmoción, ya que nginx-ingress simplemente nos diría que hubo un error en el protocolo HTTP2. Después de aproximadamente una semana de confusión, finalmente notamos en los registros de los contenedores FE que este resultado ocurría cada vez que teníamos el error de protocolo HTTP2 (en Chrome):

Una vez que cambiamos el ingreso de nginx a HTTP1, tenemos un error de ERR_CONTENT_LENGTH_MISMATCH 200, pero sigue siendo un error engañoso.

Esta es una esencia de todas nuestras configuraciones para aquellos que estén interesados: esencia

En cuanto a la versión de nginx, probé lo siguiente:

stcapaz-alpino

estable

línea principal-alpina

1.17.10-alpino

Todos dan como resultado el mismo conjunto de registros.

Cosas que he probado:

cambiar la versión de nginx para FE decirle a nginx-ingress que use HTTP 1 decirle a nginx-ingress que no use GZIP usé todo lo de este sitio tencent de alta disponibilidad en la publicación del blog de nginx activó y desactivó el almacenamiento en búfer de proxy, tanto para nginx-ingress en su conjunto como para cada ingreso secundario individual establezca max-temp-file-size en 0 en nginx-ingress establezca max-temp-file-size en 10M en nginx-ingress se eliminó Aceptar codificación, longitud del contenido y tipo de contenido de la solicitud al flujo ascendente activado Gzip para el contenedor FE establezca los procesos de trabajo en automático, establezca los procesos de trabajo en 1 en el contenedor FE establezca el tiempo de espera de keepalive en 65, configúrelo en 15 en FE cocontenedor Se actualizó el ciclo de vida preStop en la implementación de FE. establezca terminaciónGracePeriodSeconds en 60 (luego lo eliminó) de la implementación de FE

Antes de que nadie pregunte: todas las configuraciones realizadas en nginx-ingress hasta ahora han sido intentos de resolver el error del protocolo HTTP2. Obviamente, nada de esto funciona porque si el servidor ascendente no funciona, esto no importa.

Lo que puedo deducir es que mientras NGINX se está cerrando (por qué, todavía no lo sé), el contenedor en sí no se está reiniciando y, por lo tanto, ese pod es efectivamente un caso zombie. ¿Cómo puedo A. forzar un reinicio o B. forzar que la cápsula muera y reaparezca?

Por supuesto, si alguien tiene una respuesta de por qué se le dice al contenedor nginx que se apague en primer lugar, eso también sería útil.

Otro problema potencialmente relacionadoe, es que a veces las réplicas de este despliegue no arrancan, el contenedor está listo, pero no hay registros ni conexiones.

Eliminar las cápsulas manualmente parece solucionar este problema, pero no es una solución real.

El clúster ejecuta n1-estándar-2 nodos y tenemos el escalado automático habilitado, por lo que CPU/Memoria/Almacenamiento no son (no deberían ser, nunca digas nunca) un problema.

¡Gracias de antemano! Deje un comentario si puedo mejorar esta pregunta de alguna manera.

Edición n.º 1: incluido que estamos en GKE.

Edición n.º 2: agregué sondas de preparación y vivacidad. Actualicé el servidor nginx FE con una ruta de verificación de estado. Esto parece funcionar como un mecanismo de seguridad para garantizar que si el proceso interno de nginx se detiene o ni siquiera se inicia, el contenedor se reiniciará. Sin embargo, si alguien tiene mejores alternativas o ro¡Otras causas me encantaría saber! ¿Quizás debería establecer solicitudes de memoria y CPU específicas para cada pod?

1

Háganos saber si está trabajando solo con Kubernetes o si está utilizando GKE.

-José Luis Delgadillo

26/03/2021 a las 22:43



------------------------------------

Lo que te sugeriría que hicieras es cambiar la imagen de apine a debian o actualizar nginx from 1.17 a una versión más nueva. Recordé a muchas personas que luchaban con problemas de red en estas imágenes de Alpine, especialmente en aplicaciones de reacción y aplicaciones php. Otra cosa que le sugiero que haga si está ejecutando nginx con supervisord para verificar la señal de parada en ese proceso hijo o en el grupo stopas, etc., porque hay un par de configuraciones para ese. Otra cosa que quizás se pueda mejorar es cerrar correctamente y puede hacerlo en el archivo deployment.yml. También verifique los eventos de Kubernetes si obtiene OOM del sistema.

1

Probé la versión estable estándar, que creo que es la 1.18, y no tuvo ningún efecto nuevo o diferente.

- Murray Gudesblat

27 de marzo de 2021 a las 2:15



------------------------------------

¡Está bien! Después de muchas pruebas y errores intensivos, esto es lo que finalmente funcionó para nosotros.

1. Creamos una vivacidad y un ambiente agradable. sonda de preparación en nuestros contenedores nginx front-end/upstream y en la implementación.

nginx.conf

# default server block
location /healthz {
   auth_basic off;
   allow all;
   return 200;
}

despliegue.yaml

#spec.containers
livenessProbe:
  failureThreshold: 1
  httpGet:
    path: /healthz
    port: 80
readinessProbe:
  failureThreshold: 3
  httpGet:
    path: /healthz
    port: 80

Esto aseguró que, sin lugar a dudas, cuando nuestros contenedores nginx fallaran, por cualquier motivo, se reiniciarían.

2. Configuramos un apagado suave para el contenido de nginxers

despliegue.yaml

#spec.containers
lifecycle:
  preStop:
    exec:
      command: ["/bin/sh","-c","sleep 3; nginx -s quit; while pgrep -x nginx; do sleep 1; done"]

Esto aseguró que cuando se producían los reinicios, los contenedores nginx realmente se cerraran sin perder conexiones (aunque, para ser justos, esto era más raro que no).

3. Solicitudes mínimas de CPU y memoria

Con los dos cambios anteriores implementados, sentimos que estábamos en un buen lugar. Hasta que escalamos a 3 réplicas por implementación de Front End. Después de solo una noche, aparentemente elegida al azar, algunas de las réplicas en un par de implementaciones FE (habíamos configurado varias para probar, dev-1 a dev-20) se habían reiniciado más de 800 veces. ¡Locura!

No sabíamos qué podría estar causando esto. Pero por capricho, terminamos agregando algunas solicitudes mínimas de CPU y memoria, y eso terminó resolviendo el ciclo de reinicio/fallo.

# spec.containers
resources:
  requests:
    cpu: 0.001
    memory: 4M
Notas finales

Como puedasComo vemos en lo anterior, realmente terminamos agregando mucha configuración y trabajo a nuestra configuración de implementación existente. Pero nada de eso estaba relacionado con Ingress, eran todos nuestros contenedores nginx ascendentes.

La investigación de vivacidad es bastante estricta porque una vez que los contenedores comenzaron a funcionar mal, se acabó el juego para ese contenedor. No habíamos visto cómo los contenedores se arreglaban solos, por lo que una vez que la sonda de actividad detectó que la verificación de estado estaba fallando, pudimos forzar un reinicio.

El comando preStop es aproximadamente lo que se recomendó como predeterminado para nginx en la documentación de Kubernetes SOBRE los comandos preStop, como se muestra aquí. El sueño 3 se encontró en otra pregunta de stackOverflow, mientras que pgrep se usó en este artículo mediano. Definitivamente es un comando de parada improvisado, pero parece no funcionar.trabajando para nosotros.

Finalmente, las solicitudes mínimas de CPU y memoria que encontramos se basaron en las métricas de todas nuestras implementaciones FE. 0,001 CPU fue el uso medio durante una carga mayor y 4 M fue el uso medio de memoria durante una carga mayor. Pensé que es mejor cubrir las apuestas aquí y usar un poco más de CPU/Memoria de la que necesitamos (aunque obviamente este uso de CPU es pequeño).

No estoy del todo seguro de por qué la configuración de las solicitudes fue lo que finalmente resolvió el problema del reinicio. Si tuviera que adivinar, dar las solicitudes permitió a kubernetes encontrar mejores nodos para colocar estos pods. Quizás los pods que fallaban constantemente estaban apiñados en los límites de un nodo u otro y, por lo tanto, cualquier uso real causaba fallas.

Espero que esto ayude a alguien en el futuro, o tal vez tEste fue un monstruo creado por nosotros mismos y todos ya saben cómo hacer todo lo anterior.

¡Buena suerte a quien encuentre esto!

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare