K8S滚动升级
对于多实例服务,滚动更新采用对各个实例逐批次进行单独更新而非同一时刻对所有实例进行全部更新,来达到不中断服务的更新升级方式。
对于Kubernetes集群来说,一个service可能有多个pod,滚动升级(Rolling update)就是指每次更新部分Pod,而不是在同一时刻将该Service下面的所有Pod shutdown,然后去更新(例如replace --force方案),逐个更新可以避免将业务中断,(但是也可能带来数据不一致的问题,本文就不过多讨论了)。
关键代码
在spec项中增加几个参数
spec:
minReadySeconds: 5
strategy:
# indicate which strategy we want for rolling update
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
字段解释
minReadySeconds
Kubernetes在等待设置的时间后才进行升级
如果没有设置该值,Kubernetes会假设该容器启动起来后就提供服务了,所以这个可以设置的保守一些,比如我们的服务启动从3-20秒不等,我可以设置成30秒,这样防止pod启动了但是服务还没准备好导致系统不可用。
maxSurge
升级过程中最多可以比原先设置多出的POD数量
例如:maxSurage=1,replicas=5,则表示Kubernetes会先启动1一个新的Pod后才删掉一个旧的POD,整个升级过程中最多会有5+1个POD。
maxUnavaible
升级过程中最多有多少个POD处于无法提供服务的状态,当maxSurge不为0时,该值也不能为0,最好和maxSurge保持一致。
例如:maxUnavaible=1,则表示Kubernetes整个升级过程中最多会有1个POD处于无法服务的状态,可以保证有足够的pod(或者认为是足够的性能)提供服务。
举例说明
测试代码
apiVersion: apps/v1
kind: Deployment
metadata:
name: dev-api
labels:
name: dev-api
spec:
replicas: 2
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
selector:
matchLabels:
name: dev-api
template:
metadata:
labels:
name: dev-api
spec:
containers:
- name: dev-api
image: vinterhe/n-p-xh:1.1
imagePullPolicy: Never
ports:
- containerPort: 80
command: ["/bin/sh","-c"]
args:
- |
rm -f /etc/nginx/sites-enabled/default.conf
chmod -R 777 /data/
php-fpm -y /usr/local/etc/php-fpm.d/www.conf -D
/usr/sbin/nginx -g 'daemon off;'
如何滚动升级
如果修改了yaml文件
kubectl apply -f ****.yml
如果没有更改yaml文件却想要平滑重启
$ kubectl rollout restart deployment <deployment>
查看滚动升级的状态
$ kubectl rollout status deployment/<deployment>
暂停升级
$ kubectl rollout pause deployment <deployment>
恢复升级
$ kubectl rollout resume deployment <deployment>
升级完成后
查看replicaSet的状态
kubectl get rs
或者:
kubectl get replicaSet
输出:
NAME DESIRED CURRENT READY AGE
dev-api-54559c6cd8 2 2 2 26m
dev-api-759d5464bb 0 0 0 49m
也可以用describe 来查看升级的详细信息,下面我是节选了events等信息
NewReplicaSet: dev-api-54559c6cd8 (2/2 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 56m deployment-controller Scaled up replica set dev-api-759d5464bb to 2
Normal ScalingReplicaSet 33m deployment-controller Scaled up replica set dev-api-54559c6cd8 to 1
Normal ScalingReplicaSet 33m deployment-controller Scaled down replica set dev-api-759d5464bb to 1
Normal ScalingReplicaSet 33m deployment-controller Scaled up replica set dev-api-54559c6cd8 to 2
Normal ScalingReplicaSet 33m deployment-controller Scaled down replica set dev-api-759d5464bb to 0
回滚
我们已经能够滚动平滑的升级我们的Deployment了,但是如果升级后的POD出了问题该怎么办?我们能够想到的最好最快的方式当然是回退到上一次能够提供正常工作的版本,Deployment就为我们提供了回滚机制。
首先,查看Deployment的升级历史:
$ kubectl rollout history deployment <deployment>
输出:
REVISION CHANGE-CAUSE
1 kubectl apply --filename=api.yml --record=true
2 kubectl apply --filename=api.yml --record=true
注意:
record类似一个栈,先执行的apply会放到记录的最下端。也就是说你的上一个版本一定是2.
record记录的是apply的命令,所以如果每次执行的命令是一样的话,会覆盖掉。
查看某一次的revison信息
$ kubectl rollout history deployment <deployment> --revision=1
回滚到某一版本
$ kubectl rollout undo deployment <deployment> --to-revision=2
如果不写后面的--to-revision参数,默认回滚到上一个版本
拓展
所有通过kubectl xxxx --record都会被kubernetes记录到etcd进行持久化,这无疑会占用etcd资源,最重要的是,时间久了,当你kubectl get rs时,会有成百上千的垃圾RS返回给你,这其实也没有太大的作用,一般保留几个版本就可以了。
我们可以通过设置Deployment的.spec.revisionHistoryLimit参数来限制最大保留的revision 数量,比如10个版本。
另外其实rollout history中记录的revision都和ReplicaSets一一对应。如果手动delete某个ReplicaSet,对应的rollout history就会被删除,也就是还说你无法回滚到这个revison了。
原文链接:https://blog.youkuaiyun.com/winterfeng123/article/details/109075454