在软件研发过程中,“测试环境”是部署最频繁、也是开发者使用最频繁的一种运行环境,稳定而易用的测试环境能够极大提高开发者的工作效率和幸福感。为更好的将阿里巴巴在测试环境管理方面的实践和经验跟广大开发者分享,《云效说码》策划了《阿里巴巴Kubernetes测试环境开源工具箱》系列直播视频,由阿里巴巴技术专家林帆(金戟)和郑云龙(砧木) 来为大家讲述。
本系列分享共有三节内容,本文整理自砧木的第二次分享《单人开发场景下的测试环境实践》。
【以下为分享实录,有删节】
《阿里巴巴测试环境管理概述》要点回顾
在正式开始本次分享之前,我们首先回顾一下上一次分享中我的同事金戟分享的要点。在测试环境管理中,我们主要遇到两个问题,第一个是本地与集群双向互通的问题,在阿里巴巴集团内部主要通过基于CNI(Conteinre Network Interface)机制改造Kubernetes的IP逻辑实现的“扁平化的内网IP”这个方法来解决,这种方式更适合大型集团企业。第二个问题是多人协作开发时,路由的可访问性控制问题,在阿里巴巴内部我们是通过“项目环境”与“隔离域”实现的。
程序员小黑的困扰:测试环境不稳定导致集成效率低下
本次分享,我们将把视角从阿里巴巴集团内部转向外部开发者,特别是广大开发者所在的中小团队,聊聊他们如何解决前文中提到的“本地与集群双向互通”的问题。
我们先来思考一个问题:在本地开发的时候,有哪些让你感到痛苦的事情?
为了帮助大家更好回忆,我们假象了一位主人公——程序员小黑。小黑所在公司采用了微服务相关的技术实践,公司的平台根据业务情况被划分为多个“服务”,小黑所在团队负责的是其中单独一个业务领域。小黑团队会使用平台中的一些公共服务,同时他们也会为平台中的其它服务提供标准的API,方便其它服务调用数据。
为了降低整个平台的运维成本,小黑公司使用了阿里云提供的Kubernetes服务来搭建他们的测试环境及生产环境,通过云效提供的项目协作“看板”管理项目的需求及迭代进度。同时云效也提供了DevOps相关的能力支持,打通了从代码开发到软件发布上线的端到端的过程。小黑公司基于这套DevOps体系,不断的对产品进行迭代和优化。
相对于采用“DevOps”之前,小黑公司的研发效能已经得到极大提升,但近期小黑却遇到了一些困扰。他发现,由于测试环境不稳定,让他浪费了大量的时间在“集成”这件事情上。
其实,团队中的每位成员都希望尽快完成本地开发的功能的验证工作,目前情况下,小黑团队成员只能先将代码提交到代码仓库,然后通过流水线将代码部署到测试环境,因此“代码提交”会变得非常频繁,也就意味着在大部分时间里,你的测试环境会处于更新、发布状态中,整个测试环境的可用性就会变得非常差。甚至有的时候,因为个别成员在本地开发完成后,对代码没有进行充分验证就进行了测试提交,导致整个测试环境“挂掉”。有时因为有紧急的需求需要快速上线,测试环境会被这些紧急变更独占。小黑只能在测试环境可用的短暂的时间里尽可能地去验证自己开发的功能,这就导致小黑最近情绪很低落。
小黑的困扰一:联调其它服务。
其实小黑的需求很简单,他希望在本地代码开发完成之后,能够尽可能快的跟其它服务进行联调,来验证他开发的功能是否OK,但是现在他唯一能依赖的就是那套“公共环境”。
在本地完成代码开发后,如何高效的与其它服务进行联调呢?经过分析发现,在本地进行联调效率最高,使用公共环境进行测试成本最低,两全其美的办法就是,在本地直接访问云上集群的环境进行测试。对这个“命题作文”,开发者和企业有很多不同的选择,除了在第一次分享中我同事介绍的方法外,我们还推出了一个更轻量的方式通过KT-Connect工具实现。
KT-Connect是阿里巴巴云效团队研发的面向Kubernetes的本地开发者辅助工具(已经开源),通过“Connect”命令可以实现一键连接云上任意的Kubernetes集群。连接完成之后,可以快速建立本地到集群的VPN网络,同时将Kubernetes集群的DNS解析能力整合到本地,开发者可以像在集群中一样可以直接通过PodIP,ClusterIP以及DNS域名访问到集群内的服务。
小黑的困扰二:其它服务调用我
在这个案例中,小黑既是服务的消费者,同时也会提供一些公共的API供其它服务调用。这时只打通本地到集群的服务,并不能完全解决小黑的问题,必须同时让集群中的服务可以访问本地的服务。
KT-Connect同样可以帮助我们解决这个问题,这就需要使用“Exchange”和“Mesh”命令。
Exchange(交换)命令通过在集群内部署代理容器,替换集群内的原有应用,并将所有对代理容器的请求直接转发到本地端口。这是一种“完全替换”,这就意味着在同一时间点,只有一位开发者可以将他本地的服务加入到集群中。为了解决这个问题,KT-Connect提供了第三个命令——Mesh(混合)。当我们在本地运营“Mesh”命令后,我们同样会把本地服务加入到集群里面,但是会保持原有的目标服务状态不变,并且本地服务会继承目标服务中所有的标签。依照K8S本身服务发现的原理,请求流量会被随机地转发到原有服务或本地的服务。同时配合Istio的流量规则,就可以让所有正常流量依然保持对原应用的访问,而只对一些有特殊标记的的请求转发到本地。从而可以实现在一套公用测试环境的基础上各自独立的完成本地的集成联调。
KT-Connect带来高效的测试体验
如前文所述,通过KT-Connect我们可以实现从本地到集群的双向互通。在团队里,其实还有很多“小黑”,我们可以看到这样一个场景:小黑A可以通过“Mesh”命令把本地服务加入到测试环境里,并且可以让集群中一部分特定的流量转发到本地,这样他可以与集群中的其它服务进行联调。小黑B通过“Connect”命令连接到集群,直接在本地进行测试。在某些情况下,小黑B需要依赖的服务刚好是小黑A正在开发的版本,小黑B只要按照Istio的流量规则设置可以调用小黑A服务的值,就可以跟小黑A的服务进行联调。对于小黑C,他既需要调用集群中的服务,又需要集群中的服务回调到本地,所以他在本地既运营了 “Connect”又运行了“Mesh”。如上所示,小黑团队中的所有成员的测试活动都是建立在一套公共环境的基础之上,但是彼此又都有一个相对独立的测试环境,具有很好的可用性。
KT-Connect背后的原理
KT-Connect背后有什么黑科技吗?答案是:没有。我们只是综合利用了两个大家在日常工作中都会用到的能力,通过Kubectl的端口转发可以实现将集群中服务的端口映射到本地,通过SSH协议建立本地与集群之间的隧道。
以“Connect”命令为例,了解一下KT-Connect背后的原理。如上图所示,当开发者在本地运行“Connect”命令后,首先会创建一个shadow pod实例,这个实例会运行“SSH Server”和“DNS Server”,当实例创建成功之后,就可以通过“port-forward”将代理容器的22端口转映射到本地,如2222端口。此时,就可以通过本地的2222端口建立与集群内部的连接。
“Exchange”和与“Connect”命令背后的原理类似,我们也会先创建一个代理容器,并通过“port-forward”将代理容器的端口映射到本地。然后根据Exchange的目标服务,判断将代理容器的哪一个端口的请求全部转发到本地的特定端口。
“Mesh”与“Exchange”的最大的差异在于“Exhange”会将原应用的Replicas(副本)直接降到0,会将集群内所有对原应用的流量全部转发到本地。而 “Mesh”则是在保持原有应用Pod不变的前提下,创建一个新的代理容器并且继承原应用的所有标签,并会增加一个随机的version标签。配合Istio的流量规则,可以让所有正常流量依然保持对原应用的访问,而只对一些有特殊标记的的请求转发到本地。从而可以实现在一套公用测试环境的基础上各自独立的完成本地的集成联调。
最后用《持续交付》中的一句话来总结今天的分享:集成通常是一个非常痛苦的过程。那么就应该在每次提交代码后就进行集成,而且应该从项目一开始就这么做。其实句话还可以做一个调整,我们提倡在代码提交之“前”就进行验证。
非常感谢大家的聆听,欢迎大家加入云效开发者交流群和KT-Connect工具用户群与我们交流。
【下期预告】
【直播日期】5月6日 16:00
【直播主题】多人协作场景下的测试环境实践
【直播讲师】郑云龙 阿里巴巴技术专家
【观看方式】云效开发者交流群直播(钉钉群号:群号:34532418)
【关于云效】
云效,企业级一站式DevOps平台,源于阿里巴巴先进的研发理念和工程实践,致力于成为数字企业的研发效能引擎!云效提供从“需求 ->开发->测试->发布->运维->运营”端到端的在线协同服务和研发工具,通过人工智能、云原生技术的应用助力开发者提升研发效能,持续交付有效价值。