云纵持续交付环境管理进化历程
破天(李进庄)、冬草(宋玥辉) 创作于2018-9-10
一个公司的运维能力强弱和你线上环境敲命令是有关的,
你越是喜欢上线敲命令,你的运维能力就越弱,
越是通过自动化来处理问题,你的运维能力就越强。
——陈皓,2017
持续集成(Continuous Integration, CI)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译、发布、自动化测试)来验证,从而尽早地发现集成错误。
持续部署(Continuous Deployment, CD)是通过自动化的构建、测试和部署,循环快速交付高质量的产品。某种程度上代表了一个开发团队工程化的程度,毕竟快速运转的互联网公司人力成本会高于机器,投资于机器优化开发流程也提高了人效。
这都说明了环境管理自动化对于互联网公司的重要性。
Docker自2014年以来非常火热,随着容器化的如日中天,另一个理念DevOps也在不断传播。大部分IT从业者对于DevOps本身也都有一定的了解和认识,然而企业内部要想根据DevOps思想实践一条自己的路,绝对不是一件简单的事。而我司自2014年11月份开始引入容器到现在为止,一直在DevOps的路上不断地探索中,在这期间业界也没有出现一套标准的开源工具集可以借鉴,因此我们只能摸着石头过河。以下为我司的一些经验分享。
我司的环境演化史
演进历史-云纵
2014年11月份在容器化启动之前,我司的开发、测试及线上环境都是部署在基于OpenStack的虚拟化服务器上,技术团队需要维护的环境划分得很细:开发环境、测试环境、特殊测试环境、紧急测试环境、镜像环境、线上环境。
2015年9月随着容器化技术的使用以及云纵业务调整,环境管理缩减到了四个。
到了2016年3月,我司启动了CloudEngine的开发,一个基于私有云的研发协作系统。基于CloudEngine,我司初步实现了DevOps的雏形。在之后,根据业务需求,我们先后实现私有云灰度发布功能、多机房混合云多活管理功能。
基于CloudEngine的基础环境管理架构如下图所示,CloudEngine架设在TouchStone(容器化管理平台)、SimpleWay(运维自动化平台)、iDB(数据库自动化运维平台)、Jenkins(注:开源产品)等基础设施系统之上,可以看作是一个元数据管理者和流程调度的发起者,同时支持虚拟机和容器资源申请等,等同于我们的私有云管理系统+项目需求开发测试跟踪系统的结合体。
基础管理体系-云纵
环境演化推动过程
CloudEngine引入背景
在CloudEngine引入之前,开发使用开发联调环境,测试使用测试环境,此时我们最大的痛点是多需求并发开发,或多需求并发测试,这个时候我们只有两个解决方案:
- 多准备几个开发联调环境和测试环境(这也是容器化之前维护很多环境的原因之一),每个需求版本使用自己单独的环境,但是环境维护困难,开发人员排查起来问题也困难。
- 代码变更要求向上兼容,但是向上兼容有时候是比较困难的,甚至有时候只能串行。
为了解决快速部署一套开发联调环境或者测试环境,我们很早就引入了容器化技术,但是即使通过容器化技术,环境维护也是比较困难的。
CloudEngine1.0实现CI/CD流水线管理
机缘巧合之下我们接触并深入了解了蚂蚁金服的研发协作平台,我们把庞大的蚂蚁金服研发支撑体系浓缩为四个平台:ACP(阿里协作平台)、九州资源管控平台、AQC(蚂蚁质量基础设施平台)、Zpass(蚂蚁集团发布部署平台)。ACP是总驱动,九州、AQC、Zpass作为基础设施,整个形成一套CI/CD流水线。
阿里研发协作-云纵
而此时,我司的持续集成体系如下:
项目管理、测试用例、缺陷管理我们有一套管理体系;
自动化编译、自动化部署、自动化测试我们有一套管理体系;
镜像管理、应用发布、应用监测我们有一套管理体系;
容器管理、集群管理我们也有一套管理体系。
我们发现私有云体系的基础系统我们已经基本具备,现在需要一个PAAS平台来把研发从环境申请到测试发布上线整个研发测试链路管理起来,因此我们(注:牵头人是田志全)提出了CloudEngine(下面简称CE)的建设解决方案,功能点如下:
CE架构-云纵
CE机器申请:当一个需求从提出进入研发阶段后,研发经理在CE中选择应用、环境、虚拟化方案、Git地址等信息就可以做到一键完成机器申请、编译构建、环境部署和环境监控。研发在Git开发分支上进行编码开发,当开发到一定阶段随时可以在服务申请列表中找到申请的机器进行重新部署,以达到CI(持续集成)的目的。
CE提测申请:当研发开发联调完成后,研发经理在CE中可以直接创建提测单,CE把多个应用打包到一起进行提测。测试人员直接使用研发申请的环境进行测试(不会创建新的测试环境)。
CE上线发布:当测试人员测试通过之后,测试经理在CE中可以直接创建上线工单,CE调用SimpleWay直接会把之前环境的的Docker镜像推送到线上环境(一包通用),如阿里云,如自建IDC机房,以达到CD(持续部署)的目的。
在整个CI/CD流水线管理中涉及两个核心技术点要解决:
- 引入Stable环境概念
日常开发申请机器时,通常只需申请有代码变更的应用机器,所依赖的其他应用均来自于Stable环境。如下图所示,当我们订单服务有代码变更的时候,只需要申请一个Dev环境订单服务机器即可,购物车和支付服务还使用Stable环境的机器,即系统调用链路要能判断出是否有非Stable环境的应用,没有的话才会调用Stable环境应用。
稳定环境原理-云纵
我司应用之间的调用基本上使用Dubbo的RPC调用(而不是微服务的RestFull API,改造成本低一些),我们的解决方案是在容器申请时的ENV中打入环境标示,比如开发Stable环境标示为:SYS_ENV=ds,开发dev环境标示为:SYS_ENV=d,Dubbo在做服务调用时,优先选择非Stable环境的机器。
另外一个考虑点是MQ,我司使用的是自建Notify MQ,我们的Notify是按QueueName进行消息分组的,解决方案是不同的环境创建不同的QueueName即可,无需代码改造。
- 一包通用解决方案
一包通用指测试和线上使用相同的镜像包,技术难点在于配置信息可根据不同环境自动拉取配置。这样做的好处是测试人员测试的结果能真实反映到线上环境,避免上线重新编译打包引起的各种不一致问题(之前我们经常遇到上线分支合并出现问题影响到了线上环境)。
我们的解决方案是使用Diamond分布式配置管理统一管理各个应用各个环境的配置信息,各个应用的镜像在启动的时候根据dockerfile和tpl.properties(应用配置模版)从Diamond中拉取自己的配置信息,写入app.properties(应用真实配置文件),之后再进行容器启动以适配具体环境。具体流程如下。
一镜到底一包通用-云纵
CloudEngine2.0实现灰度发布管理
2017年开始随着我司业务扩张,每周都有三到四次大的上线操作,为了不影响线上用户体验,每次上线都要求在0点之后进行,上线完成之后,测试人员要通跑一遍业务流程,随着业务不断的复杂化,每次上线都要求相关测试和研发进行一次通宵,有些时候遇到上线失败回滚,还有可能通宵两次。为了解决这个痛点,我司根据自己的私有云管理情况提出了一套灰度发布解决方案。
灰度发布原理-云纵
灰度解决方案主要支持流量比例规则和指定IP规则。外网第一层Nginx的Lua脚本根据灰度规则组配置进行请求流量筛选,符合灰度条件的请求会在header中打入灰度标示并转发到灰度Nginx,从这里开始环境进行了隔离,但是到了后台服务端因为有环境重合的可能,所以我们利用ThreadLocal实现了一套灰度上下文,Dubbo做服务分发调用的时候,根据灰度上下文中的标示做判断进行灰度环境调用,整个请求处理流程如上图所示。
这里我们也想过完全的环境隔离方案,即灰度单独使用一整套自己的环境,但是我们分析灰度的业务也是线上业务,我们的诉求是请求随时可以进入灰度,随时也可以退出灰度,所以灰度库和线上库应该是一套数据库,另外上线灰度环境的应用可能是任何一个或多个应用,所以最终我们选择了侵入性比较高的强控制方案。
CE3.0+SimpleWay2.0实现跨机房多活
2018年年初开始,随着我司业务继续扩张,尤其支付业务的重要性越来越高,本年3月份我司正式提出启动异地多活项目,着重解决双机房切换问题。
异地多活的实现目标:
- 双机房同时提供服务,流量按照指定规则打到不同机房;
- 当机房A发生灾难时,能将流量全部切换到机房B且不会压垮机房B的既有服务;
- 机房之间数据双向同步,数据同步在2秒内完成。不同机房短时间内不对同一行数据进行写操作;
异地多活的技术难点主要在数据跨机房同步和流量请求控制两方面,经过多次讨论分析我们最终确定的解决方案如下:
异地双活原理-云纵
- 每个机房配备有一个管控系统、两套业务分片、一份全量MySQL节点,分片之间的应用是完全的网络隔离。
- 流量按商户ID进行规则分流,不同商户分流到不同机房。
- 每个机房有一个主分片和一个辅分片,主分片主要承接分到这个机房的流量,辅分片是另一个机房主分片的备用分片,当另一个机房挂掉,流程切到这个机房的辅分片上,主分片的业务不受影响。
- 数据库独立于分片之外,每个机房一套完整的数据库,采用Otter服务实现双向数据同步。
跨机房数据同步需要注意的点:
跨机房同步类型主要有三种:不同步、单向同步、双向同步。其中不同步不必考虑,需要考虑的只有单向和双向两种:
跨机房同步注意事项-云纵
业务系统改造点(注意点)
业务改造点-云纵
其他补充点
多活解决方案的目标主要是做机房容灾,即当A机房发生不可抗拒灾难后,我们可以快速把流量切到B机房以减少灾难造成的影响,以目前我们的解决方案,在灾难发生的一瞬间,数据双机房备份如果没有同步完成也会有一些细微的影响,目前只能人工干预,在灾难结束后人工对受影响的数据进行订正。
未来的进化方向
息壤(质量管理)
2018年已进入下半场,为了继续提升我司的生产效率,保证我司工程发布质量和合规性,同时考虑我司私有云等各种云的操作复杂性,降低学习成本和犯错几率,需要继续完善我司的大研发协作平台,对标蚂蚁的AQC(质量基础设施平台),我司在质量自动化管控方面还存在一定短板,因此后续我们考虑构建我们自己的质量协作平台“息壤”,将CloudEngine、RAP、JMeter等流程串接起来实现质量管控的自动化管理。
取名息壤的意思是:这是一块能自己生长的土壤,元数据(如接口定义)录入后,随着产品迭代,它能自己慢慢生长,自动化单元测试,测试用例自动化执行,场景自动回归,日检等等。
总结
云纵是一个笃信工程师文化的公司,我们崇尚依靠技术(及自动化)而不是依靠线下流程(注:为了避免网友误会,此流程特指线下人工流程)和管理解决问题。
我们的体系架构宏大,我们持续投入资源(注:日常20%~30%的研发资源),虽然此体系绝非一朝一夕所能完成,但是我们秉承平凡人可做非凡事和日拱一卒功不唐捐的理念,一群信仰技术的工程师边开飞机边换引擎,我们终会有实现宏伟蓝图的那一天。
参考资源:
1,2018,#研发解决方案#异地多活让商户无感知;
2,2017,轻舟已过万重山——真正的技术派公司是怎么联调、测试和发布的?;
3,2016,私有云的难处—为什么需要CloudEngine?;
4,2016,#研发解决方案#研发协作平台CloudEngine;
-EOF-
/*敬请关注我的公众号:老兵笔记*/