Kubernetes中Deployment的升级与回滚


Posted in Servers onApril 01, 2022

更新

打开 https://hub.docker.com/_/nginx 可以查询 nginx 的镜像版本,我们可以先选择一个旧一点的版本。

首先,我们创建一个 Nginx 的 Deployment,副本数量为 3。

kubectl create deployment nginx --image=nginx:1.19.0 --replicas=3

首次部署的时候,跟之前的操作一致,不需要什么特殊的命令。

注: 我们也可以加上 --record 标志将所执行的命令写入资源注解 kubernetes.io/change-cause 中。 这对于以后的检查是有用的。例如,要查看针对每个 Deployment 修订版本所执行过的命令。

其实更新 pod 是非常简单的,我们不需要控制每个 pod 的更新,也不需要担心会不会对业务产生影响,k8s 会自动控制这些过程。

我们只需要触发镜像版本更新事件,k8s 会自动为我们更新 pod 的。

kubectl set image deployment.apps/nginx nginx=nginx:1.20.0

格式为:

kubectl set image deployment.apps/{deployment名称} {镜像名称}:={镜像名称}:{版本}

我们可以查看 pod 的详细信息:

kubectl describe pods

找到 Events 描述:

... ...
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  66s   default-scheduler  Successfully assigned default/nginx-7b87485749-rlmcx to instance-2
  Normal  Pulled     66s   kubelet            Container image "nginx:1.20.0" already present on machine
  Normal  Created    66s   kubelet            Created container nginx
  Normal  Started    65s   kubelet            Started container nginx

为了记录版本更新信息,我们需要在 kubectl create deploymentkubectl set image 命令后面加上 -- --record

我们还可以通过 edit 方式更新 pod。

执行:

kubectl edit deployment nginx

然后会弹出编辑 yaml 的界面,将 .spec.template.spec.containers[0].image 从 nginx:1.19.0 更改至 nginx:1.20.0,然后保存即可。

上线

仅当 Deployment Pod 模板(即 .spec.template)发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 上线。 其他更新(如对 Deployment 执行扩缩容的操作)不会触发上线动作。Deployment 的上线动作可以为我们更新 pod 的版本。

它的上线跟我们所说的更新,有些区别。因为我们所说的更新,版本是往后的,例如 1.19.0 -> 1.20.0 ,用新版本替换旧版本才叫更新。但是 Deployment 的上线,则是任意版本。它会根据我们设置的镜像版本自动替换,可以用 1.19.0 替换 1.20.0。不过这里我们不需要纠结这些。

当我们更新 pod 版本时,k8s 会自动负载均衡,而不是把所有 pod 删除,再重新创建新版本 pod,它会以稳健的方式逐渐替换 pod。

我们可以通过命令,查看 pod 的上线状态:

kubectl rollout status deployment nginx

输出类似于:

Waiting for rollout to finish: 2 out of 3 new replicas have been updated...

或者

deployment "nginx-deployment" successfully rolled out

我们也可以通过获取 deployment 信息时,查看已更新的 pod 数量:

kubectl get deployment
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   3/3     3            3           18m

UP-TO-DATE 字段可以看到成功更新的 pod 数量。

还可以查看 ReplicaSet 和 pod:

kubectl get replicaset
kubectl get pods

输出类型于:

NAME               DESIRED   CURRENT   READY   AGE
nginx-7b87485749   0         0         0       20m
nginx-85b45874d9   3         3         3       21m
NAME                     READY   STATUS    RESTARTS   AGE
nginx-85b45874d9-nrbg8   1/1     Running   0          12m
nginx-85b45874d9-qc7f2   1/1     Running   0          12m
nginx-85b45874d9-t48vw   1/1     Running   0          12m

可以看到有两个 ReplicaSet,nginx-7b87485749 已经被全部更新到 nginx-85b45874d9 了,所以前者的数量为 0,我们也可以看到 pod 中,所有 pod 都是以 nginx-85b45874d9 作为前缀的。这几个关键信息,我们可以截图,后面再次对照。

如果我们的项目上线了,我们更新软件版本,如果一次性更新所有容器或者 pod,那么我们的软件会有一段时间处于不可用状态,直到所有 pod 都完成更新。Deployment 可确保在更新时仅关闭一定数量的 Pod,默认情况下,它确保至少所需 Pods 75% 处于运行状态,也就是说正在被更新的 pod 比例不超过 25%。当然,只有两三个 pod 的 Deployment 不会按照这个比例限定。

如果我们的 pod 数量足够大,或者在更新 Deployment 时迅速输出上线状态,可以看到新旧的 pod 数量加起来不一定就是 3 个,因为它不会杀死老 Pods,直到有足够的数量新的 Pods 已经出现。 在足够数量的旧 Pods 被杀死前并没有创建新 Pods。它确保至少 2 个 Pod 可用,同时 最多总共 4 个 Pod 可用。

Deployment 确保仅所创建 Pod 数量只可能比期望 Pods 数高一点点。 默认情况下,它可确保启动的 Pod 个数比期望个数最多多出 25%(最大峰值 25%)所以在自动更新 Deployment 时,观察到的 pod 可能为 4个。另外,在 Deployment 更新时,除了可以更改镜像的版本,也可以更改 ReplicaSet 的数量。

执行 kubectl describe deployment nginx 查看 Deployment 详细信息,我们查看 Event 字段。

Kubernetes中Deployment的升级与回滚

但是这些原理等知识我们都不需要记,也不需要深入,我们记得有这回事就行,有需要的时候也可以直接查看文档的。

回滚

默认情况下, Deployment 的上线记录都会保留在系统中,以便可以随时回滚。

我们查看 Deployment 的上线历史记录:

kubectl rollout history deployment nginx
REVISION  CHANGE-CAUSE
2         <none>
3         <none>

注:我们的版本不一定一样,因为我为了这这篇文章,进行了一些测试,可能版本数量比你的多。

可以看到有 2,3 两个版本,我们查看 版本3 的信息:

kubectl rollout history deployment nginx --revision=3
deployment.apps/nginx with revision #3
Pod Template:
  Labels:	app=nginx
	pod-template-hash=85b45874d9
  Containers:
   nginx:
    Image:	nginx:1.20.0
    Port:	<none>
    Host Port:	<none>
    Environment:	<none>
    Mounts:	<none>
  Volumes:	<none>

目前介绍了几个查看 Deployment 上线的历史记录,下面我真正来回滚 Deployment。

回滚是一个版本:

kubectl rollout undo deployment nginx

再执行 kubectl rollout history deployment nginx 会看到不一样的信息。

此时版本数量多了,我们还可以指定回滚到特点的版本。

kubectl rollout undo deployment nginx --to-revision=2

这里提一下 --record,在前面,我们创建和更新 Deployment 时,都没有使用到这个参数。我们可以试试这个参数的作用。

kubectl set image deployment.apps/nginx nginx=nginx:1.19.0
kubectl rollout history deployment nginx

输出:

REVISION  CHANGE-CAUSE
5         <none>
6         kubectl set image deployment.apps/nginx nginx=nginx:1.19.0 --record=true

说明加上了 --record ,会把我们操作时的命令记录下来。

但是我们这里目前来说,只有两个记录,我们明明提交了多次,但是这里查询的只有两条记录,这时因为我们操作的时候,只用到了 1.19.0、1.20.0 两个版本,所以也就只有这两个版本的提交记录。多用几个版本,输出结果:

REVISION  CHANGE-CAUSE
7         kubectl set image deployment.apps/nginx nginx=nginx:1.19.0 --record=true
8         kubectl set image deployment.apps/nginx nginx=nginx:1.20.0 --record=true
9         kubectl set image deployment.apps/nginx nginx=nginx:latest --record=true

缩放 Deployment

直接设置

很简单,使用 kubectl scale 命令直接设置:

kubectl scale deployment.v1.apps/nginx --replicas=10

修改 yaml 的方式也行,一是修改 yaml文件,使用 kubectl apply -f 的方式更新,或者使用 kube edit 的方式。

Pod 水平自动缩放

K8S有个 Pod 水平自动扩缩(Horizontal Pod Autoscaler) 可以基于 CPU 利用率自动扩缩 ReplicationController、Deployment、ReplicaSet 和 StatefulSet 中的 Pod 数量。

除了 CPU 利用率,也可以基于其他应程序提供的自定义度量指标 来执行自动扩缩。 Pod 自动扩缩不适用于无法扩缩的对象,比如 DaemonSet。

参考资料:https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/

命令:

kubectl autoscale deployment nginx --min=10 --max=15 --cpu-percent=80

表示目标 CPU 使用率为 80%(期望指标),副本数量配置应该为 10 到 15 之间,CPU 是动态缩放 pod 的指标,会根据具体的 CPU 使用率计算副本数量,其计算公式如下。

期望副本数 = ceil[当前副本数 * (当前指标 / 期望指标)]

算法细节请查看:https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/#algorithm-details

比例缩放

另外还有个比例缩放,允许 Deployment 支持同时运行应用程序的多个版本。

当我们设置.spec.strategy.type==RollingUpdate时,采取 滚动更新的方式更新 Pods,就可以指定 maxUnavailable 和 maxSurge 来控制滚动更新 过程。这个我们之前提到过,就是 Deployment 默认会保证一直有 75% 的 pod处于可用状态,在完成更新前可能有多个版本的 pod 共存。

这里不细说,请参考:https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/#max-unavailable

默认的话,deployment 的 yaml 是这样的:

strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate

我们可以改成:

strategy:
    rollingUpdate:
      maxSurge: 3
      maxUnavailable: 2
    type: RollingUpdate

注:执行 kubectl edit deployment nginx 直接改。

我们可以观察到这个过程:

root@instance-1:~# kubectl set image deployment nginx nginx=nginx:1.20.0
deployment.apps/nginx image updated
root@instance-1:~# kubectl get replicaset
NAME               DESIRED   CURRENT   READY   AGE
nginx-7b87485749   5         5         0       93m
nginx-85b45874d9   0         0         0       93m
nginx-bb957bbb5    8         8         8       35m

前面我们设置了最大存在两个不可用 pod(maxUnavailable=2),所以一开始会更新两个 pod,所以 nginx-bb957bbb5 8个处于可用状态。而 maxSurge 表示允许超出的期望 pod 数量,所以nginx-7b87485749 的数量不是 2 个,而是 5个,因为允许超出 3 个。其实意思就是不需要等旧的 pod 删除 一个,新的 pod 创建一个。可以多创建几个 pod,再按照慢一些的速度删除旧的 pod,最终完成版本更新。

最终:

NAME               DESIRED   CURRENT   READY   AGE
nginx-7b87485749   10        10        10      99m
nginx-85b45874d9   0         0         0       99m
nginx-bb957bbb5    0         0         0       41m

暂停 Deployment 上线

命令:

kubectl rollout pause deployment nginx

用途就是我们更新 Deployment 的 pod 版本时,可以暂停。

前面我们已经设置了这个 maxSurge 和 maxUnavailable,可以让 pod 的创建慢一些。

执行下面的命令可以快速卡住上线过程。

kubectl set image deployment nginx nginx=nginx:latest
kubectl rollout pause deployment nginx

之后,多次执行 kubectl get replicaset ,会发现副本数量不会变化。

NAME               DESIRED   CURRENT   READY   AGE
nginx-7b87485749   8         8         8       109m
nginx-85b45874d9   0         0         0       109m
nginx-bb957bbb5    5         5         5       52m

如果我们再次执行:

kubectl set image deployment nginx nginx=nginx:1.19.0

会发现虽然提示更新了,但是实际上没有变化。在暂停中,执行新的更新操作是无效的。

执行 kubectl rollout history deployment nginx 也查不到我们提交的 1.19.0 的请求。

暂停的时候,我们可以更新一些限制的 CPU 和 资源:

kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi

恢复 Deployment:

kubectl rollout resume deployment nginx

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Servers 相关文章推荐
nginx简单配置多个server的方法
Mar 31 Servers
Nginx域名转发https访问的实现
Mar 31 Servers
阿里云Nginx配置https实现域名访问项目(图文教程)
Mar 31 Servers
关于nginx 实现jira反向代理的问题
Sep 25 Servers
Kubernetes部署实例并配置Deployment、网络映射、副本集
Apr 01 Servers
Dashboard管理Kubernetes集群与API访问配置
Apr 01 Servers
docker compose 部署 golang 的 Athens 私有代理问题
Apr 28 Servers
搭建Yolov5服务器
Apr 30 Servers
使用Nginx+Tomcat实现负载均衡的全过程
May 30 Servers
netty 实现tomcat的示例代码
Jun 05 Servers
Windows server 2022创建创建林、域树、子域的步骤
Jun 25 Servers
vscode内网访问服务器的方法
Jun 28 Servers
了解Kubernetes中的Service和Endpoint
Kubernetes控制节点的部署
Apr 01 #Servers
Kubernetes部署实例并配置Deployment、网络映射、副本集
Apr 01 #Servers
iSCSI服务器CHAP双向认证配置
Apr 01 #Servers
详解使用内网穿透工具Ngrok代理本地服务
Mar 31 #Servers
Vertica集成Apache Hudi重磅使用指南
Nginx虚拟主机的配置步骤过程全解
Mar 31 #Servers
You might like
用PHP和ACCESS写聊天室(十)
2006/10/09 PHP
基于session_unset与session_destroy的区别详解
2013/06/03 PHP
解析如何在PHP下载文件名中解决乱码的问题
2013/06/20 PHP
php使用cookie保存用户登录的用户名实例
2015/01/26 PHP
Thinkphp自定义代码生成工具及用法说明(附下载地址)
2016/05/27 PHP
thinkPHP5.0框架配置格式、加载解析与读取方法
2017/03/17 PHP
ThinkPHP 3.2.3实现页面静态化功能的方法详解
2017/08/03 PHP
JS 树形递归实例代码
2010/05/18 Javascript
Js制作简单弹出层DIV在页面居中 中间显示遮罩的具体方法
2013/08/08 Javascript
JS 页面计时器示例代码
2013/10/28 Javascript
JS实现局部选择打印和局部不选择打印
2014/04/03 Javascript
iframe子页面与父页面在同域或不同域下的js通信
2014/05/07 Javascript
微信小程序--组件(swiper)详细介绍
2017/06/13 Javascript
vue项目打包后打开页面空白解决办法
2018/06/29 Javascript
JavaScript中toLocaleString()和toString()的区别实例分析
2018/08/14 Javascript
详解JavaScript中的坐标和距离
2019/05/27 Javascript
electron实现静默打印的示例代码
2019/08/12 Javascript
基于vue.js仿淘宝收货地址并设置默认地址的案例分析
2020/08/20 Javascript
使用Python解析JSON数据的基本方法
2015/10/15 Python
浅谈Python实现贪心算法与活动安排问题
2017/12/19 Python
numpy中的delete删除数组整行和整列的实例
2018/05/09 Python
pyshp创建shp点文件的方法
2018/12/31 Python
pytorch在fintune时将sequential中的层输出方法,以vgg为例
2019/08/20 Python
整理HTML5移动端开发的常用触摸事件
2016/04/15 HTML / CSS
日本网路线上商品代购服务:转送JAPAN
2016/08/05 全球购物
加拿大快时尚零售商:Ardene
2018/02/14 全球购物
ReVive利维肤美国官网:RéVive Skincare
2018/04/18 全球购物
大学毕业生工作的自我评价
2013/10/01 职场文书
大三预备党员入党思想汇报
2014/01/08 职场文书
公司新年寄语
2014/04/04 职场文书
材料化学专业求职信
2014/07/15 职场文书
党性观念心得体会
2014/09/03 职场文书
大学生学习面向未来的赶考思想汇报
2014/09/12 职场文书
后勤工作个人总结
2015/02/28 职场文书
演讲稿:​快乐,从不抱怨开始!
2019/04/02 职场文书
公司致全体员工的感谢信
2019/06/24 职场文书