节点发生故障Deployment控制器会发生什么?
定义
:在Kubernetes中,不可达节点被称为分区节点partitioned node
,为了了解操作方法,让我们创建一个分区节点方案并了解其行为。
所考虑的示例集群具有一个主节点和3个工作节点。创建具有2个副本的Nginx部署。这些副本在不同的节点上运行;kind-worker2
和kind-worker3
。图1捕获了示例集群的状态。
图1: 示例集群的状态
创建节点分区的一种简单方法是删除节点的IP地址
。那就是在kind-worker2
上所做的。图2提供了必要的步骤。
创建分区节点
work节点kind-worker2
)立即设置为**NotReady
状态,但pod继续运行。原因是,负责节点的kube-controller-manager
的节点控制器部分等待pod-eviction-timeout
**,以确保在计划将pod删除之前完全无法访问该节点。
**pod-eviction-timeout
**默认设置为5分钟,并在kube-controller-manager启动过程中进行了修改。
在pod逐出超时时间间隔(在本例中为5分钟)之后,节点控制器将在分区节点上运行的pod调度为**Termination
**状态。kube-controller-manager的Deployment Controller部分开始在其他的节点上创建新的副本replicas
和调度schedules
。在我们的示例中,在kind-worker节点上创建了一个Nginx副本。
图3捕获了Kubernetes系统上的所有状态更改。
Master节点运行Pod的状态.
让我们进入分区节点内,看看发生了什么。从**图4中,**我们可以观察到原来的pod正在继续运行。是不是有趣!。原因是API服务器无法与分区节点的Kubelet通信以删除Pod。同样,Kubelet也不知道决定要运行哪些Pod的控制器。
Pod继续在分区的工作节点上运行
一旦分区节点加入集群,即可删除pod。下面我们通过一张图总结一下集群中节点发生故障后k8s集群和Deployment控制器触发的工作流程
图5:节点发生故障时部署如何工作的流程图
与前面的实验一样,依旧通过Kind初始化一个集群,然后使用statefulset创建一个2副本的状态集,这些副本在不同的节点上运行,图6捕获了示例种类群集的状态
图6:示例集群
创建节点故障方案的另一种简单方法是删除kind-worker2。图7提供了所需的步骤。
图7:捕获创建节点故障的步骤
work节点kind-worker2
立即设置为NotReady
状态,但pod继续运行。在将pod设置为**Termination
状态之前,系统等待pod-eviction-timeout
**间隔s(默认值为5分钟
)。
令我们惊讶的是,没有为Statefulsets创建新的pod,而在类似情况下,新的副本被复制用于Deployment
部署集。图8捕获了Statefulsets发生节点故障后Kubernetes集群的状态。
图8:节点故障后Nginx状态集的状态
按照Pod-Safety[1]文件,在Kubernetes集群内系统提供了运行保证**,在任何时间点at most one pet
。该规则适用于Statefulsets,因为副本被视为pets
,而这不适用于Deployment,因为副本被视为cattle。
at most one pet
的根本原因是因为有状态集主要用于集群应用程序,这些应用程序有自己的选举主从
的方式。在节点故障的情况下,主节点没有足够的信息来确定该节点实际上是故障还是故障是由于网络分区引起的。因此,主机拒绝采取任何措施,从而导致更多问题。主机采用一种实际的方法,减少了一个实例,但以一种可靠的方式工作。
如何从这种dangling state
中恢复过来?有几种方法可以处理这种情况,设置terminationGracePeriodSeconds
为0的Pod spec
。这将确保当节点重新加入群集时,将强制forcefully
删除有状态集的容器。这样,Kubernetes主机知道可以保持Pod安全性,因此将启动一个新副本。不利的一面是,pod的关闭显然不是很正常。如果您确定节点确实发生故障或被删除,则可以采用一种自动的方法来检测节点故障并强行删除这些节点。这将确保在可用节点上重新启动有状态集的容器。
关于statefulset控制的有状态pod的相关驱逐问题,也可以参考gitlab issue1[2]和gitlab issue2[3]
[1]
Pod-safety: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/pod-safety.md
[2]
StatefulSet pod is never evicted from shutdown node: https://github.com/kubernetes/kubernetes/issues/54368
[3]
Statefulset should be able to evicted if the worker node goes down: https://github.com/kubernetes/kubernetes/issues/74947