K8s如何实现滚动升级#
k8s滚动更新机制:#
k8s创建副本应用程序的最佳方法就是部署(Deployment),部署自动创建副本集(ReplicaSet),副本集可以精确地控制每次替换的Pod数量,从而可以很好的实现滚动更新。具体来说,k8s每次使用一个新的副本控制器(replication controller)来替换已存在的副本控制器,从而始终使用一个新的Pod模板来替换旧的pod模板。
大致步骤如下:
- 创建一个新的replication controller。
- 增加或减少pod副本数量,直到满足当前批次期望的数量。
- 删除旧的replicationplication controller。
#### 实战演示:
使用kubectl更新一个已部署的应用程序,并模拟回滚。为了方便分析,将应用程序的pod副本数量设置为10。
扩容副本数量
<pre><code class="language-bash">kubectl -n k8s-apps scale deployment helloworldapi --replicas=10</code></pre>
模拟一下nginx服务
查看部署列表
kubectl get deployments -n k8s-apps
查看在运行的pod
kubectl get pods -n k8s-apps
通过pod描述,查看应用程序的当前映像版本,这里应该是能看到创建的10个副本
[root@OPPO-test ~]# kubectl describe pods helloworldapi-68d7f6dd8-6tqgl -n k8s-apps | grep image
Normal Pulled 55s kubelet, k8s-2 Container image "nginx:1.16.0" already present on machine
得知该镜像使用的是1.16.0版本的nginx镜像。现在需要将其升级到1.17.0
[root@OPPO-test ~]# kubectl -n k8s-apps set image deployment/helloworldapi nginx=nginx:1.17.0 --record
deployment.apps/helloworldapi image updated
验证升级成功:
检查rollout状态
[root@OPPO-test ~]# kubectl -n k8s-apps rollout status deployments/helloworldapi
Waiting for deployment "helloworldapi" rollout to finish: 9 out of 10 new replicas have been updated...
Waiting for deployment "helloworldapi" rollout to finish: 9 out of 10 new replicas have been updated...
Waiting for deployment "helloworldapi" rollout to finish: 9 out of 10 new replicas have been updated...
Waiting for deployment "helloworldapi" rollout to finish: 9 out of 10 new replicas have been updated...
Waiting for deployment "helloworldapi" rollout to finish: 9 out of 10 new replicas have been updated...
Waiting for deployment "helloworldapi" rollout to finish: 9 out of 10 new replicas have been updated...
Waiting for deployment "helloworldapi" rollout to finish: 2 old replicas are pending termination...
正在挨个升级
检查镜像版本
和上面一样的命令
kubectl describe pods -n k8s-apps | grep image
回滚发布
[root@OPPO-test ~]# kubectl -n k8s-apps rollout undo deployments/helloworldapi
deployment.apps/helloworldapi rolled back
查看版次
kubectl -n k8s-ecoysystem-apps rollout history deployment/helloworldapi
回滚到指定版次
kubectl -n k8s-ecoysystem-apps rollout undo deployment/helloworldapi --to-revision=<版次>
原理
k8s精确地控制着整个发布过程,分批次有序地进行着滚动更新,直到把所有旧的副本全部更新到新版本。实际上,k8s是通过两个参数来精确地控制着每次滚动的pod数量:
maxSurge 滚动更新过程中运行操作期望副本数的最大pod数,可以为绝对数值(eg:5),但不能为0;也可以为百分数(eg:10%)。默认为25%。
maxUnavailable 滚动更新过程中不可用的最大pod数,可以为绝对数值(eg:5),但不能为0;也可以为百分数(eg:10%)。默认为25%。
kubectl -n k8s-apps get deployment helloworldapi -o yaml
查看yaml里面的参数
spec:
progressDeadlineSeconds: 600
replicas: 10
revisionHistoryLimit: 10
selector:
matchLabels:
app: helloworldapi
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
[root@OPPO-test ~]# kubectl get deployments.apps -n k8s-apps
NAME READY UP-TO-DATE AVAILABLE AGE
helloworldapi 10/10 10 10 18m
DESIRED 最终期望处于READY状态的副本数
CURRENT 当前的副本总数
UP-TO-DATE 当前完成更新的副本数
AVAILABLE 当前可用的副本数
在你执行更新的时候就会出现这样的界面,展示正在进行的更新
[root@OPPO-test ~]# kubectl get deployments.apps -n k8s-apps
NAME READY UP-TO-DATE AVAILABLE AGE
helloworldapi 8/10 5 8 19m
当前可用的副本数 = 总共副本数量 - 总共副本数量 25% = ,所以AVAILABLE为8。
当前的副本总数 = 10 + 10 25% = 13
此时你会发现有13个pod,等待升级完成后就会恢复10个,
理想状态下的滚动过程:
创建了一个新的副本集,并为其分配3个新版本的pod,使副本总数达到13,一切正常。
通知旧副本集,销毁2个旧版本的pod,使可用副本总数保持到8,一起正常。
当两个副本销毁成功后,通知新副本集,再新增2个新版本的pod,使副本总数达到13,一切正常。
只要销毁成功,新副本集就会创造新的pod,一直循环,直到旧的副本集pod数量为0。
滚动升级一个服务,实际就是创建一个新的RS,然后逐渐将新RS中副本数增加到理想状态,将旧RS中的副本数减小到0的复合操作;
无论理想还是不理想,k8s最终都会使应用程序全部更新到期望状态,都会始终保持最大的副本总数和可用副本总数的不变性!!!