Kubernetes: Acelere sus servicios eliminando los límites de CPU

En 2016 estábamos en Buffer cambió a Kubernetes, y ahora alrededor de 60 nodos (en AWS) y 1500 contenedores están trabajando en nuestro clúster k8s administrado por policías. Sin embargo, pasamos a los microservicios mediante prueba y error, e incluso después de varios años de trabajar con k8 todavía nos enfrentamos a nuevos problemas. En este post hablaremos de limitaciones del procesador: por qué pensamos que eran buenas prácticas y por qué terminaron no siendo tan buenas.

Limitaciones y estrangulamiento del procesador

Como muchos otros usuarios de Kubernetes, Google recomienda encarecidamente establecer límites de CPU. Sin dicha configuración, los contenedores en un nodo pueden consumir toda la potencia del procesador, lo que a su vez provoca procesos importantes de Kubernetes (por ejemplo kubelet) dejará de responder a las solicitudes. Por lo tanto, establecer límites de CPU es una buena forma de proteger sus nodos.

Los límites del procesador establecen un contenedor en el tiempo máximo de CPU que puede usar durante un período específico (el valor predeterminado es 100 ms) y el contenedor nunca excederá este límite. En Kubernetes para estrangulamiento contenedor y evitar que exceda el límite, se utiliza una herramienta especial Cuota del CSA, pero estos límites artificiales de CPU terminan perjudicando el rendimiento y aumentando el tiempo de respuesta de tus contenedores.

¿Qué puede pasar si no ponemos límites al procesador?

Lamentablemente, nosotros mismos tuvimos que afrontar este problema. Cada nodo tiene un proceso responsable de gestionar los contenedores. kubelet, y dejó de responder a las solicitudes. El nodo, cuando esto suceda, pasará al estado NotReady, y los contenedores que contenga serán redirigidos a otro lugar y crearán los mismos problemas en nuevos nodos. No es un escenario ideal, por decir lo menos.

Manifestación del problema de estrangulamiento y respuesta.

La métrica clave para el seguimiento de contenedores es trottling, muestra cuántas veces se ha acelerado su contenedor. Notamos con interés la presencia de estrangulamiento en algunos contenedores, independientemente de si la carga del procesador era extrema o no. Como ejemplo, echemos un vistazo a una de nuestras API principales:

Kubernetes: Acelere sus servicios eliminando los límites de CPU

Como puede ver a continuación, hemos establecido el límite en 800m (0.8 o 80% del núcleo) y valores máximos en el mejor de los casos 200m (20% núcleo). Parecería que antes de estrangular el servicio todavía nos queda mucha potencia de procesador, sin embargo...

Kubernetes: Acelere sus servicios eliminando los límites de CPU
Es posible que haya notado que incluso cuando la carga del procesador está por debajo de los límites especificados (significativamente por debajo), todavía se produce una aceleración.

Ante esto, pronto descubrimos varios recursos (problema en github, presentación sobre zadano, publicar en omio) sobre la caída en el rendimiento y el tiempo de respuesta de los servicios debido a la limitación.

¿Por qué vemos estrangulamiento con una carga de CPU baja? La versión corta es: "hay un error en el kernel de Linux que provoca una limitación innecesaria de contenedores con límites de procesador específicos". Si está interesado en la naturaleza del problema, puede leer la presentación (видео и texto opciones) de Dave Chiluk.

Eliminación de restricciones de CPU (con extrema precaución)

Después de largas discusiones, decidimos eliminar las restricciones del procesador de todos los servicios que directa o indirectamente afectaban la funcionalidad crítica para nuestros usuarios.

La decisión no fue fácil porque valoramos mucho la estabilidad de nuestro clúster. En el pasado, ya experimentamos con la inestabilidad de nuestro clúster y luego los servicios consumieron demasiados recursos y ralentizaron el trabajo de todo su nodo. Ahora todo era algo diferente: teníamos una comprensión clara de lo que esperábamos de nuestros clusters, así como una buena estrategia para implementar los cambios planeados.

Kubernetes: Acelere sus servicios eliminando los límites de CPU
Correspondencia comercial sobre un tema urgente.

¿Cómo proteger sus nodos cuando se levanten las restricciones?

Aislamiento de servicios “ilimitados”:

En el pasado, ya hemos visto algunos nodos entrar en un estado notReady, principalmente debido a servicios que consumían demasiados recursos.

Decidimos colocar dichos servicios en nodos separados ("etiquetados") para que no interfieran con los servicios "relacionados". Como resultado, al marcar algunos nodos y agregar el parámetro de tolerancia a los servicios "no relacionados", logramos un mayor control sobre el clúster y nos resultó más fácil identificar problemas con los nodos. Para realizar procesos similares usted mismo, puede familiarizarse con documentación.

Kubernetes: Acelere sus servicios eliminando los límites de CPU

Asignación de una solicitud de memoria y procesador correcta:

Nuestro mayor temor era que el proceso consumiera demasiados recursos y el nodo dejara de responder a las solicitudes. Como ahora (gracias a Datadog) pudimos monitorear claramente todos los servicios de nuestro clúster, analicé varios meses de funcionamiento de aquellos que planeábamos designar como "no relacionados". Simplemente configuré el uso máximo de CPU con un margen del 20% y, por lo tanto, asigné espacio en el nodo en caso de que k8s intente asignar otros servicios al nodo.

Kubernetes: Acelere sus servicios eliminando los límites de CPU

Como puede ver en el gráfico, la carga máxima en el procesador ha alcanzado 242m Núcleos de CPU (0.242 núcleos de procesador). Para una solicitud de procesador, basta con tomar un número ligeramente mayor que este valor. Tenga en cuenta que, dado que los servicios están centrados en el usuario, los valores de carga máxima coinciden con el tráfico.

Haga lo mismo con el uso de la memoria y las consultas, y listo, ¡ya está todo configurado! Para mayor seguridad, puede agregar escalado automático de pod horizontal. Por lo tanto, cada vez que la carga de recursos sea alta, el escalado automático creará nuevos pods y Kubernetes los distribuirá a los nodos con espacio libre. En caso de que no quede espacio en el propio clúster, puedes configurar una alerta o configurar la adición de nuevos nodos a través de su escalado automático.

De las desventajas, vale la pena señalar que perdimos en "densidad del contenedor", es decir. Número de contenedores que se ejecutan en un nodo. Es posible que también tengamos muchas "relajaciones" con una baja densidad de tráfico, y también existe la posibilidad de que alcance una carga de procesador alta, pero los nodos de escalado automático deberían ayudar con esto último.

resultados

Me complace publicar estos excelentes resultados de los experimentos de las últimas semanas; ya hemos visto mejoras significativas en la respuesta en todos los servicios modificados:

Kubernetes: Acelere sus servicios eliminando los límites de CPU

Logramos los mejores resultados en nuestra página de inicio (buffer.com), allí el servicio se aceleró en ¡veintidós veces!

Kubernetes: Acelere sus servicios eliminando los límites de CPU

¿Se solucionó el error del kernel de Linux?

Sí, El error ya se solucionó y la solución se agregó al kernel. distribuciones versión 4.19 y superiores.

Sin embargo, al leer problemas de kubernetes en github para el dos de septiembre de 2020 Todavía encontramos menciones de algunos proyectos de Linux con un error similar. Creo que algunas distribuciones de Linux todavía tienen este error y están trabajando para solucionarlo.

Si su versión de distribución es inferior a 4.19, le recomendaría actualizar a la última, pero en cualquier caso debería intentar eliminar las restricciones del procesador y ver si la limitación persiste. A continuación puede ver una lista parcial de los servicios de administración de Kubernetes y distribuciones de Linux:

  • Debian: arreglo integrado en la última versión de la distribución, Buster, y se ve bastante fresco (2020 años agosto). Es posible que también se arreglen algunas versiones anteriores.
  • Ubuntu: corrección integrada en la última versión Ubuntu Focal Fosa 20.04
  • EKS todavía tiene una solución en diciembre 2019 del año. Si su versión es anterior a esta, debe actualizar la AMI.
  • kopps: Desde junio de 2020 у kops 1.18+ La imagen del host principal será Ubuntu 20.04. Si su versión de kops es anterior, es posible que deba esperar una solución. Nosotros mismos estamos esperando ahora.
  • GKE (Google Cloud): solución integrada en enero de 2020, sin embargo, hay problemas con la aceleración. todavía se observan.

¿Qué hacer si la solución solucionó el problema de limitación?

No estoy seguro de que el problema esté completamente resuelto. Cuando lleguemos a la versión del kernel con la solución, probaré el clúster y actualizaré la publicación. Si alguien ya ha actualizado, me interesaría leer sus resultados.

Conclusión

  • Si trabaja con contenedores Docker en Linux (no importa Kubernetes, Mesos, Swarm u otros), sus contenedores pueden perder rendimiento debido a la limitación;
  • Intente actualizar a la última versión de su distribución con la esperanza de que el error ya se haya solucionado;
  • Eliminar los límites del procesador solucionará el problema, pero se trata de una técnica peligrosa que debe utilizarse con extrema precaución (es mejor actualizar primero el kernel y comparar los resultados);
  • Si ha eliminado los límites de CPU, controle cuidadosamente su uso de CPU y memoria y asegúrese de que los recursos de su CPU excedan su consumo;
  • Una opción segura sería escalar automáticamente los pods para crear nuevos pods en caso de una carga de hardware elevada, de modo que Kubernetes los asigne a nodos libres.

Espero que esta publicación le ayude a mejorar el rendimiento de sus sistemas de contenedores.

PS es el autor mantiene correspondencia con lectores y comentaristas (en inglés).


Fuente: habr.com

Añadir un comentario