我们知道,在研发过程中往往需要多套环境以满足不同的阶段的研发需求,如开发、测试、预发布环境。好的环境方案可以提高开发调试、项目测试的效率,也可以降低上线的风险,从而缩短整个需求的交付周期,提高生产效率。
为应对业务快速发展的需求,收钱吧在多环境的治理上经历了数个版本的迭代。本文主要介绍这几代测试环境的发展与技术实现。
2018年之前,收钱吧的测试环境是两套物理隔离的环境:
使用Jenkins[1]+Docker[2]部署,两套环境之间互不影响。这套部署方案,技术上相对成熟,操作上简单直观,但存在以下的问题:
以上问题也对应着我们的各种诉求:
2018年,收钱吧决定将服务迁往Kubernetes[3]集群,原来的CI构建也从Jenkins迁移到Gitlab CI[4]。Gitlab CI的使用,使得从checkout源码到构建Docker镜像的整个流程透明化,而依托于Kubernetes的能力,服务部署、升级等操作流程也不再繁琐,更容易与内部系统集成,实现自动化。
虽然将服务迁移到Kubernetes集群解决了测试环境中的很多问题,但在业务需求快速迭代的场景下,测试环境最核心的诉求:同一个服务在环境中能够多版本共存,并没有得到有效解决。
在Kubernetes原生网络中,让请求访问同一个服务的两个不同版本,我们只有两种选择:
显然Kubernetes原生网络无法提供足够的支持,我们需要能够精确控制流量路由到哪个版本。在此背景下,受到阿里特性环境[5]的启发,我们提出了多泳道环境的构想。蓝图如下,同时引入了环境泳道的概念。
环境泳道是逻辑而非物理上的概念,同一泳道的服务之间可以直接访问,跨泳道的访问需要携带对应标识,访问的服务在泳道内不存在,请求也不携带标识,则默认路由到基础泳道。
若干个环境泳道,组成了多泳道环境:
这样的设计之下,我们认为传统的物理上的多环境将转变成逻辑上的多环境,从而可以大量节省硬件资源,处于开发、测试阶段的项目不会再因为环境数量限制而导致排队等待了,另外通过底层设施来控制路由,也不会再出现不同环境交叉使用的乱象。
以上构想,正是当时Service Mesh[6]着力解决的问题。不管是RedHat,还是Nginx[7],给出的Service Mesh方案都是使用Control Plane + Sidecar[8] Proxy的模式。所以工程效率团队调研了当时相对成熟的解决方案Istio[9]。
我们从Istio的Bookinfo[10]这个样例上可以了解到,Istio流量管理的核心功能是通过两份CRD[11]--VirtualService
和DestinationRule
的配置来完成。
其中VirtualService
用于配置路由规则,它可以作用于L4、L7,对于常见的HTTP流量还可以对header、uri、queryParams等进行匹配路由,如:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-route
spec:
hosts:
- reviews.prod.svc.cluster.local
http:
- name: "reviews-v2-routes"
match:
- uri:
prefix: "/wpcatalog"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v2
- name: "reviews-v1-route"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v1
而DestinationRule
定义了服务的不同版本,如:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: bookinfo-ratings
spec:
host: ratings.prod.svc.cluster.local
subsets:
- name: testversion
labels:
version: v3
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
这样来,对于多泳道环境的构思,依托于Istio的能力,可以被简化成以下逻辑:
if headers.x-env-flag == v2:
route(subset_v2)
else if request.sourceLabels.version == v2:
request.headers.x-env-flag = v2
route(subset_v2)
else:
route(subset_v1)
利用基础设施层进行流量的路由的实现还有个显而易见的好处:对当前服务的改造成本极小。当时第一批接入的后端服务,只需要升级RPC
库的版本即可。
另外,我们也配套开发了多泳道环境管理平台——Volac。它的作用便是创建环境泳道,并根据环境泳道配置对应的VirtualService和DestinationRule。
改造后测试环境的控制逻辑如下图:
VirtualService
和DestinationRule
,并部署服务Envoy
容器作为sidecar,同时Istio控制面监听VirtualService
和DestinationRule
的变化,动态地给Envoy
下发路由配置。改造后的业务流量如下图:
经过上述改造,基本解决了早期测试环境中的问题,但是却带来了新的问题。
公司内部服务部署系统涉及很多业务方面的需求,例如:
也涉及很多技术方面的细节,如:
综合以上,在多泳道环境管理平台Volac的实现过程中,还存在一些问题:
基于以上原因,我们将Volac的业务逻辑与技术细节拆解:
最终,测试环境的控制逻辑如下:
至此,依托于Kubernetes的CRD扩展和operator,测试环境实现了:
多泳道环境1.0在2019年上线,最终带来了很多直接和间接收益。
直接收益:
间接收益:
刘宁,来自技术平台部
Jenkins: https://www.jenkins.io/
[2]Docker: https://www.docker.com/
[3]Kubernetes: https://kubernetes.io/
[4]Gitlab CI: https://docs.gitlab.com/ee/ci/
[5]在阿里,我们如何管理测试环境: https://developer.aliyun.com/article/688852
[6]What's a service mesh?: https://www.redhat.com/en/topics/microservices/what-is-a-service-mesh
[7]What Is a Service Mesh?: https://www.nginx.com/blog/what-is-a-service-mesh/
[8]Microsoft: Sidecar Pattern: https://docs.microsoft.com/en-us/azure/architecture/patterns/sidecar
[9]Istio: https://istio.io/latest/
[10]Bookinfo Application: https://istio.io/latest/docs/examples/bookinfo/
[11]Extend the Kubernetes API with CustomResourceDefinitions: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
[12]Wosai/elastic-env-operator: https://github.com/WoSai/elastic-env-operator
[13]Extending Kubernetes: Operator Pattern: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/