测试的同学使用我们的k8s集群部署脚本,部署完成后发现一个pod的状态是"CreateContainerError",而且一直卡在这个状态,pod也不进行重启。kubectl describe pod,显示错误信息大意是pod创建的容器与已存在的容器重名。查看kubelet log,也有相似的内容如下

E0924 09:07:24.225646   30207 remote_runtime.go:200] CreateContainer in sandbox "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" from runtime service failed: rpc error: code = Unknown desc = Error response from daemon: Conflict. The name "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" is already in use by container xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. You have to remove (or rename) that container to be able to reuse that name.
E0924 09:07:24.225740   30207 kuberuntime_manager.go:779] container start failed: CreateContainerError: Error response from daemon: Conflict. The name "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" is already in use by container xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. You have to remove (or rename) that container to be able to reuse that name.
E0924 09:07:24.225772   30207 pod_workers.go:190] Error syncing pod xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)"), skipping: failed to "StartContainer" for "composer" with CreateContainerError: "Error response from daemon: Conflict. The name "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" is already in use by container xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. You have to remove (or rename) that container to be able to reuse that name."

https://github.com/kubernetes/kubernetes/issues/83050

分析

在github上找到了类似的问题描述。出现这种错误,主要原因是系统时间同步导致的。
假设某一个pod A启动时,创建了container A,此时container A的名字为xxx_0, createdAt 创建时间假设为8:00:05。
当containerA创建完成后。系统发现时间不一致,做了一次时间同步,将此时的时间调整为8:00:00。同时,pod A由于某种原因,出现错误,kubelet杀死containerA。并创建了containerB,containerB 启动名字为xxx_1,但是由于系统做了时间同步。containerB的createAt创建时间为8:00:01,也就是说,虽然containerB是新创建的,但是他的创建时间比containerA还要早。kubelet有定时同步容器状态的逻辑,他会去查询pod下管理的container,当pod下面有多个container时,kubelet根据时间排序找出createAt时间最新的container。根据这个处理逻辑,对于podA,kubelet每次都会拿到containerA,因为containerA的创建时间时靠后的。kubelet会发现containerA状态已经退出了,所以就会新建一个container,containerA的名字时xxx_0,所以新创建的container名字应该顺序加1,为xxx_1。但是这个名字已经被containerB占用了,所以kubelet会报名字重复的错误。并且由于kubelet每次同步都拿不到containerB。他就会block在这里,如果不手动介入的话pod用于无法启动。手动介入的解决办法也很简单,就是删掉pod。让其重新调度。或者通过docker命令删掉containerA。这样kubelet就可以获取到containerb的信息了。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐