Come posso mantenere un container in esecuzione su Kubernetes?


124

Ora sto cercando di eseguire un semplice contenitore con shell (/ bin / bash) su un cluster Kubernetes.

Ho pensato che ci fosse un modo per mantenere un container in esecuzione su un container Docker utilizzando pseudo-ttye scollega l'opzione ( -tdopzione a docker runcomando).

Per esempio,

$ sudo docker run -td ubuntu:latest

Esiste un'opzione come questa in Kubernetes?

Ho provato a eseguire un contenitore utilizzando un kubectl run-containercomando come:

kubectl run-container test_container ubuntu:latest --replicas=1

Ma il contenitore esce per alcuni secondi (proprio come l'avvio con il docker runcomando senza opzioni che ho menzionato sopra). E ReplicationController lo lancia di nuovo ripetutamente.

C'è un modo per mantenere un container in esecuzione su Kubernetes come le -tdopzioni nel docker runcomando?


Usare questa immagine (come suggerisce la documentazione di Kubernetes ) è abbastanza utile:kubectl run curl --image=radial/busyboxplus:curl -i --tty
Matheus Santana

Questa domanda è stata menzionata in questo video: Kubernetes the very hard way at Datadog with a slide-title of "Cargo culting . Da wikipedia: Il termine programmatore di cargo cult può essere applicato quando un programmatore di computer inesperto o inesperto (o uno inesperto con il problema a portata di mano) copia del codice del programma da un posto all'altro con poca o nessuna comprensione di come funziona o se è richiesto nella sua nuova posizione.
tgogos

Risposte:


49

Un contenitore esce quando termina il suo processo principale. Fare qualcosa come:

docker run -itd debian

tenere il contenitore aperto è francamente un trucco che dovrebbe essere usato solo per test ed esempi veloci. Se vuoi solo un contenitore per testare per pochi minuti, farei:

docker run -d debian sleep 300

Il che ha il vantaggio che il contenitore uscirà automaticamente se te ne dimentichi. In alternativa, potresti mettere qualcosa di simile in un whileciclo per mantenerlo in esecuzione per sempre, o semplicemente eseguire un'applicazione come top. Tutto ciò dovrebbe essere facile da fare in Kubernetes.

La vera domanda è perché dovresti farlo? Il tuo contenitore dovrebbe fornire un servizio, il cui processo manterrà il contenitore in esecuzione in background.


La ringrazio per la risposta. Ora sto cercando di capire il comportamento dei contenitori, con dozzine di contenitori in esecuzione contemporaneamente. Ciclo infinito e utilizzo di altri comandi pesanti, mi impediscono di sapere qual è il comportamento dei contenitori. Questo è il motivo per cui ho bisogno di un contenitore semplice come eseguire solo / bin / bash.
Springwell

Per il momento, cercherò di funzionamento catsenza argomenti e tope sleepcon l'argomento di un gran numero.
Springwell

30
sleep infinityfunziona in molti casi (non busybox)
rwilson04

1
Ci sono molte ragioni per farlo. Ad esempio, potresti distribuire i tuoi pod con le versioni del timone e la configurazione iniettata, il che renderà fastidiosa e scomoda la ricreazione di ambienti simili. Ma avere un contenitore con quella configurazione nei casi in cui gli altri pod si bloccano / vengono eliminati può essere infinitamente utile.
Richard Løvehjerte

Perché il mio servizio consiste in più processi.
Константин Ван

135

I contenitori devono essere eseguiti fino al completamento. Devi fornire al tuo contenitore un'attività che non finirà mai. Qualcosa di simile dovrebbe funzionare:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
spec:
  containers:
  - name: ubuntu
    image: ubuntu:latest
    # Just spin & wait forever
    command: [ "/bin/bash", "-c", "--" ]
    args: [ "while true; do sleep 30; done;" ]

Ma è questa una best practice?
aneesh joshi

3
@aneeshjoshi Non direi che questa è la migliore pratica . Questo è solo un esempio che fornisce un pod che verrà eseguito senza uscire immediatamente. La migliore pratica è creare i contenitori per svolgere il lavoro per cui sono stati progettati (un lavoro che viene eseguito fino al completamento, un server Web che viene eseguito continuamente, ecc.). Ho pubblicato questo come esempio perché Kubernetes può sembrare inizialmente frustrante quando continui a creare pod solo per vederli sparire poiché il comando predefinito esce immediatamente.
Joel B

@ JoelB Thanks. Mi chiedevo qual è il modo "giusto" di farlo.
aneesh joshi

1
grazie di questo perché ho bisogno di un contenitore che possa vivere per un po 'permettendomi di entrarci. Stavo cercando di fare lo stesso con un'immagine più chiara ubuntue bashho provato un'immagine, ma non sono riuscito a farlo funzionare. Qualche idea su come fare lo stesso con l' bashimmagine?
cryanbhu

1
@cryanbhu Per un'immagine più chiara, puoi usare alpine, la specifica del contenitore può assomigliare a: {"name": "util", "image": "alpine", "command": [ "/bin/sh", "-c", "--" ], "args": [ "while true; do sleep 30; done;" ]}(solo json perché lo yaml non verrà formattato nei commenti qui.) La parte importante è /bin/shinvece di /bin/bash.
bschlueter

111

Puoi usare questo CMD nel tuo Dockerfile:

CMD exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"

Ciò manterrà in vita il tuo contenitore finché non gli verrà detto di fermarsi. L'utilizzo di trap e wait farà reagire immediatamente il tuo container a una richiesta di stop . Senza trap / attesa, l'arresto richiederà alcuni secondi.

Per le immagini basate su busybox (utilizzate nelle immagini basate su alpine) sleep non conosce l'argomento infinity. Questa soluzione alternativa offre la stessa risposta immediata a un docker stopsimile nell'esempio precedente:

CMD exec /bin/sh -c "trap : TERM INT; (while true; do sleep 1000; done) & wait"

Sto usando lo stesso su yaml di distribuzione kubernetes per scopi di debug
sdkks

questo mi dà "sleep: invalid number 'infinity'"
arunkjn

@arunkjn Grazie per questo. Probabilmente sei bloccato con un'immagine che utilizza busybox (come le immagini alpine). Vedi la risposta aggiornata.
itsafire

24
  1. Nel tuo Dockerfile usa questo comando:

    CMD ["sh", "-c", "tail -f /dev/null"]
    
  2. Costruisci la tua immagine docker.

  3. Inseriscilo nel tuo cluster o simile, solo per assicurarti che l'immagine sia disponibile.
  4. kubectl run debug-container -it --image=<your-image>
    

Ottimi suggerimenti per il debug del contenitore.
kta

16

Per mantenere un POD in esecuzione, il POD deve eseguire determinate attività, altrimenti Kubernetes lo troverà non necessario, quindi esce. Ci sono molti modi per mantenere in esecuzione un POD.

Ho affrontato problemi simili quando avevo bisogno di un POD solo per funzionare continuamente senza fare nulla. I seguenti sono i due modi in cui hanno funzionato per me:

  1. Attivazione di un comando di sospensione durante l'esecuzione del contenitore.
  2. Esecuzione di un ciclo infinito all'interno del contenitore.

Sebbene la prima opzione sia più semplice della seconda e possa bastare al requisito, non è l'opzione migliore. C'è un limite al numero di secondi che assegnerai al comando sleep. Ma un contenitore con un ciclo infinito in esecuzione al suo interno non esce mai.

Tuttavia, descriverò entrambi i modi (considerando che stai eseguendo il contenitore busybox):

1. Comando del sonno

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  containers:
  - name: busybox
    image: busybox
    ports:
    - containerPort: 80
    command: ["/bin/sh", "-ec", "sleep 1000"]
  nodeSelector:
    beta.kubernetes.io/os: linux

2. Ciclo infinito

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  containers:
  - name: busybox
    image: busybox
    ports:
    - containerPort: 80
    command: ["/bin/sh", "-ec", "while :; do echo '.'; sleep 5 ; done"]
  nodeSelector:
    beta.kubernetes.io/os: linux

Esegui il seguente comando per eseguire il pod:

kubectl apply -f <pod-yaml-file-name>.yaml

Spero che sia d'aiuto!


Posso chiedere, cos'è il sonno? È un comando interno a Ubuntu? O il comando docker?
Faraz

@Faraz È un comando della shell di Linux, non è specifico per docker.
Arbaaz,

11

Sono stato in grado di farlo funzionare con il comando sleep infinityin Kubernetes, che manterrà aperto il contenitore. Vedi questa risposta per le alternative quando non funziona.


Questo non fornisce una risposta alla domanda. Per criticare o richiedere chiarimenti a un autore, lascia un commento sotto il suo post. - Dalla recensione
Sarà il

1
@ Will Sure it does. sleep infinitymantiene il contenitore aperto, fornendo lo stesso tipo di funzionalità richiesto dalla domanda (per la maggior parte dei tipi di contenitori). Fornisce anche un collegamento alle alternative per i casi in cui quel comando specifico non funziona
rwilson04

Questo era dalla recensione. Se aggiungi il testo del commento lì alla risposta, allora è una risposta di qualità :) La mia bandiera / elogio iniziale si basava sul dire che il tuo commento non ha avuto successo, facendomi pensare che doveva essere un commento. Aggiunta una modifica rapida e voto positivo.
Il

"... sleep infinity in Kubernetes" è un'affermazione disinformata. Implica che non ci siano unix e nessuna finestra mobile nell'immagine.
mmla

10

Il comando più semplice che può essere per k8s pod manifest per eseguire container per sempre:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
spec:
  containers:
  - name: ubuntu
    image: ubuntu:latest
    # Just sleep forever
    command: [ "sleep" ]
    args: [ "infinity" ]

5

Usa questo comando all'interno del tuo Dockerfile per mantenere il container in esecuzione nel tuo cluster K8s:

  • Coda CMD -f / dev / null

3

Nel mio caso, un pod con un initContainer non è riuscito a inizializzare. In esecuzione docker ps -ae poi docker logs exited-container-id-heremi ha dato un messaggio di registro che kubectl logs podnamenon è stato visualizzato. Mistero risolto :-)


1

Ci sono molti modi diversi per farlo, ma uno dei più eleganti è:

kubectl run -i --tty --image ubuntu:latest ubuntu-test --restart=Never --rm /bin/sh

Perché la consideri la soluzione più elegante?
mordowiciel

1

I miei pochi centesimi sull'argomento. Supponendo che funzioni, kubectlil comando più vicino che sarebbe equivalente al comando docker che hai menzionato nella tua domanda, sarebbe qualcosa del genere.

$ kubectl run ubuntu --image=ubuntu --restart=Never --command sleep infinity

Il comando sopra creerà un singolo Podnello defaultspazio dei nomi e eseguirà il sleepcomando con infinityargomento-in questo modo avrai un processo che viene eseguito in primo piano mantenendo il contenitore in vita.

Successivamente, puoi interagire con Podeseguendo kubectl execcommand.

$ kubectl exec ubuntu -it -- bash

Questa tecnica è molto utile per creare una risorsa Pod e il debug ad-hoc.


1
Funziona alla grande. Non c'è bisogno del --restart=Never, basta chiamarekubectl run ubuntu --image=ubuntu -- sleep infinity
Noam Manos
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.