前言
软件世界比以往任何时候都更快。为了保持竞争力,需要尽快推出新的软件版本,而不会中断活跃用户访问,影响用户体验。越来越多企业已将其应用迁移到 Kubernetes。
在 Kubernetes 中有几种不同的方式发布应用,所以为了让应用在升级期间依然平稳提供服务,选择一个正确的发布策略就非常重要了,本篇文章将讲解如何在 Kubernetes 使用滚动更新的方式更新镜像。
原理
策略定义为 RollingUpdate 的 Deployment。滚动更新通过逐个替换实例来逐步部署新版本的应用,直到所有实例都被替换完成为止,会有新版旧版同时存在的情况。
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 0 # 决定了配置中期望的副本数之外,最多允许超出的 pod 实例的数量
maxUnavailable: %25 # 决定了在滚动升级期间,相对于期望副本数能够允许有多少 pod 实例处于不可用状态
上述更新策略执行结果如下图所示
![]()
实践
使用 Kubernetes 原生方式升级应用
准备
image
bebullish/demo:v1
bebullish/demo:v2
deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-dp
spec:
selector:
matchLabels:
app: demo
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
template:
metadata:
labels:
app: demo
spec:
containers:
- name: demo
image: bebullish/demo:v1
ports:
- containerPort: 8080
service
apiVersion: v1
kind: Service
metadata:
name: demo-service
spec:
selector:
app: demo
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
protocol: TCP
将上述 deployment 以及 service 保存为 yaml 文件,使用 kubectl apply -f 命令创建 yaml 资源,等待创建成功后,使用 kubectl get svc 获取 EXTERNAL-IP。
测试
如果使用浏览器测试的话,你会发现每次调用都会返回同一个 pod 的名字,那是因为浏览器发出的请求包含 keepAlive,所以需要使用 curl 来保证每次发出的请求都是重新创建的。
curl -X GET http://${EXTERNAL-IP}
![]()
升级
升级之前先执行命令,以便查看镜像更新过程
while true; do curl -X GET http://${EXTERNAL-IP} ; done
更新镜像
kubectl set image deployment demo-dp demo=bebullish/demo:v2
查看日志
![]()
请求流量
![]()
结论
首先可以发现在更新过程中,程序保持一直可用的状态,在出现了 v2 版本之后,还会出现 v1 版本的日志,说明在这个期间 v1 和 v2 版本是同时存在的,等到 v2 版本的 pod 全部处于就绪状态之后,可以看到所有的请求就都是 v2 版本的了。
使用 CODING CD 方式升级应用
配置制品
![]()
使用 docker 官方镜像需要以 docker.io 开头
配置 yaml 及绑定制品
![]()
deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-dp
spec:
selector:
matchLabels:
app: demo
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
template:
metadata:
labels:
app: demo
spec:
containers:
- name: demo
image: docker.io/bebullish/demo
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 30 # 延迟 30 秒检测,以便更好的观察更新过程
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 30 # 延迟 30 秒检测,以便更好的观察更新过程
periodSeconds: 5
terminationGracePeriodSeconds: 1 # 处于 Terminating 状态多久后,强制杀死 pod
阶段中选择 部署(Manifest) ,输入上述 yaml 文件(主要增加了就绪探针和存活探针),这里需要把镜像的版本删除掉,在需要绑定的制品选择之前配置的制品。这样配置之后,每次执行的时候版本是动态传入的。
发布制品
![]()
选择应用和部署流程,输入版本 v1。
查看结果
![]()
等待一小段时间后,就可以在部署控制台中看到发布的资源了。
更新镜像版本
![]()
再次执行发布,版本输入 v2。
更新过程
![]()
可以看到此时 v2 版本的 pod 有一个正在启动,而 v1 版本的 pod 全部处于就绪状态。
![]()
v2 版本的 pod 有一个已经就绪,同时正在启动另一个新的 pod,与此同时 v1 版本的有一个 pod 已经关机了,而另外两个 pod 仍处于就绪状态。
![]()
v2 版本的 pod 有两个已经就绪,同时正在启动最后一个新的 pod,与此同时 v1 版本的有两个 pod 已经关机了,而另外一个 pod 仍处于就绪状态。
![]()
v2 版本的 pod 已经全部处于就绪状态了,同时 v1 版本的 pod 已经全部关机,至此,一次滚动更新结束。
总结
使用 Kubernetes 原生方式实现滚动更新更加简单方便,但也容易出错(人工),推荐使用 coding.net 提供的 CD 功能,配置一次,永久使用。不仅可以直观的观察到 pod 更新过程,还提供了非常丰富的 CD 功能,推荐使用哦~
参考文章
Kuerbenetes
CODING 持续部署
【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!! ![]()