图解kubernetes中断预算实现原理

今天我们来聊聊一种Pod保护的方式PDB(PodDisruptionBudget)这是一个被介绍的很复杂的概念, 本文希望以一种更简单的方式去聊聊其内部的具体实现

1. 基础概念

PDB跟其他类型的资源并无本质的差别,本身也并没有复杂的设计,其更像是一个记账簿,记录着可以操作的Pod的数量,其余的功能则依赖于其他组件,让我们一起来看下其相关的组件

1.1 驱逐到底是什么

image.png驱逐这个概念在k8s中个人理解有两种场景: apiserver端的Pod驱逐接口和kubelet里面的驱逐管理器,两者虽然都有类似的evictPod的操作,但本质上却根本不是一个东西, 在kubelet里面的驱逐最终会调用runtime来kill掉正在运行的容器, 而apiserver端的接口则是直接在etcd里面删除对应的Pod, 也是PDB真正起作用的地方, 本文后面的驱逐都是指的apiserver端的接口

1.2 Drain

drain是k8s用于维护节点扩容的时候的一个命令,事实上默认在k8s中也就只有该命令会进行驱逐接口的调用了

1.3 Pod中断预算

Pod中断预算名字很直白但看介绍是真复杂, 其实简单来说可以分为两部分:中断和预算,预算其实很容易理解,就跟大家平常花钱一样,有多少预算买多少钱的东西,这里的预算也是一样,不过这里的预算是你可以进行操作的数量,比如你允许某个资源的最多10%的Pod宕机,它就会根据你当前的状态和你的预算来计算出,你可以中断多少机器image.png那什么是中断呢?答案就是删除对应的操作其实就是删除对应的Pod, 整合在一起其实就是根据你当前的状态计算出你可以进行删除Pod操作的数量

好了基础概念就介绍到这里,下面开始其实现的探索

2. 核心实现

2.1 PDB的计算数据

image.png我们上面提到了PDB的本质就是计算允许进行删除操作的数量,那要进行这种计算需要那些数据呢?首先我们需要一个PDB(预算),然后我们需要当前Pod的状态(通过selector)这部分是不是够了呢?答案肯定不是,还缺什么呢?就是我们上面提到的total,即该Pod当前集群中期望有几个,如何获取呢?其实这个对应的就是对应的上层资源,比如Deployment、ReplicaSet、StatefulSet等,我们需要渠道对应上层资源期望的Pod的数量,也就是我们的total

2.2 上层资源的关联

image.png那么如何我才能知道我Pod的管理的上层控制器具体是谁呢?答案其实就是Controlled By字段我们可以获取对应的ownerReferences这样我们就可以知道上层的控制器是谁,然后我们就可以从对应控制器字段里面取出对应的期望的数量

2.3 中断有效时间

中断有效时间这个名字我感觉很贴切,官方的名字叫DeletionTImeout,因为在k8s里面控制器和apiserver是可以分开的两个组件,上面我提到了驱逐接口会接收到驱逐请求,那怎么把这种驱逐的Pod传递给PDB呢image.png因为他要计算还可以继续驱逐多少,除了当前的Pod和期望的Pod数量之外,也肯定需要知道当前还可以继续已经被中断(正在进行驱逐的)的数量

如果因为集群的不稳定造成PDB过了很久才收到这条消息,实际上对应的请求可能早就已经失效了,则对应的被驱逐的Pod实际上并没有被驱逐计算的时候还依旧将其计算在内,则可能会影响后续的驱逐操作,所以为了解决这种延迟和不同步问题,才有了中断有效时间,默认是2分钟,过期后就会自动删除,并且计算的时候就会跳过该Pod

2.4 整体实现大揭秘

image.png控制整体实现分为如下几个大的步骤:1.用户定义PDB要保护的资源2.controller感知资源然后计算PDB对应的数据3.eviction接口接收到驱逐请求后,检测PDB是否允许,如果允许就更新中断的Pod到PDB的DisruptedPods字段中4.PDB感知到更新之后,重新进行计算更新PDB,这样eviction下次接收到驱逐请求之后就可以使用,反反复复

此外还有另外一条分支逻辑,就是PDB里面会监听对应的Pod的增加删除更新,然后也会进行PDB的计算和更新

3. PDB的总结

PDB的主要流程基本上就如上所述,PDB剩下的会作用的则就是在调度器抢占的时候,会讲PDB做为一个计算条件来用于选择要抢占的Node的决策,整体流程就这些,欢迎一起交流,探索底层机制

kubernetes学习笔记地址: https://www.yuque.com/baxiaoshi/tyado3

微信号:baxiaoshi2020 公共号:图解源码

K8S中文社区微信公众号

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址