作者:十眠、立衡
OpenKruise 是一个基于 Kubernetes 的扩大套件,次要聚焦于云原生利用的自动化,比方部署、公布、运维以及可用性防护。本文介绍通过 OpenKruise 构建自动化运维的形式实现全链路灰度性能。
灰度公布进步利用交付的稳定性和效率
在公布利用的过程中,咱们通常心愿用大量特定流量来验证新版本的公布是否失常,以保障整体稳定性。这个过程被称为灰度公布。对于灰度公布,咱们通过逐渐减少公布的范畴,来验证新版本的稳定性。如果新版本呈现问题,咱们也能及时发现,管制影响范畴,保障整体的稳定性。
渐进式公布个别具备以下特点:
- 逐渐减少公布的影响范畴,回绝一次性全副公布;
- 阶段性的公布过程,能够通过金丝雀公布形式小心验证,以验证新版本的稳定性;
- 可暂停、可回滚、可持续、可自动化状态流转,以便灵便地管制公布过程并确保稳定性。
据调研数据 70% 的线上问题都是因为变更导致,咱们常说平安生产三板斧,可灰度、可观测、可回滚,也是为了管制变更带来的危险与影响面。通过采纳灰度公布的形式,咱们可能更加持重地公布新版本,防止因公布过程中呈现的问题而带来的损失。
微服务架构对灰度公布提出了更高的要求
在微服务架构的场景下,传统的灰度公布模式往往不能满足微服务交付的简单、多样化的需要。这是因为:
- 微服务调用链路比拟长,比较复杂。在微服务架构中,服务之间的调用链路比较复杂,一个服务的改变可能会影响到整个调用链路,从而影响整个利用的稳定性。
- 一次灰度可能波及多个模块,整个链路都要调用新版本。因为微服务架构中服务之间相互依赖,一个服务的批改可能须要其余服务的相应调整。这就导致了在进行灰度公布时,须要同时调用多个服务的新版本,减少了公布的复杂度和不确定性。
- 多个我的项目并行,须要部署多套环境,环境构建不灵便、老本高。在微服务架构中,往往会有多个我的项目并行开发,须要部署多套环境来反对不同的我的项目。这就减少了环境构建的难度和老本,从而导致公布效率低下。
为了解决这些问题,咱们须要采纳更加灵便、可控并且实用于微服务场景的公布形式,全链路灰度公布的场景也就应运而生。通常每个微服务都会有灰度环境或分组来承受灰度流量。咱们心愿进入上游灰度环境的流量也能进入上游灰度的环境中,确保 1 个申请始终在灰度环境中传递,从而造成流量“泳道”。在“泳道”内的流量链路中,即便这个调用链路上有一些微服务利用不存在灰度环境,那么这些微服务利用在申请上游利用的时候仍然可能回到上游利用的灰度环境中。
全链路灰度为微服务公布保驾护航
这种形式能够依据服务的理论状况,能够对单个服务能够进行独立的公布和流量管制,也能够管制多个服务同时进行公布变更,从而保障整个零碎的稳定性。同时,还能够采纳自动化的部署形式,实现疾速、牢靠的公布过程,进步公布效率和稳定性。
实际全链路灰度的挑战
在 K8s 中实现微服务全链路灰度公布是一个非常复杂的过程,须要波及多个组件和配置的批改与协调。以下是具体的一些步骤和问题:
- 在微服务架构中,网关是服务的入口,须要依据灰度公布的要求,调整网关配置,实现路由匹配和流量特色(比方 Header 批改)。
- 为了实现全链路灰度公布,须要新部署一套灰度应用环境,并为其打上灰度标记(新部署一套 Gray 利用以及 Gray 灰度标)。这样能够将流量流向灰度环境,从而实现灰度公布。
- 验证流量失常,将基线环境降级,销毁灰度环境,复原网关配置。在灰度公布过程中,须要对流量进行验证,确保流量的失常流向和服务的失常运行。如果验证通过,能够将基线环境降级到灰度版本,并销毁灰度环境。最初,须要复原网关的配置,以确保流量失常流向。
- 如果产生异样,须要疾速回滚。因为微服务架构简单,可能会呈现各种异常情况,比方服务解体、流量异样等。在这种状况下,须要疾速回滚,以防止产生更大的损失。因而,须要事后设计好回滚计划,并在产生异样时疾速执行回滚操作。
另外一方面,生产的流量是端到端的,那么意味着咱们须要管制流量在前端、网关、后端各个微服务等组件中闭环。不仅仅是 RPC/Http 的流量,对于异步调用比方 MQ 流量咱们也须要合乎全链路“泳道”调用的规定,这整个过程中波及到的流量管制的复杂度也是十分高的。
为了简化微服务全链路灰度公布的过程,能够应用一些自动化工具和产品,如 MSE、Kruise Rollout 等。这些工具和产品能够帮忙咱们更加便捷地实现微服务全链路灰度公布,并进步公布的效率和稳定性。
Kruise Rollout+MSE 端到端的全链路灰度公布实际
为什么要 Kruise Rollout?
Kruise Rollout [ 1] 是 OpenKruise 社区开源提出的一个渐进式交付框架。其设计理念是提供一组可能将流量公布与实例灰度相结合,反对金丝雀、蓝绿、A/B Testing 等多样化公布模式,以及反对基于 Prometheus Metrics 等自定义 Metrics 实现公布过程自动化,无感对接、易扩大的旁路式规范 Kubernetes 公布组件。次要个性如下:
- 非侵入性: 不对用户的利用交付配置做任何的侵入,应用旁路的形式来扩大渐进式交付的能力,并且可能做到即插即用的成果。
- 可扩展性: 充分考虑了对多种相似的工作负载的反对(Deployment、StatefulSet、CloneSet 以及自定义 CRD 工作负载);在流量调度方面,通过 lua 脚本的计划可能反对 Nginx、Alb、Mse、Gateway API 等多种流量调度计划。
Kruise Rollout 自身就反对各种灰度公布的能力(金丝雀、A/B Testing、蓝绿公布),深刻理解后发现它的公布模型十分符合 MSE 全链路灰度,因而与 Kruise Rollout 联合后能够十分不便的让用户实现 MSE 全链路灰度公布能力。
MSE 全链路灰度公布的最佳实际
01. 部署利用 & 配置全链路灰度公布 CRD
咱们能够参考 MSE 云原生网关全链路灰度 [ 2] 文档部署 Demo 利用。
➜ ~ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
demo-mysql 1/1 1 1 30h
nacos-server 1/1 1 1 46h
spring-cloud-a 2/2 2 2 30h
spring-cloud-b 2/2 2 2 30h
spring-cloud-c 2/2 2 2 30h
部署完利用之后,咱们首先要辨别线上流量和灰度流量。
咱们通过创立 Rollout CRD 来定义全链路灰度公布的流程。
- 将整个链路波及到的利用创立 Rollout 配置
# a rollout configuration
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
name: rollout-a
spec:
objectRef:
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: spring-cloud-a
...
# b rollout configuration
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
name: rollout-b
annotations:
rollouts.kruise.io/dependency: rollout-a
spec:
objectRef:
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: spring-cloud-b
...
# c rollout configuration
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
name: rollout-c
annotations:
rollouts.kruise.io/dependency: rollout-a
spec:
objectRef:
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: spring-cloud-c
...
- 而后为了表明线上流量与灰度流量的特色,即在入口服务上配置灰度流量规定
canary:
steps:
- matches:
- headers:
- type: Exact
name: x-user-id
value: '100'
requestHeaderModifier:
set:
- name: x-mse-tag
value: gray
trafficRoutings:
- service: spring-cloud-a
ingress:
name: spring-cloud-a
classType: mse
- 针对灰度公布中的利用,Kruise 会主动给他标识 gray 版本
# only support for canary deployment type
patchCanaryMetadata:
labels:
alicloud.service.tag: gray
装置实现 Rollout CRD 后,咱们能够查看一下:
➜ ~ kubectl get Rollout
NAME STATUS CANARY_STEP CANARY_STATE MESSAGE AGE
rollout-a Healthy 1 Completed workload deployment is completed 4s
rollout-b Healthy 1 Completed workload deployment is completed 4s
rollout-c Healthy 1 Completed workload deployment is completed 4s
到目前为止咱们定义了这样一组全链路灰度公布的规定,公布链路波及 MSE 云原生网关、A、B、C 利用,其中 x-user-id=100 的流量为灰度流量。
接下来,咱们疾速进行一次灰度公布与验证吧。
02. 灰度公布 & 验证流量
- 本次公布波及到利用 A、C 的改变,因而咱们间接编辑利用 A、C 的 Deployment yaml,进行变更操作
# a application
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-a
spec:
...
template:
...
spec:
# 批改 mse-1.0.0 -> mse-2.0.0,触发利用 A 公布,以及 MSE 全链路灰度
image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-a:mse-2.0.0
# c application
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-c
spec:
...
template:
...
spec:
# 批改 mse-1.0.0 -> mse-2.0.0,触发利用 A 公布,以及 MSE 全链路灰度
image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-c:mse-2.0.0
- 变更实现之后,咱们查看咱们以后利用的状态
➜ ~ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
demo-mysql 1/1 1 1 30h
nacos-server 1/1 1 1 46h
spring-cloud-a 2/2 0 2 30h
spring-cloud-a-84gcd 1/1 1 1 86s
spring-cloud-b 2/2 2 2 30h
spring-cloud-c 2/2 0 2 30h
spring-cloud-c-qzh9p 1/1 1 1 113s
咱们发现,Kruise Rollout 并没有间接批改咱们原先的 deployment,而是先给咱们创立了两个灰度利用 spring-cloud-a-84gcd、spring-cloud-c-qzh9p。
- 等利用启动就绪咱们别离来验证线上失常流量以及灰度流量
a. 拜访网关,如果不合乎灰度规定,走基线环境:
➜ ~ curl -H "Host: example.com" http://39.98.205.236/a
A[192.168.42.115][config=base] -> B[192.168.42.118] -> C[192.168.42.101]%
b. 如何合乎灰度规定,走灰度环境:
➜ ~ curl -H "Host: example.com" http://39.98.205.236/a -H "x-user-id: 100"
Agray[192.168.42.119][config=base] -> B[192.168.42.118] -> Cgray[192.168.42.116]%
- 如果碰到预期外的行为,咱们如何进行疾速回滚?
咱们尝试回滚一下 C 利用,只需将 C 利用的 Deployment 改回原先配置即可。
# c application
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-c
spec:
...
template:
...
spec:
# 批改 mse-2.0.0 -> mse-1.0.0,回滚 c 利用
image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-c:mse-2.0.0
批改实现后,咱们发现 C 利用的灰度 Deployment 曾经没了。
➜ ~ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
demo-mysql 1/1 1 1 30h
nacos-server 1/1 1 1 46h
spring-cloud-a 2/2 0 2 30h
spring-cloud-a-84gcd 1/1 1 1 186s
spring-cloud-b 2/2 2 2 30h
spring-cloud-c 2/2 0 2 30h
- 如何实现公布?只需 kubectl-kruise rollout approve rollouts/rollout-a 将灰度中的利用进行实现公布
03. 整合 ArgoCD 实现基于 GitOps 的全链路灰度
GitOps 是一种继续交付的形式,它的核心思想是将利用零碎的申明性基础架构和应用程序寄存在 Git 版本库中。将 Git 作为交付流水线的外围,每个开发人员都能够提交拉取申请(Pull Request)并应用 Git 来减速和简化 Kubernetes 的应用程序部署和运维工作。通过应用像 Git 这样的简略工具,开发人员能够更高效地将注意力集中在创立新性能而不是运维相干工作上(例如,利用零碎装置、配置、迁徙等)。
试想一下,做为 Developer,咱们心愿提交的 YAML 编写的利用程序定义(Deployment)能够先进行自动化的灰度环境公布,流量通过充沛验证后,确定新版本的应用程序没有问题后,再进一步进行全量的利用公布。如何能够做到呢?接下来咱们演示通过整合 ArgoCD 来实现的全链路灰度能力。
前提条件
装置 ArgoCD,参考 ArgoCD [ 3],ArgoCD 是用于 Kubernetes 的 申明性 GitOps 间断交付工具。
通过 ArgoCD 配置部署利用资源
- 在 ArgoCD 中创立 spring-cloud-c 利用
- 在 ArgoCD 治理界面,单击 NEW APP,进行如下配置。
a. 在 GENERAL 区域,配置 Application 为 spring-cloud-c,Project 为 default。
b. 在 SOURCE 区域,配置 Repository URL 为 https://github.com/aliyun/alibabacloud-microservice-demo.git,Revision 为 argocd-samples,Path 为 argocd-samples/spring-cloud-c。
c. 在 DESTINATION 区域,配置 Cluster URL 为 https://kubernetes.default.svc,Namespace 为 default。
d. 配置实现,单击页面上方的 CREATE。
- 创立实现后,在 ArgoCD 治理界面,即可查看 spring-cloud-c 利用状态
- 单击对应利用即可查看资源部署状态
- 咱们批改 argocd-samples/spring-cloud-c 中的 spring-cloud-c.yaml,并通过 git 提交
- 咱们能够发现,主动部署了 spring-cloud-c 利用的灰度版本
✗ kubectl get pods -o wide | grep spring-cloud
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
spring-cloud-a-69d577cc9-g7sbc 1/1 Running 0 16h 192.168.0.191 us-west-1.192.168.0.187 <none> <none>
spring-cloud-b-7bc9db878f-n7pzp 1/1 Running 0 16h 192.168.0.193 us-west-1.192.168.0.189 <none> <none>
spring-cloud-c-554458c696-2vp74 1/1 Running 0 137m 192.168.0.200 us-west-1.192.168.0.145 <none> <none>
spring-cloud-c-554458c696-g8vbg 1/1 Running 0 136m 192.168.0.192 us-west-1.192.168.0.188 <none> <none>
spring-cloud-c-md42b-74858b7c4-qzdxz 1/1 Running 0 53m 192.168.0.165 us-west-1.192.168.0.147 <none> <none>
架构图如下:
- 等利用启动就绪咱们别离来验证线上失常流量以及灰度流量
a. 拜访网关,如果不合乎灰度规定,走基线环境:
➜ ~ curl -H "Host: example.com" http://39.98.205.236/a
A[192.168.0.191][config=base] -> B[192.168.0.193] -> C[192.168.0.200]%
b. 如何合乎灰度规定,走灰度环境:
➜ ~ curl -H "Host: example.com" http://39.98.205.236/a -H "x-user-id: 100"
A[192.168.0.191][config=base] -> B[192.168.0.193] -> Cgray[192.168.0.165]%
- 回滚只需咱们通过 git 回滚 argocd-samples/spring-cloud-c 中的 spring-cloud-c.yaml 的上一次提交即可。
- 完结公布通过 kubectl-kruise rollout approve rollouts/rollout-c 将灰度中的利用进行实现公布。
瞻望与总结
Kruise Rollout 是 OpenKruise 社区在渐进式交付畛域的摸索,此次与 MSE 单干在云原生畛域落地了微服务场景的灰度公布场景。将来,Kruise Rollout 将在可扩展性方面做出继续的致力,比方:基于 Lua 脚本的可扩大流量调度计划,从而兼容社区更多的网关与架构(Istio、Apifix 等)。
在微服务治理架构中,全链路灰度性能能提供流量泳道,极大的不便了测试、公布时的疾速验证,通过准确的引流规定将“爆炸半径”管制到最小,可能帮忙 DevOps 晋升线上稳定性。
MSE 的全链路灰度能力也在随着客户场景的深刻而一直扩大与迭代。咱们除了通过 MSE 全链路灰度能力保障公布态的稳定性外,还能够在运行态通过 MSE 解决流量、依赖、基础设施等不稳固的危险,MSE 微服务引擎始终致力于帮忙企业打造永远在线的利用,置信只有通过客户场景继续打磨的产品才会愈发历久弥新。
相干社区
退出 OpenKruise 社区
最初,十分欢送你通过 Github/Slack/ 钉钉 / 微信 等形式退出咱们来参加 OpenKruise 开源社区。
- 退出社区 Slack channel (English)
- 退出社区钉钉群:搜寻群号 23330762 (Chinese)
- 退出社区微信群(新):增加用户 openkruise 并让机器人拉你入群 (Chinese)
如果您感觉 Higress 对您有帮忙,欢送返回 github: Higress [ 4] 为咱们 star 一下!
相干链接:
[1] Kruise Rollout
https://openkruise.io/rollouts/introduction
[2] MSE 云原生网关全链路灰度
https://help.aliyun.com/zh/mse/configure-an-end-to-end-canary-release-based-on-mse-ingress-gateways#p-omu-6xu-8wm
[3] ArgoCD
https://argo-cd.readthedocs.io/en/stable/getting_started/
[4] github: Higress
https://github.com/alibaba/higress