2019.01.15 丨 唯技术
容器环境应用一键拉起实践
2019.01.15 丨 唯技术
背景
01
PaaS平台
基于唯品会Noah云平台,我们已经在内部研发环境建立了一整套PaaS基础设施,实现对开发和测试过程的支撑。通过PaaS平台上的CI/CD流水线,实现了从代码到镜像到环境部署的整体流程;通过自研的环境管理功能(Pandora),实现了对多种不同内部开发测试部署环境的管理,支撑业务快速创建部署环境和利用容器镜像拉起应用,提高业务开发效率。
如上图所示,我们的PaaS容器部署环境目前分为功能测试环境,联调测试环境和回归测试环境三大类,其中功能测试环境包含了多个有业务开发灵活实时创建的隔离环境,用于功能验证使用,而联调和回归环境部署了所有可以上云的应用,用于各类应用的集成大联调以及上线前的回归测试验证。各个环境间通过Kubernetes的namespace进行隔离,同时在微服务应用级别也通过我们微服务基础设施提供的分区功能实现逻辑上的配置和路由隔离,从而基于同一套Kubernetes集群提供面向业务的多个逻辑上独立的环境。
02
功能环境与基础设施
针对功能环境的管理,PaaS平台的Pandora组件通过图形化的配置界面,对用户隔离了Kubernetes平台的各项细节,在Noah云基础上极大的简化了Kubernetes上的应用部署和管理。主要提供了以下功能:
●逻辑隔离环境的管理;
●应用镜像的部署,参数化配置和应用实例管理;
●基础资源服务拉起:在Kubernetes集群中为单独环境独立拉起Memcached,Redis,MySQL等服务;
●基础组件设施的集成和管理:为了支撑微服务应用生态,我们有配置中心,消息中间件服务,数据库中间件服务等。这些基础服务通过逻辑分区的方式可以灵活的提供独立环境支持;
●服务路由管理:在微服务架构下,为实现一个功能链路,单独一个应用是无法独立完成的,往往是需要依赖与其它的应用服务。被依赖的服务可以在环境内部直接访问,或者通过环境依赖的配置将请求动态路由到其它预先指定的环境内的应用(这里除了功能环境,当然也包含联调和回归环境,最大层度的重用已有服务)。
03
实际问题
尽管通过PaaS平台的Pandora图形界面极大的简化了在环境创建和应用部署管理工作,应用本身的部署依赖不是单单依靠容器的编排可以解决的问题。
通常我们部署一个容器化的应用前,需要为这个应用在配置中心创建/修改相关的配置,需要为隔离环境开通消息服务,需要准备新的数据库、Schema和初始数据或Redis容器实例为独立的应用服务,等等一系列的操作。
对于一个应用的业务测试部署人员而言,这些信息相对容易获取,但是其他人需要在一个环境中部署自己或其它开发组织开发的应用用于测试和联调时,就必须依赖阅读现有文档或者需求其他人的帮助以便正确配置依赖的基础服务,这同时也是一项比较耗时和容易出错的工作。这些准备工作往往会占用比部署应用本身更多的时间和精力。
我们希望达到的目标是能够非常快速的和可重复的一键拉起环境和应用,自动化的解决各项依赖问题,从而极大的减少人工工作,使得业务开发专注于业务的创新,从各项环境部署和管理工作中解脱出来,提高工作效率。
对于一个自动化的部署流程,我们期望是可以在分钟级别完成整套独立环境的创建,各项基础服务的开通,数据资源容器的拉起和数据初始化以及应用的启动。并且整个流程的执行是可以动态创建和监控的,从而可以同时作为一个工具服务提供给外部自动化测试以及软件工程管理系统使用。
应用场景
对于一键拉起功能,主要有三大应用场景和阶段:
●应用的开发和集成测试环境:通过版本化的环境定义,自动创建环境和应用以及相关数据服务和Mock服务,从而实现组件自动化测试中的全自动化部署
●软件项目的生命周期自动化的一部分:将实际测试环境管理创建工作从开发和测试团队工作中分离出来。开发测试只需要定义软件相关依赖和配置,各种环境完全根据配置创建出来,并且在项目结束后自动回收。作为整体项目周期,实现从项目创建开始,关联代码repo和分支,代码质量,部署配置,自动化测试,软件部署环境以及项目结束周期。
●基于Noah云的整体CICD流程关键支撑:通过将版本化的环境定义作为单一数据源,实现研发测试流程中环境的创建测试验证过程中配置数据的管理标准化,进而打通测试完成发布上线步骤的配置变更自动识别生成对比,实现和推动全CICD流程自动化。
目前我们主要关注的是第一部分,即是应用的开发和集成测试环境的快速自动化环境,用于简化开发测试阶段的环境管理。
01
一键拉起与开发/集成测试环境
目前在业务团队中,开发与测试还是遵循比较传统的分工方式:开发完成代码修改,在测试环境或者本地完成简单功能验证后提交测试部署和完成测试验收。其中的自动化过程主要有单元测试,集成测试和系统测试。通常开发只负责单元测试和部分可在本地运行的集成测试自动化,其余涉及数据准备和环境部署的测试代码通常由测试团队完成和维护。
当我们需要一个敏捷团队以最快的速度来交付稳定的产品时,这种模式无法很好的帮助我们的业务开发团队在保证高质量的同时提高交付速度:
●测试开发分离,需要更多的沟通和协调;
●可用环境有限,提测需要排队,多个不同功能分支无法并发执行测试;
●反馈周期长,开发阶段不能发现的问题需要等到提测合并到发布分支后才能得到反馈。
相对传统单元测试而言(更多偏向于单个类/文件本身逻辑的测试),目前更多的测试用例实际上是类似集成测试的,对于环境包括数据库、缓存以及其他服务有一定的依赖。这种模式下相应带来的好处在于我们可以更多的按照实际业务流程以BDD(Behavior-driven development)的方式来进行测试设计开发,专注于重要的业务需求。这也要求开发人员能够更多的参与到自动化集成测试用例的设计与执行过程中去,从而更快的获取测试执行结果,了解和解决出现的问题。
目前的自动化测试运行分两类:
●类似单元测试,但是依赖数据库/缓存和简单mock服务运行:共享外部数据库资源,没有隔离,容易发生冲突,需要协调;
●AutoV集成测试,需要本地启动数据库/缓存以及依赖的服务或mock来运行:本地资源占用大,运行和调试比较费时,速度和体验不佳。
对于开发阶段,单个应用的自动化集成测试,主要需要关注的问题包括:
●测试环境应该尽量只包含待测应用和相关基础服务依赖,如数据库、缓存等,其余需要依赖的服务尽量以mock形式配置,减少不确定性和环境复杂性;
●测试环境可以随时可重复的创建和销毁,保证环境和测试的可重复性以及有效利用资源,更多的运行测试;
●应用的行为可以通过参数化的方式来配置或者实时控制(例如通过配置中心下发配置改变应用行为)。
同样,对于同一产品线下面多个应用的集成测试也是需要遵循类似的原则,保证环境的可重复创建性以及通过Mock来隔离外部的依赖。
通过一键拉起方式管理环境,可以极大的简化环境的部署配置工作,让一般比较少接触应用部署的开发人员也可以方便快速的获取单独的开发/测试环境,进而推动和方便开发人员编写和运行更多的自动化测试用例,尽早发现问题,提高整体的交付效率。
解决方案与工作流程
要解决实际使用中的困难,统一定义和维护一套适配唯品会应用基础设施实际情况的标准化应用模型是首先需要解决的问题。我们的应用模型具体会体现为应用描述的yaml文件,可以单独和自动化测试工程保存在git repo,也可以与应用包和镜像的版本关联,保存到应用目录服务中,从而和应用一起实现版本化的同步管理。
针对我们的实际情况,应用会需要部署到不同的环境中,在不同环境需要对应用的配置按需调整,所以我们需要将应用部署描述和环境部署描述做一个分离,从而实现应用和环境描述的解耦,通过环境对应用的引用来自动化的动态组合各个应用。
对于单个应用而言,部署时除了标准的容器CPU/内存需求之外,还会有如下应用相关的配置元素:
●应用启动需要的环境变量配置;
●应用在配置中心的各种变量配置;
●应用需要创建的消息队列;
●应用需要消费的消息队列;
●应用对于数据资源服务的要求: MC, Redis,Mysql,以及通过数据中间件接入的配置;
●应用对数据库Schema/初始数据的配置。
相应在部署阶段,会有对环境的描述要求,包括:
●环境基础服务的依赖;
●环境资源服务:是否有公用资源服务,还是需要单独拉起资源使用,资源如何分配给每个应用;
●环境需要部署的应用,版本,系统资源分配;
●环境依赖信息:额外的域名解析配置,对其他环境服务的依赖,Mock服务依赖。
对于一个最简单的环境部署配置而言,只需要声明需要包含的应用和版本,系统应该自动根据应用部署描述生成环境配置:
●环境基础服务依赖:预先配置好可用的基础服务集合,部署只需要声明需要哪一组服务;
●系统资源分配:按应用类型默认值或者使用应用最低要求;
●资源服务的拉起:按应用描述要求收集汇总,拉起共享服务供应用使用;
●环境依赖:需单独声明,和环境相关。
整体而言,我们需要实现:
●通过流水线生成收集版本化的应用描述模板,生成应用目录;
●基于应用目录,结合软件项目,定义每个项目的环境部署需求,生成环境部署描述;
●基于应用描述和环境描述自动构建独立部署环境和应用配置:
☛自动关联环境依赖的各项基础服务;
☛自动创建所需数据服务资源,并且与特定应用自动绑定;
☛自动部署应用集成版本到环境,自动处理环境更新;
☛自动处理应用对环境的各项依赖。
01
自动化测试的开发和运行
基于以上解决方案,对于开发人员,我们可以比较方便的通过环境描述的声明来快速的获取一个用于开发的部署环境。
在最简单的情况下,通过声明需要的应用版本即可快速创建一个环境供使用。需要依赖的服务,可以通过对Vmock的配置获取Mock服务或者直接在当前环境中拉起实例使用。由于预先提供的应用描述已经包含数据库、缓存等信息,对应的服务也会自动在这个隔离的环境中创建出来,并且初始化完成。
对于本地测试的开发,可以直接连接这个环境运行各项测试用例而不会干扰其他人的工作或者被其他正在执行的测试干扰。
对于持续集成,也可以在代码提交编译通过后自动创建单独隔离环境运行。从而快速的获取反馈,了解修改带来的影响以及是否成功完成。
同时,如果应用已经集成了Flyway的数据迁移工具,流水线可以自动打包相关迁移脚本,从而在环境创建/应用更新过程中执行迁移,保证数据库的自动同步,让数据库版本和应用版本一起管理,减少数据不一致带来额外排查负担。
更进一步,对于开发过程中的联调,我们也不再需要依赖某一个特定环境。对方应用提供一个简单的应用配置放入环境描述以后,我们就可以在隔离环境快速的获取一个用于联调的应用实例,更好的对接口功能进行验证。
架构与实现
如前所述,我们在Pandora环境管理应用中实现了一键拉起的功能并且结合应用目录服务提供给脚本,项目管理工具和自动化测试使用。应用部署功能主要通过Noah提供的API实现容器镜像部署,同时也通过监控Kubernetes事件来实现应用和服务启动过程的跟踪,驱动整个环境拉起工作流。
01
核心功能设计与实现
一键拉起的整体基于Pandora已经实现的环境管理功能,核心部分在于通过应用模型和环境模型的解析,根据声明和依赖动态生成环境、应用拉起工作流,进而通过对工作流任务的并发和顺序执行,完成资源准备,服务开通和应用部署等各项任务。
相对于目前公用云和各项开源软件提供的服务,一大优势在于用户无需显式的关注一个应用或者一组应用的初始化过程,仅仅需要按照标准模型来描述应用和部署环境要求,系统会自动确定各项任务的执行顺序和并发执行能力,以最快的路径来执行应用部署流程。
对于应用的版本更新,原理是一样的。用户只需要提供一个环境中应用的最终版本要求,系统会自动对比差异,确定需要重新部署或者重新启动的应用,自动完成环境更新。
02
事件监控与分布式处理转发
工作流的执行是一个异步过程,因此我们需要一个事件管理机制来实现事件的统一处理和转发。这里的事件包含多个事件来源:
●Kubernetes Events:数据基础服务容器和应用容器的启动监控
●服务调用完成事件:各基础服务初始化,数据初始化等事件
●流程管理事件:比如取消流程执行等处理
我们使用Apache Kakfa作为统一的事件总线,多个Pandora流程调度器实例会订阅该事件Topic,各自实现对当前实例内管理的流程的处理。从而可以实现动态的扩容,无需担心大规模使用后流程的分布式管理问题。
03
数据库的初始化与版本管理
数据的管理通常是比较复杂的。不同应用会采取不同的方式来管理Schema和初始数据。我们也提供了多种方式来兼容不同的数据管理机制,包括:
●SQL脚本;
●从集中的数据Schema治理系统获取数据Schema;
●基于Flyway的数据自动初始化和数据迁移管理工具。
从初始数据的注入来看,由于有些应用没有很好的维护数据脚本,通常需要从一个基础的测试数据库导出初始化的SQL脚本。这种情况下数据集通常会比较大。我们在初始化执行过程中进行了优化,采用批量提交执行的策略,能够快速的批量导入数据,降低数据准备时间。
总结与使用实践
在完成核心功能开发以后,我们和一个业务小组联合对实际经常需要同时部署的一组应用做了试用和验证,总体而言比较好的满足了复杂应用部署的要求。
这一组应用的基本情况如下:
●多个应用域(7~20个),需要在同一个环境部署实现端到端的验证;
●资源服务配置复杂,目前维护了众多的虚拟机:
☛MySQL,多达128个分库。初始数据多达18000行SQL;
☛Redis:单实例/Sharding/Cluster配置并存;
☛数据库中间件:不同应用多项服务注册使用,并且有不同应用共用同一服务的情况.
●消息队列服务众多,往常需要逐条Channel/Queue进行配置;
●环境变量配置工作繁重:包括多个MySQL分库,Redis实例的配置信息;
●经常需要切换各个应用配置适应不同测试场景。
我们从现有部署环境导出了应用描述以后,经过简单定义修改数据服务相关描述,快速实现了在6~7分钟内完成所有数据库实例的初始化和应用的配置和启动,并且该过程是可以重复执行的,也就是说可以非常方便的随时根据测试场景要求快速准备出测试环境,无需手工维护各项配置和应用。对于应用版本更新,由于各基础服务已经存在,我们只需要创建新增的基础服务以及重新部署应用,可以在1~2分钟内完成。
文章来源:唯技术公众号,欢迎大家前去关注!