Como posso manter um contêiner em execução no Kubernetes?

124

Agora estou tentando executar um contêiner simples com shell (/ bin / bash) em um cluster Kubernetes.

Eu pensei que havia uma maneira de manter um contêiner em execução em um contêiner do Docker usando pseudo-ttye desanexando a opção ( -tdopção no docker runcomando).

Por exemplo,

$ sudo docker run -td ubuntu:latest

Existe uma opção como esta no Kubernetes?

Eu tentei executar um contêiner usando um kubectl run-containercomando como:

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

Mas o contêiner sai por alguns segundos (como iniciar com o docker runcomando sem as opções mencionadas acima). E o ReplicationController o lança novamente repetidamente.

Existe uma maneira de manter um contêiner em execução no Kubernetes como as -tdopções no docker runcomando?

Springwell
fonte
Usar esta imagem (como sugere a documentação do Kubernetes ) é bastante útil:kubectl run curl --image=radial/busyboxplus:curl -i --tty
Matheus Santana
Esta pergunta foi mencionada neste vídeo: Kubernetes da maneira mais difícil no Datadog, com o título de slide "Cultivo de carga . Da wikipedia: O termo programador de cult de carga pode ser aplicado quando um programador de computador não qualificado ou iniciante (ou um inexperiente com o problema na mão) cópias algum código de programa de um lugar para outro com pouca ou nenhuma compreensão de como ele funciona ou se é necessária a sua nova posição.
tgogos

Respostas:

49

Um contêiner sai quando seu processo principal termina. Fazendo algo como:

docker run -itd debian

manter o contêiner aberto é francamente um truque que deve ser usado apenas para testes e exemplos rápidos. Se você quiser apenas um contêiner para teste por alguns minutos, eu faria:

docker run -d debian sleep 300

O que tem a vantagem de o contêiner sair automaticamente se você o esquecer. Como alternativa, você pode colocar algo assim em um whileloop para mantê-lo em execução para sempre ou apenas executar um aplicativo como o top. Tudo isso deve ser fácil no Kubernetes.

A verdadeira questão é por que você quer fazer isso? Seu contêiner deve estar fornecendo um serviço, cujo processo manterá o contêiner em execução em segundo plano.

Adrian Mouat
fonte
Obrigado pela sua resposta. Agora estou tentando entender o comportamento dos contêineres, com dezenas de contêineres sendo executados ao mesmo tempo. Loop infinito e usando outro comando pesado, impedem-me de saber qual é o comportamento dos contêineres. Essa é a razão pela qual eu preciso de um contêiner simples como apenas running / bin / bash.
Springwell
Por enquanto, vou tentar correr catsem argumentos e tope sleepcom o argumento de grande número.
Springwell
30
sleep infinityfunciona em muitos casos (não busybox)
rwilson04
1
Existem muitas razões para fazer isso. Por exemplo, você pode implantar seus pods com liberações de leme e configuração injetada, o que tornará a recreação de ambientes semelhantes irritante e complicada. Mas ter um contêiner com essa configuração nos casos em que os outros pods travam / são excluídos pode ser infinitamente útil.
Richard Løvehjerte 26/11
Porque meu serviço consiste em vários processos.
Константин Ван
134

Os contêineres devem ser executados até a conclusão. Você precisa fornecer ao seu contêiner uma tarefa que nunca será concluída. Algo assim deve 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;" ]
Joel B
fonte
Mas essa é uma prática recomendada?
Aneesh Joshi
3
@aneeshjoshi Eu não diria que essa é uma prática recomendada . Este é apenas um exemplo que fornece um pod que será executado sem sair imediatamente. A melhor prática é criar seus contêineres para executar o trabalho para o qual foram projetados (um trabalho que é executado até a conclusão, um servidor da web que é executado perpetuamente etc.). Postei isso como um exemplo, porque o Kubernetes pode se sentir inicialmente frustrante quando você continua criando pods apenas para desaparecer, já que o comando padrão sai imediatamente.
Joel B
@JoelB Thanks. Eu queria saber qual é a maneira "certa" de fazê-lo.
precisa saber é o seguinte
1
obrigado por isso, pois estou precisando de um contêiner que possa viver por um tempo, permitindo que eu entre nele. Eu estava tentando fazer o mesmo com uma imagem mais clara do que ubuntue tentei a bashimagem, mas não consegui fazê-la funcionar. Alguma idéia de como fazer o mesmo com esta bashimagem?
Cryanbhu
Eu sei que esse é um problema antigo; no entanto, o Kubernetes é iniciado para suportar contêineres efêmeros. link: kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers . Esses contêineres têm algumas limitações, como limites de recursos, mas são projetados para fins de depuração.
Shubham Singh 26/03
111

Você pode usar esse CMD em Dockerfile:

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

Isso manterá seu recipiente vivo até que seja solicitado que ele pare. O uso de trap and wait fará com que seu contêiner reaja imediatamente a uma solicitação de parada . Sem parar a captura / espera, levará alguns segundos.

Para imagens baseadas em busybox (usadas em imagens alpinas), o sono não conhece o argumento infinito. Esta solução alternativa fornece a mesma resposta imediata a um docker stopexemplo no exemplo acima:

CMD exec /bin/sh -c "trap : TERM INT; (while true; do sleep 1000; done) & wait"
itsafire
fonte
Estou usando o mesmo em Kubernetes yaml implantação para fins de depuração
sdkks
isso me dá "sono: número inválido" infinito"
arunkjn
@arunkjn Obrigado por isso. Você provavelmente está preso a uma imagem que usa o busybox (como imagens alpinas). Veja a resposta atualizada.
Itsafire
24
  1. No seu Dockerfile, use este comando:

    CMD ["sh", "-c", "tail -f /dev/null"]
    
  2. Crie sua imagem do Docker.

  3. Empurre-o para o cluster ou similar, apenas para garantir que a imagem esteja disponível.
  4. kubectl run debug-container -it --image=<your-image>
    
Radu Gabriel
fonte
Ótimas dicas para depurar o contêiner.
kta
16

Para manter um POD em execução, o POD deve executar determinadas tarefas, caso contrário, o Kubernetes achará desnecessário e, portanto, será encerrado. Existem muitas maneiras de manter um POD em execução.

Eu enfrentei problemas semelhantes quando precisei de um POD apenas para executar continuamente sem fazer nada. A seguir, estão as duas maneiras pelas quais isso funcionou para mim:

  1. Ativando um comando de suspensão durante a execução do contêiner.
  2. Executando um loop infinito dentro do contêiner.

Embora a primeira opção seja mais fácil que a segunda e possa ser suficiente, não é a melhor opção. Como, há um limite até o número de segundos que você irá atribuir no comando de suspensão. Mas um contêiner com loop infinito rodando dentro dele nunca sai.

No entanto, descreverei as duas maneiras (considerando que você está executando o container busybox):

1. Comando de suspensã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. Loop 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

Execute o seguinte comando para executar o pod:

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

Espero que ajude!

Arbaaz
fonte
Posso perguntar, o que é sono? É um comando interno ao Ubuntu? Ou comando docker?
Faraz 30/03
@ Faraz É um comando linux shell, não é específico para o docker.
Arbaaz 30/03
11

Consegui fazer isso funcionar com o comando sleep infinityno Kubernetes, que manterá o contêiner aberto. Veja esta resposta para alternativas quando isso não funcionar.

rwilson04
fonte
Isso não fornece uma resposta para a pergunta. Para criticar ou solicitar esclarecimentos a um autor, deixe um comentário abaixo da postagem. - Da avaliação
Will
1
@Will Com certeza. sleep infinitymantém o contêiner aberto, fornecendo o mesmo tipo de funcionalidade que a pergunta faz (para a maioria dos tipos de contêineres). Ele também fornece um link para alternativas para casos em que o comando específico não trabalho
rwilson04
Isto foi da revisão. Se você adicionar o texto do comentário à resposta, será uma resposta de qualidade :) Meu sinalizador / recomendação inicial foi baseado em dizer que seu comentário não foi bem-sucedido, fazendo-me pensar que deveria ser um comentário. Adicionada uma edição rápida e votada.
Will
"... infinito sono em Kubernetes" é uma afirmação desinformada. Isso implica que não há unix nem docker na imagem.
mmla
10

O comando mais simples possível para o k8s pod manifest executar o contêiner para sempre:

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

Use este comando dentro do Dockerfile para manter o contêiner em execução no cluster do K8s:

  • Cauda CMD -f / dev / null
Omar Khaled
fonte
3

No meu caso, um pod com um initContainer falhou ao inicializar. Em execução docker ps -ae, em seguida, docker logs exited-container-id-hereme deu uma mensagem de log que kubectl logs podnamenão foi exibida. Mistério resolvido :-)

Stefan L
fonte
1

Existem muitas maneiras diferentes de conseguir isso, mas uma das mais elegantes é:

kubectl run -i --tty --image ubuntu:latest ubuntu-test --restart=Never --rm /bin/sh
Ivan Aracki
fonte
Por que você considera a solução mais elegante?
mordowiciel 27/04
0

Meus poucos centavos sobre o assunto. Supondo que kubectlesteja funcionando, o comando mais próximo que seria equivalente ao comando docker que você mencionou na sua pergunta seria algo parecido com isto.

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

O comando acima criará um único Podno defaultespaço para nome e executará o sleepcomando com o infinityargumento - dessa forma, você terá um processo que é executado em primeiro plano, mantendo o contêiner ativo.

Afterwords, você pode interagir Podexecutando o kubectl execcomando

$ kubectl exec ubuntu -it -- bash

Essa técnica é muito útil para criar um recurso de Pod e depuração ad-hoc.

Lukasz Dynowski
fonte
1
Funciona bem. Não há necessidade de --restart=Never, basta ligarkubectl run ubuntu --image=ubuntu -- sleep infinity
Noam Manos