¿Cómo puedo mantener un contenedor funcionando en Kubernetes?


124

Ahora estoy tratando de ejecutar un contenedor simple con shell (/ bin / bash) en un clúster de Kubernetes.

Pensé que había una manera de mantener un contenedor ejecutándose en un contenedor Docker mediante el uso pseudo-ttyy la opción de desconexión ( -tdopción en el docker runcomando).

Por ejemplo,

$ sudo docker run -td ubuntu:latest

¿Hay una opción como esta en Kubernetes?

Intenté ejecutar un contenedor utilizando un kubectl run-containercomando como:

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

Pero el contenedor sale por unos segundos (al igual que se inicia con el docker runcomando sin las opciones que mencioné anteriormente). Y ReplicationController lo vuelve a lanzar repetidamente.

¿Hay alguna manera de mantener un contenedor ejecutándose en Kubernetes como las -tdopciones en el docker runcomando?


Usar esta imagen (como sugiere Kubernetes docs ) es bastante útil:kubectl run curl --image=radial/busyboxplus:curl -i --tty
Matheus Santana

Esta pregunta ha sido mencionada en este video: Kubernetes de la manera más difícil en Datadog con un título deslizante de "Cultivo de carga . De wikipedia: El término programador de culto de carga puede aplicarse cuando un programador informático no calificado o novato (o uno inexperto con el problema) a mano) copias algún código de programa de un lugar a otro con poca o ninguna comprensión de cómo funciona o si se requiere en su nueva posición.
tgogos

Respuestas:


49

Un contenedor sale cuando sale su proceso principal. Haciendo algo como:

docker run -itd debian

Francamente, mantener el contenedor abierto es un truco que solo debe usarse para pruebas y ejemplos rápidos. Si solo desea un contenedor para probar durante unos minutos, yo haría:

docker run -d debian sleep 300

Lo cual tiene la ventaja de que el contenedor saldrá automáticamente si lo olvida. Alternativamente, puede poner algo como esto en un whilebucle para mantenerlo funcionando para siempre, o simplemente ejecutar una aplicación como top. Todo esto debería ser fácil de hacer en Kubernetes.

La verdadera pregunta es ¿por qué querrías hacer esto? Su contenedor debe proporcionar un servicio, cuyo proceso mantendrá el contenedor ejecutándose en segundo plano.


Gracias por su respuesta. Ahora estoy tratando de entender el comportamiento de los contenedores, con docenas de contenedores ejecutándose al mismo tiempo. El bucle sin fin y el uso de otro comando pesado, me impiden saber cuál es el comportamiento de los contenedores. Esa es la razón por la que necesito un contenedor simple como solo ejecutar / bin / bash.
Springwell

Por ahora, intentaré ejecutar catsin argumentos topy sleepcon argumentos de gran número.
Springwell

30
sleep infinityfunciona en muchos casos (no busybox)
rwilson04

1
Hay muchas razones para hacer esto. Por ejemplo, puede implementar sus pods con lanzamientos de timones y configuración inyectada, lo que hará que la recreación de entornos similares sea molesta y engorrosa. Pero tener un contenedor con esa configuración en los casos en que los otros pods se bloquean / se eliminan puede ser infinitamente útil.
Richard Løvehjerte

Porque mi servicio consta de múltiples procesos.
Константин Ван

135

Los contenedores están destinados a ejecutarse hasta su finalización. Debe proporcionar a su contenedor una tarea que nunca terminará. Algo como esto debería funcionar:

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;" ]

¿Pero es esta una mejor práctica?
aneesh joshi

3
@aneeshjoshi No diría que esta es la mejor práctica . Este es solo un ejemplo que proporciona un pod que se ejecutará sin salir inmediatamente. La mejor práctica es crear sus contenedores para hacer el trabajo para el que fueron diseñados (un trabajo que se ejecuta hasta su finalización, un servidor web que se ejecuta perpetuamente, etc.). Publiqué esto como un ejemplo porque Kubernetes puede sentirse inicialmente frustrante cuando sigue creando pods solo para que desaparezca, ya que el comando predeterminado se cierra de inmediato.
Joel B

@ JoelB Gracias. Me preguntaba cuál es la forma "correcta" de hacerlo.
aneesh joshi

1
gracias por esto, ya que necesito un contenedor que pueda vivir por un tiempo que me permita ingresar. ubuntuIntenté hacer lo mismo con una imagen más clara que la que probé bashpero no pude hacer que funcionara. ¿Alguna idea de cómo hacer lo mismo con la bashimagen?
cryanbhu

1
@cryanbhu Para una imagen más clara, puede usar alpine, la especificación del contenedor puede verse así: {"name": "util", "image": "alpine", "command": [ "/bin/sh", "-c", "--" ], "args": [ "while true; do sleep 30; done;" ]}(solo json porque el yaml no se formateará en los comentarios aquí). Lo importante es en /bin/shlugar de /bin/bash.
bschlueter

111

Puede usar esta CMD en su Dockerfile:

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

Esto mantendrá su contenedor con vida hasta que se le indique que se detenga. El uso de trap y wait hará que su contenedor reaccione de inmediato a una solicitud de detención . Sin trampa / espera, la detención demorará unos segundos.

Para las imágenes basadas en busybox (utilizadas en imágenes basadas en alpinos) sleep no conoce el argumento de infinito. Esta solución le da la misma respuesta inmediata a un me docker stopgusta en el ejemplo anterior:

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

Estoy usando lo mismo en kubernetes implementación yaml para fines de depuración
sdkks

esto me da "sueño: número inválido 'infinito'"
arunkjn

@arunkjn Gracias por esto. Probablemente esté atrapado con una imagen que utiliza busybox (como imágenes alpinas). Ver la respuesta actualizada.
itsafire

24
  1. En su Dockerfile, use este comando:

    CMD ["sh", "-c", "tail -f /dev/null"]
    
  2. Construye tu imagen acoplable.

  3. Empújalo a tu clúster o similar, solo para asegurarte de que la imagen esté disponible.
  4. kubectl run debug-container -it --image=<your-image>
    

Grandes consejos para depurar el contenedor.
kta

16

Para mantener un POD en ejecución, el POD debe realizar cierta tarea, de lo contrario, Kubernetes lo encontrará innecesario, por lo tanto, se cierra. Hay muchas formas de mantener un POD en funcionamiento.

Me he enfrentado a problemas similares cuando necesitaba un POD solo para funcionar continuamente sin hacer nada. Las siguientes son las dos formas en que funcionaron para mí:

  1. Activando un comando de suspensión mientras se ejecuta el contenedor.
  2. Ejecutando un bucle infinito dentro del contenedor.

Aunque la primera opción es más fácil que la segunda y puede satisfacer el requisito, no es la mejor opción. Como, hay un límite en cuanto a la cantidad de segundos que va a asignar en el comando de suspensión. Pero un contenedor con bucle infinito que se ejecuta dentro nunca sale.

Sin embargo, describiré ambas formas (teniendo en cuenta que está ejecutando el contenedor busybox):

1. Comando del sueño

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. bucle 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

Ejecute el siguiente comando para ejecutar el pod:

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

¡Espero eso ayude!


¿Puedo preguntar qué es dormir? ¿Es un comando interno de Ubuntu? O el comando docker?
Faraz

@Faraz Es un comando de shell de Linux, no es específico de Docker.
Arbaaz

11

Pude hacer que esto funcione con el comando sleep infinityen Kubernetes, que mantendrá el contenedor abierto. Vea esta respuesta para alternativas cuando eso no funciona.


Esto no proporciona una respuesta a la pregunta. Para criticar o solicitar una aclaración de un autor, deje un comentario debajo de su publicación. - De la crítica
Will

1
@ Seguro que sí. sleep infinitymantiene el contenedor abierto, proporcionando el mismo tipo de funcionalidad sobre la que se hace la pregunta (para la mayoría de los tipos de contenedores). También proporciona un enlace a alternativas para casos en que ese comando específico no funciona
rwilson04

Esto fue de revisión. Si agrega el texto del comentario a la respuesta, entonces es una respuesta de calidad :) Mi indicador / recomendación inicial se basó en decir que su comentario no fue exitoso, haciéndome pensar que se suponía que era un comentario. Se agregó una edición rápida y se votó.
Será

"... dormir infinito en Kubernetes" es una declaración desinformada. Implica que no hay unix ni docker en la imagen.
mmla

10

El comando más simple como puede ser que el manifiesto de pod k8s ejecute el contenedor para siempre:

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

5

Use este comando dentro de su Dockerfile para mantener el contenedor ejecutándose en su clúster K8:

  • CMD tail -f / dev / null

3

En mi caso, un pod con un initContainer no pudo inicializarse. Ejecutando docker ps -ay luego docker logs exited-container-id-hereme dio un mensaje de registro que kubectl logs podnameno se mostró. Misterio resuelto :-)


1

Hay muchas formas diferentes de lograr esto, pero una de las más elegantes es:

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

¿Por qué lo consideras la solución más elegante?
mordowiciel

0

Mis pocos centavos sobre el tema. Suponiendo que kubectlestá funcionando, el comando más cercano que sería equivalente al comando docker que mencionó en su pregunta sería algo como esto.

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

El comando anterior creará un solo Poden el defaultespacio de nombres y ejecutará el sleepcomando coninfinity argumento, de esta manera tendrá un proceso que se ejecuta en primer plano manteniendo vivo el contenedor.

Después de eso, puede interactuar Podejecutando el kubectl execcomando.

$ kubectl exec ubuntu -it -- bash

Esta técnica es muy útil para crear un recurso Pod y una depuración ad-hoc.


1
Funciona genial. No es necesario --restart=Never, solo llamekubectl run ubuntu --image=ubuntu -- sleep infinity
Noam Manos
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.