如何在Kubernetes上保持容器运行?


124

我现在正在尝试在Kubernetes集群上运行带有shell(/ bin / bash)的简单容器。

我以为有一种方法可以通过使用pseudo-ttyand detach选项(命令上的-td选项docker run)来保持容器在Docker容器上运行。

例如,

$ sudo docker run -td ubuntu:latest

Kubernetes中有这样的选择吗?

我试过使用kubectl run-container类似以下的命令来运行容器:

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

但是容器会退出几秒钟(就像使用docker run上面没有提到的选项的命令启动一样)。然后ReplicationController反复再次启动它。

有没有办法像命令中的-td选项那样保持容器在Kubernetes上运行docker run


使用此图像(如Kubernetes文档所建议的)非常方便:kubectl run curl --image=radial/busyboxplus:curl -i --tty
Matheus Santana

这个问题已经在这个视频被提到:Kubernetes在Datadog非常艰难地用幻灯片标题“货物culting维基百科:术语货物邪教程序员可以申请当不熟练还是新手的计算机程序员(或者一个没有经验的问题)将一些程序代码从一个地方复制到另一个地方,而对它的工作原理或是否需要在新位置上
一无所知

Answers:


49

容器在其主进程退出时退出。做类似的事情:

docker run -itd debian

坦率地说,将容器保持打开状态是一种hack,只能用于快速测试和示例。如果您只想要一个容器进行几分钟的测试,我会这样做:

docker run -d debian sleep 300

这样做的好处是,如果您忘记了它,容器将自动退出。另外,您可以将类似这样的内容放入while循环中以使其永久运行,或者只运行诸如之类的应用程序top。所有这些都应该在Kubernetes中很容易做到。

真正的问题是您为什么要这样做?您的容器应提供服务,其过程将使容器在后台运行。


谢谢您的回答。我现在试图了解容器的行为,同时运行数十个容器。无休止的循环和使用其他繁重的命令,使我无法知道容器的行为。这就是为什么我需要简单的容器(例如仅运行/ bin / bash)的原因。
springwell

现在,我将尝试在cat不带参数topsleep带大参数的情况下运行。
springwell

30
sleep infinity在很多情况下都可以工作(不是busybox)
rwilson04

1
这样做的理由很多。例如,您可能会使用掌舵版本和注入配置来部署您的Pod,这将使重新创建类似环境变得烦人且麻烦。但是在其他吊舱崩溃/被删除的情况下拥有具有这种配置的容器可能会无限有用。
理查德·洛维耶特(RichardLøvehjerte)

因为我的服务包含多个流程。
КонстантинВан

133

容器应运而生。您需要为您的容器提供永远无法完成的任务。这样的事情应该起作用:

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

但这是最佳做法吗?
aneesh joshi

3
@aneeshjoshi我不会说这是最佳实践。这只是提供无需运行即可运行的pod的示例。最佳实践是创建容器以完成其设计的工作(运行至完成的工作,永久运行的网络服务器等)。我以这个示例为例,因为当您继续创建Pod时,Kubernetes最初会感到沮丧,因为默认命令会立即退出,从而使Pod消失。
Joel B

@JoelB谢谢。我想知道这样做的“正确”方法是什么。
aneesh joshi

1
谢谢你,因为我需要一个可以生存一段时间并允许我进入的容器。我试图用比ubuntu试过的bash图像更浅的图像来做同样的事情,但是无法正常工作。知道如何使用bash图像执行此操作吗?
cryanbhu

我知道这是一个老问题;但是,Kubernetes开始支持临时容器。链接:kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers。这些容器有一些限制,例如资源限制,但是它们是为调试目的而设计的。
Shubham Singh

111

您可以在以下位置使用此CMD Dockerfile

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

这将使您的容器保持活动状态,直到被告知停止为止。使用trap and wait将使您的容器立即对停止请求作出反应。没有陷阱/等待停止将花费几秒钟。

对于基于busybox的图像(用于基于高山的图像),睡眠不知道无穷大参数。此解决方法可为您提供与上述示例中相同的立即响应docker stop

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

我正在kubernetes部署yaml上使用相同的内容进行调试
sdkks

这使我“睡眠:无效数字'infinity'”
arunkjn

@arunkjn谢谢你。您可能会陷入使用busybox的图像(如高山图像)的困境。查看更新后的答案。
itsafire

24
  1. 在您的Dockerfile中,使用以下命令:

    CMD ["sh", "-c", "tail -f /dev/null"]
    
  2. 构建您的docker映像。

  3. 将其推送到您的群集或类似的群集中,只是为了确保它可用。
  4. kubectl run debug-container -it --image=<your-image>
    

调试容器的重要技巧。
kta

16

为了使POD保持运行,POD应该执行某些任务,否则Kubernetes会发现它是不必要的,因此退出。有很多方法可以使POD保持运行。

当我需要一个POD来连续运行而不做任何事情时,我也遇到了类似的问题。以下是为我工作的两种方式:

  1. 在运行容器时发出睡眠命令。
  2. 在容器内运行无限循环。

尽管第一种选择比第二种选择更容易并且可以满足要求,但这不是最佳选择。另外,在睡眠命令中要分配的秒数有一个限制。但是,在其中运行无限循环的容器永远不会退出。

但是,我将描述两种方式(考虑您正在运行busybox容器):

1.睡眠命令

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.无限循环

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

运行以下命令以运行Pod:

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

希望能帮助到你!


请问什么是睡眠?这是Ubuntu内部的命令吗?还是docker命令?
法拉兹

@Faraz这是一个Linux shell命令,并非特定于docker。
Arbaaz

11

我能够sleep infinity使它与Kubernetes中的命令一起使用,它将使容器保持打开状态。如果不可行,请参阅此答案以找到替代方案。


这不能为问题提供答案。要批评或要求作者澄清,请在其帖子下方发表评论。- 评论
将于

1
@肯定会的。sleep infinity保持容器打开,提供问题所要求的相同类型的功能(对于大多数类型的容器)。它还为特定命令不起作用的情况提供了替代方法的链接
rwilson04 '02

这是从审查。如果您在评论中添加评论文本,那么这是一个高质量的答案:)我最初的口号/赞扬是基于您的评论不成功,让我认为这应该是评论。添加了快速编辑并进行了投票。
2016年

“ ... Kubernetes中的睡眠无限”是一个不明智的声明。这意味着图片中没有Unix,也没有docker。
mmla

10

最简单的命令,因为它可以让k8s pod清单永久运行容器:

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


3

在我的情况下,具有initContainer的容器无法初始化。运行docker ps -a,然后docker logs exited-container-id-here给了我一条kubectl logs podname未显示的日志消息。谜团已揭开 :-)


1

有许多不同的方法可以完成此操作,但是最优雅的方法之一是:

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

您为什么认为它是最优雅的解决方案?
mordowiciel

0

我在这个问题上的几分钱。假设该kubectl命令正在运行,则与您在问题中提到的docker命令等效的最接近的命令将是这样的。

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

上面的命令将Poddefault名称空间中创建一个,并执行sleep带有infinity参数的命令-这样,您将拥有一个在前景中运行的进程,使容器保持活动状态。

后记,您可以Pod通过运行kubectl exec命令进行交互。

$ kubectl exec ubuntu -it -- bash

此技术对于创建Pod资源和临时调试非常有用。


1
效果很好。无需--restart=Never致电,只需致电kubectl run ubuntu --image=ubuntu -- sleep infinity
Noam Manos
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.