如何在不中断作业执行的情况下更新Kubernetes中的应用版本

有这么一个案例:

Q部门在开发一个应用,应用部署在Kubernetes中,应用中有一个功能是定时或即时地运行用户所配置的作业任务,这些作业通常要耗时几分钟到十几分钟,应用的部署和更新由Kubernetes中的deployment控制,每次部署更新,都是修改deployment中的容器镜像版本,Kubernetes就会逐步把旧版本pod删除掉,并创建出新版本的pod,现在Q部门遇到了这么一个问题:每次部署更新应用的版本时,总是会导致应用中作业执行被中断,他们想在更新版本时避免任务中断

怎么解决这个问题呢?

这里我有两个思路,这两个思路有些类似又有些不同。

类似的地方在于,这两个思路都需要将应用分成两部分,一部分为控制侧,一部分为工作侧,控制侧负责作业的管理、配置、调度等,工作侧负责作业的执行,我们的部署更新只会更新控制侧,工作侧的更新交由给控制侧来控制。

具体来讲,第一个思路里,工作侧会是若干个工作节点,工作节点是常驻的,有任务就执行,没任务就待机,工作节点可以主动从控制侧拉取任务,或者是由控制侧向工作节点发送任务执行命令。

在部署更新时,我们首先只更新控制侧的应用版本,然后由控制侧通过Kubernetes API更新工作节点,更新节点前首先确认当前节点是否正在执行任务,只有节点处于空闲状态时才会进行更新,并且在更新前会将节点状态设为“维护中”,使其在更新完成前不会接受新的任务。

节点的更新可以自动触发,或者是设置一个管理按钮,点一下即可开始升级各个节点。

另一个思路和上面的类似,只是工作侧从常驻的工作节点换成了暂态的作业执行器,每次需要执行作业时,都创建出一个作业执行器,由执行器负责作业的执行。

在这里,控制侧永远只会创建作业执行器,而不会对其进行更新,作业执行器所负责的作业执行完成后就不再工作等待销毁,新作业会由新创建的执行器负责执行。

这两个思路都是将应用分成了控制侧工作侧,应用部署时只更新控制侧的应用版本,工作侧的更新由控制侧通过Kubernetes的API来控制进行,区别是,第一个方案里,工作侧是长生命周期的不停执行作业的工作节点,第二个方案里工作侧是只执行一次特定作业的短生命周期的一次性执行器。

很可惜的是,这两个方案都没有被Q部门采用,因为Q部门不愿意将作业执行部分从应用中分离出来(我猜可能是认为做起来比较麻烦吧),而选择容忍应用部署更新时对作业执行的中断。 不过如果遇到无法容忍应用更新导致作业中断的场景的话,这两个思路应该是值得参考的。

如果您有其它思路的话,欢迎同我分享~