导读:在云原生时代下,软件的迭代速度越来越快,对开发测试的要求也越来越高。文库的整体架构上云后,配套的项目测试流程产生了变化,随之暴露出来了很多问题。
全文4349字,预计阅读时间11分钟。
首先,我们把上云前文库研发团队的项目流程进行分析,如下。
- 这一系列的问题都会造成我们的开发测试人员,不能专注在自己擅长的事情上。
除此之外,部门业务迭代和新同学的加入,对于软件运行的环境、资源的精细化管理、动态调整都有了更高的要求。需要一套项目开发测试流程管理的高效自动化平台来解决以上的问题和推动整体基础架构的良性演进。为了解决这些问题,文库通过使用容器编排技术,结合业务架构把线上服务拆分成多个子环境。研发、QA同学可以在接到需求后,按需申请项目所需的环境套餐,平台很快会产出一套满足测试需求的标准化容器组。环境管理平台高效支撑了业务快速迭代,支持同时容纳500+子环境,可以理解为至少100个迭代项目可以并行测试。2019 年环境创建2073个 ,2020 年环境创建8908个 ,2021 年环境创建16801个 ,2022 年至今环境创建数已经达到5000+。同时,基于平台实现质量控制流程,建立自动化测试构建规范,解决过去缺少测试标准规范带来的程序质量问题。PAAS上云后,如何选定一套合适的技术栈,在解决开发测试底层环境引擎仿真性问题的同时,系统能够实现高性能,高可用的质量保障,流程上能够变得简易轻量,构建效率提升。再者,避免手动搭建引入的安全问题,软件崩溃,文档不全,效率低、耗时长、机器资源浪费等缺陷。经过充分调研,平台基于Kubernetes容器编排和docker容器引擎技术,结合git,flanneld,etcd等开源项目,bcc,icode,bns,agile,uuap等厂内服务搭建而成,具备以下好处。平台的核心功能实现,是由Master节点、Etcd独立集群、22个Node节点的内网集群和私有化镜像仓库构成的。自动化部署脚本对集群设定部署规范,独立部署的etcd高可用集群存储分布式系统中的关键数据,网络插件flannel协同进行集群内网络的的划分,保证每个容器具有全集群唯一的虚拟IP地址,创建新的虚拟网卡flannel0和docker网桥数据,构建路由表进行接收和发送数据的封包和转发操作,最后设置iptables规则管理进出云服务器的流量的安全调度,构成了一套可以支持秒级搭建,动态交付,安全可靠的容器编排集群。- 降本提效:开启devops新模式,需申请环境资源,分钟级构建环境,提升测试效率,实现规模化自动化构建环境,降低人力运维成本。
- 安全可控:提供稳定、灵活、可控的流水线构建方式和网络通信,保障安全性。
- 简单易用:无需直接管理云资源,在一个页面即可完成全部人工操作,余下的编排调度任务交给自动化集群。
选定了一套技术栈后,如何把复杂的文库业务项目和技术栈结合起来,让技术为人服务?这需要解决线下线上代码不同步、使用部分公共服务导致结果不完全可靠,覆盖度低,测试数据缺失,场景覆盖度小等问题。用户通过在平台前端入口提交资源申请,审批通过后,任务写入DB,常驻进程执行任务。细节如下图所示。根据任务生成Yaml资源清单,读取镜像仓库创建容器,完成一个测试所需环境组的申请、审批、生成、构建、检查、 代理转发、子环境串联、代码更新、最后到期释放的生命周期。环境的生命周期流程是按照一定顺序执行的一系列特定的步骤,每个环节都按照计划的系统的执行。每个环节有不同的目标和交付产物,来支持平台可以实现不同测试需求的功能。这里展开说下。下图简明地展示了环境的生命周期,分为代码更新,镜像更新,环境申请,资源审批,环境构建,代理转发,环境串联,环境回收,这8个环节。技术选型保证了线上线下运行环境的底层引擎的一致性,那么如何保证代码库的高度一致性?这里我们实现了环境镜像的天级别更新,具体细节如下展开:- 独立部署一台具备登录访问线上运行层实例的云服务器;
- 通过执行shell命令,ssh远程登录线上实例执行tar压缩命令打包运行环境文件;
- scp传输到本机目录,实现线上线下的环境代码同步(这里不依赖代码库版本,而是直接打包线上实例文件的好处,是可以解决增量上线带来的文件差异);
- 通过配置文件的前置替换工作,完成环境的conf文件更新;
- docker run -d 本地启动一个和线上实例相同的基础镜像;
- docker cp把文件拷贝至启动的容器中,清理无用日志文件;
- docker stop & rm 停止销毁这个启动的容器,一并docker rmi删除掉生成到本地的子环境镜像。
已上流程是一个子环境的线下镜像更新流程,crontab天级别执行,实现了上层结构的环境天级别同步。如何实现平台化的管理环境,避免引入手工搭建的困扰,用户可以只在平台UI页面即可管理环境。这离不开环境在每个环节的自动化管理。- 【审批】经过管理员审批之后,库表状态流转至待创建;
- 【生成】常驻进程会调用创建应用函数,根据创建的环境类型选择合适的服务器代理端口,根据用户名、应用类型、服务器代理端口,容器资源规格等参数,生成的xxx.yaml资源清单,传输至master节点执行命令kubectl create -f xxx.yaml,发布成功则进入下一个流程,创建失败则任务失败。
- 【构建】常驻进程从数据库中获取构建任务,根据不同的应用类型,调用应用的初始化环境函数初始化环境,调用应用的更新代码环境数据函数更新容器内的代码文件目录,调用应用的启动环境函数启动环境,执行成功则流转至代理阶段,执行失败则任务失败发邮件通知用户;
- 【代理转发】常驻进程从数据库中获取代理端口映射任务,根据应用中的服务器代理端口,产生服务器代理文件,传输到proxy云服务器nginx的vhost conf目录,软重启加载新的端口映射转发配置文件,执行失败则任务失败;
- 【子环境串联】多个子环境端口串联,是一个后置替换的过程,通过子环境间的依赖和调用关系,更新子环境内的webserver端口配置,重启服务使串联生效。这个环节支持用户自主选择串联关系,同时支持通过流水线标准化默认串联。
- 【回收】研发、测试同学在平台前端可以主动释放环境,或者按照任务创建的环境套餐到达了到期时间。常驻进程会把库表中docker容器组的状态流转到待删除,这个状态的容器所在pod,service,deployment将被回收进程处理,对应的宿主机机器资源释放。
在文库的研发团队项目迭代中,业务架构里包含许多服务,服务之间存在链式依赖,难以独立启动运行。这时就很容易出现“共用测试环境相互干扰”的问题,比如一个开发者重新部署、重启测试环境时,可能会打断所有正在测试的开发者;一个开发者提交了有BUG的代码,所有开发者都可能受影响;一个开发者为了排查问题,单步调试测试环境服务时,所有开发者测试请求会被拦截。如何来解决这个问题呢?以往的思路是准备多套完整的测试环境。虽然这种方式可以暂时缓解开发过程中的相互影响,隔离不同项目的运行结果,但是这会带来额外的资源分配和管理问题,特别是当大量测试项目需求用不到的服务仍然被创建时,会产生非常严重的资源浪费。通过前面讲过的环境生命周期管理,改进了一下,用完即删。该方法在一定程度上解决闲置资源回收的问题,但是也没有那么“完美”。在实际操作过程中,环境的创建其实并没有那么“快速”,往往需要等待几分钟甚至几十分钟的时间。而且如果为每个测试项目需求都分别申请一整套环境,资源浪费依然严重。在多人协同场景下,如何做到测试环境不相互干扰又不产生极大的资源浪费呢?我们通过拆分子环境的方案解决。为了资源效能提升和环境仿真性(保证服务调用和环境部署的方式完全一致),子环境的拆分粒度贴合线上的服务单元部署方式。因此平台支持的子环境包括:- wap前端服务(wknode_wapwenku_offline)
- pc前端服务(wknode_pcwenku_offline)
- 付费前端服务(wknode_fufei_offline)
依赖的公共服务包含用户中心,存储中心,下载服务,检索站搜,转码等等。后端服务之间实现rpc调用,将频繁迭代的服务打包成独立子环境,前后端子环境之前串联端口,把长期不迭代的依赖服务抽离出来,搭建为线下的公共服务。基于当前文库所支持的业务迭代场景,为消除碎片化环境带来的业务部署困难,文档缺失等问题,建立了如上的环境管理平台。随着技术栈从php向golang的迁移,异构部署的微服务数量增加,应对qa同学对环境提出更多需求,平台在授权梳理、性能测试、故障定位、日志搜集、配置切换、支持外网、集成流水线、环境分享协作、中间件安全加固的方方面面进行升级改造,和业务共同成长。平台将继续支撑业务高效高质量迭代,丰富产品功能,解决产品痛点,驱动产品目标达成。Spark离线开发框架设计与实现
爱番番微前端框架落地实践
云原生时代的搜索服务算力管理
浅谈小程序开源业务架构建设之路