图解kubernetes控制器Deployment核心机制
Deployment是k8s中部署更新的关键实现,今天我们一起初探下其关键机制包括: 暂停、回滚、扩缩容、更新策略的实现
1. 基础概念
Deployment本质上其实只是一种部署策略,在了解其实现之前,先简单介绍一下部署系统里面常见的概念,Deployment里面的各种参数和设计其实也都是围绕着这些展开的
1.1 ReplicaSet
Deployment本身并不直接操作Pod,每当其更新的时候通过构建ReplicaSet来进行版本更新,在更新的过程中通过scale up(新的RS)和scale down(旧的RS)来完成
1.2 部署状态
在k8s的官方文档中主要是介绍了Deployment的三种状态, 对应的Condition分别为Available、Progressing、ReplicaFailure三种状态, 并且每个状态下面又会很有导致对应状态切换的不同的Reson,Reson可能是运维过程中最需要关注的点
1.3 部署策略
部署策略是Deployment控制ReplicaSet更新的策略,通过对新旧ReplicaSet的扩缩容,再满足部署策略的情况下,将系统更新至最新的目标状态,Deployment本身并没有太多可选的策略,默认只有两种Recreate和RollingUpdate
在一些大版本产品更新的时候,新旧版本的数据库模型都不一致的情况下,通常会选择停服操作,此时可以选择Recreate即将所有老的副本都干掉,然后重新创建一批。当然默认情况下大部分业务还是RollingUpdate即滚动更新即可
1.4 可用性与高低水位
部署过程中最常被提到的可能就是可用性问题了,即在更新的过程中(RollingUpdate策略下)需要保证系统中可用的Pod在一个指定的水位,保证对应服务的可用性
高低水位(deployment并没有这个词)其实就是对应的上面的可用性来说的,Deployment通过一些参数让我们可以自由控制在滚动更新的过程中,我们可以创建的Pod的最多数量(高水位)和可以删除的最多的Pod(低水位), 从而达到可用性保护的目标
部署的概念就介绍到这里, 接下来就一起看看Deployment中这些关键机制的具体实现
2. 核心实现
Deployment的实现上相对复杂一点,但是从场景上又可以简单的分为:删除、暂停、回滚、扩缩容、更新几个大的场景
2.1 暂停部署
暂停部署是用于中断Deployment更新流程的一种方式,但由于k8s中是基于事件驱动的最终一致性的系统,这里的中断仅仅意味着Deployment层不会进行的进行后续的副本变更,而底层的replicaSet此时如果还没有达到目标的副本,则就需要继续更新, 同时在暂停的过程中如果发现并没有尝试进行回滚到指定版本的操作,这时候还会进行一些副本的清理工作,即只保留最近的指定数量的历史副本
2.2 回滚控制
回滚控制里面的信息跟其他参数有些不同,其主要是通过在Annotations中存储的DeprecatedRollbackTo来进行指定版本的回滚
回滚的实现本质上就是从指定的Revisions中获取对应的replicaset的Pod模板,去覆盖当前的Deployment的Pod模板,并且更新Deployment即可, 那如果对应的版本不存在怎么办,如果是这种情况,其实就需要你自己去寻找历史版本了,并且k8s会给新添加一个RollbackRevisionNotFound类型的事件提示你版本不存在
2.3 扩缩容机制
扩缩容机制主要是指的Deployment的scale操作,在进行Deployment更新之前,会首先检查对应Deployment的副本的期望是否得到满足,只有期望的副本数得到满足,才会进行更新操作,所以在k8s中如果之前进行了扩缩容操作,则在该操作完成之前,是不会进行模板更新的
2.4 Recreate策略
Recreate部署策略在实现上通过两种机制保证之前的Pod一定被删除:所有活跃副本都为0和所有Pod都处于(PodFailed和PodSucceeded)两种状态下,然后才会创建新的副本,如果对应的副本完全就绪,还会进行清理历史副本
2.5 RollingUpdate策略
RollingUpdate策略可能是最复杂的部分之一了,里面很有多的参数控制,都作用于该策略,来一起看下
2.5.1 缩容过多的新版本
首先在更新的时候要做一致性检测,如果发现新版本的ReplicaSet比当前的deployment设定的副本数目多,则首先干掉这部分Pod, 同时会根据当前的Deployment的副本数来设定当前的期望副本数DesiredReplicasAnnotation, 并且根据maxSurge来计算当前最大的副本数量MaxReplicasAnnotation, 同时在这个同步ReplicaSet的minReadySeconds
2.5.2 扩容新副本
如果说新副本的数量不足,则就需要根据当前的maxSurege来设定,同时会再次计算当前的RS的所有Pod,如果发现Pod数量过多即超过Deployment的Replicas+maxSurge,则也不会进行操作
// Find the total number of pods currentPodCount := GetReplicaCountForReplicaSets(allRSs) // 最大pod数量 maxTotalPods := *(deployment.Spec.Replicas) + int32(maxSurge) // 当前pod数量》总的运行的pod数量 if currentPodCount >= maxTotalPods { // Cannot scale up. return *(newRS.Spec.Replicas), nil }
否则则就会进行计算允许scale up的数量
scaleUpCount := maxTotalPods - currentPodCount scaleUpCount = int32(integer.IntMin(int(scaleUpCount), int(*(deployment.Spec.Replicas)-*(newRS.Spec.Replicas))))
2.5.3 缩容旧的副本
缩容计数器的算法计算主要是根据Deployment的Replcas和maxUnavailable(通过surge和maxUnavailable)共同计算而来,最终的公式其实如下,有了缩容的数量,就可以更新旧ReplicaSet的数量了
minAvailable := *(deployment.Spec.Replicas) - maxUnavailable // 新副本不可用数量 newRSUnavailablePodCount := *(newRS.Spec.Replicas) - newRS.Status.AvailableReplicas // 最大缩容大小=所有pod统计-最小不可用-新副本不可用副本 maxScaledDown := allPodsCount - minAvailable - newRSUnavailablePodCount
整理如下
最小可用副本 = Deployment的副本-最大不可用副本 新副本不可用统计= 新副本数量-可用副本数量 最大缩容数量 = 全部副本Pod计数-最小可用副本-新副本不可用统计
至此我们知道了Deployment扩缩容的核心的副本计算实现,也知道了扩缩容的流程,那还缺什么呢?答案是状态
2.5.4 Available状态
Deployment的状态主要是由新旧副本以及当前集群中的Pod决定的,其计算公式如下, 则认为当前可用否则即为不可用
前可用的副本数量计数>=Deployment的副本数量-最大不可用副本计数
if availableReplicas >= *(deployment.Spec.Replicas)-deploymentutil.MaxUnavailable(*deployment) { minAvailability := deploymentutil.NewDeploymentCondition(apps.DeploymentAvailable, v1.ConditionTrue, deploymentutil.MinimumReplicasAvailable, "Deployment has minimum availability.") deploymentutil.SetDeploymentCondition(&status, *minAvailability) } else { noMinAvailability := deploymentutil.NewDeploymentCondition(apps.DeploymentAvailable, v1.ConditionFalse, deploymentutil.MinimumReplicasUnavailable, "Deployment does not have minimum availability.") deploymentutil.SetDeploymentCondition(&status, *noMinAvailability) }
2.5.5 Processing状态
首先并不是所有的Deployment都有该状态,只有设置了progressDeadlineSeconds参数的才会有该状态,其主要实在Deployment未完成的时候,进行一些状态决策,从而避免一个Deployment无期限的运行,其关键状态有两个即运行中与超时决策, 其流程实现上分为两步 1)首先如果判断是正在运行中,就更新LastTransitionTime
condition := util.NewDeploymentCondition(apps.DeploymentProgressing, v1.ConditionTrue, util.ReplicaSetUpdatedReason, msg) condition.LastTransitionTime = currentCond.LastTransitionTime
2)超时检测则及时通过记录之前的转换时间,然后决策是否超时
from := condition.LastUpdateTime now := nowFn() delta := time.Duration(*deployment.Spec.ProgressDeadlineSeconds) * time.Second timedOut := from.Add(delta).Before(now)
2.5.6 ReplicaFailure状态
该状态相对简单,检测当前的所有的副本,如果发现有副本失败,就取最新的一条失败的信息来填充Condition
3. 小结
更新机制的核心实现可能就这些,代码实现上还是相对复杂的,主要是集中在为了保证伸缩和更新时为了保证可用性而做了大量的计算,还有很多的边界条件的处理,先就关注到这里,里面的具体的更细的细节,等出问题的时候,再详细琢磨,今天就到这里了
kubernetes学习笔记地址: https://www.yuque.com/baxiaoshi/tyado3
微信号:baxiaoshi2020 关注公告号阅读更多源码分析文章 更多文章关注 www.sreguide.com
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
入门 Serverless:Serverless Framework 开发者工具
Serverless 架构是云发展的产物,是一种去服务器化更加明显的架构。然而,细心的朋友可能会发现,有一个开发者工具也叫 Serverless,那么 Serverless 到底是一个架构,还是一个开发者工具呢?这个开发者工具和 Serverless 架构又有什么关系呢? 初探 Serverless 开发者工具 Serverless 架构开始发展没多久,就有一群人注册了 serverless.com 的域名,成立了一家叫 Serverless 的公司,同时还开发了一款同名工具。 Serverless 架构和 Serverless 开发者工具是两个不同的东西,如果类比一下的话,就相当于中国电信,一方面指的是中国电信行业,另一方面也指的是中国电信运营商。 从 Serverless 的公司名称,我们也可以推断出其推出的产品与 Serverless 架构紧密相关。在各个云厂商都有自己函数计算业务的时候,Serverless 团队做了一个类似多云管理平台的工具,可以认为是多 Serverless 管理的工具。利用这个工具,可以快速直接使用 AWS 的 Lambda、Azure 的 Funtion...
- 下一篇
徒手撸一个扫码登录示例工程
徒手撸一个扫码登录示例工程 不知道是不是微信的原因,现在出现扫码登录的场景越来越多了,作为一个有追求、有理想新四好码农,当然得紧跟时代的潮流,得徒手撸一个以儆效尤 本篇示例工程,主要用到以下技术栈 qrcode-plugin:开源二维码生成工具包,项目链接: https://github.com/liuyueyi/quick-media SpringBoot:项目基本环境 thymeleaf:页面渲染引擎 SSE/异步请求:服务端推送事件 js: 原生 js 的基本操作 <!-- more --> I. 原理解析 按照之前的计划,应该优先写文件下载相关的博文,然而看到了一篇说扫码登录原理的博文,发现正好可以和前面的异步请求/SSE 结合起来,搞一个应用实战,所以就有了本篇博文 关于扫码登录的原理,请查看: 聊一聊二维码扫描登录原理 1. 场景描述 为了照顾可能对扫码登录不太了解的同学,这里简单的介绍一下它到底是个啥 一般来说,扫码登录,涉及两端,三个步骤 pc 端,登录某个网站,这个网站的登录方式和传统的用户名/密码(手机号/验证码)不一样,显示的是一个二维码 app 端,...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS6,CentOS7官方镜像安装Oracle11G
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- CentOS6,7,8上安装Nginx,支持https2.0的开启