如果pod是通过Deployment创建的,则用户可以在运行时修改Deployment的pod定义(sepc.template)或镜像名称,并应用到Deployment对象上,系统即可完成Deployment的自动更新操作。如果在更新过程中发生了错误,则还可以通过回滚操作恢复Pod的版本。
Deployment的升级
以Deployment nginx为例:
kubectl create -f nginx-deployment.yaml --record=true
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:- containerPort: 80
现在pod镜像需要被更新为 nginx:1.9.1,我们可以通过kubectl set image 命令为Deployment设置新的镜像名称:
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
另外一种方法是使用kubectl edit命令直接修改Deployment的配置,将image从nginx:1.7.9更改为nginx:1.9.1。
kubectl edit deployment/nginx-deployment
一旦镜像名发生了修改,则将触发系统完成Deployment所有运行pod的滚动升级操作,可以使用kubectl rollout status 命令查看Deployment的更新过程:
kubectl rollout status deployment/nginx-deployment
运行kubectl get rs 命令,可以看到两个ReplicaSet的最终状态:
更新策略:
在deployment的定义中,可以通过spec.strategy指定pod更新的策略,目前支持两种策略:Recreate(重建)和RollingUpdate(滚动更新)策略,默认值为RollingUpdate。
Recreate:设置spec.strategy.type=Recreate,表示Deployment在更新pod时,会先杀掉所有正在运行的pod,然后创建新的pod。
RollingUpdate:设置spec.strategy.type=RollingUpdate,表示Deployment会以滚动更新的方式来逐个更新pod。同时,可以通过设置spec.strategy.rollingUpdate下的两个参数(maxUnavailable和maxSurge)来控制滚动更新的过程。
Deployment是如何完成Pod更新的呢?通过kubectl describe deployment nginx-deployment 可以看到详细的事件信息:
spec.strategy.rollingUpdate.maxUnavailable:用于指定Deployment在更新过程中不可用状态的pod数量的上限。该参数的数值可以是绝对值(例如5)或pod期望的副本数的百分比(例如10%),如果被设置为百分比,那么系统会先以向下取整的方式计算出绝对值。而当另一个参数maxSurge被设置为0时,maxUnavailable则必须被设置为绝对值大于0。默认值为25%。
spec.strategy.rollingUpdate.maxSurge:用于指定Deployment在更新过程中pod总数超过pod期望副本数部分的最大值,该maxSurge的数值可以是绝对值(例如5)或pod期望副本数的百分比(例如10%),如果设置为百分比,那么系统会先按照向上取整的方式计算出绝对值。默认值为25%
多重更新(Rollover)的情况
如果deployment的上一次更新正在进行,此时用户再次发起deployment的更新操作,那么deployment会为每一次更新都创建一个ReplicaSet,而每次在新的ReplicaSet创建成功后,会逐个增加pod副本数,同时将之前正在扩容的ReplicaSet停止扩容更新,并将其加入旧版本ResplicaSet列表中,然后开始缩容至0的操作。
假设我们创建了一个deployment,这个deployment开始创建了5个nginx:1.7.9的pod副本,在这个创建pod动作尚未完成时,我们又将deployment进行更新,在副本数量不变的情况下将pod模板中的镜像修改为nginx:1.9.1,又假设此时deployment已经创建了3个nginx:1.7.9的pod副本,则deployment会立即杀掉已创建的3个nginx:1.7.9 pod,并开始创建nginx:1.9.1 pod。deployment不会在等待nginx:1.7.9的pod创建到5个之后再进行更新操作。
Deployment的回滚
kubectl create -f nginx-deployment.yaml --record=true
在创建deployment时使用--record=true参数,就可以在历史命令中看到每个版本所执行的命令了
假如我们在更新deployment镜像时,将容器镜像名称设置错误为nginx:1.7(一个不存在的镜像),则部署过程会卡在拉取镜像过程中。
这时,我们需要回滚到之前稳定版本的deployment。
首先,使用kubectl rollout history命令查看deployment部署的历史记录:
kubectl rollout history deployment nginx-deployment
如果需要查看某一条命令的详细信息,则可以加上--reversion=<N>参数
kubectl rollout history deployment nginx-deployment --reversion=3
我们可以看到image的版本是nginx1.7,并不存在此镜像!!!
现在我们决定撤销本次发布并回滚到上一个部署版本:
kubectl rollout undo deployment nginx-deployment
也可以使用--to-revision参数指定回滚到的部署版本号:
kubectl rollout undo deployment nginx-deployment --to-revision=2
这样就可以回滚到之前的稳定版本了。