Kubernetes Deployment滚动更新场景分析

基于Kubernetes v1.7.4

关于Kubernetes Deployment滚动更新

场景1:正常滚动更新流程

  • 新建deployment:webserver,replicas=10,image=tomcat。
  • 滚动更新应用镜像为:nginx
  • 观察Replicasets的变化,可发现升级后会创建新的Replicasets,删除老的Replicasets实例,滚动创建新实例。
  • 观察deployment的变化

  • DESIRED: 10(一直为10)
  • CURRENT: 在[replicas-maxUnavailable, replicas+maxSurge]:[8,13]之间变动,最终等于DESIRED值
  • UP-TO-DATE: 已更新为nginx镜像的实例,最终等于DESIRED值。
  • AVALIABLE: 新老replicaset总的实例数,最终等于DESIRED值。

场景2:应用滚动更新时,用户删除应用

  • 新建deployment:webserver,replicas=10,image=tomcat。
  • 更改容器镜像,触发deployment的滚动更新。
  • 新老Replicaset开始进行滚动更新。
  • 使用kubectl删除正在滚动更新的deployment。
  • 新老replicaset的实例数被缩减为0,实例开始被删除。
  • 观察deployment实例变化如下

从红框处,DESIRED=0,实例逐渐被删除。

场景3:应用滚动更新时,用户对该应用进行扩容

  • 新建deployment:webserver,replicas=15,image=tomcat。
  • 更改容器镜像,触发deployment的滚动更新。

开始进行滚动更新:

  • 更改deployment的实例数到20
  • 新老RS根据比例进行实例数扩容
    • RS实例数根据比例进行相应的增加: RS扩容后的实例数=扩容前实例数占比*扩容后最大实例数

    在此次升级中,在扩容前 | NAME | DESIRED | CURRENT | READY | |----|----|----|----| | Webserver-1078791221 | 10 | 10 | 12 | | Webserver-3236788441 | 7 | 7 | 3 | 升级前的总实例数:10+7=17 升级前最多实例数:15+MaxSurge(25%)=19 升级后最多实例数:20+ MaxSurge(25%)=25 当前需扩容的总数:25-17=8 所以: webserver-1078791221扩容后实例数=(10/19)*25=13.15(+0.5取整)=13 webserver-3236788441扩容后实例数=(7/19)*25=9.21(+0.5取整)=9

    • 剩余的实例分配给实例数最多的rs webserver-1078791221 较扩容前增加:13-10=3 webserver-3236788441较扩容前增加:9-7=2 仍剩余的实例(8-3-2=3个)分配给webserver-1078791221 所以webserver-1078791221总实例数=10+3+3=16 如下所示:

5)实例数更新以后,滚动升级继续进行,最终老的replicaset实例被删,替换为新的

场景4:应用滚动更新时,用户对该应用进行缩容

  • 新建deployment:webserver,replicas=15,image=tomcat。
  • 更改容器镜像,触发deployment的滚动更新。

开始进行滚动更新:

  • 更改deployment的实例数到4

- 新老RS根据比例进行实例数缩容 RS实例数根据比例进行相应的缩减(计算方法如扩容): RS缩容后的实例数=缩容前实例数占比*缩容后最大实例数

| NAME | DESIRED | CURRENT | READY | |----|----|----|----| |Webserver-1078791221 | 9 | 10 | 10| |Webserver-3236788441 | 9 | 8 | 4 |

升级前的总实例数:9+9=18 升级前最多实例数:15+MaxSurge(25%)=19 升级后最多实例数:4+ MaxSurge(25%)=5 当前需缩容的总数:18-5=13 所以 webserver-1078791221缩容后实例数=-(9/19)*5=-2.36(-0.5取整)=2 webserver-3236788441缩容后实例数=-(9/19)*5=-2.36(-0.5取整)=2

  • 多缩容的实例分配给实例数最多的rs

webserver-1078791221 较缩容前减少:9-2=7 webserver-3236788441较缩容前减少:9-2=7 多缩容的实例(7+7-13=1个)分配给实例数最多的rs(由于新老RS实例数都为9,则按照创建时间进行排序,分给最新的实例webserver-3236788441) 所以webserver-3236788441总实例数=9-7+1=3

如下所示:  
  • 最终老的replicaset实例被删,替换为新的,且缩容到指定个数。

从deployment角度观察结果如下:

场景5:应用扩容时,进行滚动更新

  • 新建deployment:webserver,replicas=10,image=tomcat。
  • 更改deployment的实例数到20

RS的实例数变为20,开始扩容

  • 更改容器镜像,触发deployment的滚动更新。
  • 新老的replicaset的实例变化。 创建新的RS,按照滚动升级策略开始更新,如下:
  • 最终老的replicaset实例被删,替换为新的
  • 观察deployment的实例变化如下:

场景6:应用缩容时,进行滚动更新

  • 新建deployment:webserver,replicas=25,image=tomcat。
  • 更改deployment的实例数到4

RS的实例数变为4,开始缩容

  • 更改容器镜像,触发deployment的滚动更新。
  • 新老的replicaset的实例变化 老的RS的实例会被逐渐删除,同时新的RS开始滚动更新,符合滚动升级策略。
  • 最终老的replicaset实例被删,替换为新的
  • 观察deployment的实例变化如下:

deployment的实例数先被缩容到4; UP-TO-DATE从25-0-4,表明实例被滚动到最新版本。 CURRENT 实例数在开始滚动更新后,最大数不超过5,符合滚动更新的实例数区间。

场景7:应用回滚

  • 新建deployment:webserver,replicas=10,image=tomcat。
  • 更改容器镜像为nginx,触发deployment的滚动更新。

等待滚动更新完成:

3)更改容器镜像为httpd,触发deployment的滚动更新。

等待滚动更新完成:

4)回滚到nginx版本。

等待滚动更新完成:

回滚到 –to-revision=2 nginx版本后,nginx版本又成为了最新的版本vision:4。

场景8:滚动更新未完成时,又开始新的滚动更新

  • 新建deployment:webserver,replicas=15,image=tomcat。
  • 更改容器镜像为nginx,触发deployment的滚动更新。

更新后,触发滚动升级:

  • 在上个滚动更新未完成的情况下,接着更改容器镜像为httpd,再次触发deployment的滚动更新。

更新后,再次触发滚动升级:

  1. 第二次滚动升级webserver-2480438009初始DESIRED=0,因为两个老的RS当前实例总数为12+7=19,已经达到最大值,所以初始为0。
  2. 缩减老的RS时,遵循两个原则
    • 遍历所有老的RS,优先缩减那些unavailable的实例。 webserver-3236788441缩减前7/7/ 3(还有4个unacailable),所以先被缩减到3/7/3。
    • 在保证最小available个实例的前提下,缩减老的RS。 计算方法如下: 最小可用数minAvailable = deployment.Replicas – maxUnavailable; 当前总可用数:availablePodCount = 所有RS的AvailableReplicas总和; 可缩减的总数:totalScaleDownCount = availablePodCount - minAvailable; 将老的RS按创建时间从新到老排序,逐个进行缩减。 例如,在第一次缩减webserver-1078791221时: webserver-2480438009 7/7/1 webserver-1078791221 9/9/9 webserver-3236788441 3/3/3 minAvailable=15-15*25%=12 availablePodCount=1+9+3=13 totalScaleDownCount=13-12=1

所以将webserver-1078791221缩减1个实例到 8/9/9(如上图最下面的红框)

再次缩减时: webserver-2480438009 8/8/2 webserver-1078791221 8/8/8 webserver-3236788441 3/3/3 minAvailable=15-15*25%=12 availablePodCount=2+8+3=13 totalScaleDownCount=13-12=1

webserver-1078791221缩减为0/0/0,开始用同样的方法缩减 webserver-3236788441,这里不再敖述。 相关处理Replicasets代码在: pkg/controller/deployment/rolling.go:reconcileOldReplicaSets

  • 从deployment角度观察滚动过程如下:

附录:

  • https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

感谢同事陈俊超辛苦的测试分析。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Django中文社区

已知小问题修正

在模型中指定排序 为了让文章(Post)按发布时间逆序排列,即最新发表的文章排在文章列表的最前面,我们对返回的文章列表进行了排序,即各个视图函数中都有类似于 P...

3034
来自专栏对角另一面

读Zepto源码之Gesture模块

Gesture 模块基于 IOS 上的 Gesture 事件的封装,利用 scale 属性,封装出 pinch 系列事件。 读 Zepto 源码系列文章已经放到...

2350
来自专栏大前端_Web

几种方法实现ajax请求内容时使用浏览器后退和前进功能

版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/articl...

1812
来自专栏SHERlocked93的前端小站

JS throttle与debounce的区别

一般在项目中我们会对input、scroll、resize等事件进行节流控制,防止事件过多触发,减少资源消耗;在vue的官网的例子中就有关于lodash的deb...

1403
来自专栏Google Dart

开始使用-编写你的第一个Flutter应用程序 顶

这是创建您的第一个Flutter应用程序的指南。 如果您熟悉面向对象的代码和基本编程概念(如变量,循环和条件),则可以完成本教程。 您不需要以前使用Dart或移...

912
来自专栏Golang语言社区

Golang笔记——并发

o语言中的main函数也是运行在一个单独的goroutine中的,一般称为 main goroutine,main函数结束时,会打断其它 goroutine 的...

3525
来自专栏烂笔头

Django 1.10中文文档-第一个应用Part4-表单和通用视图

目录[-] 本教程接Part3开始。继续网页投票应用程序,并将重点介绍简单的表单处理和精简代码。 一个简单表单 更新一下在上一个教程中编写的投票详细页面的...

3284
来自专栏有趣的Python

IDEA 神器使用技巧

标记上bookmarks之后可以ctrl 1 ctrl 2 ctrl 3 按标签序号进行跳转

1003
来自专栏黄Java的地盘

提高开发效率之VS Code基础配置篇

VS Code可以通过名为代码片段的功能像编辑器中插入一段指定的文本,具体操作步骤为首选项->用户代码片段->新建全局代码片段。

2242
来自专栏高性能服务器开发

libevent源码深度剖析十一 时间管理

(1)libevent源码深度剖析一 序 (2)libevent源码深度剖析二 Reactor模式 (3)libevent源码深度剖析三 libevent基本使...

821

扫码关注云+社区