创建部署详见 Kubernetes(K8S) Deployment 部署 Pod
传统应用升级,一般是V1.0的jar包,有一个应对 1.0 的 shell 启动脚本。升级时,传 2.0 的 jar包,配置 2.0 的 shell 脚本。
执行顺序为,停1.0的服务,启2.0的服务,有问题时,把2.0停掉再执行 1.0的shell脚本,手动恢复到1.0 版本,服务多的情况下,就很崩溃,而且服务会中断不可用。
高并发、高可用系统普及的今天,服务的升级更新至少要做到“业务不中断”。而滚动更新(Rolling-update)恰是满足这一需求的一种系统更新升级方案。对于Kubernetes集群部署的Service来说,Rolling update就是指一次仅更新一个Pod,然后逐个进行更新,而不是在同一时刻将该Service下面的所有Pod shutdown,然后去更新,逐个更新可以避免将业务中断;
RollingUpdate命令:通过自动扩缩容实现自动滚动升级
指令格式:kubectl rolling-update 旧控制器 新控制器 --image=新镜像
1. 发布新版到阿里云镜像仓库
Last login: Tue Oct 18 16:39:53 2022 from 172.16.0.66 [root@localhost ~]# cd /opt/demo/ [root@localhost demo]# ll 总用量 17160 -rw-r--r--. 1 root root 17566582 10月 19 11:50 demojenkins.jar -rw-r--r--. 1 root root 126 10月 18 17:56 Dockerfile [root@localhost demo]# docker login --username=hiXXXXXX@aliyun.com registry.cn-shanghai.aliyuncs.com Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded [root@localhost demo]# docker build -t demo:2.0 . Sending build context to Docker daemon 17.57MB Step 1/4 : FROM openjdk:8-jdk-alpine ---> a3562aa0b991 Step 2/4 : VOLUME /tmp ---> Using cache ---> a98cf1fbeb9d Step 3/4 : ADD ./demojenkins.jar demojenkins.jar ---> 12bfc15e5295 Step 4/4 : ENTRYPOINT ["java","-jar","/demojenkins.jar", "&"] ---> Running in 2908dd94dfa7 Removing intermediate container 2908dd94dfa7 ---> 3041db93b6df Successfully built 3041db93b6df Successfully tagged demo:2.0 [root@localhost demo]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE demo 2.0 3041db93b6df About a minute ago 122MB demo 1.0 1952e02daef9 19 hours ago 122MB openjdk 8-jdk-alpine a3562aa0b991 3 years ago 105MB java 8 d23bdf5b1b1b 5 years ago 643MB [root@localhost demo]# docker tag 3041db93b6df registry.cn-shanghai.aliyuncs.com/vipsoft/vipsoft:2.0 [root@localhost demo]# docker push registry.cn-shanghai.aliyuncs.com/vipsoft/vipsoft:2.0 The push refers to repository [registry.cn-shanghai.aliyuncs.com/vipsoft/vipsoft] c38fa2e9a247: Pushed ceaf9e1ebef5: Layer already exists 9b9b7f3d56a0: Layer already exists f1b5933fe4b5: Layer already exists 2.0: digest: sha256:785c4707e7e629d22b5609310d8f945c107b277b94925cc0dbebdb3621b size: 1159 [root@localhost demo]#
2. 查看现有Pod信息(升级后对比用)
# 查看创建的 Deployment 对象 [root@k8smaster ~]# kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE javademo1 3/3 3 3 19h nginx 1/1 1 1 5d21h # 查看 Deployment 上线状态 [root@k8smaster ~]# kubectl rollout status deployment/javademo1 deployment "javademo1" successfully rolled out # 查看 Deployment 对象创建的 ReplicaSet: [root@k8smaster ~]# kubectl get rs NAME DESIRED CURRENT READY AGE javademo1-84dd5c9485 3 3 3 4h25m nginx-f89759699 1 1 1 5d21h # 查看 Deployment 对象操作 ReplicaSet 创建的 Pod,并显示生成的标签: [root@k8smaster ~]# kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS javademo1-84dd5c9485-7vgkr 1/1 Running 0 4h20m app=javademo1,pod-template-hash=84dd5c9485 javademo1-84dd5c9485-8ckk6 1/1 Running 0 4h26m app=javademo1,pod-template-hash=84dd5c9485 javademo1-84dd5c9485-8hfmd 1/1 Running 0 4h20m app=javademo1,pod-template-hash=84dd5c9485 nginx-f89759699-5hkdw 1/1 Running 0 5d21h app=nginx,pod-template-hash=f89759699 #查看当前运行的 Pod [root@k8smaster ~]# kubectl get pods NAME READY STATUS RESTARTS AGE javademo1-84dd5c9485-7vgkr 1/1 Running 0 4h31m javademo1-84dd5c9485-8ckk6 1/1 Running 0 4h37m javademo1-84dd5c9485-8hfmd 1/1 Running 0 4h31m nginx-f89759699-5hkdw 1/1 Running 0 5d21h # 查看 Deployeement 详情 [root@k8smaster ~]# kubectl describe deployment/javademo1 Name: javademo1 Namespace: default CreationTimestamp: Tue, 18 Oct 2022 18:51:25 +0800 Labels: app=javademo1 Annotations: deployment.kubernetes.io/revision: 2 Selector: app=javademo1 Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=javademo1 Containers: vipsoft: Image: registry.cn-shanghai.aliyuncs.com/vipsoft/vipsoft:1.0 Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Progressing True NewReplicaSetAvailable Available True MinimumReplicasAvailable OldReplicaSets: <none> NewReplicaSet: javademo1-84dd5c9485 (3/3 replicas created) Events: <none>
Deployment, kubectl get deployments 所显示的字段有:
- NAME:列出了名字空间中 Deployment 的名称。
- READY:显示应用程序的可用的“副本”数。显示的模式是“就绪个数/期望个数”。
- UP-TO-DATE:显示为了达到期望状态已经更新的副本数。
- AVAILABLE:显示应用可供用户使用的副本数。
- AGE:显示应用程序运行的时间。
ReplicaSet, kubectl get rs 输出中包含以下字段:
- NAME:列出名字空间中 ReplicaSet 的名称;[Deployment名称]-[随机字符串]
- DESIRED:显示应用的期望副本个数,即在创建 Deployment 时所定义的值。 此为期望状态;
- CURRENT:显示当前运行状态中的副本个数;
- READY:显示应用中有多少副本可以为用户提供服务;
- AGE:显示应用已经运行的时间长度。
3. Deployment 升级
方法1
# 查看 Deployeement 详情 里可以看到 Containers 内容 # Containers: # vipsoft: # Image: registry.cn-shanghai.aliyuncs.com/vipsoft/vipsoft:1.0 # 设置vipsoft容器中的镜像,镜像版本变了,就会触发重新拉取动作 [root@k8smaster ~]# kubectl set image deployment/javademo1 vipsoft=registry.cn-shanghai.aliyuncs.com/vipsoft/vipsoft:2.0 deployment.apps/javademo1 image updated [root@k8smaster ~]# kubectl rollout status deployment/javademo1 deployment "javademo1" successfully rolled out [root@k8smaster ~]#
方法2:Jenkins 的时候比较常用,早期使用 Kubernetes Continuous Deploy 插件,现已重淘汰,可使用 Config File Provider 代替
# Containers: # vipsoft: # Image: registry.cn-shanghai.aliyuncs.com/vipsoft/vipsoft:1.0 #将 :1.0 改成 2.0 # 一旦镜像名(或 Pod 定义)发生了修改,则触发 k8s 系统完成 Deployment 所有运行 Pod 的滚动升级操作 [root@k8smaster ~]# kubectl edit deployment/javademo1 deployment "javademo1" edited
查看已更新的 Deployment 的信息
[root@k8smaster ~]# kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE javademo1 3/3 3 3 20h nginx 1/1 1 1 5d22h # 扩容了3个副本,将旧的 ReplicaSet 缩容到了 0 个副本,完成了Pod的升级 [root@k8smaster ~]# kubectl get rs NAME DESIRED CURRENT READY AGE javademo1-5476dc8d7d 3 3 3 11m javademo1-84dd5c9485 0 0 0 5h17m nginx-f89759699 1 1 1 5d22h #只有最新的 5476dc8d7d 信息 [root@k8smaster ~]# kubectl get pods NAME READY STATUS RESTARTS AGE javademo1-5476dc8d7d-bf6m5 1/1 Running 0 11m javademo1-5476dc8d7d-ttt5b 1/1 Running 0 11m javademo1-5476dc8d7d-zd4c7 1/1 Running 0 11m nginx-f89759699-5hkdw 1/1 Running 0 5d22h [root@k8smaster ~]# kubectl describe deployment/javademo1 Name: javademo1 Namespace: default CreationTimestamp: Tue, 18 Oct 2022 18:51:25 +0800 Labels: app=javademo1 Annotations: deployment.kubernetes.io/revision: 3 Selector: app=javademo1 Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=javademo1 Containers: vipsoft: Image: registry.cn-shanghai.aliyuncs.com/vipsoft/vipsoft:2.0 Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: javademo1-5476dc8d7d (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 12m deployment-controller Scaled up replica set javademo1-5476dc8d7d to 1 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set javademo1-84dd5c9485 to 2 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set javademo1-5476dc8d7d to 2 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set javademo1-84dd5c9485 to 1 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set javademo1-5476dc8d7d to 3 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set javademo1-84dd5c9485 to 0 [root@k8smaster ~]#
上面 Events: 可以看出,先 up javademo1-5476dc8d7d to 1,再停 javademo1-84dd5c9485 to 2,Pod 逐个 滚动式更新,如下图:
Deployment 更新策略
在 Deployment 的定义中,可以通过 spec.strategy 指定 Pod 的更新策略,目前支持两种更新策略:
Recreate(重建):设置 spec.strategy.type=Recreate,表示 Deployment 在更新 Pod 时,会先杀掉所有正在运行的 Pod,然后创建新的 Pod。
RollingUpdate(滚动更新):设置 spec.strategy.type=RollingUpdate,表示 Deployment 会以滚动更新的方式来逐个更新 Pod。同时,可以通过设置 spec.strategy.rollingUpdate 下的两个参数(maxUnavailable 和 maxSurge)来控制滚动更新的过程。
4. Deployment 回滚
# 查看 Deployment 部署历史, CHANGE-CAUSE 里没有值,需要在创建 Deployment 时,使用 --record 参数,就可以在 CHANGE-CAUSE 列看到每个版本使用的命令了 [root@k8smaster ~]# kubectl rollout history deployment/javademo1 deployment.apps/javademo1 REVISION CHANGE-CAUSE 1 <none> 2 <none> # 查看版本 2 的信息: [root@k8smaster ~]# kubectl rollout history deployment/javademo1 --revision=2 deployment.apps/javademo1 with revision #2 Pod Template: Labels: app=javademo1 pod-template-hash=84dd5c9485 Containers: vipsoft: Image: registry.cn-shanghai.aliyuncs.com/vipsoft/vipsoft:1.0 Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> # kubeetl rollout undo deployment/javademo1 --to-revision=2 加上参数,回滚到指定版本 # 这边没加参加,回滚到上一个版本 [root@k8smaster ~]# kubectl rollout undo deployment/javademo1 deployment.apps/javademo1 rolled back [root@k8smaster ~]# kubectl describe deployment/javademo1 Name: javademo1 Namespace: default CreationTimestamp: Tue, 18 Oct 2022 18:51:25 +0800 Labels: app=javademo1 Annotations: deployment.kubernetes.io/revision: 4 Selector: app=javademo1 Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=javademo1 Containers: vipsoft: Image: registry.cn-shanghai.aliyuncs.com/vipsoft/vipsoft:1.0 Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: javademo1-84dd5c9485 (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 51m deployment-controller Scaled up replica set javademo1-5476dc8d7d to 1 Normal ScalingReplicaSet 50m deployment-controller Scaled down replica set javademo1-84dd5c9485 to 2 Normal ScalingReplicaSet 50m deployment-controller Scaled up replica set javademo1-5476dc8d7d to 2 Normal ScalingReplicaSet 50m deployment-controller Scaled up replica set javademo1-5476dc8d7d to 3 Normal ScalingReplicaSet 50m deployment-controller Scaled down replica set javademo1-84dd5c9485 to 1 Normal ScalingReplicaSet 50m deployment-controller Scaled down replica set javademo1-84dd5c9485 to 0 Normal ScalingReplicaSet 20s (x2 over 5h57m) deployment-controller Scaled up replica set javademo1-84dd5c9485 to 1 Normal ScalingReplicaSet 17s deployment-controller Scaled down replica set javademo1-5476dc8d7d to 2 Normal ScalingReplicaSet 17s deployment-controller Scaled up replica set javademo1-84dd5c9485 to 2 Normal ScalingReplicaSet 15s deployment-controller Scaled down replica set javademo1-5476dc8d7d to 1 Normal ScalingReplicaSet 14s (x2 over 5h51m) deployment-controller Scaled up replica set javademo1-84dd5c9485 to 3 Normal ScalingReplicaSet 9s deployment-controller Scaled down replica set javademo1-5476dc8d7d to 0 [root@k8smaster ~]#
history 中 CHANGE-CAUSE 里没有值,需要在创建 Deployment 时,使用 --record 参数,就可以在 CHANGE-CAUSE 列看到每个版本使用的命令了