前言
在上一篇我们聊了k8s中各种控制器的使用,本篇将以控制器中比较常用的一种控制器Deployment 进行详细的说明。
一、Deployment 简介
为了更好解决服务编排的问题,kubernetes在V1.2版本开始,引入了Deployment控制器;
需要说明的是,Deployment控制器并不直接管理pod,而是通过管理ReplicaSet来简介管理Pod,即:Deployment管理ReplicaSet,ReplicaSet管理Pod,所以Deployment比ReplicaSet功能更加强大。
二、Deployment 功能
Deployment主要功能如下:
- 支持ReplicaSet的所有功能;
- 支持发布的停止、继续;
- 支持滚动升级和回滚版本;
三、Deployment 配置文件核心参数说明
如下为Deployment配置模板文件中的部分参数,结合备注进行理解
apiVersion: apps/v1 # 版本号
kind: Deployment # 类型
metadata: # 元数据
name: # rs名称
namespace: # 所属命名空间
labels: #标签
controller: deploy
spec: # 详情描述
replicas: 3 # 副本数量
revisionHistoryLimit: 3 # 保留历史版本
paused: false # 暂停部署,默认是false
progressDeadlineSeconds: 600 # 部署超时时间(s),默认是600
strategy: # 策略
type: RollingUpdate # 滚动更新策略
rollingUpdate: # 滚动更新
max违规词汇: 30% # 最大额外可以存在的副本数,可以为百分比,也可以为整数
maxUnavailable: 30% # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
selector: # 选择器,通过它指定该控制器管理哪些pod
matchLabels: # Labels匹配规则
app: nginx-pod
matchExpressions: # Expressions匹配规则
- {key: app, operator: In, values: [nginx-pod]}
template: # 模板,当副本数量不足时,会根据下面的模板创建pod副本
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
Deployment 操作演示
在当前目录下创建deployment-ep.yaml配置文件,内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-eam
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
执行下面的命令进行deployment和pod的创建
kubectl create -f deployment-ep.yaml
上述结果参数说明
- UP-TO-DATE 最新版本的pod的数量;
- AVAILABLE 当前可用的pod的数量
通过查看rs与pod的信息,再次印证了本文开篇的时候 deployment,rs以及与pod的对应关系;
三、Deployment 扩缩容
在实际生产中,随着业务量上升或下降,有必要对运行中Pod数量进行扩缩容,从而达到合理的利用机器的资源的目的;
使用Deployment 进行扩容或缩容比较简单,可以通过命令的方式直接变更,或修改yaml的形式;
使用命令行操作
在上面的操作中,通过Deployment创建了3个Pod;
变更副本数量为5个
kubectl scale deploy deployment-eam --replicas=5 -n default
执行之后,可以看到此时当前的Deployment下面就有5个Pod了;
在线编辑Deployemnt配置文件
使用下面的命令在线编辑Deployment配置文件进行修改
kubectl edit deploy deployment-eam -n default
找到下面这个地方,将其修改为3
保持退出之后,查看Pod可以看到此时Pod的数量就发生了变化
四、Deployment 升级策略
deployment支持两种更新策略:重建更新,滚动更新;
重建更新:旧的Pod直接删掉,然后创建新的;
滚动更新:一边删除旧版本Pod,同时再创建新版本的Pod(整个过程中,新老版本并存);
更新策略可以通过strategy指定策略类型,支持两个属性,配置选项如下:
strategy:指定新的Pod替换旧的Pod的策略, 支持两个属性:
type:指定策略类型,支持两种策略
Recreate:在创建出新的Pod之前会先杀掉所有已存在的Pod
RollingUpdate:滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本Pod
rollingUpdate:当type为RollingUpdate时生效,用于为RollingUpdate设置参数,支持两个属性:
maxUnavailable:用来指定在升级过程中不可用Pod的最大数量,默认为25%
max违规词汇: 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为25%
重建更新策略操作演示
1)在配置文添加如下配置参数
2)启动Pod
kubectl apply -f deployment-ep.yaml
3)开启另一个窗口,监测当前Pod的变动情况
目前可以看到有3个Pod处于运行中;
4)更新镜像
使用下面的命令对镜像进行更新
kubectl set image deploy 上面的deployment名称 nginx=nginx:1.17.2 -n default
执行上述命令之后,通过监测窗口的输出变化信息,很明显,这种更新策略,就是按照先干掉老的Pod再创建新Pod的过程完成镜像的更新;
滚动更新策略操作演示
将配置更新策略的位置修改为滚动更新
删除上面的deployment,然后重新创建deployment
再次进行镜像更新
kubectl set image deploy 上面的deployment名称 nginx=nginx:1.17.3 -n default
通过另一个窗口监测Pod的信息变化,从下图中展示的STATUS的变化,不难发现,整个过程中,之前正在运行中的Pod和新的Pod是一个你来我往的交替的过程,简单来说,就是一边开启新的Pod,一边停止老的Pod,直到新的Pod全部更新完成为止;
五、Deployment 实现版本回退
版本回退这个概念对于很多使用过docker部署微服务的同学来说并不陌生,在使用docker部署微服务的时候,只需要给制作好的镜像打上版本标签,如果最新的版本上线有严重的bug,只需快速找到某个标签版本的镜像就可以快速完成版本的回退;
从上面的这张图可以了解到,Deployment是通过控制res来达到控制Pod的目的,在上述演示升级策略的过程中,我们通过另一个窗口监测到了Deployment和Pod的变化情况,对于Deployment,如果要实现版本回退该怎么做呢?
在创建Deployment过程中,通过指定 record 可以记录本次的版本信息
接下来通过实际操作,演示下record在版本回退中的作用;
1、创建Deployment并使用record
kubectl create -f deployment.yaml --record=true
也可以具体的查看下rs的详细信息,此时运行着如下这个rs,可以记住其尾号为:4f89;
2、执行镜像更新
kubectl set image deploy deployment名称 nginx=nginx:1.17.3 -n default
deployment信息
rs 信息
从rs的变化过程来看,对于4f89 ,即之前的rs来说,其下面挂着3个Pod,随着执行镜像更新策略,之前的Pod在不断的停止,所以从rs的信息来看,4f89下面的Pod数量逐渐减少;
同时,产生了一个新的尾号为8b8c的rs,随着时间的推移,这个rs下面的Pod数量从1开始,直到增加到3个,这么来看就容易理解了,简而言之:
带有record参数的镜像更新的过程中,老的rs下面的Pod逐渐减少并销毁,新产生的rs下的Pod逐渐增加,最后停止之前的rs;
用一张图来看,整个过程的经历,大概长下面这样
等待跟新的过程完成之后再次查看rs的信息,可以看到集群中老的rs下已经没有Pod了;
为什么k8s并没有将这个老的rs一起删掉呢?因为这个rs就是后面用于版本回退使用的
3、版本回退
deployment支持版本升级过程中的暂停、继续功能以及版本回退等诸多功能,即:kubectl rollout,支持下面的选项:
- status 显示当前升级状态;
- history 显示 升级历史记录;
- pause 暂停版本升级过程;
- resume 继续已经暂停的版本升级过程;
- restart 重启版本升级过程;
- undo 回滚到上一级版本(可以使用--to-revision回滚到指定版本);
基于上面演示使用的Pod,使用rollout进行版本回退
查看当前升级版本的状态
kubectl rollout status deploy deployment名称 -n default
查看升级历史记录
kubectl rollout history deploy deployment名称 -n default
此时如果再升级一个版本,然后再看看升级历史记录信息,可以看到此时的最大版本号来到3;
此时,查看rs的信息也能发现,升级到最新的那个rs下面挂着3个Pod;
执行版本回退
kubectl rollout undo deployment pc-deployment --to-revision=1 -n default
执行完成后,再次查看rs的信息,不难发现这时候集群中的Pod重新挂在第一次创建的那个rs下面了;
关于回退参数说明
- --to-revision=1回滚到了1版本,版本号可以自己指定,即你想回退到的某个历史版本号;
- 如果省略这个选项,就回退到上个版本,即上图中的3个版本的第二个版本(当前版本为3)
六、Deployment 实现金丝雀发布
在生产环境的版本变更中,金丝雀发布这个概念,对很多同学来说并不陌生,一种典型的应用场景就是,整个发布过程中,新旧版本同时存在,这样一部分流量打到新服务,一部分服务仍然打到老的服务,这样在确保整体服务的可用性同时,还能让一部分用户体验新功能的目的;
在上面的版本回退相关的参数中,还有pause和resume这两个参数没有提到,Deployment控制器支持控制更新过程中的控制,如“暂停(pause)”或“继续(resume)”更新操作。
Deployment中的金丝雀发布可以如下理解;
例如,有一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本。然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望的方式运行。确定没问题之后再继续完成余下的Pod资源滚动更新,否则立即回滚更新操作,这就是所谓的金丝雀发布。
操作演示
更新deployment版本,并配置暂停deployment
kubectl set image deploy deployment名称 nginx=nginx:1.17.4 -n default && kubectl rollout pause deployment deployment名称 -n default
该命令的意思可以理解为升级当前的Pod-nginx版本为1.17.4,升级过程中,立即使用pause暂停版本升级过程,执行上面的命令观察效果;
查看rs变化
从rs的信息展示来看,执行命令之后,集群中同时存在两个rs,一个rs下面挂了3个Pod,另一个rs里面挂了一个Pod,不难理解,上面的命令前半部分执行没多久,老的Pod还来不及停止,新的Pod还没有完全创建完成就被Pause了;
查看更新状态
kubectl rollout status deploy deployment名称 -n default
这段信息意思大概是:等待当前的deployment更新,新的rs中,3个Pod中有1个Pod得到了更新;
确保更新的pod没问题之后,继续更新
kubectl rollout resume deploy deployment名称 -n default
观察rs的变化情况
观察更新状态的变化信息,不难理解,其反应的状态正好就是老的Pod停止,而新的rs下面的Pod更新的过程;