在生产环境中更新和配置应用程序通常是件令人望而生畏的事。面对如此多的可用选项,应如何选择最适合你的用例的部署策略?
部署策略用于升级或配置正在运行的应用程序。在下文中,我们将讨论三种部署策略:
值得注意的是,还可通过许多其他方式来发布应用程序的新版本。你可点击此处,查看针对其中一部分方式进行的讨论。
在整篇文章中,我们将使用本地 Kubernetes 环境来演示所讨论的各种部署策略。
如果可以的话,你也可以使用云环境。
下文提到了演示所需的所有文件和命令,也可以在该项目的 Github 存储库中找到。
顺带一提,Ori Hoch 撰写的一篇博文已探讨了使用 Kubernetes 来支持 CI 构建(见第 1 部分和第 2 部分)。在这篇文章中,我们将更多地关注 CI/CD 的 CD 部分,也就是部署。
来看看我们的 Kubernetes YAML 文件:
version1-deployment.yml
——部署 6 个副本,运行一个简单的 Web 应用程序,呈现“版本 1
# version2-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-2
spec:
selector:
matchLabels:
app: nginx
version: 'v1.1'
replicas: 6
template:
metadata:
labels:
app: nginx
version: 'v1.1'
spec:
containers:
- name: nginx
image: my_project/web-app:version2
ports:
- containerPort: 80
version2-deployment.yml
部署
——部署 6 个副本,运行一个简单的 Web 应用程序,呈现“版本 2”
# version2-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-2
spec:
selector:
matchLabels:
app: nginx
version: 'v1.1'
replicas: 6
template:
metadata:
labels:
app: nginx
version: 'v1.1'
spec:
containers:
- name: nginx
image: my_project/web-app:version2
ports:
- containerPort: 80
production-service.yml
——我们应用程序的生产服务。用户将使用该服务访问应用程序的第一版本(version1)。
# production-service.yml
apiVersion: v1
kind: Service
metadata:
name: production-service
spec:
type: LoadBalancer
selector:
app: nginx
version: 'v1.0'
ports:
- protocol: TCP
port: 80
targetPort: 80
重建部署(基本部署)
你有没有问过自己:“要部署我的应用程序,最糟糕的方式是什么?”
如果有,那么答案就是重建部署。
玩笑归玩笑,针对这种方法也有一些有效的用例。
例如,在并行运行多个版本的同时,升级基于微服务的复杂应用程序,可能会导致数据丢失或引发严重的网络问题。
采用这种方法后,在部署新版本之前必须完全关闭当前版本。在关闭当前版本直至完全部署好新版本期间,用户将经历停机时间。
在我们所讨论的所有部署策略中,重建部署是最易实现且成本最低的,但也是风险最大的。万一新版本出现严重 bug,所有用户都会注意到它,而且任何必要的回滚都将导致停机时间变得更长。
优点:
缺点:
1.部署应用程序的第一版本
kubectl apply -f version1-deployment.yml && kubectl rollout status -f version1-deployment.yml
2.应用生产服务
kubectl apply -f production-service.yml
3.删除应用程序的第一版本
kubectl delete -f version1-deployment.yml
4.彻底删除第一版本后,部署应用程序的新版本
kubectl apply -f version2-deployment.yml && kubectl rollout status -f version2-deployment.yml
5.现在,剩下的工作就是更改服务以指向新版本
kubectl patch service production-service --patch '{"spec": {"selector": {"version": "v1.1"}}}'
如果你最大的担忧是停机时间,则考虑使用下一种方法。
蓝绿部署,也称为“红黑部署”(如果你猜到是谁嵌入了这个术语,加一分*),是一种零停机时间部署策略,应用程序的当前版本(“蓝色”实例)和新版本(“绿色”实例)在生产环境中并行运行。两个版本同时运行,但公开的应用程序的服务仅指向当前版本。
在用户可以访问新版本之前,需要在环境中对其进行测试。当确定其满足所有要求后,剩下的工作就是更改应用程序的服务以指向绿色实例。
*(还没有猜到吗?答案是 Netflix!你可以点击此处查看更多相关信息。)
从此时起,旧版本作为新版本的备份,与其一起运行。万一发生故障,回滚很容易——只需将流量从绿色实例切换到蓝色实例。
部署成功并删除蓝色实例后,绿色实例将在下一次更新中充当蓝色实例。
优点:
缺点:
如需实现蓝绿部署:
1.应用蓝色实例的部署
kubectl apply -f version1-deployment.yml && kubectl rollout status -f version1-deployment.yml
2.应用绿色实例的部署
kubectl apply -f version2-deployment.yml && kubectl rollout status -f version2-deployment.yml
3.应用生产服务
kubectl apply -f production-service.yml
4.就绿色实例运行测试
1.如果测试期间在新版本中发现了问题,删除新版本的部署,
kubectl delete -f version2-deployment.yml
并在重新部署之前修复应用程序的代码。
2.如果新版本测试成功,且该版本已准备就绪可用于生产,则更改服务以指向绿色实例
kubectl patch service production-service --patch '{"spec": {"selector": {"version": "v1.1"}}}'
即可!
若采用金丝雀部署这种方法,在将应用程序新版本发布给所有用户之前,逐步向一小部分用户推出,以进行初始测试。此方法的目的是针对少量用户收集性能度量指标,并预测对用户的影响,以便进行全面部署。在这组用户使用了应用程序的新版本后,将收集和分析度量指标,以确定该版本是否已准备就绪可用于生产,是否需要推广到环境的其他部分(或到下一阶段),或者是否需要回滚以进一步排除故障。
这种策略最适用于测试结果不明确、不可靠或流量大小可能影响应用程序性能的情况。
金丝雀部署可以分两步或小阶段实现(例如,5% 的用户,到 25%,再到 50%……),当部署一个新的应用程序代码后,它将公开给多个用户。
与其他策略相比,这种方法带来的风险最低,因为它提供了控制。
你可以定义在每个阶段将转发到新版本的请求的确切百分比,因此,如果发生错误,只有少数用户会受到影响,并且你可以快速、毫不费力地执行回滚。
为了成功实现金丝雀部署,性能度量指标应该是明确的,并且两个版本应该在相同的条件下部署在同一环境中。
采用这种方法,可以选择针对自定义客户群部署新版本。你可以按用户的应用程序体验层级、所处地理位置或使用频率对用户进行排序。
做一个更好的应用程序,这一目标始终不变,但重要的是要考虑你希望通过金丝雀部署获得哪些信息,比如选择一个信任度高的子网,还是丧失客户信任的影响很小的子网。
使用金丝雀部署的一个缺点是,你必须同时管理应用程序的多个版本。甚至还可以在生产中同时运行两个以上的版本。但是,最好将同时运行的版本数量控制在最低限度。
你可以读一读 LaunchDarkly(一家专注于部署解决方案的公司)撰写的这篇博文,了解更多关于针对不同客户群推出不同版本这一做法的信息。
为何要使用这种部署策略?
优点:
缺点:
如需实现金丝雀部署:
实现金丝雀部署可采用的方法和工具有很多。下文提供了最简单的一种,无需任何附加工具即可使用。
1.部署应用程序第一版本的三个实例
kubectl apply -f version1-deployment.yml && kubectl rollout status -f version1-deployment.yml
2.应用生产服务
kubectl apply -f production-service.yml
3.将当前版本的实例数减少到 3
kubectl scale --replicas=3 -f version1-deployment.yml && kubectl rollout status -f version1-deployment.yml
4.就 3 个实例部署应用程序的新版本
kubectl apply -f version2-deployment.yml && kubectl scale --replicas=3 -f version2-deployment.yml && kubectl rollout status -f version2-deployment.yml
5.当 3 个实例为当前版本,3 个实例为新版本时,更改服务以指向两个版本。换言之,50% 的用户将访问新版本,50% 的用户将访问当前版本
kubectl patch service production-service --patch '{"spec": {"selector": {"version": null}}}'
6.对新版本的实例运行测试
1.如果在测试过程中发现新版本有问题,则回滚到之前的版本(删除新版本的部署,并将之前版本的实例数增加到原来的数目)
kubectl delete -f version2-deployment.yml && kubectl scale --replicas=6 -f version1-deployment.yml && kubectl rollout status -f version1-deployment.yml
2.如果该版本运行良好,则删除当前版本的部署,并将新版本的实例数增加到原来的数目,从而完成推出
kubectl delete -f version1-deployment.yml && kubectl scale --replicas=6 -f version2-deployment.yml && kubectl rollout status -f version2-deployment.yml
金丝雀部署也带来了挑战。最大的障碍之一是管理服务和不同版本的组件之间的依赖关系。在某些情况下,有些旧版本组件仍然是应用程序的一部分,但新版本组件无法与此类组件很好地交互,反之亦然。因此,实现新旧版本间通信兼容并非易事。针对这一挑战,有几个不错的解决方案,但我们不会在此进行讨论,因为这将超出本文的范围。
无论你是想在本地 Kubernetes 集群还是云环境中部署应用程序的新版本,都有多种部署方式可供选择,而最佳方式取决于你的需求和基础设施成本。
在将某个版本发布到开发/模拟环境时,或者当并行运行多个版本期间可能会出现应用程序性能问题时,重建部署是一个不错的选择。
对于生产环境,若基础设施成本不成问题(因为要求具备可提供双倍资源的能力),蓝/绿部署可能是你的最佳解决方案,但需要针对新应用程序运行适当的测试。
如果对软件的影响/稳定性没什么信心,对用户体验感到担忧,或者你的应用程序需要在某个可进行筛选(例如地理位置或体验层级)的特定客户群中测试某项新功能,那么你可能要使用金丝雀部署。
相关文章:
软件发布管理流程技巧
如何成功实现功能发布控制
点击了解 Incredibuild 的 CI/CD 加速的解决方案!
同时,Incredibuild 还有纯云 / 混合云的编译加速解决方案!