当想要更新启动的pod镜像时,可以通过滚动更新,不停止Pod的情况下,将版本更新完成,非常简单 滚动更新是一次只更新一小部分副本,成功后,再更新更多的副本,最终完成所有副本的更新。滚动更新的最大的好处是零停机,整个更新过程始终有副本在运行,从而保证了业务的连续性。
如:更新httpd镜像版本
先部署3个httpd:2.2.31的副本
[root@node1 ~]# vim httpd.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd
spec:
selector:
matchLabels:
run: httpd
replicas: 3
template:
metadata:
labels:
run: httpd
spec:
containers:
- name: httpd
image: httpd:2.2.31
ports:
- containerPort: 80
运行文件
[root@node1 ~]# kubectl apply -f httpd.yml
deployment.apps/httpd created
查看使用镜像
[root@node1 ~]# kubectl get deployments -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
httpd 3/3 3 3 79s httpd httpd:2.2.31 run=httpd
[root@node1 ~]# kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
httpd-5f8664fc66 3 3 3 93s httpd httpd:2.2.31 pod-template-hash=5f8664fc66,run=httpd
部署的过程是:
创建Deployment:httpd
创建ReplicaSet:httpd-5f8664fc66
创建三个Pod
先将文件中的镜像版本修改为httpd:2.2.32
[root@node1 ~]# vim httpd.yml
# 修改镜像版本
image: httpd:2.2.32
重新部署
[root@node1 ~]# kubectl apply -f httpd.yml
deployment.apps/httpd configured
查看pod的变化
[root@node1 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
httpd-5f8664fc66-hcpgc 1/1 Running 0 6m28s
httpd-5f8664fc66-rpc69 1/1 Running 0 6m28s
httpd-5f8664fc66-xvgxw 1/1 Running 0 6m28s
httpd-6998bd9ff5-d9nzj 0/1 ContainerCreating 0 10s
现在在创建一个新的Pod
再次查看,有一个Pod状态为Terminating,是之前使用2.2.31镜像的Pod
[root@node1 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
httpd-5f8664fc66-hcpgc 1/1 Running 0 7m6s
httpd-5f8664fc66-rpc69 1/1 Running 0 7m6s
httpd-5f8664fc66-xvgxw 1/1 Terminating 0 7m6s
httpd-6998bd9ff5-d9nzj 1/1 Running 0 48s
httpd-6998bd9ff5-zts66 0/1 ContainerCreating 0 2s
更新结束后查看镜像版本
[root@node1 ~]# kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
httpd-5f8664fc66 0 0 0 8m30s httpd httpd:2.2.31 pod-template-hash=5f8664fc66,run=httpd
httpd-6998bd9ff5 3 3 3 2m12s httpd httpd:2.2.32 pod-template-hash=6998bd9ff5,run=httpd
2.2.31已经没有在运行Pod了,而2.2.32运行了三个Pod
综上所述,证明在进行版本的滚动更新时,不会影响Pod的正常访问,是一个一个Pod进行替换的,永远有pod在不间断运行
这种现象还在swarm集群的service中出现过,滚动更新也是为了保证处于期望状态,将新版本的镜像下载好之后,先将旧版本的Pod停止一个,然后创建一个,完成之后,在按照这个方式,更换其他Pod为新版本,整个过程始终有副本在运行,从而保证了业务的连续性。这就是滚动更新的策略
查看ReplicaSet还可以看到旧版本的存在,只不过没有被删除,期望状态转移到了新版本的ReplicaSet下
[root@node1 ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
httpd-5f8664fc66 0 0 0 13m
httpd-6998bd9ff5 3 3 3 6m43s
在这个过程中Deployment是没有更换的,直接更换了ReplicaSet。
整个替换过程在Deployment的events事件中是有写入的
[root@node1 ~]# kubectl describe deployments httpd
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 14m deployment-controller Scaled up replica set httpd-5f8664fc66 to 3
# 2.2.31的Pod有3个
Normal ScalingReplicaSet 8m25s deployment-controller Scaled up replica set httpd-6998bd9ff5 to 1
# 开始替换后,2.2.32版本的开始运行第一个
Normal ScalingReplicaSet 7m39s deployment-controller Scaled down replica set httpd-5f8664fc66 to 2
# 关闭了2.2.31的一个Pod,还剩2个
Normal ScalingReplicaSet 7m39s deployment-controller Scaled up replica set httpd-6998bd9ff5 to 2
# 2.2.32在运行第二个Pod,已经运行了2个
Normal ScalingReplicaSet 7m4s deployment-controller Scaled down replica set httpd-5f8664fc66 to 1
# 关闭第二个2.2.31的Pod,还剩一个
Normal ScalingReplicaSet 7m4s deployment-controller Scaled up replica set httpd-6998bd9ff5 to 3
# 2.2.32运行的第三个Pod,已经运行3个
Normal ScalingReplicaSet 7m1s deployment-controller Scaled down replica set httpd-5f8664fc66 to 0
# 2.2.31的Pod全部关闭
查看Deployment的事件详情,可以看到ReplicaSet在轮换的进行Scaled up
和Scaled down
查看滚动状态是否成功
[root@node1 ~]# kubectl rollout status deployment httpd
deployment "httpd" successfully rolled out
然后可以将旧的ReplicaSet删除就好了,看好再删,别把更新完的ReplicaSet删了
[root@node1 ~]# kubectl delete replicasets.apps nginx-deployment-5bf87f5f59
[root@node1 ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
httpd-deployment-5dd67c6b75 3 3 3 114m
nginx-deployment-5f8c6846ff 2 2 2 91m
每次替换的 Pod 数量是可以定制的。Kubernetes 提供了两个参数 maxSurge
和 maxUnavailable
来精细控制 Pod 的替换数量,后面会写到
回滚镜像版本
kubectl apply
每次更新应用时 Kubernetes 都会记录下当前的配置,保存为一个 revision(版次),这样就可以回滚到某个特定 revision。
默认配置下,Kubernetes 只会保留最近的几个 revision,可以在 Deployment 配置文件中通过 revisionHistoryLimit
属性增加 revision 数量。
先将之前的更新过的Deployment给删除
[root@node1 ~]# kubectl delete -f httpd.yml
deployment.apps "httpd" deleted
修改yml文件,添加revisionHistoryLimit
[root@node1 ~]# vim httpd.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd
spec:
revisionHistoryLimit: 10 # 添加
selector:
matchLabels:
run: httpd
replicas: 3
template:
metadata:
labels:
run: httpd
spec:
containers:
- name: httpd
image: httpd:2.4.16 # 修改镜像为2.4.16
ports:
- containerPort: 80
运行Pod,--record
的作用是将当前命令记录到 revision 记录中
[root@node1 ~]# kubectl apply -f httpd.yml --record
deployment.apps/httpd created
查看Pod是否运行成功
[root@node1 ~]# kubectl get pod -l run=httpd
NAME READY STATUS RESTARTS AGE
httpd-79bcc48899-9bfms 1/1 Running 0 100s
httpd-79bcc48899-9kz5b 1/1 Running 0 100s
httpd-79bcc48899-vqsrd 1/1 Running 0 100s
修改版本进行重新部署
[root@node1 ~]# cp httpd.yml httpd.v1.yml
# 修改版本为2.4.17
[root@node1 ~]# vim httpd.v1.yml
image: httpd:2.4.17
[root@node1 ~]# kubectl apply -f httpd.v1.yml --record
deployment.apps/httpd configured
# 等待更新完成
[root@node1 ~]# kubectl get deployments -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
httpd 3/3 3 3 21m httpd httpd:2.4.17 run=httpd
修改版本再次部署
[root@node1 ~]# cp httpd.yml httpd.v2.yml
# 修改版本为2.4.18
[root@node1 ~]# vim httpd.v1.yml
image: httpd:2.4.18
[root@node1 ~]# kubectl apply -f httpd.v2.yml --record
deployment.apps/httpd configured
[root@node1 ~]# kubectl get deployments -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
httpd 3/3 3 3 29m httpd httpd:2.4.18 run=httpd
查看记录到的revision历史记录
[root@node1 ~]# kubectl rollout history deployment httpd
deployment.apps/httpd
REVISION CHANGE-CAUSE
1 kubectl apply --filename=httpd.yml --record=true
2 kubectl apply --filename=httpd.v1.yml --record=true
3 kubectl apply --filename=httpd.v2.yml --record=true
如果要回滚,可以直接指定REVISION字段下的数字即可
如:回滚到1
[root@node1 ~]# kubectl rollout undo deployment httpd --to-revision=1
deployment.apps/httpd rolled back
这个时候revision的历史记录也会将1更新为最新的数字
[root@node1 ~]# kubectl rollout history deployment httpd
deployment.apps/httpd
REVISION CHANGE-CAUSE
2 kubectl apply --filename=httpd.v1.yml --record=true
3 kubectl apply --filename=httpd.v2.yml --record=true
4 kubectl apply --filename=httpd.yml --record=true
查看镜像版本
[root@node1 ~]# kubectl get deployments -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
httpd 3/3 3 3 36m httpd httpd:2.4.16 run=httpd