【阿里云&CNCF视频系列】第6课-应用编排与管理: Deployment(管理部署发布的控制器)

目录

 

0.引入

1.需求来源

1.1背景问题

1.2解决方案

2.用例解读

2.1Deployment语法

2.2查看Deployment状态

2.3查看Pod

2.4更新镜像

2.5快速回滚

2.6DeploymentStatus(部署状态)

3.操作演示

3.1查看当前集群的nodes

3.2创建对应的 deployment

3.3查看Deployment 的结构 

3.4查看pods

3.5选择一个Pod看一下状态

3.6查看最新的副本集合并升级deployment

3.7历史版本保留 revisionHistoryLimit

3.8回滚

3.9命令总结

4.架构设计

4.1管理模式

4.2Deployment 控制器

4.3ReplicaSet 控制器

4.4扩容模拟 

4.5发布模拟

4.6回滚模拟

4.7 spec 字段解析

4.8升级策略字段解析

5.课后思考实践


 

0.引入

阿里云原生官方关于本节内容的笔记

1.需求来源

1.1背景问题

1.2解决方案

可以看到我们通过 Deployment 将应用A、B、C分别规划到不同的Deployment中,每个Deployment其实
是管理的一组相同的应用Pod,这组Pod我们认为它是相同的一个副本,那么Deployment能帮我们做什么事
情呢?

首先,Deployment定义了一种Pod期望数量,比如说应用A,我们期望Pod数量是四个,那么这样的话,
controller就会持续维持Pod数量为期望的数量.当我们与Pod出现了网络问题或者宿主机问题的话,
controller能帮我们恢复,也就是新扩出来对应的Pod,来保证可用的Pod数量与期望数量一致;


配置Pod发布方式,也就是说controller会按照用户给定的策略来更新Pod,而且更新过程中,也可以设定
不可用Pod数量在多少范围内;


如果更新过程中发生问题的话,即所谓“一键”回滚,也就是说你通过一条命令或者一行修改能够将Deployment 
下面所有Pod更新为某一个旧版本.

2.用例解读

2.1Deployment语法

上图可以看到一个最简单的Deployment的yaml文件.

“apiVersion:apps/v1”,也就是说Deployment当前所属的组是apps,版本是v1.“metadata”是我们看到的 
Deployment元信息,也就是往期回顾中的Labels、Selector、Pod.image,这些都是在往期中提到的知识点.


Deployment作为一个K8s资源,它有自己的metadata元信息,这里我们定义的Deployment.name是nginx.Deployment.

Deployment.spec中首先要有一个核心的字段,即replicas,这里定义期望的Pod数量为三个;
selector其实是Pod选择器,那么所有扩容出来的Pod,它的Labels必须匹配selector层上的image.labels,
也就是app.nginx。

就如上面的Pod模板template中所述,这个template它其实包含了两部分内容:

(1)我们期望Pod的metadata,其中包含了labels,即跟selector.matchLabels相匹配的一个Labels;
(2)template包含的一个 Pod.spec,这里 Pod.spec其实是 Deployment,最终创建出来Pod的时候,
它所用的Pod.spec,这里定义了一个container.nginx,它的镜像版本是 nginx:1.7.9.

下面是遇到的新知识点:
(1)replicas-是Deployment中期望的或者终态数量;
(2)template-是Pod 相关的一个模板.

 

2.2查看Deployment状态

当我们创建出一个Deployment的时候,可以通过kubectl get deployment,看到Deployment总体的一个状态.
上图中可以看到:
DESIRED:期望的Pod数量是3个;
CURRENT:当前实际Pod数量是3个;
UP-TO-DATE:其实是到达最新的期望版本的Pod数量;
AVAILABLE:这个其实是运行过程中可用的Pod数量,后面会提到,这里AVAILABLE并不简单是可用的,也就是 
Ready状态的,它其实包含了一些可用超过一定时间长度的Pod;
AGE:deployment创建的时长,如上图Deployment就是已经创建了80分钟.

2.3查看Pod

最后我们可以查看一下Pod,如上图所示:
上图中有三个Pod,从Pod名字格式我们不难看到.

最前面一段:nginx-deployment,其实是Pod所属Deployment.name;
中间一段:template-hash,这里三个Pod是一样的,因为这三个Pod其实都是同一个template中创建出来的.


最后一段,是一个random的字符串,我们通过get.pod可以看到,Pod的ownerReferences即Pod所属的 
controller资源,并不是Deployment,而是一个 ReplicaSet.这个ReplicaSet的name,其实是nginx-
deployment加上pod.template-hash,后面会提到.所有的Pod都是ReplicaSet创建出来的,
而ReplicaSet它对应的某一个具体的Deployment.template版本.

 

2.4更新镜像

接下来我们可以看一下,如何对一个给定的Deployment更新它所有Pod的镜像版本呢?这里我们可以执行一个
kubectl命令:

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


首先 kubectl 后面有一个set image 固定写法,这里指的是设定镜像;其次是一个 deployment.v1.apps,
这里也是一个固定写法,写的是我们要操作的资源类型,deployment 是资源名、v1 是资源版本、apps是资源
组,这里也可以简写为deployment或者deployment.apps,比如说写为deployment的时候,默认将使用apps组 
v1版本.

第三部分是要更新的deployment的name,也就是我们的nginx-deployment;再往后的nginx其实指的是 
template,也就是Pod中的container.name;这里我们可以注意到:一个Pod 中,其实可能存在多个container,
而我们指定想要更新的镜像的container.name,就是nginx.

最后,指定我们这个容器期望更新的镜像版本,这里指的是nginx:1.9.1.
如下图所示:当执行完这条命令之后,可以看到deployment中的template.spec已经更新为nginx: 1.9.1。

2.5快速回滚

如果我们在发布过程中遇到了问题,也支持快速回滚.
通过kubectl执行的话,其实是“kubectl rollout undo”这个命令,可以回滚到Deployment 上一版本;
通过“rollout undo”加上“to-revision”来指定可以回滚到某一个具体的版本.

 

2.6DeploymentStatus(部署状态)

前面的课程我们学习到,每一个资源都有它的spec.Status.这里可以看一下,deploymentStatus中描述的
三个其实是它的conversion状态,也就是Processing、Complete以及Failed.

以 Processing 为例:Processing 指的是Deployment正在处于扩容和发布中.比如说Processing状态的 
deployment,它所有的replicas及Pod副本全部达到最新版本,而且是available,这样的话,就可以进入
complete状态.而complete状态如果发生了一些扩缩容的话,也会进入processing这个处理工作状态.

如果在处理过程中遇到一些问题:比如说拉镜像失败了,或者说 readiness probe检查失败了,就会进入 
failed 状态;如果在运行过程中即complete状态,中间运行时发生了一些pod readiness probe检查失
败,这个时候deployment也会进入failed状态.进入failed状态之后,除非所有点replicas均变成 
available,而且是updated最新版本,deployment才会重新进入complete状态.

3.操作演示

3.1查看当前集群的nodes

3.2创建对应的 deployment

创建对应的deployment,可以看到deployment中的desired、current、up-to-date以及available
已经都达到了可用的期望状态。

3.3查看Deployment 的结构 

用kubectl edit deployment nginx-deployment(:q退出编辑)查看Deployment的结构.
这里看到spec中的replicas是三个,selector以及template labels中定义的标签都是app:nginx,
spec中的image是我们期望的nginx: 1.7.9;status中的available.replicas,readReplicas以及
updatedReplicas都是3个.

3.4查看pods

3.5选择一个Pod看一下状态

我们可以再选择一个Pod看一下状态,命令如3.4中所示.

可以看到:
Pod中ownerReferences的功能(kind那一项)是ReplicaSet;
pod.spec.container 里的镜像是 1.7.9.
这个Pod已经是Running状态,而且它的conditions.status是“true”,表示它的服务已经可用了.

3.6查看最新的副本集合并升级deployment

avatar

kubectl set image”这个操作命令,后面接“deployment”,加deployment.name,最后指定容器名,以及我
们期望升级的镜像版本.

接下来我们看下deployment中的template中的image已经更新为1.9.1

这个时候我们再 get pod 看一下状态:

avatar

三个 pod 已经升级为新版本,pod 名字中的 pod-template-hash 也已更新:

avatar

可以看到:旧版本 replicaset 的 spec 数量以及 pod 数量是都是 0,新版本的 pod 数量是 3 个。

假设又做了一次更新,这个时候 get.pod 其实可以看到:当前的 pod 其实是有两个旧版本的处于 running,另一个旧版本是在删除中;

而两个新版本的 pod,一个已经进入 running,一个还在 creating 中。

这时我们可用的 pod 数量即非删除状态的 pod 数量,其实是 4 个,已经超过了 replica 原先在 deployment 设置的数量 3 个。

这个原因是我们在 deployment 中有 maxavailable 和 maxsugar 两个操作,这两个配置可以限制我们在发布过程中的一些策略。在后面架构设计中会讲到这个问题。

avatar

3.7历史版本保留 revisionHistoryLimit

上图看到,我们当前最新版本的 replicaset 是 3 个 pod,另外还有两个历史版本的 replicaset,那么会不会存在一种情况:就是随着 deployment 持续的更新,

这个旧版本的 replicaset 会越积越多呢?其实 deployment 提供了一个机制来避免这个问题:在 deployment spec 中,有一个 revisionHistoryLimit,它的默认

值为 10,它其实保证了保留历史版本的 replicaset 的数量,我们尝试把它改为 1。

avatar

avatar

由上面第二张图,可以看到两个 replicaset,也就是说,除了当前版本的 replicaset 之外,旧版本的 replicaset 其实只保留了一个。

3.8回滚

最后再尝试做一下回滚。首先再来看一下 replicaset,这时发现旧版本的 replicaset 数量从 0 个增到 2 个,而新版本的 replicaset 数量从 3 个削减

为 2 个,表示它已经开始在做回滚的操作。然后再观察一下, 旧版本的数量已经是 3 个,即已经回滚成功,而新版本的 pod 数量变为 0 个。

avatar

我们最后再 get pod 看一下:

avatar

这时,3 个 pod.template-hash 已经更新为旧版本的 hash,但其实这 3 个 pod 都是重新创建出来的,而并非我们在前一版本中创建的 3 个 pod。换句话说,

也就是我们回滚的时候,其实是创建了 3 个旧版本的 pod,而并非把先前的 3 个 pod 找回来。

3.9命令总结

kubectl create -f nginx-deployment.yaml	按照配置文件nginx-deployment.yaml进行部署
kubectl get deployment	查看部署信息
kubectl edit deployment nginx-deployment	编辑部署文件nginx-deployment,:q退出
kubectl get pod	查看pod的情况
kubectl get pod/nginx-deployment-5c689d88bb-ck974 -o yaml	查看编号为nginx-deployment-5c689d88bb-ck974的pod的情况并输出到yaml文件中
kubectl edit pod nginx-deployment-5c689d88bb-ck974	编辑编号为nginx-deployment-5c689d88bb-ck974的pod,:q退出
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1	更新镜像
kubectl rollout undo deployment/nginx-deployment	回滚到当前部署的上一个版本
kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2	回滚到某一个具体的版本
kubectl get nodes	查看当前集群的nodes

 

4.架构设计

4.1管理模式

avatar

管理模式:Deployment 只负责管理不同版本的 ReplicaSet,由 ReplicaSet 来管理具体的 Pod 副本数,每
个 ReplicaSet 对应 Deployment template 的一个版本。在上文的例子中可以看到,每一次修改 
template,都会生成一个新的 ReplicaSet,这个 ReplicaSet 底下的 Pod 其实都是相同的版本。


如上图所示:Deployment 创建 ReplicaSet,而 ReplicaSet 创建 Pod。他们的 OwnerRef 其实都对应了其
控制器的资源。

 

4.2Deployment 控制器

avatar

我们所有的控制器都是通过 Informer 中的 Event 做一些 Handler 和 Watch。这个地方 Deployment 控制
器,其实是关注 Deployment 和 ReplicaSet 中的 event,收到事件后会加入到队列中。而 Deployment 
controller 从队列中取出来之后,它的逻辑会判断 Check Paused,这个 Paused 其实是 Deployment 是否
需要新的发布,如果 Paused 设置为 true 的话,就表示这个 Deployment 只会做一个数量上的维持,不会做
新的发布。


如上图,可以看到如果 Check paused 为 Yes 也就是 true 的话,那么只会做 Sync replicas。也就是说把
 replicas sync 同步到对应的 ReplicaSet 中,最后再 Update Deployment status,那么 controller 
这一次的 ReplicaSet 就结束了。


那么如果 paused 为 false 的话,它就会做 Rollout,也就是通过 Create 或者是 Rolling 的方式来做更
新,更新的方式其实也是通过 Create/Update/Delete 这种 ReplicaSet 来做实现的。

4.3ReplicaSet 控制器

如上图,可以看到如果 Check paused 为 Yes 也就是 true 的话,那么只会做 Sync replicas。也就是说把 
replicas sync 同步到对应的 ReplicaSet 中,最后再 Update Deployment status,那么 controller 这
一次的 ReplicaSet 就结束了。

那么如果 paused 为 false 的话,它就会做 Rollout,也就是通过 Create 或者是 Rolling 的方式来做更
新,更新的方式其实也是通过 Create/Update/Delete 这种 ReplicaSet 来做实现的。


当 Deployment 分配 ReplicaSet 之后,ReplicaSet 控制器本身也是从 Informer 中 watch 一些事件,这
些事件包含了 ReplicaSet 和 Pod 的事件。从队列中取出之后,ReplicaSet controller 的逻辑很简单,就
只管理副本数。也就是说如果 controller 发现 replicas 比 Pod 数量大的话,就会扩容,而如果发现实际
数量超过期望数量的话,就会删除 Pod。

上面 Deployment 控制器的图中可以看到,Deployment 控制器其实做了更复杂的事情,包含了版本管理,而它
把每一个版本下的数量维持工作交给 ReplicaSet 来做。

4.4扩容模拟 

下面来看一些操作模拟,比如说扩容模拟。这里有一个 Deployment,它的副本数是 2,对应的 ReplicaSet 
有 Pod1 和 Pod2。这时如果我们修改 Deployment replicas, controller 就会把 replicas 同步到当前
版本的 ReplicaSet 中,这个 ReplicaSet 发现当前有 2 个 Pod,不满足当前期望 3 个,就会创建一个新的 
Pod3。

4.5发布模拟

我们再模拟一下发布,发布的情况会稍微复杂一点。这里可以看到 Deployment 当前初始的 template,比如说 
template1 这个版本。template1 这个 ReplicaSet 对应的版本下有三个 Pod:Pod1,Pod2,Pod3。

这时修改 template 中一个容器的 image, Deployment controller 就会新建一个对应 template2 的 
ReplicaSet。创建出来之后 ReplicaSet 会逐渐修改两个 ReplicaSet 的数量,比如它会逐渐增加 
ReplicaSet2 中 replicas 的期望数量,而逐渐减少 ReplicaSet1 中的 Pod 数量。

那么最终达到的效果是:新版本的 Pod 为 Pod4、Pod5和Pod6,旧版本的 Pod 已经被删除了,这里就完成了一
次发布。

4.6回滚模拟

来看一下回滚模拟,根据上面的发布模拟可以知道 Pod4、Pod5、Pod6 已经发布完成。这时发现当前的业务版
本是有问题的,如果做回滚的话,不管是通过 rollout 命令还是通过回滚修改 template,它其实都是把 
template 回滚为旧版本的 template1。

这个时候 Deployment 会重新修改 ReplicaSet1 中 Pod 的期望数量,把期望数量修改为 3 个,且会逐渐减
少新版本也就是 ReplicaSet2 中的 replica 数量,最终的效果就是把 Pod 从旧版本重新创建出来。


发布模拟的图中可以看到,其实初始版本中 Pod1、Pod2、Pod3 是旧版本,而回滚之后其实是 Pod7、Pod8、
Pod9。就是说它的回滚并不是把之前的 Pod 重新找出来,而是说重新创建出符合旧版本 template 的 Pod。

4.7 spec 字段解析

最后再来简单看一些 Deployment 中的字段解析。首先看一下 Deployment 中其他的 spec 字段:

MinReadySeconds:Deployment 会根据 Pod ready 来看 Pod 是否可用,但是如果我们设置了 
MinReadySeconds 之后,比如设置为 30 秒,那 Deployment 就一定会等到 Pod ready 超过 30 秒之后才认
为 Pod 是 available 的。Pod available 的前提条件是 Pod ready,但是 ready 的 Pod 不一定是 
available 的,它一定要超过 MinReadySeconds 之后,才会判断为 available;

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


paused:paused 是标识,Deployment 只做数量维持,不做新的发布,这里在 Debug 场景可能会用到;


progressDeadlineSeconds:前面提到当 Deployment 处于扩容或者发布状态时,它的 condition 会处于一
个 processing 的状态,processing 可以设置一个超时时间。如果超过超时时间还处于 processing,那么 
controller 将认为这个 Pod 会进入 failed 的状态

4.8升级策略字段解析

升级策略字段解析
最后来看一下升级策略字段解析。

Deployment 在 RollingUpdate 中主要提供了两个策略,一个是 MaxUnavailable,另一个是 MaxSurge。这两个字段解析的意思,可以看下图中详细的 comment,或者简单解释一下:

MaxUnavailable:滚动过程中最多有多少个 Pod 不可用;
MaxSurge:滚动过程中最多存在多少个 Pod 超过预期 replicas 数量。
上文提到,ReplicaSet 为 3 的 Deployment 在发布的时候可能存在一种情况:新版本的 ReplicaSet 和旧版本的 ReplicaSet 都可能有两个 replicas,加在一起就是 4 个,超过了我们期望的数量三个。这是因为我们默认的 MaxUnavailable 和 MaxSurge 都是 25%,默认 Deployment 在发布的过程中,可能有 25% 的 replica 是不可用的,也可能超过 replica 数量 25% 是可用的,最高可以达到 125% 的 replica 数量。

这里其实可以根据用户实际场景来做设置。比如当用户的资源足够,且更注重发布过程中的可用性,可设置 MaxUnavailable 较小、MaxSurge 较大。但如果用户的资源比较紧张,可以设置 MaxSurge 较小,甚至设置为 0,这里要注意的是 MaxSurge 和 MaxUnavailable 不能同时为 0。

理由不难理解,当 MaxSurge 为 0 的时候,必须要删除 Pod,才能扩容 Pod;如果不删除 Pod 是不能新扩 Pod 的,因为新扩出来的话,总共的 Pod 数量就会超过期望数量。而两者同时为 0 的话,MaxSurge 保证不能新扩 Pod,而 MaxUnavailable 不能保证 ReplicaSet 中有 Pod 是 available 的,这样就会产生问题。所以说这两个值不能同时为 0。用户可以根据自己的实际场景来设置对应的、合适的值。

5.课后思考实践

练习本节内容.

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值