Je ne pose pas de question sur l'utilisation d'un superviseur avec des dockers mais je veux juste que ma compréhension soit validée.
Je comprends que docker exécute un seul processus lorsqu'il est exécuté. En outre, le superviseur est utilisé lorsque nous devons exécuter plusieurs processus dans le conteneur.
J'ai vu plusieurs exemples où un conteneur est démarré à partir d'une image de base et plusieurs services sont installés et le conteneur s'engage à former une nouvelle image, le tout sans superviseur.
Donc, mon doute fondamental était quelle est la différence entre les deux approches.
Ma compréhension est que lorsque le conteneur Docker est arrêté, il envoie un signal d'arrêt au processus avec PID 1, PID 1 gère le processus enfant et arrête tous les enfants, ce qui est exactement ce qui est fait par le superviseur, tandis que nous pouvons installer plusieurs processus sans superviseur, un seul peut être exécuté lorsque docker run
est émis et lorsque le conteneur est arrêté, seul le PID 1 recevra des signaux et les autres processus en cours ne seront pas arrêtés normalement.
Veuillez confirmer à quel point ma compréhension de l'utilisation de supervisord
est correcte.
bien que nous puissions installer plusieurs processus sans superviseur, un seul processus peut être exécuté lors de l'exécution du docker et lorsque le conteneur est arrêté, seul le PID 1 recevra des signaux et les autres processus en cours d'exécution ne seront pas arrêtés normalement.
Oui, bien que cela dépende de la façon dont votre processus principal s'exécute (premier plan ou arrière-plan) et de la façon dont il collecte les processus enfants.
C'est ce qui est détaillé dans " Trapping des signaux dans les conteneurs Docker "
docker stop
Arrête un conteneur en cours d'exécution en lui envoyant un signalSIGTERM
, laisse le processus principal le traiter et, après une période de grâce, utiliseSIGKILL
pour terminer l'application.Le signal envoyé au conteneur est géré par le processus principal en cours d'exécution (PID 1).
Si l'application est au premier plan, ce qui signifie que l'application est le processus principal dans un conteneur (PID1), elle pourrait traiter directement les signaux.
Mais:
Le processus à signaler peut être le processus d'arrière-plan et vous ne pouvez pas envoyer de signaux directement. Dans ce cas, une solution consiste à configurer un script Shell comme point d'entrée et à orchestrer tout le traitement du signal dans ce script.
Le problème est détaillé dans " Docker et le problème de récolte de zombies PID 1 "
Unix est conçu de telle manière que les processus parents doivent explicitement "attendre" la fin du processus enfant, afin de collecter son état de sortie. Le processus zombie existe jusqu'à ce que le processus parent ait effectué cette action, à l'aide de la famille d'appels système
waitpid()
.L'action d'appeler waitpid () sur un processus enfant afin d'éliminer son zombie, est appelée "récolte".
Le processus
init
- PID 1 - a une tâche spéciale. Sa tâche consiste à "adopter" des processus enfants orphelins.
Le système d'exploitation s'attend à ce que le processus init récolte également les enfants adoptés.
Problème avec Docker:
Nous voyons que beaucoup de gens exécutent un seul processus dans leur conteneur, et ils pensent que lorsqu'ils exécutent ce seul processus, ils ont terminé.
Mais très probablement, ce processus n'est pas écrit pour se comporter comme un processus d'initialisation approprié.
Autrement dit, au lieu de récolter correctement les processus adoptés, il s'attend probablement à ce qu'un autreinit
processus fasse ce travail, et à juste titre.
Utiliser une image comme phusion/baseimage-docker
aide à gérer un (ou plusieurs) processus tout en gardant un processus principal conforme à l'init.
Il utilise runit
au lieu de supervisord
, pour la gestion multi-processus:
Runit n'est pas là pour résoudre le problème de récolte. Il s'agit plutôt de prendre en charge plusieurs processus. Plusieurs processus sont encouragés pour la sécurité (grâce à l'isolation des processus et des utilisateurs).
Runit utilise moins de mémoire que Supervisord car Runit est écrit en C et Supervisord en Python.
Et dans certains cas d'utilisation, les redémarrages de processus dans le conteneur sont préférables aux redémarrages de conteneurs entiers.
Cette image inclut un my_init
Script qui s'occupe du problème de "récolte".
Dans baseimage-docker, nous encourageons l'exécution de plusieurs processus dans un seul conteneur. Pas nécessairement plusieurs services cependant.
Un service logique peut comprendre plusieurs processus de système d'exploitation, et nous fournissons les installations nécessaires pour le faire facilement.
Mise à jour septembre 2016 pour docker 1.12 (T4 2016/Q1 2017)
Arnaud Porterie juste twitté :
[????] Vient de fusionner: avec
docker run --init
, Rick Grimes s'occupera de tous vos zombies.
( commit eabae09 )
Voir PR 26061 : " Ajouter un processus d'initialisation pour la lutte contre les zombies et la gestion du signal " (et PR 26736 =)
Cela ajoute un petit binaire C pour combattre les zombies. Il est monté sous/dev/init et est ajouté aux arguments spécifiés par l'utilisateur. Vous l'activez via un indicateur de démon, dockerd --init, car il est désactivé par défaut pour la compatibilité descendante.
Vous pouvez également remplacer l'option démon ou la spécifier par conteneur avec
docker run --init=true|false
.Vous pouvez le tester en exécutant un processus comme celui-ci en tant que pid 1 dans un conteneur et voir le zombie supplémentaire qui apparaît dans le conteneur pendant son exécution.
int main(int argc, char ** argv) {
pid_t pid = fork();
if (pid == 0) {
pid = fork();
if (pid == 0) {
exit(0);
}
sleep(3);
exit(0);
}
printf("got pid %d and exited\n", pid);
sleep(20);
}
Le démon docker a maintenant l'option
--init
Exécutez une init dans des conteneurs pour transmettre des signaux et récolter des processus