(六)Pod 升级、回滚
本章将会以 nginx 的三个镜像版本 1.19.10、1.20.0、latest 作为实验对象
滚动更新
部署环境
# 清除旧环境
kubectl delete service nginx
kubectl delete deployment nginx
# 创建一个 Nginx 的 Deployment,副本数量为 3
kubectl create deployment nginx --image=nginx:1.19.0 --replicas=3
# 查看 images 版本
kubectl get pods
kubectl describe pods | grep -i image

更新
更新 Pod 非常简单,我们不需要控制每个 Pod 的更新,也不需要担心会不会对业务产生影响,k8s 会自动控制这些过程。我们只需要触发镜像版本更新事件,k8s 会自动为我们更新所有 Pod 的
kubectl set image 可以更新现有资源对象的容器镜像,对象包括 Pod、Deployment、DaemonSet、Job、ReplicaSet。在更新版本中,单个容器的 Pod,对于多个容器的 Pod 行为是差不多的,所以我们使用单容器 Pod 练习即可
如果镜像版本没有变化,即使是执行了 kubectl set image ,也不会产生影响
# 更新 Deployment 中的镜像版本,触发 Pod
kubectl set image deployment nginx nginx=nginx:1.20.0
# kubectl set image deployment {deployment名称} {镜像名称}:={镜像名称}:{版本}
# 查看 Pod 信息
kubectl describe pods | grep -i image
可以看到已经更新完成了,更新过程中,会创建新版本的 Pod,旧的 Pod 会被逐渐移除,这个更新时间可能不会很短,所以需要耐心等待

在创建 Deployment 时,生成了三个 Pod ,而当我们触发镜像版本更新时,Pod 不会一次性更新,而是按照一定规则每次只重新部署一部分 Pod

kubectl edit deployment nginx
修改此处,保存退出即可

上线
上线状态的意思就是 Deployment 进行一次版本更新时的执行状态,本质上是 这次 Deployment 更新是否已经完成,新的 Pod 是否已经全部成功替换旧 Pod
大白话就是 发布新版本
上线 仅当 Deployment Pod 模板(即 .spec.template)发生改变时,例如模板的标签或容器镜像被更新,才会触发 Deployment 上线
其他更新(如对 Deployment 执行扩缩容的操作)不会触发上线动作,Deployment 的上线动作可以为我们更新 Pod 的版本(Pod 中的容器版本)
这里的 上线/更新版本,因为容器版本会发生变化,而更新一般指修改了 YAML 等,不一定会对容器产生影响
# 查看 Pod 上线状态
kubectl rollout status deployment nginx
kubectl get deployment
kubectl get replicaset
kubectl get pods
上线状态输出结果一般有两种,分别是已经完成、还在更新
- deployment "nginx-deployment" successfully rolled out
- Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
可以看到有两个 ReplicaSet,nginx-687879bf49 是 1.19.0 版本,已经被全部更新到 1.20.0 版本 了,所以前者的数量为 0,我们也可以看到 Pod 中,所有 Pod 都是以 nginx-78c8c78dc7 作为前缀的,命名规则为
[deployment名称]-[ReplicaSet的哈希值]-[Pod的随机后缀] ## 滚动更新 在更新版本的时候,旧的 Pod 版本会被替换,但是 ReplicaSet 副本记录是不会被删除的,滚动更新就是控制副本数量,原本 1.19.0 的副本数为 3,现在变成 0,1.20.0 的副本数变成 3
当更新版本时,出现的一个问题就是,软件在一段时间内是处于不可用状态的,直到所有的 Pod 更新完成,Deployment 可确保在更新时仅关闭一定数量的 Pod,默认情况下,它确保至少所需 Pods 75% 处于运行状态,也就是说正在被更新的 Pod 比例不超过 25%
在当前 3 副本情况下,更新期间,通常至少有 2 个 Pod 可用,同时最多可能短暂出现 4 个新旧版本混合的 Pod,因此更新过程中看到的 Pod 总数不一定始终等于 3 个
查看上线记录
kubectl rollout history deployment nginx
kubectl rollout history deployment nginx --revision=1 (| grep -i image)
kubectl rollout history deployment nginx --revision=2 (| grep -i image)
可以看到有两个版本,但是 CHANGE-CAUSE 为 <none> ,原因是 在更新版本的时候,没有加上 --record 参数记录信息,但是通过查看 revision ,可以看到确实是镜像更新了

回滚
当部署的新版本发现严重 bug 影响平台稳定性时,可能就需要将项目切换为上一个版本
# 回滚到上一个修订
kubectl rollout undo deployment nginx
kubectl rollout status deployment nginx
# 查看信息
kubectl describe pods
# 查看记录
kubectl rollout history deployment nginx --revision=3 (| grep -i image)
revision 记录的是部署记录,与 Pod 的镜像版本无关,每次更新版本或进行回滚等操作时, revision 会自动递增 1

kubectl rollout undo deployment nginx --to-revision=2
我们创建和更新 Deployment 时,可以加上 --record 参数,可以有效的帮我查看信息
# 可以多试几次
kubectl set image deployment nginx nginx=nginx:1.19.0 --record
kubectl rollout history deployment nginx
这里会有一个警告,就是 --record 参数在当前的 kubectl 1.36.1 版本是被抛弃的

暂停上线
如果在上线过程中,发现机器不够用了,或者需要调整一些配置等,可以暂停上线过程,命令是 kubectl rollout pause
# 扩容,需要等待创建
kubectl scale deployment nginx --replicas=10
kubectl get pods
# 编辑
kubectl edit deployment nginx
《〈《〈《
# maxSurge 允许额外创建 3 个 Pod
# maxUnavailable 允许旧 Pod 每次减少 2 个
strategy:
rollingUpdate:
maxSurge: 3
maxUnavailable: 2
type: RollingUpdate
》〉》〉》
# 直接复制执行,卡住上线过程,暂停滚动更新
kubectl set image deployment nginx nginx=nginx:latest
kubectl rollout pause deployment nginx
# 查看
kubectl get replicaset
可以看到,所有的 Pod 加起来数量大于 10,旧容器以每次 2 个的数量减少;新容器以每次 3 个的数量创建

kubectl set image deployment nginx nginx=nginx:1.19.0
kubectl rollout history deployment nginx

kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi
# 恢复上线
kubectl rollout resume deployment nginx
关于发布
有广为人知的三种项目发布方式:蓝绿发布、金丝雀发布等,这些发布主要是通过网络将用户流量重新导向,让新旧版本共存,当测试没问题后,才会最终替换全部旧的版本
- 蓝绿发布是一种以最小的停机时间做服务升级的策略。 需要维护的两个版本的环境分别称为 “蓝环境” 和 “绿环境”。一般当前生产流量指向环境为绿环境,而在蓝环境上部署新版本,短时间内作为测试环境
- 红黑发布 通过两个环境完成软件版本的升级,将当前生产流量指向的环境称为红环境,新版本环境称为黑环境
- 灰度发布 属于增量发布,新老版本同时为用户提供服务。灰度发布的主要目的是保证系统的可用性。每一次的线上变更都无法保证系统 100% 的无 bug,所以变更后要在线上小范围验证,等没问题再全面放开,而金丝雀发布是灰度发布的一种实现
总结
本章涉及了 Pod 的升级和回滚以及暂停上线的知识,虽然都是些基础的内容,不必要求自己完全记住,只需要有印象就可以了
愿诸君顺遂