K8S发布策略-滚动更新(rollingUpdate)
现在很多公司都使用K8S(kubernetes)进行容器管理和编排,今天来说下k8s的发布策略: 滚动更新。
滚动更新的优点:允许通过使用新的实例逐步更新Pods实例来实现部署的更新,从而实现零停机 。应用程序始终可用。 在金丝雀发布基础上的进一步优化改进, 滚动更新是一种自动化程度较高的发布方式,用户体验比较平滑,是目前成熟型技术组织所采用的主流发布方式,
滚动更新的缺点: 发布过程是比较缓慢 。 一次滚动发布一般由若干个发布批次组成,每批的数量一般是可以配置的(可以通过发布模 板定义),例如第一批 1 台,第二批 10%,第三批 50%,第四批 100%。每个批次之间留观察间隔,通过手工验证或监控反馈确保没有问题再发下一批次,所以总体上滚动式发布过程是比较缓慢的。
滚动更新(rollingUpdate)
滚动更新步骤:
1. 准备一个新版本的POD,比如新版本为V2,旧版本为V1。
2. 当V2版本的POD准备好后,在负载均衡中的实例池中将V2的版本加入。
3. 在实例池中剔除一个V1版本的POD。
4. 逐个实例替换,直到每个版本都是V2版本。
如下图:
滚动更新使用的YAML方式如下:
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2 # 一次可以添加多少个Pod
maxUnavailable: 1 # 滚动更新期间最大多少个Pod不可用
我们准备两个版本, fffmo.com-app-v1.yaml文件。
apiVersion: v1
kind: Service
metadata:
name: fffmo.com-app
labels:
app: fffmo.com-app
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: http
selector:
app: fffmo.com-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: fffmo.com-app
labels:
app: fffmo.com-app
spec:
replicas: 3
selector:
matchLabels:
app: fffmo.com-app
strategy:
type: Recreate
selector:
matchLabels:
app: fffmo.com-app
template:
metadata:
labels:
app: fffmo.com-app
version: v1.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9101"
spec:
containers:
- name: fffmo.com-app
image: containersol/k8s-deployment-strategies
ports:
- name: http
containerPort: 8080
- name: probe
containerPort: 8086
env:
- name: VERSION
value: v1.0.0
livenessProbe:
httpGet:
path: /live
port: probe
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: probe
periodSeconds: 5
然后我们再准备一下滚动更新的v2版本,
fffmo.com-app-rolling-update.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: fffmo.com-app
labels:
app: fffmo.com-app
spec:
replicas: 10
# maxUnavailable设置为0可以完全确保在滚动更新期间服务不受影响,还可以使用百分比的值来进行设置。
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: fffmo.com-app
template:
metadata:
labels:
app: fffmo.com-app
version: v2.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9101"
spec:
containers:
- name: fffmo.com-app
image: containersol/k8s-deployment-strategies
ports:
- name: http
containerPort: 8080
- name: probe
containerPort: 8086
env:
- name: VERSION
value: v2.0.0
livenessProbe:
httpGet:
path: /live
port: probe
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: probe
# 初始延迟设置高点可以更好地观察滚动更新过程
initialDelaySeconds: 15
periodSeconds: 5
接下来,我们按如下步骤进行操作:
1. 启动fffmo.com-app-v1应用
2. 启动fffmo.com-app-rollingupdate应用
3. 观察所有容器版本变为V2版本
启动fffmo.com-app-v1应用并观察,都已经启动,我们进行接口调用。
apply -f fffmo.com-app-v1.yaml
kubectl get pods -l app=fffmo.com-app
NAME READY STATUS RESTARTS AGE
fffmo.com-app-847874cd75-h3d2e 1/1 Running 0 47s
fffmo.com-app-847874cd75-p4l8f 1/1 Running 0 47s
fffmo.com-app-847874cd75-qnt7p 1/1 Running 0 47s
$ kubectl get svc fffmo.com-app
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
fffmo.com-app NodePort 10.109.99.184 <none> 80:30486/TCP 1m
确认更新完成
kubectl rollout status deployment/fffmo.com-app
$ curl http://127.0.0.1:30486
Host: fffmo.com-app-847874cd75-qnt7p, Version: v1.0.0
在当前窗口监控容器的情况,执行命令
watch kubectl get pods -l app=fffmo.com-app
打开一个新的窗口,然后执行滚动更新命令
kubectl apply -f fffmo.com-app-rolling-update.yaml
查看部署
kubectl get deployments -l run=fffmo.com-app
查看正在运行的Pods$ kubectl get pods -o wide
在watch的终端观察,开始的时候并没删除旧的pod,而是创建好新的pod后,然后进行挨个替,我们可以使用如下命令观察接口请求, 渐渐的有了第二个版本的请求。
$ while sleep 0.1; do curl http://127.0.0.1:30486; done
Host:fffmo.com-app-847874cd75-h3d2e, Version: v1.0.0
......
Host: fffmo.com-app-847874cd75-h3d2e, Version: v1.0.0
Host: fffmo.com-app-6b5479d97f-2fk24, Version: v2.0.0
在这个过程中,我们发现第二个版本有问题,我们需要进行回滚,此时我们需要执行一下如下命令
kubectl rollout undo deploy fffmo.com-app
如果想两个版本都观察一下,这个时候需要执行命令。
kubectl rollout pause deploy fffmo.com-app
如果发现第二个版本没有问题,那么我们要恢复执行,也就是我们说的回滚。
kubectl rollout resume deploy fffmo.com-app
最后我们清理一下所有的部署
kubectl delete -l app=fffmo.com-app
总结一下:
1. k8s发布策略-滚动部署没有控制流量的情况。
2. 各个版本部署的时候需要一定的时间。
3. 在k8s中,更新是版本化的,任何部署更新都可以恢复为以前的(稳定)版本。