Perché si consiglia di eseguire solo un processo in un contenitore?


79

In molti post di blog e opinione generale, c'è un detto che dice "un processo per contenitore".

Perché esiste questa regola? Perché non eseguire ntp, nginx, uwsgi e altri processi in un unico contenitore che deve avere tutti i processi per funzionare?

post di blog che menzionano questa regola:


Ma sarebbe giusto avere un contenitore molto "pesante" con dozzine di processi per organizzare un lancio e il funzionamento di un server aziendale che non può ancora avere Docker?
Peter,

@ J.Doe probabilmente non andrà bene. i contenitori sono diversi dalle macchine virtuali, ci sono molti piccoli problemi anche per una piccola applicazione: per un'implementazione aziendale sarà un progetto di due anni, perché tutto verrà eseguito in un contenitore in primo luogo.
Evgeny,

Risposte:


65

Dimentichiamo gli argomenti architettonici e filosofici di alto livello per un momento. Mentre ci possono essere alcuni casi limite in cui più funzioni in un singolo contenitore possono avere un senso, ci sono ragioni molto pratiche per cui potresti voler considerare di seguire una "funzione per contenitore" come una regola empirica:

  • Il ridimensionamento dei contenitori in orizzontale è molto più semplice se il contenitore è isolato in una singola funzione. Hai bisogno di un altro contenitore Apache? Girane uno altrove. Tuttavia, se il mio contenitore Apache ha anche il mio DB, il cron e altri pezzi dentro, questo complica le cose.
  • Avere una singola funzione per container consente di riutilizzare facilmente il container per altri progetti o scopi.
  • Inoltre, rende gli sviluppatori più portatili e prevedibili per eliminare un componente dalla produzione per risolvere i problemi localmente piuttosto che un intero ambiente applicativo.
  • Patch / upgrade (sia il sistema operativo che l'applicazione) possono essere eseguiti in modo più isolato e controllato. La manipolazione di più bit e bob nel contenitore non solo consente di ottenere immagini più grandi, ma collega anche questi componenti. Perché chiudere l'applicazione X e Y solo per aggiornare Z?
    • Quanto sopra vale anche per distribuzioni di codice e rollback.
  • La suddivisione delle funzioni in più contenitori consente una maggiore flessibilità dal punto di vista della sicurezza e dell'isolamento. Potresti voler (o richiedere) che i servizi siano isolati a livello di rete - fisicamente o all'interno di reti overlay - per mantenere una solida posizione di sicurezza o conformarsi a cose come PCI.
  • Altri fattori minori come la gestione di stdout / stderr e l'invio di registri nel registro contenitore, mantenendo i contenitori il più effimeri possibile ecc.

Nota che sto dicendo funzione, non processo. Quella lingua è obsoleta. La documentazione ufficiale sulla finestra mobile si è spostata dal dire "un processo" a raccomandare invece "un problema" per container.


1
Tuttavia, sembra che l'argomento di basso livello contro i thread si adatti qui ... web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf
jeffmcneill

Ottima risposta completa!
Rob Wells,

L'idea che la domanda non significasse davvero "processo" nel senso del sistema operativo - che la finestra mobile e gli scritti correlati utilizzavano una terminologia diversa che ora è stata chiarita passando alla parola "funzione"? Perché altrimenti, pur riconoscendo che questa è la risposta accettata e più votata, non penso che risponda alla domanda che è stata posta.
Tom,

27

Avendo ucciso un contenitore di "due processi" qualche giorno fa, ci sono alcuni punti dolenti per me che mi hanno fatto usare due contenitori invece di uno script Python che ha avviato due processi:

  1. Docker è bravo a riconoscere i contenitori danneggiati. Non può farlo quando il processo principale sembra a posto, ma qualche altro processo è morto in modo orribile. Certo, puoi monitorare il tuo processo manualmente, ma perché reimplementarlo?
  2. i registri della finestra mobile diventano molto meno utili quando più processi inviano i loro registri alla console. Ancora una volta, puoi scrivere il nome del processo nei log, ma anche la finestra mobile lo può fare.
  3. Testare e ragionare su un container diventa molto più difficile.

Questa dovrebbe essere la risposta accettata.
ClintM,

Concordato. Mentre ci sono altre risposte con alcuni ottimi punti, il punto chiave è sulla gestione da parte della docker del PID 1.
Brett Wagner

13

La raccomandazione deriva dall'obiettivo e dal design della virtualizzazione a livello di sistema operativo

I contenitori sono stati progettati per isolare un processo per altri, dandogli il proprio spazio utente e filesystem.
Questa è la logica evoluzione del chrootfornire un filesystem isolato, il passo successivo è stato isolare i processi dagli altri per evitare sovrascritture di memoria e consentire di utilizzare la stessa risorsa (ad esempio la porta TCP 8080) da più processi senza conflitti.

L'interesse principale in un contenitore è quello di impacchettare la libreria necessaria per il processo senza preoccuparsi dei conflitti di versione. Se esegui processi multipli che richiedono due versioni della stessa libreria nello stesso spazio utente e nello stesso filesystem, avresti dovuto modificare almeno LDPATH per ciascun processo in modo da trovare prima la libreria corretta e alcune librerie non possono essere modificate in questo modo, poiché il loro percorso è hard coded nell'eseguibile al momento della compilazione, vedere questa domanda SO per maggiori dettagli.
A livello di rete dovrai configurare ogni processo per evitare di usare le stesse porte.

L'esecuzione di più processi nello stesso contenitore richiede alcune pesanti modifiche e alla fine della giornata sconfigge lo scopo dell'isolamento, se sei ok per eseguire processi multipli nello stesso spazio utente, condividendo lo stesso filesystem e le stesse risorse di rete, quindi perché non eseguirli sull'host stesso?

Ecco l'elenco non esaustivo delle modifiche / insidie ​​pesanti che mi vengono in mente:

  • Gestire i registri

    O essere con un volume montato o interleaved su stdout questo porta un po 'di gestione. Se si utilizza un volume montato, il proprio contenitore dovrebbe avere il proprio "posto" sull'host o due contenitori stessi combatteranno per la stessa risorsa. Quando interleaving su stdout per trarne vantaggio docker logspuò diventare un incubo per l'analisi se le fonti non possono essere identificate facilmente.

  • Fai attenzione ai processi di zombi

    Se uno dei tuoi processi si interrompe in un contenitore, supervisord potrebbe non essere in grado di ripulire i bambini in uno stato di zombi e l'iniz host non li erediterà mai. Una volta esaurito il numero di pid disponibili (2 ^ 22, quindi circa 4 milioni), un sacco di cose falliranno.

  • Separazione degli interessi

    Se esegui due cose separate, come un server apache e logstash all'interno dello stesso contenitore, ciò potrebbe facilitare la gestione dei log, ma devi chiudere apache per aggiornare il logstash. (In realtà, è necessario utilizzare il driver di registrazione di Docker). Sarà un arresto grazioso in attesa che le sessioni attuali finiscano o no? Se si tratta di un arresto grazioso, potrebbe essere necessario un po 'di tempo e potrebbe richiedere molto tempo per eseguire il lancio della nuova versione. Se esegui un'uccisione, avrai un impatto sugli utenti per un mittente di log e questo dovrebbe essere evitato IMHO.

Infine, quando hai più processi, stai riproducendo un sistema operativo, e in questo caso l'utilizzo di una virtualizzazione hardware sembra più in linea con questa necessità.


3
Trovo questi argomenti non convincenti. C'è un'enorme differenza tra un processo con più contenitori e in esecuzione sull'host. Mentre spiegare l'intenzione originale dei contenitori è in qualche modo rilevante, non è in realtà un motivo convincente per evitare contenitori multi-processo. IOW, stai rispondendo "why not" con "why yes", che non è così utile come potrebbe essere. Può essere molto comodo eseguire più processi nello stesso contenitore - ecco perché. Il perché non rimane da spiegare.
Assaf Lavie

1
Non hai approfondito il tipo di modifiche che avevi in ​​mente. E non hai ipotizzato che questa modifica sia più un lavoro che impostare più contenitori. Facciamo un esempio concreto: spesso vedete immagini di docker impacchettate che hanno supervisord che esegue un processo principale e un processo ausiliario. Questo è molto facile da configurare; probabilmente altrettanto facile quanto separare i contenitori. ad es. app e log shipper. Quindi, credo che spetti a te spiegare perché non è così.
Assaf Lavie

1
A proposito, credo che ci siano argomenti validi contro i contenitori multi-processo, ma non ne hai menzionato nessuno. Ma in ogni caso, è ben lungi dall'essere un caso chiaro. In alcuni casi è perfettamente accettabile consentire più di un processo. Diamine, alcune immagini molto popolari generano diversi sottoprocessi: è anche questo male? Quello che sto dicendo è che ci sono dei compromessi e la tua risposta dipinge un'immagine unilaterale priva di sfumature e dettagli.
Assaf Lavie

1
interessante ... Sembra che abbiamo un'opinione simile (identica) su questo. Forse dovresti semplicemente ignorarlo in questo caso, perché proveniva da qualcuno che voleva guadagnare il badge Critico ... e ha deciso di abusare della tua risposta per ottenere quel badge ...
Pierre.Vriens

1
Non mi affretto alla conclusione ... Ti consiglio solo di ignorarlo. Ma "tu" non puoi cambiare idea su ciò che ho visto con i miei occhi su chi sia l'anonimo downvoter della tua risposta. Comunque, è ora di andare avanti ...
Pierre.Vriens

6

Come nella maggior parte dei casi, non è tutto o niente. La guida di "un processo per contenitore" nasce dall'idea che i contenitori dovrebbero servire a uno scopo distinto. Ad esempio, un contenitore non dovrebbe essere sia un'applicazione Web che un server Redis.

Ci sono casi in cui ha senso eseguire più processi in un singolo contenitore, purché entrambi i processi supportino un'unica funzione modulare.


2

Il processo che chiamerò qui come servizio, 1 contenitore ~ ​​1 servizio , se uno qualsiasi dei miei servizi è fallito, farò girare solo quel rispettivo contenitore e entro pochi secondi tutto sarà di nuovo attivo. Quindi, non ci saranno dipendenze tra i servizi. È consigliabile mantenere dimensioni del contenitore inferiori a 200 MB e max 500 MB (ad eccezione dei contenitori nativi di Windows più di 2 GB), altrimenti sarà simile alla macchina virtuale, non esattamente, ma le prestazioni sono sufficienti. Inoltre, prendi in considerazione alcuni parametri come il ridimensionamento, come posso rendere resilienza dei miei servizi, distribuzione automatica, ecc.

Inoltre, è semplicemente una tua chiamata il modo in cui devi realizzare i tuoi modelli architettonici come il micro-servizio in un ambiente poligot usando la tecnologia dei contenitori che meglio si adatta al tuo ambiente e automatizzerà le cose per te.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.