魅族运维团队通过构建持续集成云端交付平台提高应对变化的能力,实现主动应对变化提高效益的价值目标,向用户以及产品团队提供高效的交付体验。通过这段自研历程,希望能给大家带来些启示。
2017 年 12 月 01 日-02 日,由 51CTO 主办的 WOTD 全球软件开发技术峰会在深圳中州万豪酒店隆重举行。
本次峰会以软件开发为主题,魅族资深架构师古日旗在创新运维探索专场与来宾分享"魅族持续集成云端交付之路"的主题演讲,为大家带来魅族在运维自动化建设的探索以及实践经验。
本次分享分为三个部分:
- 自动化建设历程
- 持续集成及云端交付
- 展望运维智能化
自动化建设历程
魅族持续集成的建设背景,如上图:
- 2003 年到 2008 年,互联网 1.0 时代。我们的互联网业务还仅限于官网和 BBS,服务端即为 PHP + MySQL。
- 2009 年到 2011 年,互联网 2.0 时代。我们这时有了真正意义上的服务端和运维的工作,包括:LVS 的架构模式和主从复制的数据库设计。但是我们的各个业务仍然运行在单个 IDC 上。
- 2012 年到 2013 年,互联网 2.5 时代。在互联网业务方面,我们增加了应用中心、多媒体、和 O2O 等。
在架构方面,我们将主从复制的数据库进行了分库、分表,和路由选择。
在缓存方面,我们引入了 Redis 集群,并且增添了分布式的存储 MFS(MooseFS)。
与此同时,一些相应的支撑服务也随之出现,如搜索引擎、各种 MQ(Message Queue)等。
- 到了 2014 年,迈入互联网 3.0 时代。这个时代一个重要的里程碑就是:我们的互联网业务已经成为了主营业务之一。
发展给运维带来的挑战
在从互联网 1.0 到 3.0 的演变过程中,随着业务的急速增长,我们的运维面对了各种挑战,主要从质量、效率、成本、安全四个方面来进行解析。
质量方面,衡量质量的最佳方式是看它的可用性指标。一般我们分为直接和间接两种。
直接指标,我们可以从监控上看到网络、服务、应用、以及系统的可用性;间接指标,我们可以对标一些体验性的参数,比如说运行速度;也可以对标一些业务上的参数,比如说手机短信的到达率。
我们的业务可用性曾经非常低,没有一个完善的监控体系。同时我们的监控状态也比较混乱,不但覆盖率较低,而且经常会造成一些误报、漏报、错报等状况。这些直接导致了整个监控的不可相信。
效率方面,效率是衡量运维平台功能性的标准,主要体现为服务器的交付,线上的各种变更,以及我们对故障的及时发现水平。我们频繁地交付和变更,却没有将流程与自动化结合起来,因此整体效率低下。
成本方面,主要体现在业务的总体调度,和交付能力的改进与优化。由于我们的流程不完善、工作不透明,导致了某个业务到底需要多少容量完全无法评估。因此“填坑”、“救火”、“背锅”就成了我们运维的“家常便饭”。
安全方面,是整个互联网产品的生命基线。所以在早期产品研发的过程中,我们就制定了一些安全的规范和制度。
随后又建立了一套比较完善的安全体系,从而通过系统、数据和应用等维度,来体现团队对于安全问题的管控程度。
运维平台现状
我们以价值为导向建立了一系列的系统。从功能上来看,主要分成以下几个系统:
- 资源管理系统,我们通过 KVM + Docker 建立了一个云平台。基于该云平台,我们组建了一个虚拟化计算与网络的资源管理系统,并通过 CMDB 进行管控。
- 配置管理系统,我们拥有 LVS、CDN、DNS 等管理系统。同时我们对外开放了一些 API,这样做的好处在于可以精细化其相应的权限,从而实现所有的操作都能在我们的系统上得到管控。
- 自动化系统,我们有工单、日志、发布、自研运维通道、以及自动巡检系统。这些都能为运维的交付和变更提供效率上的提升。
- 监控和容量系统,我们有基础监控、自定义监控、业务监控、和容量系统。容量系统既可以帮我们评估某个业务到底需要多少资源,又可以针对该业务实现成本上的管控。
- 安全系统,我们所有的运维都是通过堡垒机进行登录的。此举可方便我们审计用户的各种操作。
通过自研的 WAF 系统和漏洞管理系统,我们可以自主地发现攻击和各个漏洞。然后进一步将漏洞信息导入到漏洞管理平台中,进行迭代、修复、与跟踪。
发布平台演进
我们的发布平台经历了周发布、日发布和自助发布三个发布历程。由于业务刚开始时较简单,我们当时采用的是手动方式。
后来随着业务的大幅增长,手动操作不得不被自动化工具所取代。比如:我们用自动化工具向服务器下发各种命令、脚本、以及任务。
这样虽然解决了一些问题,但是其整体的发布效率仍比较低下,而且成功率也不高。
针对此问题,我们在发布平台将 CMDB 的“业务树”与业务模块进行了关联,并制定出了发布的一些相关规范和指标,从而提升了发布的成功率和容错性。
为了把发布做得更为灵活,我们把权限下发到了各个业务部门,由各个业务部门的负责人来进行审核。如此一来,我们的整个发布过程就不需要运维的参与了。
我们来看当前的发布平台现状。我们的特点是发布策略比较多,有自主发布、一键重启、静态文件发布等。
同时,支持的发布类型也比较多,常见的有 Jetty、task、chef、PHP、C++ 等。
如图所示,我们发布的成功率一直都能保持在 98% 以上,而我们的自助发布率也是在持续增长中。在发布的过程,我们有超过 90% 的业务不需要运维的参与。
交付流程
我们的交付流程可分为开发、测试和生产三个环境。开发,是在本地编写代码,通过自测、然后再提交到页面。
通过 Jenkins 的打包,然后再到 WTS Redmine。这样的测试就会进行一次测试环境的部署,然后再进行一些自动或者手动的验证。
而我们在对生产环境进行运维时都会准备一些基础性的环境,以提供给那些自动部署的服务进行各种日志的搜集、报警监控、和应用的快速扩容等。
这里存在着一个微妙的平衡:它要求我们有一套比较完善的技术环境,而且负责自主框架的人员应当尽可能地稳定。
这样有利于我们拥有良好的文档和技术上的沉淀。否则一旦该平衡被打破,如一些流程没有被遵守、或是我们的相关人员出现离职、又或者我们的框架更新太快,都会导致整个交付变得不可完成。
那么在交付过程中,存在过哪些问题呢?我们总结如下:
- 在质量上,我们发现有些代码未完成单元测试,我们需要统计其相应的覆盖率和 Bug 数量。
- 在效率上,自动化部署、自动化测试和自动化构建这些都服务分散在不同的职能部门,造成了“围墙”未被打通,因此我们也无法做到精细化的运营。
- 沟通的成本高,交付变得很复杂。
- 我们的代码是否安全,是否能通过安全测试,这些都需要予以解决。
那么我们追求的是一个什么样的价值框架呢?如图所示,最下面是一个开发框架平台。
首先我们的云平台需要实现落地环境的自动化,这样就可以保证我们所交付出去的环境都是标准化的。
其次是整体开发框架,我们的技术委员会持续推行基础性的开发框架、及架构,从而保证我们拥有一套基础性的技术栈,和一个环境化的自动化流程。
交付流水线的一个核心原则就是:将标准化的流程自动化。我们在其中制定了较多的流程和规范,以实现一个可靠的、可重复的持续交付流水线。
该过程会包含许多的内容,如:提交编译阶段的并行研发、编译构建、单元测试,以及验证阶段的系统测试与集成测试。
最后是发布与运维阶段的生产交付,涉及到某个发布的回滚,以及后继的生产监控。这些过程都是在该流水线上完成的。
另外,该系统是一个多角色的平台,上面会有一些负责开发的人员角色和一些运维测试的人员进行各种协调,使得该平台对于我们整个团队都能受益。
持续集成及云端交付
标准化建设
我们的自动化分为三个阶段,分别是标准化、自动化和智能化。
在标准化方面,我们有硬件的标准化、组件的标准化,和技术栈的标准化(例如我们所用到的协议类型),以及监控的标准化。
在测试自动化方面,我们会涉及到广泛的内容,包括:单元测试、单元覆盖率、测试的准入准出条件,例如在交付的过程中,是否允许遗留一些 Bug 等。
而在建设过程中曾有两种可选的技术方案:
- 全开源,我们可以用 Docker 来进行环境自动化标准的相关操作,并且用 ES 来做日志系统。但是该方案对于我们现有系统的冲击较大。
- 基于现有的各种平台系统实践,我们在 CMDB、发布平台上做出了一些规范及流程。
最终我们选择了第二个方案,当然在方案的实施过程中,由于需要对接的平台较多,我们也遇到了不小的阻力。
鉴于这些平台分散在 PMO、测试、运维等不同的部门,要打通这些部门,我们在开发的过程中就用到了不同的规范,例如:
- 在运维处,发布平台会涉及到与机房有关的规范,包括机房里面有哪些服务器,服务器上又有哪些业务,哪些服务器是灰度环境的,哪些服务器属于生产环境等。这些都是通过 CMDB 的业务树来进行运营的。
- 在开发处,开发人员可能会用到一些全开源的平台,如 Jenkins。由于它是完全开源,且未经改造过,那么其包含的各种运营规范和一些名字的标识,是无法与我们的业务树相对应的。这些无不增加了改造的难度。
因此在该平台建设中,我们的一种做法是统一入口。鉴于 Jenkins 是打包过的,我们完全可以调用 Jenkins 的 API,把该打包操作整合到自己的平台之中。同时,我们把需求的信息也同步到了 Redmine。
此外,为了实现对 Bug 的录入和跟踪,我们将 Bug 录入的入口也整合到此平台之上。
此举既不会对我们前期操作造成大的冲击,又解决了相互间需求与Bug数量相关联的问题。
最后由于它是一个多用户的平台,我们还需要把相关人员的信息(包括开发、测试、运维等负责人)都录入、且同步到该系统之中。
自动化建设
我们再来看持续集成流程:
- 首先是需求阶段,比如:我们的某个产品运营人员会把他的需求录入到该系统中。随后开发负责人就会对此需求进行分析或预演,评估出一个交付的日期。
- 然后进入开发阶段,包括编写代码、提交代码、以及编译构建。在构建的时候还会进行一些静态的扫描,同时涉及到代码的覆盖率。
- 而在测试阶段,系统又会进行一次测试环境的部署,同时进行一些自动化的测试,其中包括各种安全测试和性能测试。
当然,我们也会进行一些手动的验证,来检查它是不是符合测试的准入标准。如果有问题的话,该流程就会被退回开发部门,需要他们重新提交代码,并再执行一次准入的流程。
- 如果该阶段没有问题的话,开发负责人或者业务运维人员就开始进行发布的审核,并且把代码发布到灰度环境之中。
在灰度环境里,我们同样需要做一些自动化的测试,以检查该服务的安全性。只有达到其接口通过率,我们才能最后发布到生产环境中。
可见,从项目需求到发布的整个阶段,我们都是在自己的平台上进行操作的,整个交付流程实现了细粒度的进度管理。
下面我们再来看发布流程:
- 首先是环境检查,这里主要检查服务器上是否有一系列的用户目录,以及一些相关的权限。
- 同时,我们会从打包平台将文件拉取到 IDC 处。
- 然后需要关闭监控。因为在该服务的部署过程中,会有短暂的不可用,进而会引发监控的报警;所以我们会针对相应的服务器进行监控的关闭。
- 当然也要将 Web 下线,从而使得新的流量不再涌入。
- 随后便是停止服务,以确保该文件不会被占用。
- 我们进行更新文件操作。
- 我们在上述过程完成之后再启动服务。
- 而在启动服务之后,我们还需进行监控检查。该检查的主要目的是为了保证我们更新上去的服务为可用的。
- 随后就是 Web 上线,我们把服务加入到 LVS 的集群之上。
- 最后再开启监控。
在上述发布的过程中,我们会针对业务的某些特点进行并行或者串性的发布。这样在能够保证成功率的前提下,也能够进一步地提升我们的发布效率。
有了该持续交付平台之后,我们就可以用它来支撑互联网常见的、急速迭代的产品研发模式。
我们既可以实现迭代前的需求计划,又能保证迭代中的开发、测试和发布,以及迭代后的回顾。
通过收集信息和数据,我们可以看到:系统在代码质量上有没有出现过严重的问题,有没有发生阻塞的情况。
另外,Bug fix 的情况也是一目了然。我们还可以获取代码的覆盖率,代码测试的通过率,性能测试、安全测试和接口测试的数据。
同时,我们不但能够获知编译的通过率、发布的成功率,还能够获取其他与效率相关的数据。
这些质量数据可以驱动和提升我们的技术能力,保证系统在上线前的质量。当然我们也可以利用这些数据来进一步地完善和优化交付流程,以确保交付过程的可靠。
运维智能化
回顾上述自动化建设的三个阶段,我们可以发现:运维智能化主要是通过搜集数据来进行学习,并实现分析和预测的目的。
例如:搜集的数据如果显示近期磁盘的换盘率比较高,那么我们就能预测到该磁盘下一次可能出故障的时间。
同时,我们还能进一步预测那些可能导致数据中心全面瘫痪的关键交换机的出错点。