如何解决如果我重新启动运行了某些Pod的节点会发生什么
假设Kubernetes节点上运行着Deployments / StatefulSet / DaemonSet等中的一些容器。
然后我直接重新启动节点,然后启动docker,使用相同的参数启动kubelet。
那些豆荚会发生什么?
- 是否使用从kubelet本地保存的元数据重新创建了它们?还是使用从api服务器检索到的信息?还是从OCI运行时恢复并表现为什么都没有发生?
- 是否只能正常恢复无状态的pod(无--local-data)?如果其中任何一个具有本地PV / dir,是否可以正常连接回去?
- 如果我很长时间没有重启节点怎么办? api服务器会分配其他节点来创建那些容器吗?默认超时值是多少?我该如何配置?
据我所知:
apiserver
^
|(sync)
V
kubelet
^
|(sync)
V
-------------
| CRI plugin |(like api)
| containerd |(like api-server)
| runc |(low-level binary which manages container)
| c' runtime |(container runtime where containers run)
-------------
当kubelet从kube-api-server接收到PodSpec时,它像远程服务一样调用CRI,步骤如下:
- 创建PodSandbox(又称“暂停”图像,始终“停止”)
- 创建容器
- 运行容器
因此,我猜测,当节点和泊坞窗重新启动时,步骤1和2已经完成,容器处于“已停止”状态;然后,在重新启动kubelet时,它从kube-api-server提取最新信息,发现容器未处于“运行”状态,因此它调用CRI运行容器,然后一切恢复正常。
请帮助我确认。
谢谢你〜
解决方法
好问题。首先是几件事; Pod未固定到某个节点。节点通常被视为Kubernetes可以用来运行其工作负载的“服务器场”。例如。您给Kubernetes设置了一组节点,还给了一组例如Deployment
-应在服务器上运行的应用程序的理想状态。 Kubernetes负责调度这些Pod,并在集群中的某些内容发生更改时保持它们运行。
独立Pod不受任何管理,因此,如果Pod崩溃,则无法恢复。您通常希望将无状态应用程序部署为Deployments
,然后启动ReplicaSets
来管理一组Pod,例如4个Pod-您的应用实例。
您想要的状态; Deployment
,例如replicas: 4
保存在Kubernetes控制平面内的 etcd 数据库中。
然后,Deployment
和ReplicaSet
的一组控制器负责使您的应用程序的4个副本保持活动状态。例如。如果某个节点变得不负责任(或死亡),则新的Pod将在其他节点上创建,如果它们由ReplicaSet
的控制器进行管理。
Kubelet接收到已调度到该节点的PodSpec,然后通过定期运行状况检查使这些Pod保持活动状态。
是否只能正常恢复无状态的pod(没有--local-data)?
应将Pod视为临时的-例如可以消失-但由管理它们的控制器恢复-除非部署为独立的Pod。因此,请勿在本地容器中存储本地数据。
还有StatefulSet
个Pod,它们用于有状态工作负载-但是分布式有状态工作负载,例如3个Pod,它们使用Raft复制数据。 etcd数据库是使用Raft的分布式数据库的一个示例。
正确答案:这取决于。
想象一下,您有3个节点集群,在其中创建了具有3个副本和3-5个独立pod的Deployment。
已创建Pod并将其调度到节点。
一切就绪并运行。
让我们假设工作节点node1
拥有1个部署副本和1个或更多独立Pod。
节点重新启动过程的一般顺序如下:
- 节点重新启动,例如。使用
sudo reboot
- 重新启动后,节点按
systemd
依赖关系指定的顺序启动所有OS进程 - 启动
dockerd
时不执行任何操作。此时,所有以前的容器都处于Exited
状态。 - 启动
kubelet
时,它会向集群apiserver
请求节点属性等于其节点名称的Pod列表。 - 从
apiserver
获得答复后,kubelet
使用Docker CRI启动apiserver
答复中所述的所有容器的容器。 - 为列表中的每个Pod启动
pause
容器时,它会获得由CNI二进制文件配置的新IP地址,该IP地址由网络插件Daemonset的Pod部署。 - 在节点上启动
kube-proxy
Pod之后,它会考虑到新Pod的IP地址,更新iptables规则以实现Kubernetes Services所需的配置。
现在事情变得有点复杂了。
取决于apiserver
,kube-controller-manager
和kubelet
的配置,它们会对节点没有延迟响应的事实做出反应。
如果节点重新启动的速度足够快,则kube-controller-manager
不会驱逐Pod,并且它们都保留在同一节点上,并在它们的新容器变为RESTARTS
之后增加其Ready
的数量。 / p>
示例1。
集群是在KCP中创建的Ubuntu 18.04
VM上使用带有Flannel网络附加组件的Kubeadm创建的。
Kubernetes版本为v1.18.8
Docker版本为19.03.12
重新启动节点后,将使用新的IP地址在节点上启动所有Pod的容器。豆荚保留其名称和位置。
如果节点长时间停止,则该节点上的Pod保持Running
状态,但是连接尝试显然超时。
如果节点仍处于停止状态,则在约5分钟后,kube-controller-manager
将在该节点上调度的Pod逐出并终止。如果我要在驱逐之前启动节点,则所有吊舱都将保留在节点上。
在逐出的情况下,独立的Pod会永远消失,部署和类似的控制器会创建必要数量的Pod来替换逐出的Pod,并且kube-scheduler
会将它们放置到适当的节点。如果不能在另一个节点上安排新的Pod,例如。由于缺少所需的卷,它将一直处于“待处理”状态,直到满足调度要求为止。
在使用Ubuntu 18.04 Vagrant box和Virtualbox虚拟机管理程序以及专用于Kubernetes网络的仅主机适配器创建的群集上,已停止节点上的pod仍处于Running
,但即使两个小时后仍处于Readiness: false
状态,并且从未被驱逐。在2小时内启动节点后,所有容器都已成功重新启动。
从Kubernetes v1.7
到最新的v1.19.2
,此配置的行为一直相同。
示例2。
使用默认的kubenet
网络插件在Google云(GKE)中创建集群:
Kubernetes的版本为1.15.12-gke.20
节点操作系统为Container-Optimized OS (cos)
节点重新启动后(大约需要15至20秒),所有吊舱都将使用新的IP地址在节点上启动。豆荚保留其名称和位置。 (与示例1相同)
如果节点已停止,则在短时间(T1等于30-60秒)后,节点上的所有Pod都将状态更改为“正在终止”。几分钟后,它们从Pods列表中消失。由Deployment管理的Pod会在其他具有新名称和ip地址的节点上重新安排。
如果节点池是使用Ubuntu节点创建的,则apiserver会在以后终止Pods,T1大约等于2-3分钟。
示例表明,在不同群集上,工作节点重新启动后的情况有所不同,最好在特定群集上运行实验,以检查是否可以获得预期的结果。
如何配置这些超时时间:
- How Can I Reduce Detecting the Node Failure Time on Kubernetes?
- Kubernetes recreate pod if node becomes offline timeout
当节点重新启动并且在其上安排了由Deployment
或ReplicaSet
管理的Pod时,这些控制器将负责安排另一个正常运行的节点上所需数量的副本。因此,如果您有2个副本在重新启动的节点上运行,它们将被终止并计划在其他节点上。
在重新启动节点之前,您应该使用kubectl cordon
到mark the node as unschedulable,并给kubernetes时间重新安排pod的时间。
无状态Pod不会在其他任何节点上重新安排,它们将被终止。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。