关于阿里云:在阿里我们如何管理测试环境

45次阅读

共计 7679 个字符,预计需要花费 20 分钟才能阅读完成。

作者:林帆(花名金戟),阿里巴巴研发效力部技术专家

相干浏览:在阿里,咱们如何治理代码分支

阿里的许多实际看似简略,背地却蕴涵着许多思考,譬如测试环境的治理。

互联网产品的服务通常是由 Web 利用、中间件、数据库和许多后盾业务程序组成的,一套运行环境就是一个自成一体的小生态。最根本的运行环境是线上环境,部署产品的正式公布版本,为用户提供继续牢靠的服务。

除此以外,还有许多不对外部用户凋谢的运行环境,用于产品团队日常的开发和验证,统称为测试环境。正式环境的稳定性,除去软件本身的品质因素,次要与运行的主机、网络等基础设施相干,而测试环境的稳定性则更多受到人为因素影响。因为频繁的版本变更,以及部署未经充沛验证的代码,测试环境出故障的状况不足为奇。

良好的代码提交习惯、适当的变更前查看有助于缩小故障的产生,但无奈彻底杜绝后患。减少多套测试环境正本可能无效管制故障的影响范畴,然而企业的资源终归无限,升高测试环境老本和进步测试环境稳定性成为了矛盾的两面。

在这个畛域里,步人后尘的阿里研发效力团队设计了一种服务级复用的虚拟化技术,称为“个性环境”,其奇妙的思路令人赞叹。本文将围绕测试环境治理的话题,聊聊这种具备阿里特色的工作形式。

测试环境治理的困局

测试环境的用处很宽泛,常见的测试环境譬如系统集成测试环境、用户验收测试环境、预公布测试环境、灰度测试环境等,它们体现了产品的交付生命周期,也间接反映出整个团队的组织构造。

小作坊型产品团队的测试环境治理起来非常简略,每个工程师本地就能启动全套软件组件进行调试,假使不释怀,再加上一个公共的集成测试环境也就足够。

随着产品规模扩充,本地启动所有服务组件逐步变得既费时又麻烦,工程师们只能在本地运行一部分待调试的组件,而后利用公共测试环境上的其余组件组成残缺零碎。

与此同时,团队规模的扩张,使得每个团队成员的职责进一步细分,新的子团队被划分进去,这意味着我的项目的沟通成本增加,公共测试环境的稳定性开始变得难以管制。在这个过程中,测试环境治理复杂性带来的影响,不仅体现在服务联调变得繁琐,更间接反映在交付流程和资源老本的变动上。

在交付流程方面,一个显著的变动是测试环境品种增多。出于不同的用处和目标,工程师们设计出了各式各样的专用测试环境。这些测试环境的组合造成了各个企业独具特色的交付流程。下图展现了一种用于大型项目的简单交付流程。

从独自服务的角度来看,环境与环境之间是由流水线相连的,再加上自动化测试或手工审批操作组成关卡,实现环境之间的传递。通常越高级别环境的部署频率越低,因而绝对稳定性也越高。与之相同,在级别较低的环境上,就随时可能存在新的部署,会打搅正在应用该环境的其他人。有时为了复现某些非凡的问题场景,一些开发者不得不间接登录到服务器下面去“搞事件”,进一步影响环境的稳定性和可用性。

面对随时可能解体的测试环境,小企业会试着去“堵”:束缚服务变更工夫、设立严格的变更标准,大企业则长于用“疏”:减少测试环境正本,隔离故障影响范畴。显然,不堪重负的测试环境肯定越“堵”越“漏”,千年以前大禹治水的故事早就揭示了的情理,刻意的管控援救不了软弱的测试环境。

近年来,DevOps 文化的衰亡,端到端解放了开发者的双手,这对于测试环境的治理而言却是一把双刃剑。一方面,DevOps 激励开发人员参加运维,理解产品的残缺生命周期,有助于缩小不必要的低级运维事变;另一方面,DevOps 让更多的手伸向测试环境,更多的变更、更多的 Hotfix 呈现了。这些实际从全局来看利大于弊,然而并不能缓解测试环境的动荡。单纯的流程畅通同样援救不了软弱的测试环境。

那么该投入的还得投入。将不同团队所用的低级别测试环境各自独立,此时每个团队看到的都是线性流水线,从整体上察看,则会程现出河流汇聚的形态。

由此推广,现实状况下,每位开发者都应该失去独占且稳固的测试环境,各自不受烦扰的实现工作。然而因为老本因素,事实中在团队内往往只能共享无限的测试资源,不同成员在测试环境互相烦扰成为影响软件开发品质的隐患。减少测试环境正本数实质上是一种进步老本换取效率的办法,然而许多试图在老本和效率之间寻找最优均衡的探索者们,仿佛都在同一条不归路上越行越远。

因为主观的规模和体量,上述这些测试环境治理的麻烦事儿,阿里的产品团队都无奈幸免。

首先是测试环境品种的治理。

在阿里外部,同样有非常丰盛的测试环境辨别。各种测试环境的命名与其作用非亲非故,尽管业界有些罕用的名称,但都未造成权威的规范。实际上,环境的名称只是一种模式,要害还在于各种测试环境该当别离适配于特定利用场景,且场景之间该当或多或少存在一些差别。

这种差别有些在于运行的服务品种,譬如性能测试环境很可能只须要运行与压力测试相干的那局部访问量最大的要害业务服务,其余服务运行了也是浪费资源。有些差别在于接入数据的起源,譬如开发自测的环境的数据源与正式环境必定不一样,这样测试应用的假数据就不会净化线上用户的申请;预公布环境(或用户验收测试环境)会用与正式环境统一的数据源(或正式数据源的拷贝),以便反映新性能在实在数据上运行的状况;自动化测试相干的环境会有独自的一套测试数据库,以避测试运行过程中受到其他人为操作的烦扰。

还有些差别在于使用者的不同,譬如灰度和预公布环境都应用正式的数据源,但灰度环境的使用者是一小撮实在的内部用户,而预公布环境的使用者都是内部人员。总之,没必要为一个不存在业务特殊性的测试场景专门创造一种测试环境。

在团体层面,阿里对流水线模式的束缚绝对宽松。主观的讲,只有在一线的开发团队晓得最适宜团队的交付流程应该是什么样子。阿里的开发平台只是标准了一些举荐的流水线模板,开发者可在此基础上进行施展。列举几个典型的模板例子:

这里呈现了几种外界不太常见的环境类型名称,稍后会具体介绍。

其次是测试环境老本的治理。

老本治理的问题非常辣手且非常值得深究。与测试环境相干的老本次要包含治理环境所需的“人工成本”和购买基础设施所需的“资产老本”。通过自动化以及自服务化的工具能够无效升高人工相干的老本,自动化又是个很大的话题,宜另起一篇文章探讨,此处暂且收住。

资产购买老本的升高依赖技术的改进和提高(排除规模化洽购带来的价格变动因素),而基础设施技术的发展史包含两大畛域:硬件和软件。硬件倒退带来的老本大幅降落,通常来自于新的资料、新的生产工艺、以及新的硬件设计思路;软件倒退带来的基础设施老本大幅降落,目前看来,大多来自于虚拟化(即资源隔离复用)技术的冲破。

最早的虚拟化技术是虚拟机,早在 20 世纪 50 年代,IBM 就开始利用这种硬件级的虚拟化办法取得成倍的资源利用率晋升。虚拟机上的不同隔离环境之间各自运行残缺操作系统,具备很好的隔离性,通用性强,但对于运行业务服务的场景,显得略为轻便。2000 年后,KVM、XEN 等开源我的项目使得硬件级虚拟化宽泛遍及。

与此同时,另一种更轻量的虚拟化技术呈现了,以 OpenVZ、LXC 为代表的晚期容器技术,实现了建设于操作系统内核之上的运行环境虚拟化,缩小了独立操作系统的资源耗费,以就义肯定隔离性为代价,取得更高的资源利用率。

之后诞生的 Docker 以其镜像封装和单过程容器的理念,将这种内核级虚拟化技术推上百万人追捧的高度。阿里紧随技术后退的步调,早早的就用上了虚拟机和容器,在 2017 年双十一时,在线业务服务的容器化比例曾经达到 100%。然而,接下来的挑战是,基础设施资源利用率还能做得更高吗?

甩掉了虚拟机的硬件指令转换和操作系统开销,运行在容器中的程序与一般程序之间只有一层薄薄的内核 Namespace 隔离,齐全没有运行时性能损耗,虚拟化在这个方向上仿佛曾经倒退到了极限。惟一的可能是,抛开通用场景,专一到测试环境治理的特定场景上,持续寻找冲破。终于,阿里在这个畛域里发现了新的宝藏:服务级虚拟化。

所谓服务级虚拟化,实质上是基于音讯路由的管制,实现集群中局部服务的复用。在服务级虚拟化形式下,许多表面宏大的独立测试环境理论只须要耗费极小的额定基础设施资源,即便给每个开发者装备一套专用的测试环境集群都不再是吹牛。

具体来说,在阿里的交付流程上,蕴含两种非凡类型的测试环境:“公共根底环境”和“个性环境”,它们造成了具备阿里特色的测试环境应用办法。公共根底环境是一个全套的服务运行环境,它通常运行一个绝对稳固的服务版本,也有些团队将始终部署各服务的最新版本的低级别环境(称为“日常环境”)作为公共根底环境。

个性环境是这套办法中最有意思的中央,它是虚构的环境。从外表上看,每个个性环境都是一套独立残缺的测试环境,由一系列服务组成集群,而实际上,除了个别以后使用者想要测试的服务,其余服务都是通过路由零碎和消息中间件虚构进去的,指向公共根底环境的相应服务。因为在阿里通常的开发流程中,开发工作须要通过个性分支、公布分支和诸多相干环节最初公布上线,大多数环境都从公布分支部署,唯独这种开发者自用的虚拟环境部署来自代码个性分支的版本,故可称为“个性环境”(阿里外部叫“我的项目环境”)。

举个具体例子,某交易系统的残缺部署须要由鉴权服务、交易服务、订单服务、结算服务等十几种小零碎以及相应的数据库、缓存池、消息中间件等组成,那么它的公共根底环境就是这样一套具备所有服务和周边组件的残缺环境。假如此时有两套个性环境在运行,一套只启动了交易服务,另一套启动了交易服务、订单服务和结算服务。对于第一套个性环境的使用者而言,尽管除交易服务外的所有服务实际上都由公共根底环境代理,但在应用时就像是本人独占一整套残缺环境:能够随便部署和更新环境中交易服务的版本,并对它进行调试,不必放心会影响其余用户。对于第二套个性环境的使用者,则能够对部署在该环境中的三个服务进行联调和验证,假使在场景中应用到了鉴权服务,则由公共根底环境的鉴权服务来响应。

咋看起来,这不就是动静批改域名对应的路由地址、或者音讯主题对应的投递地址么?实事并没那么简略,因为不能为了某个个性环境而批改公共根底环境的路由,所以单靠正统路由机制只能实现单向指标管制,即个性环境里的服务被动发动调用可能正确路由,若申请的发起方在公共根底环境上,就无奈晓得该将申请发给哪个个性环境了。对于 HTTP 类型的申请甚至很难解决回调的状况,当处于公共根底环境的服务进行回调时,域名解析会将指标指向公共根底环境上的同名服务。

如何能力实现数据双向的正确路由和投递呢?无妨先回到这个问题的实质上来:申请应该进入哪个个性环境,是与申请的发起人相干的。因而实现双向绑定的关键在于,辨认申请发起人所处的个性环境和进行端到端的路由管制。这个过程与“灰度公布”很有几分类似,可采纳相似的思路解决。

得益于阿里在中间件畛域的技术积攒,和鹰眼等路由追踪工具的宽泛应用,辨认申请发起人和追溯回调链路都不算难事。如此一来,路由管制也就瓜熟蒂落了。当应用个性环境时,用户须要“退出”到该环境,这个操作会将用户标识(如 IP 地址或用户 ID)与指定的个性环境关联起来,每个用户只能同时属于一个个性环境。当数据申请通过路由中间件(音讯队列、音讯网关、HTTP 网关等),一旦辨认到申请的发起人以后处在个性环境中,就会尝试把申请路由给该环境中的服务,若该环境没有与指标统一的服务,才路由或投递到公共根底环境上。

个性环境并不是孤立存在的,它能够建设在容器技术之上,从而取得更大的灵活性。正如将容器建设在虚拟机之上失去基础设施获取的便利性一样,在个性环境中,通过容器疾速而动静的部署服务,意味着用户能够随时向个性环境中减少一个须要批改或调试的服务,也能够将环境中的某个服务随时销毁,让公共根底环境的主动接替它。

还有一个问题是服务集群调试。

配合 AoneFlow 的个性分支工作形式,假使将几个服务的不同个性分支部署到同一个个性环境,就能够进行多个性的即时联调,从而将个性环境用于集成测试。不过,即便个性环境的创立老本很低,毕竟服务是部署在测试集群上的。这意味着每次批改代码都须要期待流水线的构建和部署,节约了空间开销,却没有缩短工夫开销。

为了进一步的降低成本、提高效率,阿里团队又捣鼓出了一种开脑洞的玩法:将本地开发机退出个性环境。在团体外部,因为开发机和测试环境都应用内网 IP 地址,稍加变通其实不难将特定的测试环境申请间接路由到开发机。这意味着,在个性环境的用户即便拜访一个理论来自公共根底环境的服务,在后续解决链路上的一部分服务也能够来自个性环境,甚至来自本地环境。当初,调试集群中的服务变得非常简单,再也不必期待漫长的流水线构建,就像整个测试环境都运行在本地一样。

DIY 体验个性环境

感觉服务级虚拟化太小众,离一般开发者很远?实事并非如此,咱们当初就能够入手 DIY 个体验版的个性环境来玩。

阿里的个性环境实现了包含 HTTP 调用、RPC 调用、音讯队列、音讯告诉等各类罕用服务通信形式的双向路由服务级虚拟化。要实现这样的功能齐全的测试环境有点吃力,从通用性角度思考,咱无妨从最合乎公众口味的 HTTP 协定开始,做个反对单向路由的繁难款。

为了便于管理环境,最好得有一个能跑容器的集群,在开源社区里,功能齐全的 Kubernetes 是个不错的抉择。在 Kubernetes 中有些与路由管制无关的概念,它们都以资源对象的模式展示给用户。

简略介绍一下,Namespace 对象能隔离服务的路由域(与容器隔离应用的内核 Namespace 不是一个货色,勿混同),Service 对象用来指定服务的路由指标和名称,Deployment 对象对应实在部署的服务。类型是 ClusterIP(以及 NodePort 和 LoadBalancer 类型,暂且疏忽它们)的 Service 对象可路由雷同 Namespace 内的一个实在服务,类型是 ExternalName 的 Service 对象则可作为内部服务在以后 Namespace 的路由代理。这些资源对象的治理都能够应用 YAML 格局的文件来形容,大抵理解完这些,就能够开始动工了。

基础设施和 Kubernetes 集群搭建的过程略过,上面间接进正题。先得筹备路由兜底的公共根底环境,这是一个全量测试环境,包含被测系统里的所有服务和其余基础设施。暂不思考对外拜访,公共根底环境中的所有服务相应的 Service 对象都能够应用 ClusterIP 类型,假如它们对应的 Namespace 名称为 pub-base-env。这样一来,Kubernetes 会为此环境中的每个服务主动赋予 Namespace 内可用的域名“服务名.svc.cluster”和集群全局域名“服务名.pub-base-env.svc.cluster”。有了兜底的保障后,就能够开始创立个性环境了,最简略的个性环境能够只蕴含一个实在服务(例如 trade-service),其余服务全副用 ExternalName 类型的 Service 对象代理到公共根底环境上。假如它应用名称为 feature-env- 1 的 Namespace,其形容的 YAML 如下(省略了非关键字段的信息):


kind: Namespace

metadata:

  name: feature-env-1

---

kind: Service

metadata:

  name: trade-service

  namespace: feature-env-1

spec:

  type: ClusterIP

  ...

---

kind: Deployment

metadata:

  name: trade-service

  namespace: feature-env-1

spec:

  ...

---

kind: Service

metadata:

  name: order-service

  namespace: feature-env-1

spec:

  type: ExternalName

  externalName: order-service.pub-base-env.svc.cluster

  ...

---

kind: Service

...

留神其中的 order-service 服务,它在以后个性环境 Namespace 中能够应用部分域名 order-service.svc.cluster 拜访,申请会路由到它配置的全局域名 order-service.pub-base-env.svc.cluster,即公共根底环境的同名服务上解决。处于该 Namespace 中的其它服务感知不到这个差别,而是会感觉这个 Namespace 中部署了所有相干的服务。

若在个性的开发过程中,开发者对 order-service 服务也进行了批改,此时应该将批改过的服务版本增加到环境里来。只需批改 order-service 的 Service 对象属性(应用 Kubernetes 的 patch 操作),将其改为 ClusterIP 类型,同时在以后 Namespace 中创立一个 Deployment 对象与之关联即可。

因为批改 Service 对象只对相应 Namespace(即相应的个性环境)内的服务无效,无奈影响从公共根底环境回调的申请,因而路由是单向的。在这种状况下,个性环境中必须蕴含待测调用链路的入口服务和蕴含回调操作的服务。例如待测的个性是由界面操作发动的,提供用户界面的服务就是入口服务。即便该服务没有批改,也应该在个性环境中部署它的主线版本。

通过这种机制也不难实现把集群服务部分替换老本地服务进行调试开发的性能,假使集群和本地主机都在内网,将 ExternalName 类型的 Service 对象指向本地的 IP 地址和服务端口就能够了。否则须要为本地服务减少公网路由,通过动静域名解析来实现。

与此同时,云效也正在逐步完善基于 Kubernetes 的个性环境解决方案,届时将会提供更加全面的路由隔离反对。值得一提的是,因为私有云的特殊性,在联调时将本地主机退出云上集群是个必须克服的难题。为此云效实现了通过隧道网络 +kube-proxy 本身路由能力,将本地局域网主机(无需公网 IP 地址)退出到不在同一内网 Kubernetes 集群进行联调的形式。其中的技术细节也将在近期的云效公众号向大家揭晓,敬请注意。

小结

当许多人还在期待,在虚拟机和容器之后,下一轮虚拟化技术的风口何时到来的时候,阿里曾经给出了一种答案。创业者的心态让阿里人懂得,能省必须省。其实,限度翻新的往往不是技术而是想象力,服务级虚拟化的理念冲破了人们对环境正本的传统认知,以独特的角度化解了测试环境老本与稳定性的矛盾。

作为一种颇具特色的技术载体,个性环境的价值不仅仅在于轻量的测试环境治理体验,更在于为每位开发人员带来晦涩的工作形式,实则是“简洁而不简略”。

实际出真知,阿里巴巴云效平台致力于解决大型项目合作、麻利高速迭代、海量代码托管、高效测试工具、分布式秒级构建、大规模集群部署公布等世界级业务和技术难题,为阿里巴巴团体外部、生态搭档以及云上开发者服务。诚挚欢送业界同行与咱们探讨交换。

相干浏览:

在阿里,咱们如何治理代码分支

当 kubernetes 利用遇到阿里分批公布模式

正文完
 0