¿Por qué se recomienda ejecutar solo un proceso en un contenedor?

79

En muchas publicaciones de blog y opiniones generales, hay un dicho que dice "un proceso por contenedor".

¿Por qué existe esta regla? ¿Por qué no ejecutar ntp, nginx, uwsgi y más procesos en un solo contenedor que necesita tener todos los procesos para funcionar?

publicaciones de blog que mencionan esta regla:

Evgeny
fuente
Pero, ¿estaría bien tener un contenedor muy "gordo" con docenas de procesos para organizar el lanzamiento y la operación de un servidor empresarial que todavía no puede tener Docker?
Peter
@ J.Doe probablemente no estará bien. los contenedores son diferentes a las máquinas virtuales, existen múltiples problemas pequeños incluso para una aplicación pequeña: para una implementación empresarial, será un proyecto de dos años para que todo se ejecute en un contenedor en primer lugar.
Evgeny

Respuestas:

65

Olvidemos los argumentos arquitectónicos y filosóficos de alto nivel por un momento. Si bien puede haber algunos casos extremos en los que varias funciones en un solo contenedor pueden tener sentido, existen razones muy prácticas por las que es posible que desee considerar seguir "una función por contenedor" como regla general:

  • Escalar contenedores horizontalmente es mucho más fácil si el contenedor está aislado de una sola función. ¿Necesita otro contenedor de apache? Gira uno en otro lugar. Sin embargo, si mi contenedor de apache también tiene mi DB, cron y otras piezas calzadas, esto complica las cosas.
  • Tener una sola función por contenedor permite que el contenedor se reutilice fácilmente para otros proyectos o propósitos.
  • También hace que sea más portátil y predecible para los desarrolladores extraer un componente de producción para resolver problemas localmente en lugar de un entorno de aplicación completo.
  • Los parches / actualizaciones (tanto el sistema operativo como la aplicación) se pueden hacer de manera más aislada y controlada. Hacer malabarismos con múltiples bits en su contenedor no solo crea imágenes más grandes, sino que también une estos componentes. ¿Por qué tener que cerrar la aplicación X e Y solo para actualizar Z?
    • Lo anterior también es válido para implementaciones de código y retrocesos.
  • La división de funciones en múltiples contenedores permite una mayor flexibilidad desde una perspectiva de seguridad y aislamiento. Es posible que desee (o requiera) que los servicios estén aislados a nivel de red, ya sea físicamente o dentro de redes superpuestas, para mantener una postura de seguridad sólida o cumplir con cosas como PCI.
  • Otros factores menores, como tratar con stdout / stderr y enviar registros al registro de contenedores, mantener los contenedores lo más efímeros posible, etc.

Tenga en cuenta que estoy diciendo función, no proceso. Ese lenguaje está desactualizado. La documentación oficial de la ventana acoplable ha pasado de decir "un proceso" a recomendar "una preocupación" por contenedor.

Jon
fuente
1
Aún así, parece que el argumento de bajo nivel en contra de los hilos encaja aquí ... web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf
jeffmcneill
Gran respuesta integral!
Rob Wells el
¿Es la idea de que la pregunta realmente no significa "proceso" en el sentido del sistema operativo: que Docker y escritos relacionados estaban usando una terminología diferente que ahora se ha aclarado al cambiar a la palabra "función"? Porque de lo contrario, aunque reconozco que esta es la respuesta aceptada y mejor calificada, no creo que responda la pregunta que se hizo.
Tom
27

Habiendo matado un contenedor de "dos procesos" hace unos días, hubo algunos puntos débiles para mí que me hicieron usar dos contenedores en lugar de un script de Python que inició dos procesos:

  1. Docker es bueno para reconocer contenedores estrellados. No puede hacer eso cuando el proceso principal se ve bien, pero otro proceso tuvo una muerte espantosa. Claro, puede monitorear su proceso manualmente, pero ¿por qué volver a implementar eso?
  2. los registros de Docker se vuelven mucho menos útiles cuando varios procesos arrojan sus registros a la consola. De nuevo, puede escribir el nombre del proceso en los registros, pero Docker también puede hacerlo.
  3. Las pruebas y el razonamiento sobre un contenedor se vuelven mucho más difíciles.
Christian Sauer
fuente
Esta debería ser la respuesta aceptada.
ClintM
Convenido. Si bien hay algunas otras respuestas con algunos puntos excelentes, el punto clave es sobre el manejo de PID por parte de Docker 1.
Brett Wagner
13

La recomendación proviene del objetivo y el diseño de la virtualización a nivel del sistema operativo

Los contenedores han sido diseñados para aislar un proceso para otros al darle su propio espacio de usuario y sistema de archivos.
Esta es la evolución lógica de chrootproporcionar un sistema de archivos aislado, el siguiente paso fue aislar los procesos de los demás para evitar sobrescrituras de memoria y permitir el uso del mismo recurso (por ejemplo, el puerto TCP 8080) de múltiples procesos sin conflictos.

El interés principal en un contenedor es empaquetar la biblioteca necesaria para el proceso sin preocuparse por los conflictos de versión. Si ejecuta múltiples procesos que necesitan dos versiones de la misma biblioteca en el mismo espacio de usuario y sistema de archivos, tendría que ajustar al menos LDPATH para cada proceso para que la biblioteca adecuada se encuentre primero, y algunas bibliotecas no se pueden ajustar de esta manera, debido a que su ruta está codificada en el ejecutable en el momento de la compilación, vea esta pregunta SO para obtener más detalles.
A nivel de red, deberá configurar cada proceso para evitar el uso de los mismos puertos.

La ejecución de múltiples procesos en el mismo contenedor requiere algunos ajustes pesados ​​y, al final del día, anula el propósito del aislamiento, si puede ejecutar múltiples procesos dentro del mismo espacio de usuario, compartiendo el mismo sistema de archivos y recursos de red, entonces ¿por qué no ejecutarlos? en el propio host?

Aquí está la lista no exhaustiva de los grandes ajustes / trampas que se me ocurren:

  • Manejando los troncos

    Ya sea con un volumen montado o intercalado en stdout, esto trae algo de administración. Si usa un volumen montado, su contenedor debe tener su propio "lugar" en el host o dos mismos contenedores lucharán por el mismo recurso. Al intercalar en stdout para aprovecharlo docker logs, puede convertirse en una pesadilla para el análisis si las fuentes no se pueden identificar fácilmente.

  • Cuidado con los procesos zombies

    Si uno de los procesos en un contenedor se bloquea, es posible que el supervisor no pueda limpiar al niño en estado zombie, y el host init nunca los heredará. Una vez que haya agotado la cantidad de pids disponibles (2 ^ 22, aproximadamente 4 millones), un montón de cosas fallarán.

  • Separación de intereses

    Si ejecuta dos cosas separadas, como un servidor apache y logstash dentro del mismo contenedor, eso puede facilitar el manejo de registros, pero debe apagar apache para actualizar logstash. (En realidad, debe usar el controlador de registro de Docker) ¿Será una parada elegante esperar a que finalicen las sesiones actuales o no? Si es una parada elegante, puede llevar algún tiempo y demorar mucho en lanzar la nueva versión. Si matas, afectarás a los usuarios de un cargador de troncos y eso debería evitarse en mi humilde opinión.

Finalmente, cuando tiene múltiples procesos, está reproduciendo un sistema operativo y, en este caso, usar una virtualización de hardware suena más acorde con esta necesidad.

Tensibai
fuente
3
Encuentro estos argumentos poco convincentes. Hay una gran diferencia entre un proceso con múltiples contenedores y la ejecución en el host. Si bien la explicación de la intención original de los contenedores es algo relevante, no es realmente una razón convincente para evitar contenedores multiproceso. IOW, estás respondiendo "por qué no" con "por qué sí", que no es tan útil como podría ser. Puede ser muy conveniente ejecutar múltiples procesos en el mismo contenedor, por eso sí. El por qué no queda por explicar.
Assaf Lavie
1
No ha elaborado el tipo de ajustes que tenía en mente. Y no ha argumentado que este ajuste es más trabajo que configurar múltiples contenedores. Tomemos un ejemplo concreto: a menudo ve imágenes acopladas de acopladores que tienen supervisores ejecutando algún proceso principal y algún proceso auxiliar. Esto es muy fácil de configurar; podría decirse que es tan fácil como separar los contenedores. por ejemplo, la aplicación y el cargador de registros. Entonces, creo que es su responsabilidad argumentar por qué este no es el caso.
Assaf Lavie
1
Por cierto, creo que hay argumentos válidos contra los contenedores multiproceso, pero no mencionó ninguno de ellos. Pero en cualquier caso, está lejos de ser un caso claro. En algunos casos, es perfectamente aceptable permitir más de un proceso. Heck, algunas imágenes muy populares generan varios subprocesos, ¿eso también es malo? Lo que digo es que hay compensaciones, y su respuesta pinta una imagen unilateral que carece de matices y detalles.
Assaf Lavie
1
interesante ... Parece que tenemos una opinión similar (idéntica) sobre esto. Tal vez deberías ignorarlo en este caso, porque fue de alguien que quería ganar la insignia de Crítico ... y decidió abusar de tu respuesta para obtener esa insignia ...
Pierre.Vriens
1
No me apresuro a llegar a una conclusión ... solo recomiendo que lo ignoren. Pero "usted" no puede cambiar de opinión sobre lo que he visto con mis propios ojos acerca de quién es el votante anónimo de su respuesta. De todos modos, es hora de seguir adelante ...
Pierre.Vriens
6

Como en la mayoría de los casos, no es todo o nada. La guía de "un proceso por contenedor" se deriva de la idea de que los contenedores deben cumplir un propósito distinto. Por ejemplo, un contenedor no debe ser tanto una aplicación web como un servidor Redis.

Hay casos en los que tiene sentido ejecutar múltiples procesos en un solo contenedor, siempre que ambos procesos admitan una única función modular.

Dave Swersky
fuente
2

El proceso que llamaré como servicio aquí, 1 contenedor ~ 1 servicio , si alguno de mis servicios falla, entonces solo activaré ese contenedor respectivo y en cuestión de segundos todo volverá a funcionar. Por lo tanto, no habrá dependencias entre los servicios. Es una buena práctica mantener el tamaño de su contenedor por debajo de 200 MB y un máximo de 500 MB (la excepción a los contenedores nativos de Windows son más de 2 GB) de lo contrario, será similar a la máquina virtual, no exactamente, pero el rendimiento es suficiente. Además, tenga en cuenta algunos parámetros como el escalado, cómo podría hacer que mis servicios sean resistentes, se implementen automáticamente, etc.

Y es puramente su decisión cómo debe hacer sus patrones arquitectónicos como microservicio en un entorno polygot utilizando la tecnología de contenedores que mejor se adapta a su entorno y automatizará las cosas por usted.

mohan08p
fuente