浅入Kubernetes(12):Deployment 的升级、回滚
本篇内容讨论 Pod 的更新和回滚,内容不多。
更新
打开 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 deployment
、kubectl 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 字段。
但是这些原理等知识我们都不需要记,也不需要深入,我们记得有这回事就行,有需要的时候也可以直接查看文档的。
会滚
默认情况下, 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
浅入Kubernetes(12):Deployment 的升级、回滚的更多相关文章
- 浅入Kubernetes(11):了解 Service 和 Endpoint
目录 Srevice Service 的创建及现象 Service 定义 Endpoint slices 创建 Endpoint.Service Service 创建应用 创建 Endpoint 浅入 ...
- 浅入Kubernetes(8):外网访问集群
目录 查询 Service Service 外部服务类型 配置 ServiceType 伸缩数量 阶段总结 在前面几篇文章中,我们学习了 kubeadm .kubectl 的一些命令,也学会了 Dep ...
- 浅入Kubernetes(6):CKAD认证中的部署教程
目录 预设网络 kubeadm 安装 k8s 配置 calico 自动补全工具 状态描述 目前为止,笔者已经写了 5 篇关于 k8s 的文章,这一篇笔者将介绍 CKAD 认证官方课程中,如何部署 k8 ...
- 入门Kubernetes - 滚动升级/回滚
一.前言 上一篇文章中对yaml文件格式进行了解,并对k8s中各种主要资源通过yaml创建时的定义模板.接来下就进一步学习k8s的各种特点.并应用在示例中. 接下来先实现.Net Core Api程序 ...
- kubernetes之deployment滚动升级
参考:https://blog.51cto.com/wutengfei/2116663 创建和管理多个Pod--Deployment Deployment 为 Pod 和 ReplicaSet 提供了 ...
- Swarm平滑升级回滚
#滚动更新创建服务: docker service create --name my_web --replicas=5 nginx:1.12更新为1.14 docker service update ...
- 浅入Kubernetes(7):应用部署实例,Deployment、Service、ReplicaSet
目录 Deployment 创建 Deployment kubectl apply/create 网络端口映射和更新 Deployment ReplicaSet 在本文之前,你需要阅读: 尝试 kub ...
- 浅入kubernetes(2):Kubernetes 的组成
目录 说明 Kubernetes集群的组成 What are containerized applications? What are Kubernetes containers? What are ...
- 浅入kubernetes(1):Kubernetes 入门基础
目录 Kubernetes 入门基础 Introduction basic of kubernetes What Is Kubernetes? Components of Kubernetes Kub ...
随机推荐
- where & having 关键字
where和having都是做条件筛选的 where执行的时间比having要早 where后面不能出现组函数 having后面可以出现组函数 where语句要跟在from后面 ,where 不能单独 ...
- Vue前端项目的搭建流程
1. 安装Vue和Nodejs 2. 创建项目 vue create eduonline-web
- Java数组之二分查找
简单的二分查找 package com.kangkang.array; public class demo03 { public static void main(String[] args) { / ...
- vue核心---虚拟dom的实现
生成dom的过程 由vue模板生成虚拟dom 虚拟dom转换成真实dom渲染到html页面 代码实现 要实现的真实dom <div id="box"> <p cl ...
- Python3+pygame实现的90坦克大战 代码完整 有演示效果
我是一个典型的80后,年轻时玩过了特别多的游戏,所以这几天用Python3+pygame实现了一个另外小游戏"坦克大战"(其他的游戏,请翻阅我的博客) 本实例代码量有些多,完整的版 ...
- 2020年12月-第02阶段-前端基础-CSS Day02
CSS Day02 复合选择器 后代选择器 并集选择器 1. CSS复合选择器 理解 理解css复合选择器分别的应用场景 为什么要学习css复合选择器 CSS选择器分为 基础选择器 和 复合选择器 , ...
- 前端学习 node 快速入门 系列 —— 初步认识 node
其他章节请看: 前端学习 node 快速入门 系列 初步认识 node node 是什么 node(或者称node.js)是 javaScript(以下简称js) 运行时的一个环境.不是一门语言. 以 ...
- ubuntu18.04+gunicorn+nginx+supervisor+mysql+redis安装django项目
Ubuntu18.04 install Django project 项目准备: ECS 实例 (云服务器) 此安装部署方案适合本地ubuntu18.04系统安装和虚拟机中ubuntu18.04系统安 ...
- 对于如何从SM2的pfx证书文件中解析公钥和私钥,并从二次加密的密文中解密
首先呢,由于我的域名之前处理点问题,然后备案第二个网站时候,第一个网站没法访问,所以备案没过,阿里云告诉我要删除一个网站的备案,但是他没告诉我要删除主体,所以我的备案主体成了空壳主体,要传真或者发快递 ...
- Shell编程中变量用法
1. 变量替换 语法 说明 ${变量名#匹配规则} 从变量开头进行规则匹配,将符合最短的数据删除 ${变量名##匹配规则} 从变量开头进行规则匹配,将符合最长的数据删除,贪婪匹配 ${变量名%匹配规则 ...