在Pod内重启容器

203

我有一个名为 test-1495806908-xn5jn 的Pod,其中包含2个容器。 我想重新启动其中一个名为 container-test 的容器。 是否可以重新启动Pod中的单个容器? 如果不行,那么如何重新启动Pod?

该Pod是使用deployment.yaml创建的:

kubectl create -f deployment.yaml
16个回答

209

如何重新启动一个单独的容器?

不能通过kubectl进行操作,但是根据你的集群设置,你可以“作弊”并执行docker kill the-sha-goes-here,这将导致Kubelet重新启动“失败”的容器(当然,Pod的重启策略也必须是这样做的)。

如何重新启动Pod?

这取决于Pod的创建方式,但根据您提供的Pod名称,似乎它处于ReplicaSet的监管之下,所以您只需要执行kubectl delete pod test-1495806908-xn5jn,Kubernetes将会在原位置创建一个新的Pod (新的Pod将具有不同的名称,因此请不要期望kubectl get pods再次返回test-1495806908-xn5jn)。


13
默认的重启策略是始终重启。 - Hem
2
如果我可以执行这个命令:docker kill the-sha-goes-here,那么为什么不执行 docker container restart the-sha-goes-here 呢?为什么要依赖 kubelet 来重启容器呢?无论如何,真正的问题是在哪里运行 docker 命令,即使是杀死容器。在 could-shell 上,docker 并不显示来自 k8s 集群的容器! - Nawaz
一个好的建议是在你的运行容器中将 POD_NAME 设为环境变量。这样,当你需要添加一些逻辑来重新启动 pod/container 时,你可以通过使用定义的环境变量 $POD_NAME 来轻松地引用它。 - Paul Chibulcuteanu
1
我觉得这需要一个最新的答案(我目前无法提供)。Docker将不再是k8s支持的计算引擎。也许有一个crictl命令或更完整的指令来调整角色绑定并使用kubectl删除/重新应用pod或特定容器。 - Lon Kaut
正确的答案是将容器移动到它自己的 Pod 中。 - MikeKulls
除了使用 docker kill 命令之外,直接在主机上终止容器的主进程或在容器内部使用 kill 1 命令(如果它不是 distroless 镜像,则使用临时容器)如何? - SOFe

112

有时候你想要重启一个特定的容器而不是删除Pod并让Kubernetes重新创建它。

对我而言,执行 kubectl exec POD_NAME -c CONTAINER_NAME /sbin/killall5 命令有效。

(根据以下建议,我将命令从 reboot 更改为 /sbin/killall5。)


33
并非每个容器都有 reboot 命令;我更倾向于执行 /sbin/killall5 命令,该命令会终止所有进程并退出容器。 - Ingo Karkat
1
并非每个容器都有root用户 ;) - JuliSmz
6
-1,因为...您正在利用“重新启动”命令杀死所有进程以及Kubernetes对其的恢复副作用。这会做出许多假设:以root身份运行、容器中可用二进制文件、启用了restartPolicy等等。此外,这会使有关进程失败的日志变得混乱,这并不理想。 - gertvdijk
9
看起来Alpine系统中没有killall命令,但是/sbin/reboot命令非常有效。kubectl exec POD_NAME -c CONTAINER_NAME /sbin/reboot非常顺利地运行。 - Atif
@Atif,我能否在执行“重启”后防止容器内丢失我的更改?例如,我安装了vim,但在调用重启后找不到vim(如果未持久化,则对于任何文件更改都是如此)。 - Mohammed Noureldin
重启会丢失更改吗?我认为只有在 k8s 杀死并重新生成 POD 时才会保留更改。如果您需要调试工具,我认为还有一个技巧可以附加一个调试容器。您可能想要搜索一下如何操作。我自己没有尝试过。 - Atif

97

Pod和容器都是短暂的,尝试使用以下命令停止特定的容器,k8s集群将重新启动一个新的容器。

kubectl exec -it [POD_NAME] -c [CONTAINER_NAME] -- /bin/sh -c "kill 1"

这将向容器中运行的主进程1发送SIGTERM信号。所有其他进程将是进程1的子进程,并在进程1退出后终止。请参阅kill manpage了解其他可以发送的信号。


10
我尝试了其他答案,但只有这个有效,我认为这是最通用的。 - Batato
1
当我尝试这个操作时,我的Alpine容器进入了某种不健康的状态。kubectl get po显示该Pod的状态列中出现错误。 - Atif
尝试了其他建议的命令后,终于成功了。谢谢。 - Jaydeep Soni
我感到沮丧,为什么其他人说这是不可能的,而实际上是可以做到的。 它完美地运行了。谢谢! - wajdi_jurry
这对我来说是最好的选择。唯一的问题是我需要更改容器运行方式,从进程入口点运行,以便进程能够接收到信号。 - lior.i
显示剩余4条评论

28

我正在使用

kubectl rollout restart deployment [deployment_name]
或者
kubectl delete pod [pod_name]


1
kubectl 回滚 重启 deployment -n [命名空间] [deployment_name] - walker
kubectl 删除 POD_NAME 的 Pod - Kasthuri Shravankumar

25

Kubernetes最主要的作用就是为您管理容器,这样您就不必太关心Pod中容器的生命周期。

由于您已经设置了使用副本集的部署,因此可以使用kubectl delete pod test-1495806908-xn5jn删除Pod,Kubernetes将管理创建带有2个容器的新Pod而无需停机时间。手动重新启动Pod中单个容器会抵消Kubernetes的所有好处。


5
我的终止 Pod 进程变为 0/1,导致系统停机。 - Dean Christian Armada
12
请注意不要轻易使用“没有任何停机时间”的说法,这取决于您的具体配置。此外,无停机时间本身也存在挑战。 - Nicolas
6
每当我删除只有一个副本的部署中的一个 pod 时,我总会遇到停机时间。 - Nyein Chan Wynn
只要是你的开发环境,就很安全 :D - Jalal

16

以上所有答案都提到了删除Pod...但如果您有许多相同服务的Pod,则删除每个Pod将非常繁琐...

因此,我提出以下解决方案:重启

  • 1)将规模设置为零:

     kubectl scale deployment <<name>> --replicas=0 -n service 
    

    以上命令将终止所有名称为<<name>>的Pod

  • 2) 要重新启动Pod,请将副本数设置为大于0

  • kubectl scale deployment <<name>> --replicas=2 -n service
    

    上述命令将使用2个副本重新启动您的Pod。


12
如何在一个pod中重启单个容器? - Chris Beach
此外,对于高可用应用程序来说,缩小到 0 个 pod 是行不通的。请改用 kubectl patch deployment <deployment name> -p "{\"spec\": {\"template\": {\"metadata\": { \"labels\": { \"redeploy\": \"$(date +%s)\"}}}}}" 命令。这将更新部署并根据滚动更新策略重新创建所有由其管理的 pod。 - Kostrahb

5
我们使用一个非常方便的命令行来强制重新部署集成 pod 上的新镜像。
我们注意到我们的 alpine 容器都在 PID 5 上运行它们的 "sustaining" 命令。因此,向其发送 SIGTERM 信号会关闭容器。将 imagePullPolicy 设置为 Always 会在 kubelet 将容器重新启动时重新拉取最新的镜像。
kubectl exec -i [pod name] -c [container-name] -- kill -15 5

1
-15和5代表什么? - John Balvin Arias
4
在上面的描述中已经提到了,kill -15 5命令是将信号“-15”发送给进程ID为5的进程。这就告诉进程您希望终止它(SIGTERM),并且让它有时间清理任何打开的资源(临时文件、回滚数据库事务、关闭连接等)。与-9(SIGKILL)相比,后者会立即杀掉进程,不允许它清理已经打开的资源。 - Conrad.Dean

4
kubectl exec -it POD_NAME -c CONTAINER_NAME bash - then kill 1

假设容器以root身份运行,这是不建议的。

在我的情况下,当我更改应用程序配置时,我必须重新启动容器,该容器被用作旁路模式,在此过程中,我将终止由docker用户拥有的spring boot应用程序的PID。


1
如果你写 kubectl exec -it ${POD_NAME?} -c ${CONTAINER_NAME?} bash ...,那么人们复制/粘贴起来就容易多了。 - William Pursell
Docker 不允许你执行 kill -9 PID 1 操作。 - Tigraine

3

coredns pod中出现了问题,我通过删除该pod来解决问题。

kubectl delete pod -n=kube-system coredns-fb8b8dccf-8ggcf

它的Pod将会自动重启。


2

我知道这个问题早已有答案,但是我想分享一下我的方法。

每当我想要进行这个操作时,我只需轻微更改Pod容器中的镜像字段,这会导致Kubernetes重新启动该容器。

如果您无法在2个不同但等效的标签之间切换(例如:latest/:1.2.3,其中latest实际上是版本1.2.3),那么您可以将它快速切换到一个无效的标签(例如我在末尾放置了一个X,如:latestX),然后立即重新编辑并删除X,这确实会导致容器在几秒钟内无法成功启动,因为出现了镜像拉取错误。

所以举个例子:

kubectl edit po my-pod-name

找到想要终止的spec.containers[].name,然后找到它的image

apiVersion: v1
kind: Pod
metadata:
  #...
spec:
  containers:
  - name: main-container
    #...
  - name: container-to-restart
    image: container/image:tag
#...

您需要搜索要重新启动的容器,然后将其镜像更新为不同的内容,这将强制Kubernetes为您执行受控重启。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接