应用编排与管理:Deployment

本文是CNCF × Alibaba 云原生技术公开课的第七章应用编排与管理:Deployment学习笔记。

关键词:k8s

需求来源

假如我们直接管理集群中所有的Pod,应用A、B、C的Pod,其实是散乱的分布在集群中。

而且在使用过程中存在以上问题。然后就引入了今天课程的主题。

Deployment:管理部署发布的控制器

首先明确Doployment是管理部署发布的控制器

Doployment将应用A、B、C分别规划到不同的Deployment中,每个Deployment是管理一组相同的应用Pod,这组Pod是相同的副本

  1. Deployment定义了一种Pod期望数量。例如对于应用A,我们期望Pod的数量是四个,controller会持续维持Pod数量为期望的数量。当Pod出现了网络问题或者宿主机出现了问题时,controller可以帮我们恢复也就是新起来对应的Pod,来;
  2. 配置Pod发布方式。controller按照用户给定的策略来更新Pod更新过程中可以设定不可用Pod的数量在多少范围内。
  3. 如果更新过程中发生问题,支持一键回滚。Deployment在更新应用时不是一次性更新全部Pod,而是一个Pod一个Pod的进行更新。如果新的Pod无法起来,这样也不影响旧版本的Pod正常运行。

用法用例

Deployment语法

  • apiVersion:当前Deployment所属的组是apps,版本是v1
  • metadata:当前Deployment的元信息。.metedata.name是nginx-deployment,.metadata.labels是app=nginx
  • spec:期望状态。核心字段是replicas,即期望的Pod数量,controller会一直控制Pod在这个数量;selector是Pod选择器,这里label的要与下文中Pod模板的label一致;template是Pod的模板,包含了Pod的元信息,这里是app=nginx,还包含了Pod的期望状态,这里有容器的一些如镜像版本、容器名称、端口映射等信息。

查看Deployment状态

1
$kubectl get deployment 

  • READY:期望的Pod数量/实际Pod的数量
  • UP-TO-DATE:达到最新期望版本的Pod数量
  • AVAILABLE:运行过程中的可用Pod数量。这里Pod并不简单是可用的(Ready状态),其实包含了一些可用超过一定时间长度的Pod
  • AGE:deployment创建的时长,如上图Deployment就已经创建了80分钟

查看Pod状态

1
$kubectl get pods

  • Pod的名字格式是{deployment-name}-{pod模板的hash}-{随机字符串},Pod的ownerReferencesPod所属的controller资源不是Deployment而是ReplicaSet。这个
    • ReplicaSet的name其实是nginx-deployment加上pod.template-hash
    • 所有的Pod都是ReplicaSet创建出来的,ReplicaSet对应的某个Deployment.template版本

更新镜像

1
$kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1

快速回滚

如果在发布过程中遇到了问题,支持快速回滚。

快速回滚到Deployment上一个版本

1
$kubectl rollout undo deployment/nginx-deployment

回滚Deployment到上一个版本,需要先查询版本列表

1
$kubectl rollout history deployment/nginx=deployment

这里的CHANGE-CAUSE列全都是<none>,在应用资源清单时可以使用如下命令使得api-server记录:

1
$kubectl apply -f nginx-deployment.yml --record
设置历史版本保留

通过.spec.revisionHistoryLimit字段可以设置保留历史版本的replicaset的数量,默认值是10

DeploymentStatus

每一个资源都有它的spec.Status,这里deploymentStatus中描述的是它的转换状态:也就是Processing、Complete、和Failed。

  • 以Processing为例:Processing指的是Deployment正在处于扩容和发布状态。当Processing状态的deployment所有的ReplicasSet以及Pod副本全部达到最新版本,而且是avilable,这样就会进入Complete状态。而Complete状态如果发生了一些扩缩容的话,也会进入Processing的状态。
  • 如果在处理过程中遇到一些问题:比如说拉取镜像失败了,或者就绪探针检查失败了,就会进入failed状态;如果在运行过程中即complete状态,中间运行时发生了一些探针检查失败,此时deployment也会进入failed状态。进入failed状态后,除非所有副本均变成available,而且是update到最新版本,deployment才会进入Complete状态。

架构设计

管理模式

  • Deployment负责管理不同版本的ReplicaSet,由ReplicaSet来管理具体的Pod副本数
  • 每个ReplicaSet对应Deployment template的一个版本。每修改一次template,都会生成一个新的ReplocaSet,这个ReplicaSet下的Pod其实是相同版本。

Deployment控制器

控制器实现原理

所有的控制器都是通过Informer中的一些事件做处理和监听。Deployment控制器关注Deployment和ReplicaSet的事件,收到事件后加入队列。控制器从队列中取出来后,进行check paused的处理,paused其实是检查deployment是否需要新的发布,如果paused设置为true,就表示Deployment只会做副本数量上的维持而不是发布。

  • 当check paused为yes,那么控制器只会做同步副本,也就是说把副本同步到对应的ReplicaSet中,最后在更新Deployment的状态。
  • 当check paused为false,那么控制器会跟更新副本,也就是通过Create或者Rolling的方式来更新,更新方式也是通过Create/Update/Delete ReplicaSet来实现的

ReplicaSet控制器

当Deployment分配了ReplicaSet之后,ReplicaSet控制器也是通过Informer中监听一些事件,这些事件包含了ReplicaSet和Pod的事件。ReplicaSet控制器管理副本数,使得状态向spec规定的副本数无限靠近。

Deployment控制器做了更复杂的时区,包含了版本管理。Deployment控制器把每一个版本的数量维持工作交给ReplicaSet控制器来做。

扩/缩容模拟

发布模拟

  • 若修改template中的一个容器的image,Deployment控制器会新建一个对应template2中的ReplicaSet,创建出来之后会逐渐增加ReplicaSet2 中 Pod 的数量,同时逐渐减少 ReplicaSet1 中的 Pod 数量。
  • 最终新版本的Pod为Pod4、Pod5和Pod6,旧版本的Pod被删除,这里就完成了一次发布。

回滚模拟

  • 如果此时发现当前业务版本使用有问题时,此时需要回滚,不管是通过rollout命令还是通过回滚修改template,都是把当前的templete回滚为旧版本的templete
  • 此时Deployment会修改ReplicationSet1中Pod的期望数量,把期望数量修改为3个,而且会逐渐减少新版本 ReplicaSet2 中的 replica 数量,最终的效果就是把 Pod 从旧版本重新创建出来。回滚并不是把之前的 Pod 重新找出来,而是说重新创建出符合旧版本 template 的 Pod。

spec字段解析

  • MinReadySeconds:Deployment会根据Pod ready查看Pod是否可用,默认值是0。如果设置MinReadySeconds=30(秒),Deployment会等到超过30秒以后才认为Pod是avaliable的。Pod available的前提条件是Pod ready,但ready 的Pod不一定是available的。一定要超过MinReadySeconds之后才会判断为available

  • revisionHistoryLimit:保留历史revision,即保留历史ReplicaSet的数量,默认值为10个,这里可以设置为一个或者两个,如果回滚可能性比较大的话可以设置数量超过10;

  • progressDeadlineSecond:当Deployment处于扩容或者发布状态时,pod会处于一个processing的状态,可以设置这个状态的超时时间,如果超过了这个超过时间还处于processing,那么可以认为这个Pod进入了failed的状态。

升级策略字段解析

可以在.spec.strategy字段下设置升级策略。

  • maxUnavailable:滚动升级过程中最多有多少个Pod不可用;
  • maxSurge:滚动升级过程中最多存在多少个Pod超过预期replica数量。

.spec.replicas=3的Deployment在发布时可能存在一种情况:新版本的ReplicaSet和旧版本的ReplicaSet加起来是4个,超过了期望数3个。这是因为默认的Max Unavailable和MaxSurge都是25%,默认Deployment在发布过程中,可能有25%的replicas是不可用的,也可能会有25%的replica是可用的,因此最高可以达到125%的replica数量。

这里可以根据用户实际场景来设置:当用户的资源足够时,且更注重发布过程中的可用性,此时可以设置maxUnavailable较小,maxSurge较大。但是如果用户的资源比较紧张,此时可以设置MaxSurge较小,甚至设置为0。

maxUnavailable和maxSurge不能同时为0:当MaxSurge为0时,必须要删除Pod,才能扩容Pod;当maxUnavailable为0时,限制了升级过程中无法删除Pod,因为一旦删除就会有Pod不可用。两者产生了冲突。

小结

  • Deployment时K8s中一种常见的工作负载,支持部署多版本的Pod
  • Deployment时管理多版本的方式,是针对每个版本的模版创建一个ReplicaSet,由ReplicaSet维护一盒一定数量的Pod副本,而Deployment只需要关心不同版本的ReplicaSet要制定多少数量的Pod;
  • 因此Deployment发布部署的根本原理,就是Deployment调整不同版本的ReplicaSet的中期望副本数,以此来达到多版本Pod的升级和回滚