5.3.2 更新策略

如前所述,ReplicaSet 控制器的应用更新需要手动分成多步并以特定的次序进行,过程繁琐且容易出错,而Deployment却只需要由用户指定在Pod模板中要改动的内容,例如容器镜像文件的版本,余下的步骤可交由其自动完成。同样,更新应用程序的规模也只需要修改期望的副本数量,余下的事情交给Deployment控制器即可。

Deployment控制器的详细信息中包含了其更新策略的相关配置信息,如 myapp-deploy 控制器资源 “kubectl describe” 命令中输出的 StrategyType、RollingUpdateStrategy 字段等。

**[terminal]
**[delimiter $ ]**[command kubectl describe deployments myapp-deploy]
Name:                   myapp-deploy
Namespace:              default
CreationTimestamp:      Fri, 11 Sep 2020 16:22:37 +0800
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=myapp
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=myapp
  Containers:
   myapp:
    Image:        ikubernetes/myapp:v1
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   myapp-deploy-5cbd66595b (3/3 replicas created)
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  2m26s  deployment-controller  Scaled up replica set myapp-deploy-5cbd66595b to 3

Deployment 控制器支持两种更新策略:滚动更新(rolling update)和重新创建(recreate)。默认为滚动更新。重新创建更新类似于前文中ReplicaSet的第一种更新方式,即首先删除现有的Pod对象,而后由控制器基于新模板重新创建出新版本资源对象。通常,只应该在应用的新旧版本不兼容(如依赖的后端数据库的schema不同且无法兼容)时才会使用recreate策略,因为它会导致应用替换期间暂时不可用,好处在于它不存在中间状态,用户访问到的要么是应用的新版本,要么是旧版本。

滚动更新是默认的更新策略,它在删除一部分就版本Pod资源的同时,补充创建一部分新版本的Pod对象进行应用升级,其优势是升级期间,容器中应用提供的服务不会中断,但要求应用程序能够应对新旧版本同时工作的情形,例如新旧版本兼容同一个数据库方案等。不过,更新操作期间,不同客户端得到的响应内容可能会来自不同版本的应用。

Deployment控制器的滚动更新操作并非在同一个ReplicaSet控制器对象下删除并创建Pod资源,而是将它们分置于两个不同的控制器之下:旧控制器的Pod对象不断减少的同时,新控制器的Pod对象数量不断增加,直到旧控制器的Pod对象,而新控制的副本数量变得完全符合期望值为止,如图5-8所示。

Deployment的滚动更新
图 1.7.3.2 - Deployment的滚动更新

滚动更新时,应用升级期间还要确保可用的Pod对象数量不低于某阈值以确保可以持续处理客户端的服务请求,变动的方式和Pod对象的数量分为将通过spec.strategy.rollingUpdate.maxSurgespec.strategy.rollingUpdate.maxUnavailable两个属性协同进行定义,它们的功用如图5-9所示:

  • maxSurge:指定升级期间存在的总Pod对象数量最多可超出期望值的个数,其值可以是0或正整数,也可以是一个期望值的百分比;例如,如果期望值为3,当前的属性值为1,则表示Pod对象的总数不能超过4个。

  • maxUnavailable:升级期间正常可用的Pod副本数(包括旧版本)最多不能地域期望值的个数,其值可以是0或正整数,也可以是一个期望值的百分比;默认值为1,该值意味着如果期望值是3,则升级期间至少要有两个Pod对象处于正常提供服务的状态。

maxSurge和maxUnavailable的作用方式
图 1.7.3.2 - maxSurge和maxUnavailable的作用方式

maxSurge 和 maxUnavailable 属性的值不可同时为0,否则Pod对象的副本数量在符合用户期望的数量后无法做出合理变动以进行滚动更新操作。

配置时,用户还可以使用Deployment控制器的spec.minReadySeconds属性来控制应用升级的速度。新旧更替过程中,新创建的Pod对象一旦成功响应就绪探测即被视作可用,而后即可立即开始下一轮的替换操作。而spec.minReadySeconds能够定义在新的Pod对象创建后至少要等待多久才将其视作就绪,在此期间,更新操作会被阻塞。因此,它可以用来让Kubernetes在每次创建出Pod资源后都要登上一段时长后再开始下一轮的更替,这个时间长度的理想值是等到Pod对象中的应用已经可以接受并处理请求流量。事实上,一个精心设计的等待时长和就绪性试探能让Kubernetes系统规避一部分因程序Bug而导致的升级故障。

Deployment 控制器也支持用户保留其滚动更新历史中的旧ReplicaSet对象版本,如图5-10所示,这赋予了控制器进行应用回滚的能力:用户可按需回滚到指定的历史版本。控制器可保存的历史版本数量有“spec.revisionHistoryLimit”属性进行定义。当然,也只有保存于revision历史中的ReplicaSet版本可用于回滚,因此,用户要习惯性地在更新操作时指定保留旧版本。

Deployment的版本历史记录
图 1.7.3.2 - Deployment的版本历史记录

为了保存版本升级的历史,需要在创建Deployment对象时于命令中使用“--record”选项。

尽管滚动更新以节约系统资源著称,但它也存在一些劣势。直接改动现有环境,会使系统引入不确定性风险,而且升级过程中出现问题后,执行回滚操作也会较为缓慢。有鉴于此,金丝雀部署可能使较为理想的实现方式,当然,如果不考虑系统资源的可用性,那么传统的蓝绿部署也是不错的选择。

results matching ""

    No results matching ""