Comment puis-je maintenir un conteneur en cours d'exécution sur Kubernetes?

124

J'essaie maintenant d'exécuter un simple conteneur avec shell (/ bin / bash) sur un cluster Kubernetes.

Je pensais qu'il y avait un moyen de garder un conteneur en cours d'exécution sur un conteneur Docker en utilisant l' pseudo-ttyoption and detach ( -tdoption sur docker runcommande).

Par exemple,

$ sudo docker run -td ubuntu:latest

Existe-t-il une option comme celle-ci dans Kubernetes?

J'ai essayé d'exécuter un conteneur en utilisant une kubectl run-containercommande comme:

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

Mais le conteneur quitte pendant quelques secondes (tout comme le lancement avec la docker runcommande sans options que j'ai mentionnées ci-dessus). Et ReplicationController le relance à plusieurs reprises.

Existe-t-il un moyen de maintenir un conteneur en cours d'exécution sur Kubernetes comme les -tdoptions de la docker runcommande?

Springwell
la source
Utiliser cette image (comme le suggère la documentation de Kubernetes ) est assez pratique:kubectl run curl --image=radial/busyboxplus:curl -i --tty
Matheus Santana
Cette question a été mentionnée dans cette vidéo: Kubernetes à la dure chez Datadog avec un titre de diapositive de "Cargo culting . De wikipedia: Le terme programmeur de culte du fret peut s'appliquer lorsqu'un programmeur informatique non qualifié ou novice (ou inexpérimenté avec le problème à portée de main) copie du code de programme d'un endroit à un autre avec peu ou pas de compréhension de son fonctionnement ou s'il est nécessaire dans sa nouvelle position.
tgogos

Réponses:

49

Un conteneur sort lorsque son processus principal se termine. Faire quelque chose comme:

docker run -itd debian

tenir le conteneur ouvert est franchement un hack qui ne devrait être utilisé que pour des tests rapides et des exemples. Si vous voulez juste un conteneur pour tester pendant quelques minutes, je ferais:

docker run -d debian sleep 300

Ce qui présente l'avantage que le conteneur se fermera automatiquement si vous l'oubliez. Alternativement, vous pouvez mettre quelque chose comme ça dans une whileboucle pour le faire fonctionner indéfiniment, ou simplement exécuter une application telle que top. Tout cela devrait être facile à faire dans Kubernetes.

La vraie question est pourquoi voudriez-vous faire cela? Votre conteneur doit fournir un service dont le processus maintiendra le conteneur en arrière-plan.

Adrian Mouat
la source
Merci pour votre réponse. J'essaie maintenant de comprendre le comportement des conteneurs, avec des dizaines de conteneurs fonctionnant en même temps. Boucle sans fin et utilisation d'autres commandes lourdes, m'empêchent de savoir quel est le comportement des conteneurs. C'est la raison pour laquelle j'ai besoin d'un conteneur simple comme uniquement exécuter / bin / bash.
springwell
Pour l'instant, je vais essayer de courir catsans arguments et topet sleepavec un argument de grand nombre.
springwell
30
sleep infinityfonctionne dans de nombreux cas (pas occupé)
rwilson04
1
Il y a de nombreuses raisons de le faire. Par exemple, vous pouvez déployer vos pods avec des versions de barre et une configuration injectée, ce qui rendra la recréation d'environnements similaires ennuyeuse et encombrante. Mais avoir un conteneur avec cette configuration dans les cas où les autres pods plantent / sont supprimés peut être infiniment utile.
Richard Løvehjerte
Parce que mon service se compose de plusieurs processus.
Константин Ван
135

Les conteneurs sont censés fonctionner jusqu'à la fin. Vous devez fournir à votre conteneur une tâche qui ne se terminera jamais. Quelque chose comme ça devrait fonctionner:

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;" ]
Joël B
la source
Mais est-ce une bonne pratique?
aneesh joshi
3
@aneeshjoshi Je ne dirais pas que c'est la meilleure pratique . Ceci est juste un exemple fournissant un pod qui fonctionnera sans quitter immédiatement. La meilleure pratique consiste à créer vos conteneurs pour faire le travail pour lequel ils ont été conçus (un travail qui s'exécute jusqu'à son terme, un serveur Web qui s'exécute en permanence, etc.). J'ai posté ceci à titre d'exemple car Kubernetes peut se sentir initialement frustrant lorsque vous continuez à créer des pods pour les faire disparaître car la commande par défaut se termine immédiatement.
Joel B
@JoelB Merci. Je me demandais quelle est la «bonne» façon de procéder.
aneesh joshi
1
merci pour cela car j'ai besoin d'un conteneur qui peut vivre pendant un certain temps me permettant d'y entrer. J'essayais de faire la même chose avec une image plus claire ubuntuet j'ai essayé une bashimage mais je n'ai pas pu la faire fonctionner. Une idée comment faire la même chose avec l' bashimage?
cryanbhu
1
@cryanbhu Pour une image plus claire, vous pouvez utiliser alpine, la spécification du conteneur peut ressembler à: {"name": "util", "image": "alpine", "command": [ "/bin/sh", "-c", "--" ], "args": [ "while true; do sleep 30; done;" ]}(uniquement json car le yaml ne sera pas formaté dans les commentaires ici.) L'important étant à la /bin/shplace de /bin/bash.
bschlueter le
111

Vous pouvez utiliser ce CMD dans votre Dockerfile:

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

Cela gardera votre conteneur en vie jusqu'à ce qu'on lui dise d'arrêter. L'utilisation de piège et d'attente fera réagir votre conteneur immédiatement à une demande d'arrêt . Sans interruption / attente, l'arrêt prendra quelques secondes.

Pour les images basées sur busybox (utilisées dans les images alpines), sleep ne connaît pas l'argument infini. Cette solution de contournement vous donne la même réponse immédiate à un docker stopcomme dans l'exemple ci-dessus:

CMD exec /bin/sh -c "trap : TERM INT; (while true; do sleep 1000; done) & wait"
itsafire
la source
J'utilise la même chose sur le déploiement de kubernetes yaml à des fins de débogage
sdkks
cela me donne "sommeil: nombre invalide 'infini'"
arunkjn
@arunkjn Merci pour cela. Vous êtes probablement coincé avec une image qui utilise busybox (comme les images alpines). Voir la réponse mise à jour.
itsafire
24
  1. Dans votre Dockerfile, utilisez cette commande:

    CMD ["sh", "-c", "tail -f /dev/null"]
    
  2. Créez votre image docker.

  3. Poussez-le vers votre cluster ou similaire, juste pour vous assurer que l'image est disponible.
  4. kubectl run debug-container -it --image=<your-image>
    
Radu Gabriel
la source
Bons conseils pour déboguer le conteneur.
kta
16

Afin de garder un POD en cours d'exécution, le POD doit effectuer certaines tâches, sinon Kubernetes le trouvera inutile, donc il se ferme. Il existe de nombreuses façons de faire fonctionner un POD.

J'ai rencontré des problèmes similaires lorsque j'avais besoin d'un POD juste pour fonctionner en continu sans rien faire. Voici les deux façons dont cela a fonctionné pour moi:

  1. Lancement d'une commande de veille lors de l'exécution du conteneur.
  2. Exécution d'une boucle infinie à l'intérieur du conteneur.

Bien que la première option soit plus facile que la seconde et puisse suffire à l'exigence, ce n'est pas la meilleure option. En tant que, il existe une limite au nombre de secondes que vous allez attribuer dans la commande de veille. Mais un conteneur avec une boucle infinie à l'intérieur ne sort jamais.

Cependant, je décrirai les deux façons (étant donné que vous exécutez le conteneur busybox):

1. Commande Sleep

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. Boucle infinie

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

Exécutez la commande suivante pour exécuter le pod:

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

J'espère que ça aide!

Arbaaz
la source
Puis-je demander, qu'est-ce que le sommeil? Est-ce une commande interne à Ubuntu? Ou commande docker?
Faraz
@Faraz C'est une commande shell Linux, elle n'est pas spécifique à docker.
Arbaaz
11

J'ai pu faire fonctionner cela avec la commande sleep infinitydans Kubernetes, qui gardera le conteneur ouvert. Voir cette réponse pour des alternatives lorsque cela ne fonctionne pas.

rwilson04
la source
Cela ne répond pas à la question. Pour critiquer ou demander des éclaircissements à un auteur, laissez un commentaire sous sa publication. - De l'avis
Will
1
@ Sûr que oui. sleep infinitygarde le conteneur ouvert, en fournissant le même type de fonctionnalité que la question pose (pour la plupart des types de conteneurs). Il fournit également un lien vers des alternatives pour les cas où cette commande spécifique ne fonctionne pas
rwilson04
C'était de l'examen. Si vous ajoutez le texte du commentaire à la réponse, c'est une réponse de qualité :) Mon premier drapeau / recommandation était basé sur le fait que votre commentaire n'avait pas abouti, ce qui m'a fait penser que c'était censé être un commentaire. Ajout d'une modification rapide et vote positif.
Sera le
"... sleep infinity in Kubernetes" est une déclaration non informée. Cela implique qu'il n'y a pas d'Unix ni de docker dans l'image.
mmla
10

La commande la plus simple possible pour le manifeste du pod k8s d'exécuter le conteneur pour toujours:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
spec:
  containers:
  - name: ubuntu
    image: ubuntu:latest
    # Just sleep forever
    command: [ "sleep" ]
    args: [ "infinity" ]
Wlodek B.
la source
5

Utilisez cette commande dans votre Dockerfile pour maintenir le conteneur en cours d'exécution dans votre cluster K8s:

  • CMD queue -f / dev / null
Omar Khaled
la source
3

Dans mon cas, un pod avec un initContainer n'a pas pu s'initialiser. En cours d'exécution docker ps -a, puis docker logs exited-container-id-herem'a donné un message de journal qui kubectl logs podnamene s'affiche pas. Mystère résolu :-)

Stefan L
la source
1

Il existe de nombreuses façons d'accomplir cela, mais l'une des plus élégantes est:

kubectl run -i --tty --image ubuntu:latest ubuntu-test --restart=Never --rm /bin/sh
Ivan Aracki
la source
Pourquoi considérez-vous que c'est la solution la plus élégante?
mordowiciel le
1

Mes quelques centimes sur le sujet. En supposant que cela kubectlfonctionne, la commande la plus proche qui équivaudrait à la commande docker que vous avez mentionnée dans votre question serait quelque chose comme ça.

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

La commande ci-dessus créera un seul Poddans l' defaultespace de noms et, elle exécutera la sleepcommande avec l' infinityargument -de cette façon, vous aurez un processus qui s'exécute au premier plan en gardant le conteneur en vie.

Afterwords, vous pouvez interagir avec Poden exécutant la kubectl execcommande.

$ kubectl exec ubuntu -it -- bash

Cette technique est très utile pour créer une ressource Pod et un débogage ad hoc.

Lukasz Dynowski
la source
1
Fonctionne très bien. Pas besoin d' --restart=Neverappeler, il suffit d'appelerkubectl run ubuntu --image=ubuntu -- sleep infinity
Noam Manos