一、什么是滚动更新
当某个服务需要升级时,传统的做法是,先将要更新的服务下线,业务停止后再更新版本和配置,然后重新启动服务。
如果业务集群规模较大时,这个工作就变成了一个挑战,而且全部停止了服务,再逐步升级的方式会导致服务较长时间不可用。
针对这个问题,k8s提供了滚动更新(rolling-update)的方式来解决上述问题。
滚动更新是针对pod来操作的,它通过一次只更新一小部分副本,成功后,再更新更多的副本,最终完成所有副本的更新。
滚动更新的最大的好处是零停机,整个更新过程始终有副本在运行,从而保证了服务的连续性。
二、实例分析滚动更新实现逻辑
部署一个http应用,三个副本,初始镜像为 httpd:2.4.33,然后将其更新到 httpd:2.4.38。
编写一个Deployment文件http-service.yml
vim http-service.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpservice-deployment
spec:
replicas: 5
selector:
matchLabels:
run: httpservice
strategy:
rollingUpdate:
#指定更新时最大扩展的pod数
maxSurge: 2
#指定可接受的不可用pod数
maxUnavailable: 1
template:
metadata:
labels:
run: httpservice
spec:
containers:
- name: http-service
image: httpd:2.4.33
ports:
- containerPort: 80
应用deployment
$ kubectl apply -f http-service.yml
deployment.apps/httpservice-deployment created
查看replicaset和deployment的状态
$ kubectl get replicaset -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
httpservice-deployment-66d9fd5f76 5 5 5 6m39s http-service httpd:2.4.33 pod-template-hash=66d9fd5f76,run=httpservice
$ kubectl get deployments -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
httpservice-deployment 5/5 5 5 6m48s http-service httpd:2.4.33 run=httpservice
可以看到本版是2.4.33
查看pod状态
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
httpservice-deployment-66d9fd5f76-85xdg 1/1 Running 0 6m50s 10.244.2.22 centos7907 <none> <none>
httpservice-deployment-66d9fd5f76-9rbsb 1/1 Running 0 6m50s 10.244.3.16 centos7906 <none> <none>
httpservice-deployment-66d9fd5f76-f5fj4 1/1 Running 0 6m50s 10.244.3.17 centos7906 <none> <none>
httpservice-deployment-66d9fd5f76-trx7k 1/1 Running 0 6m50s 10.244.3.18 centos7906 <none> <none>
httpservice-deployment-66d9fd5f76-zntf9 1/1 Running 0 6m50s 10.244.2.21 centos7907 <none> <none>
将http-service.yml文件中,镜像的版本改为httpd:2.4.38
,再次执行更新操作
vim http-service.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpservice-deployment
spec:
replicas: 5
selector:
matchLabels:
run: httpservice
template:
metadata:
labels:
run: httpservice
spec:
containers:
- name: http-service
image: httpd:2.4.38
ports:
- containerPort: 80
更新deployment
$ kubectl apply -f http-service.yml
deployment.apps/httpservice-deployment configured
再查看状态
从中可以发现:新创建的ReplicaSet镜像为httpd:2.4.38,并且管理了三个新的 Pod。
而老的ReplicaSet里面已经没有任何Pod。结论是老的ReplicaSet的三个httpd:2.4.33 Pod 已经被新的ReplicaSet的三个httpd:2.4.38 Pod逐渐替换了。
更新完成
具体替换过程
kubectl describe deployments httpservice-deployment
对照具体版本
Scaled up replica set httpservice-deployment-66d9fd5f76 to 5 将76结尾的RS的pod增加到5个
Scaled up replica set httpservice-deployment-7ccf67cf77 to 2 将77结尾的RS的pod增加到2个
Scaled down replica set httpservice-deployment-66d9fd5f76 to 4 将76结尾的RS的pod减少到4个
Scaled up replica set httpservice-deployment-7ccf67cf77 to 3 将77结尾的RS的pod增加到3个
Scaled down replica set httpservice-deployment-66d9fd5f76 to 3 将76结尾的RS的pod减少到3个
Scaled up replica set httpservice-deployment-7ccf67cf77 to 4 将77结尾的RS的pod增加到4个
Scaled down replica set httpservice-deployment-66d9fd5f76 to 2 将76结尾的RS的pod减少到2个
Scaled up replica set httpservice-deployment-7ccf67cf77 to 5 将77结尾的RS的pod增加到5个
Scaled down replica set httpservice-deployment-66d9fd5f76 to 1 将76结尾的RS的pod减少到1个
Scaled down replica set httpservice-deployment-66d9fd5f76 to 0 将76结尾的RS的pod减少到0个
三、k8s中版本回滚方法
在执行kubectl apply命令更新应用时,K8s都会记录下当前的配置,保存为一个revision(版本),通过这个版本记录,就可以回滚到某个特定的revision。
默认配置下,K8s只会保留最近的几个版本,不过可以在Deployment配置文件中通过revisionHistoryLimit
属性增加revision的数量。
下面具体来演示一下K8s中版本回滚的方法。编写四个Deployment文件httpd-2.4.33.yml、httpd-2.4.39.yml、httpd-2.4.41.yml、httpd-2.4.43.yml,分别对应的httpd镜像为2.4.33、2.4.39、2.4.41和2.4.43
httpd-2.4.33.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpservice-deployment
spec:
#设置可保存的记录版本数
revisionHistoryLimit: 10
replicas: 3
selector:
matchLabels:
run: httpservice
template:
metadata:
labels:
run: httpservice
spec:
containers:
- name: http-service
image: httpd:2.4.33
ports:
- containerPort: 80
这是第一个文件http-2.4.33.yml,其它三个文件中,对应的httpd镜像分别为2.4.39、2.4.41和2.4.43,其它配置均一样。
先执行发布http-2.4.33.yml
$ kubectl apply -f httpd2.4.33.yml
deployment.apps/httpservice-deployment created
$ kubectl get deployments -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
httpservice-deployment 3/3 3 3 14s http-service httpd:2.4.33 run=httpservice
然后再更新其他三个版本
$ kubectl apply -f httpd2.4.39.yml --record
deployment.apps/httpservice-deployment configured
$ kubectl apply -f httpd2.4.41.yml --record
deployment.apps/httpservice-deployment configured
$ kubectl apply -f httpd2.4.43.yml --record
deployment.apps/httpservice-deployment configured
其中,--record
的作用是将当前命令记录到revision记录中,这样就可以知道每个revison对应的是哪个配置文件了。
每个版本之前间隔一段时间
更新好查看历史版本
$ kubectl rollout history deployment httpservice-deployment
deployment.apps/httpservice-deployment
REVISION CHANGE-CAUSE
1 <none>
2 kubectl apply --filename=httpd2.4.39.yml --record=true
3 kubectl apply --filename=httpd2.4.41.yml --record=true
4 kubectl apply --filename=httpd2.4.43.yml --record=true
查看replicaset
$ kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
httpservice-deployment-66d9fd5f76 0 0 0 27m http-service httpd:2.4.33 pod-template-hash=66d9fd5f76,run=httpservice
httpservice-deployment-6777b8d7cf 3 3 3 4m49s http-service httpd:2.4.43 pod-template-hash=6777b8d7cf,run=httpservice
httpservice-deployment-6d578ff989 0 0 0 10m http-service httpd:2.4.41 pod-template-hash=6d578ff989,run=httpservice
httpservice-deployment-7b8f89958b 0 0 0 25m http-service httpd:2.4.39 pod-template-hash=7b8f89958b,run=httpservice
查看测试的deployment
$ kubectl get deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
httpservice-deployment 3/3 3 3 46m http-service httpd:2.4.43 run=httpservice
要回滚到某个版本,只需要指定revision就可以了
例如,我们需要回滚到第三个版本,也就是httpd2.4.41
$ kubectl rollout undo deployment httpservice-deployment --to-revision=3
deployment.apps/httpservice-deployment rolled back
查看replicaset
$ kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
httpservice-deployment-66d9fd5f76 0 0 0 80m http-service httpd:2.4.33 pod-template-hash=66d9fd5f76,run=httpservice
httpservice-deployment-6777b8d7cf 0 0 0 57m http-service httpd:2.4.43 pod-template-hash=6777b8d7cf,run=httpservice
httpservice-deployment-6d578ff989 3 3 3 63m http-service httpd:2.4.41 pod-template-hash=6d578ff989,run=httpservice
httpservice-deployment-7b8f89958b 0 0 0 78m http-service httpd:2.4.39 pod-template-hash=7b8f89958b,run=httpservice
可以看到,当前的三个副本都是2.4.41版本
查看历史版本
$ kubectl rollout history deployment httpservice-deployment
deployment.apps/httpservice-deployment
REVISION CHANGE-CAUSE
1 <none>
2 kubectl apply --filename=httpd2.4.39.yml --record=true
4 kubectl apply --filename=httpd2.4.43.yml --record=true
5 kubectl apply --filename=httpd2.4.41.yml --record=true
可以看到原本的3版本已经变成了5版本
第一个版本和其他相比,少了执行的命令
因此,有回滚需求的话,一定要在执行kubectl apply
时加上 --record
参数。
四、自定义滚动更新策略
maxSurge
和maxUnavailable
用来控制滚动更新的更新策略
取值范围
数值
1、maxUnavailable: [0, 副本数]
2、maxSurge: [0, 副本数]
注意:两者不能同时为0。
比例
1、maxUnavailable: [0%, 100%] 向下取整,比如10个副本,5%的话==0.5个,但计算按照0个;
2、maxSurge: [0%, 100%] 向上取整,比如10个副本,5%的话==0.5个,但计算按照1个;
注意:两者不能同时为0。
建议配置
1、maxUnavailable == 0
2、maxSurge == 1
这是我们生产环境提供给用户的默认配置。即“一上一下,先上后下”最平滑原则:
1个新版本pod ready(结合readiness)后,才销毁旧版本pod。此配置适用场景是平滑更新、保证服务平稳,但也有缺点,就是太慢了。
总结
- maxUnavailable:和期望的副本数比,不可用副本数最大比例(或最大值),这个值越小,越能保证服务稳定,更新越平滑;
- maxSurge:和期望的副本数比,超过期望副本数最大比例(或最大值),这个值调的越大,副本更新速度越快。
自定义策略
修改更新策略:maxUnavailable=1,maxSurge=1
1、直接命令修改
$ kubectl patch deployment myapp-v1 -p '{"spec":{"strategy":{"rollingUpdate": {"maxSurge":1,"maxUnavailable":1}}}}'
2、通过修改yaml文件修改
....
spec:
replicas: 3
revisionHistoryLimit: 5
selector:
matchLabels:
app: http
strategy:
rollingUpdate:
#指定更新时最大扩展的pod数
maxSurge: 2
#指定可接受的不可用pod数
maxUnavailable: 1
template:
......
最后应用
$ kubectl apply -f test.yaml
查看myapp-v1这个控制器的详细信息
$ kubectl describe deployment myapp-v1
显示如下:
RollingUpdateStrategy: 1 max unavailable, 1 max surge
上面可以看到RollingUpdateStrategy: 1 max unavailable, 1 max surge
这个rollingUpdate更新策略变成了刚才设定的,因为我们设定的pod副本数是3,1和1表示最少不能少于2个pod,最多不能超过4个pod
这个就是通过控制RollingUpdateStrategy这个字段来设置滚动更新策略的
标签:kubectl,滚动,httpd,httpservice,更新,deployment,pod,k8s,2.4 From: https://www.cnblogs.com/guangdelw/p/17154142.html