一、更新原理
滚动更新一次只更新一小部分副本,成功后,再更新更多的副本,最终完成所有副本的更新。
k8s提供了两个参数
maxUnavailable
,
maxSurge
来控制滚动更新速率。
好处在于零停机,整个更新过程始终有副本在运行,进而保证业务的连续性。
二、部署三副本应用,初始镜像为 httpd:2.2.31,然后将其更新到 httpd:2.2.32
# 编辑httpd_deployment.yaml (
httpd:2.2.31 的配置文件
)
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-deployment
spec:
selector: # 通过标签选择被控制的pod
matchLabels:
app: httpd
replicas: 3
template:
metadata:
labels:
app: httpd # 给pod打上标签,Service、Deployment 将会用这个 label 来挑选 Pod
spec:
containers:
- name: httpd
image: httpd:2.2.31
ports:
- containerPort: 80 # 转发到后端pod的端口号
kubectl apply -f httpd_deployment.yaml部署:

将配置文件中 httpd:2.2.31 替换为 httpd:2.2.32,再次执行
kubectl apply -f httpd_deployment.yaml

如下变化:
-
Deployment http-deployment的镜像更新为httpd:2.2.32
-
新创建的ReplicaSet httpd-deployment-7d98db6f46,镜像为httpd:2.2.32,并且管理了3个镜像
-
之前的ReplicaSet httpd-deployment-6b96d79d79已经没有任何Pod。
具体过程可以通过
kubectl describe deployment httpd-deployment 查看:

三、滚动更新控制速率--maxUnavailable,maxSurge参数
-
maxUnavailable:和期望ready的副本数比,不可用副本数最大比例(或最大值),这个值越小,越能保证服务稳定,更新越平滑;
-
maxSurge:和期望ready的副本数比,超过期望副本数最大比例(或最大值),这个值调的越大,副本更新速度越快。

数值:
-
maxUnavailable: [0, 副本数]
-
maxSurge: [0, 副本数]
注意:两者不能同时为0。
比例:
-
maxUnavailable: [0%, 100%] 向下取整,比如10个副本,5%的话==0.5个,但计算按照0个;
-
maxSurge: [0%, 100%] 向上取整,比如10个副本,5%的话==0.5个,但计算按照1个;
建议配置:(默认)
maxUnavailable == 0
maxSurge == 1
这是提供给用户的默认配置。即“一上一下,先上后下”最平滑原则:1个新版本pod ready(结合readiness)后,才销毁旧版本pod。此配置适用场景是平滑更新、保证服务平稳,但也有缺点,就是“太慢”了。
四、回滚
4.1、原理
kubectl apply每次更新应用时kubernetes会记录当前的配置,保存为一个revision(版次),这样就可以回滚到某个特定的revision。
默认配置下,Kubernetes 只会保留最近的几个 revision,可以在 Deployment 配置文件中通过 revisionHistoryLimit 属性增加 revision 数量。
4.2、实践回滚功能
httpd-deployment.v1.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-deployment
spec:
revisionHistoryLimit: 10 # 控制保留revision的数量,默认10个
selector: # 通过标签选择被控制的pod
matchLabels:
app: httpd
replicas: 3
template:
metadata:
labels:
app: httpd # 给pod打上标签,Service、Deployment 将会用这个 label 来挑选 Pod
spec:
containers:
- name: httpd
image: httpd:2.4.16
ports:
- containerPort: 80 # 转发到后端pod的端口号
httpd-deployment.v2.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-deployment
spec:
revisionHistoryLimit: 10
selector: # 通过标签选择被控制的pod
matchLabels:
app: httpd
replicas: 3
template:
metadata:
labels:
app: httpd # 给pod打上标签,Service、Deployment 将会用这个 label 来挑选 Pod
spec:
containers:
- name: httpd
image: httpd:2.4.17
ports:
- containerPort: 80 # 转发到后端pod的端口号
httpd-deployment.v3.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-deployment
spec:
revisionHistoryLimit: 10
selector: # 通过标签选择被控制的pod
matchLabels:
app: httpd
replicas: 3
template:
metadata:
labels:
app: httpd # 给pod打上标签,Service、Deployment 将会用这个 label 来挑选 Pod
spec:
containers:
- name: httpd
image: httpd:2.4.18
ports:
- containerPort: 80 # 转发到后端pod的端口号
通过 kubectl apply 部署并更新应用:

--record:将当前命令记录到revision记录中,这样便可知道每个revision对应的哪个配置文件。
通过kubectl rollout history deployment httpd-deployment查看revision历史记录:

CHANG-CAUSE就是--record的结果。若要回滚到某个版本,比如revision 1,可以执行命令:
kubectl rollout undo deployment httpd-deployment --to-revision=1

此时,revison 历史记录也会发生相应变化:revison 1 变成了 revison 4。不过我们可以通过 CHANGE-CAUSE 知道每个 revison 的具体含义。
所以一定要在执行 kubectl apply 时加上 --record参数。

4.3、命令实现
kubectl set image deployments/httpd-deployment httpd=httpd:2.4.18 # 将当前image 2.4.16版本升级到2.4.18
kubectl rollout status deployments/httpd-deployment # 查看升级状态
kubectl rollout history deployment httpd-deployment # 查看revision历史记录
kubectl rollout undo deployment httpd-deployment # 回滚到上一个版本
kubectl rollout undo deployment httpd-deployment --to-revision=1 # 回滚到某个版本,比如revision 1