Pourquoi est-il recommandé d'exécuter un seul processus dans un conteneur?

79

Dans de nombreux articles de blog et dans l'opinion générale, il y a un dicton qui dit "un processus par conteneur".

Pourquoi cette règle existe-t-elle? Pourquoi ne pas exécuter ntp, nginx, uwsgi et davantage de processus dans un même conteneur nécessitant le fonctionnement de tous les processus?

les articles de blog mentionnant cette règle:

Evgeny
la source
Mais serait-il acceptable d’avoir un conteneur très "lourd" avec des dizaines de processus afin d’organiser le déploiement et le fonctionnement d’un serveur d’entreprise qui ne peut toujours pas avoir Docker?
Peter
@ J.Doe, ce ne sera probablement pas bien. les conteneurs sont différents des ordinateurs virtuels, il existe de nombreux petits problèmes, même pour une petite application - pour un déploiement en entreprise, ce sera un projet de deux ans, le tout étant exécuté dans un conteneur.
Evgeny

Réponses:

65

Oublions les arguments architecturaux et philosophiques de haut niveau pour un moment. Il peut y avoir des cas où plusieurs fonctions dans un même conteneur peuvent avoir un sens, mais il y a des raisons très pratiques pour lesquelles vous pouvez envisager de suivre "une fonction par conteneur" en règle générale:

  • La mise à l'échelle des conteneurs horizontalement est beaucoup plus facile si le conteneur est isolé d'une seule fonction. Besoin d'un autre conteneur Apache? Faites-en tourner une autre part. Cependant, si mon conteneur Apache contient également ma DB, mon cron et d’autres pièces, cela complique les choses.
  • Avoir une seule fonction par conteneur permet de réutiliser facilement le conteneur pour d’autres projets ou objectifs.
  • Il est également plus facile et prévisible pour les développeurs de retirer un composant de la production pour le dépannage local, plutôt que d’un environnement d’application complet.
  • Les correctifs / mises à niveau (à la fois le système d'exploitation et l'application) peuvent être effectués de manière plus isolée et contrôlée. Jongler avec plusieurs objets dans votre conteneur crée non seulement des images plus grandes, mais lie également ces composants. Pourquoi faut-il arrêter les applications X et Y uniquement pour mettre à niveau Z?
    • Ce qui précède est également valable pour les déploiements et les restaurations de code.
  • La division des fonctions en plusieurs conteneurs offre davantage de flexibilité du point de vue de la sécurité et de l'isolation. Vous pouvez souhaiter (ou exiger) que les services soient isolés au niveau du réseau, que ce soit physiquement ou au sein de réseaux superposés, afin de maintenir une position de sécurité renforcée ou de vous conformer à des éléments tels que le PCI.
  • D'autres facteurs plus mineurs tels que le traitement de stdout / stderr et l'envoi de journaux au journal des conteneurs, la conservation des conteneurs aussi éphémère que possible, etc.

Notez que je dis fonction, pas processus. Ce langage est obsolète. La documentation officielle du menu fixe a cessé de dire "un processus" au lieu de recommander "une préoccupation" par conteneur.

Jon
la source
1
Pourtant, il semble que l'argument de bas niveau contre les threads convient ici ... web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf
jeffmcneill
Super réponse complète!
Rob Wells le
Est-ce que l'idée que la question ne signifie pas vraiment «processus» au sens OS - que docker et les écrits associés utilisaient une terminologie différente qui a maintenant été clarifiée en passant au mot «fonction»? Parce que sinon, même si je reconnais que c'est la réponse acceptée et la mieux notée, je ne pense pas que cela réponde à la question qui a été posée.
Tom
Les préoccupations peuvent ne pas toujours correspondre 1: 1 aux processus. Que se passe-t-il si je dois faire quelque chose à propos de mon service? Le travail n'est pas indépendant du service. Mais je connais des gens qui fabriquent un conteneur pour chaque processus unix sans tricher. Et ils continuent à chanter un processus = un mantra de conteneur comme justification pour le faire. Quelque chose me semble.
Gherman il y a
27

Après avoir tué un conteneur "deux processus" il y a quelques jours, j'ai eu quelques problèmes qui m'ont amené à utiliser deux conteneurs au lieu d'un script python qui a démarré deux processus:

  1. Docker sait reconnaître les conteneurs écrasés. Cela ne peut pas être le cas lorsque le processus principal semble aller bien, mais un autre processus est mort d'une mort horrible. Bien sûr, vous pouvez surveiller votre processus manuellement, mais pourquoi le réimplémenter?
  2. Les journaux de Docker deviennent beaucoup moins utiles lorsque plusieurs processus vomissent leurs journaux sur la console. Là encore, vous pouvez écrire le nom du processus dans les journaux, mais docker peut également le faire.
  3. Tester et raisonner sur un conteneur devient beaucoup plus difficile.
Christian Sauer
la source
Cela devrait être la réponse acceptée.
ClintM
D'accord. Bien qu'il y ait d'autres réponses avec quelques points intéressants, le point clé concerne le traitement du PID 1 par docker.
Brett Wagner
13

La recommandation provient de l'objectif et de la conception de la virtualisation au niveau du système d'exploitation.

Les conteneurs ont été conçus pour isoler un processus pour d'autres en lui donnant son propre espace utilisateur et son système de fichiers.
Il s’agit de l’évolution logique chrootqui consistait à fournir un système de fichiers isolé. La prochaine étape consistait à isoler les processus des autres afin d’éviter les écrasements de mémoire et à utiliser la même ressource (par exemple, le port TCP 8080) de plusieurs processus sans conflit.

L'intérêt principal d'un conteneur est de conditionner la bibliothèque nécessaire au processus sans se soucier des conflits de version. Si vous exécutez plusieurs processus nécessitant deux versions de la même bibliothèque dans le même espace utilisateur et le même système de fichiers, vous deviez ajuster au moins LDPATH pour chaque processus afin que la bibliothèque appropriée soit trouvée en premier et que certaines bibliothèques ne puissent pas être modifiées de cette façon. parce que leur chemin est codé en dur dans l'exécutable au moment de la compilation, consultez cette question SO pour plus de détails.
Au niveau du réseau, vous devrez configurer chaque processus pour éviter d'utiliser les mêmes ports.

L'exécution de plusieurs processus dans le même conteneur nécessite de lourdes modifications et, en fin de journée, annulez l'objectif d'isolation. Si vous êtes autorisé à exécuter plusieurs processus dans le même espace utilisateur, en partageant le même système de fichiers et les mêmes ressources réseau, pourquoi ne pas les exécuter sur l'hôte lui-même?

Voici la liste non exhaustive des torts / pièges lourds auxquels je peux penser:

  • Manipulation des grumes

    Que ce soit avec un volume monté ou entrelacé sur stdout, cela apporte un peu de gestion. Si vous utilisez un volume monté, votre conteneur doit avoir sa propre "place" sur l'hôte ou deux conteneurs identiques se battront pour la même ressource. Entrelacer sur stdout pour en tirer parti docker logspeut devenir un cauchemar pour l'analyse si les sources ne peuvent pas être identifiées facilement.

  • Attention aux processus zombies

    Si l'un de vos processus se bloque dans un conteneur, Supervisord risque de ne pas pouvoir nettoyer les enfants dans un état zombie, et l'hôte init ne les héritera jamais. Une fois que vous avez épuisé le nombre de pids disponibles (2 ^ 22, soit environ 4 millions), un tas de choses vont échouer.

  • Séparation des préoccupations

    Si vous exécutez deux choses séparées, comme un serveur Apache et logstash dans le même conteneur, cela peut faciliter la gestion des journaux, mais vous devez fermer apache pour mettre à jour logstash. (En réalité, vous devez utiliser le pilote de journalisation de Docker. Sera-ce un arrêt gracieux d’attendre la fin des sessions en cours ou non? Si c'est un arrêt gracieux, la nouvelle version peut prendre un certain temps et devenir longue. Si vous faites un kill, vous aurez un impact sur les utilisateurs d'un expéditeur de journaux, ce qui devrait être évité à mon humble avis.

Enfin, lorsque vous avez plusieurs processus, vous reproduisez un système d'exploitation. Dans ce cas, l'utilisation d'une virtualisation matérielle semble plus adaptée à ce besoin.

Tensibai
la source
3
Je trouve ces arguments peu convaincants. Il existe une énorme différence entre un processus avec plusieurs conteneurs et une exécution sur un hôte. Bien que l'explication de l'intention initiale des conteneurs soit quelque peu pertinente, ce n'est pas vraiment une raison impérieuse pour éviter les conteneurs multi-processus. IOW, vous répondez "pourquoi pas" avec "pourquoi oui", ce qui n'est pas aussi utile qu'il pourrait l'être. Il peut être très pratique d'exécuter plusieurs processus dans le même conteneur - c'est pourquoi oui. Le pourquoi pas reste à expliquer.
Assaf Lavie
1
Vous n'avez pas précisé le type de modification que vous aviez à l'esprit. Et vous n'avez pas prétendu que ces ajustements demandaient plus de travail que la configuration de plusieurs conteneurs. Prenons un exemple concret: vous voyez souvent des images de docker empaquetées dans lesquelles supervisord exécute un processus principal et un processus auxiliaire. C'est très facile à mettre en place. aussi facile que de séparer les conteneurs. par exemple app & log expéditeur. Je crois donc qu'il vous incombe de démontrer pourquoi ce n'est pas le cas.
Assaf Lavie
1
BTW, je crois qu'il existe des arguments valables contre les conteneurs multi-processus, mais vous n'en avez mentionné aucun. Mais dans tous les cas, l’affaire est loin d’être claire. Dans certains cas, il est parfaitement acceptable d'autoriser plusieurs processus. Heck, certaines images très populaires génèrent plusieurs sous-processus - est-ce aussi un mal? Ce que je dis, c'est qu'il y a des compromis, et votre réponse brosse un tableau unilatéral qui manque de nuance et de détail.
Assaf Lavie
1
intéressant ... Il semble que nous ayons une opinion similaire (identique) à ce sujet. Peut-être devriez-vous simplement l'ignorer dans ce cas, car c'était quelqu'un qui voulait obtenir l' insigne de critique ... et qui a décidé d'abuser de votre réponse pour obtenir cet insigne ...
Pierre.Vriens
1
Je ne "précipite" pas la conclusion ... Je vous recommande simplement de l'ignorer. Mais "vous" ne pouvez pas changer d'avis sur ce que j'ai vu de mes propres yeux sur l'identité de l'auteur anonyme de votre réponse. Quoi qu'il en soit, il est temps de passer à autre chose ...
Pierre.Vriens
6

Comme dans la plupart des cas, ce n'est pas du tout ou rien. L’indication "un processus par conteneur" découle de l’idée que les conteneurs doivent avoir un objectif distinct. Par exemple, un conteneur ne doit pas être à la fois une application Web et un serveur Redis.

Il existe des cas où il est judicieux d'exécuter plusieurs processus dans un même conteneur, à condition que les deux processus prennent en charge une seule fonction modulaire.

Dave Swersky
la source
2

Le processus que j'appellerai comme service ici, 1 conteneur ~ 1 service , si l'un de mes services est défaillant, je ne ferai qu'activer ce conteneur respectif et dans quelques secondes tout sera à nouveau opérationnel. Donc, il n'y aura pas de dépendances entre les services. Il est recommandé de conserver une taille de conteneur inférieure à 200 Mo et maximale de 500 Mo (à l'exception de 2 Go pour les conteneurs natifs Windows), sinon, elle sera similaire à la machine virtuelle, mais pas exactement, mais les performances suffiront. Prenez également en considération quelques paramètres tels que la mise à l'échelle, comment puis-je rendre les services résilients, le déploiement automatique, etc.

Et c’est purement votre appel, comment vous devez adapter vos schémas architecturaux tels que le micro-service dans un environnement polygot à l’aide de la technologie de conteneur la mieux adaptée à votre environnement et l’automatisant pour vous.

mohan08p
la source