2015年前,猪八戒网80%的项目都是PHP语言开发的,剩余少部分系统使用Node.js和Java。2015年一个关键的里程碑,开启了猪八戒网SOA服务转变,这就是腾云7号行动。php
腾云7号可谓意义深远,它使用Java语言将核心业务代码进行了重构,创建了以Dubbo为核心的SOA服务框架,使用ZooKeeper + Swoole为核心的业务调用提供机制。html
知足新业务使用Java语言编写、老业务仍然使用PHP编写,同时支持两种语言调用Dubbo服务的能力。前端
在SOA架构的基础上,2016年开始全面推行先后端分离,因而出现了三足鼎立的局面:node
剩余部分小系统或者边缘化的工具使用其余语言开发,或者在此三种语言基础上的一些变种:nginx
系统架构以及语言体系的变化,随之而来的是项目工程的指数级增加:docker
项目工程的增加,给软件研发过程管理带来了较大压力,这时候公司开始推行敏捷。shell
区别于业界流行的敏捷开发模式,猪八戒网根据公司实际状况作了一点小小的变化,即增长了deploy的概念,整个层级变成:deploy->story→task。后端
deploy是story的集合,做为一次上线发布的内容汇总,它主要负责从开发到测试到运维的交付件说明,以及开发-测试-性能-预发布-灰度-线上各环境代码发布的准入准出标准控制,deploy这部分将在后面DevOps中作详细介绍。api
业务扩张对运维又带来了压力,大量的项目须要进行发布,因此虚拟机的数量也不断增加,管理难度随之加大,运维人数最多增长到三十多人:浏览器
为了下降维护难度,咱们开始作CMDB,指定各类规范,同时进行多数据中心建设,业务上作异地双活。
Nginx加载Upstream进行灰度和生产环境流量控制,DNS负责数据中心切换,能达到在某个数据中心挂掉的状况下快速切换到另一个数据中心。
敏捷开发、快速增加的项目工程、不一样语言的编译构建、不一样数据中心的部署和代码发布、不一样数据中心和不一样环境之间的服务监控以及反馈链路,如何知足这些需求而且将它们连起来,这是猪八戒网须要解决的重点问题。
为了知足业务快速扩张的需求,2016年底开始组建DevOps团队,集合了运维、配置管理、Java技术人员等。团队专门负责DevOps方法论以及技术的落地,全公司使用统一的标准进行软件开发,并使用统一的工具进行项目管理。一张图看猪八戒网的DevOps:
上图中的DevOps是一个平台,它集成了从开发到测试到上线的整个过程,基于这个图重点介绍:
在2016年开始,公司搭建了GitLab,后来发现GitLab和SVN你们都在用,那么整个发布系统须要支持两种版本库(那个时候的发布系统并非Jenkins,而是公司本身开发的syn2,基于Django框架的Python前端,调用后端shell实现编译构建和发布),虽然当时都支持了,但为了统一版本库,下降维护成本,咱们关闭了SVN,将全部SVN项目迁移到GitLab中。
同时咱们提供了Java的Dubbo和API工程模版,Node.js的两个框架工程模版,用户在DevOps平台能够直接选择工程模版,而后自动建立一个Git工程并返回给用户Git地址。
针对开发语言的不一样,咱们提供了12种编译方式,分别为:Java、PHP、Node.js、Utopia、Scala、GNode、Jello、FIS、HTML、TPL、Thrift、BLG。
针对不一样的编译方式,咱们提供了不一样的Jenkins构建环境,固然,咱们把它集成在了一块儿,Jenkins采用Master/Slave的架构,支持任何语言的编译,Jenkins将在后续介绍。
Java的组件,构建后发布到Nexus组件仓库,原来咱们的Nexus组件仓库不受控制,开发人员能够随意上传组件,不论是snapshots仍是release,因此致使不少release版本问题,后来咱们作了权限控制,发布也统一块儿来,开发人员能够在本地将snapshots上传到Nexus仓库,可是release的必须使用DevOps提供的能力上传,这极大的保护了release版本的稳定性。
Java的API接口实现,这里有三个功能:发布组件到Nexus仓库、自动生成API接口文档、将代码转换为PHP和Node.js生成物(这里没有历史,只有此生)。
这三个功能用户能够一键触发,因此任何部门的API接口,只要一发布,必然有最新的接口文档,避免了接口文档认为更新不及时的问题。
流水线的演变是基于测试环境的变化而变化的,曾经咱们的测试环境比较单一,流水线也相对简单,但随着业务的快速发展,单一的环境凸显大量的问题,因此咱们开始在环境和流水线上进行优化改造。
曾经猪八戒网的测试环境都是由DevOps团队统一管理和维护的,随着环境和流水线的不断优化,后来交接给运维团队负责,目前已经在慢慢将测试环境交给开发和测试自行维护,但你们意识上仍是比较多的依赖于DevOps和运维帮忙解决环境上的问题,这里先介绍流水线上发布模式进化的三个阶段:
第一阶段:咱们叫它大锅饭年代
这个时期的流水线很简单,环境也很简单,问题点主要也就是上图中的状况。
第二阶段:又叫公交车模式
在这个阶段,咱们的系统架构尚未Dubbo,此次调整只是为了解决环境共用致使的相互影响,因此搭建了t一、t二、等t系列测试环境。测试完成后将代码合并到Trunk推送预发布,在预发布作回滚测试,上线时直接将预发布的代码同步到生产环境,保证预发布的代码和生产环境代码一致。
公交车模式解决了第一个阶段提到的1和2两个问题,但项目仍然耦合。因此咱们以公交车模式经过下降线上变动频率【每周2、四15点,公交车司机准点发车,将预发布上的代码同步到线上(并非将Trunk代码发布到线上)】来达到耦合带来的问题;虽然解决了一部分问题,但随之而来的须要大量人工劳动力去维护这大量的测试环境,环境一致性问题随之突出。
第三阶段:也叫出租车模式
为了解决项目的耦合问题,以及环境一致性问题,咱们开始给每一个项目指定开发负责人,这种责任人制度,很大程度上解决了耦合的问题,你们都开始将各自负责的项目权限收起来了,业务范围和边界更清晰。同时引入Docker技术,实现构建一次到处运行,解决了环境一致性问题。分支策略也变得很是简单:branches开发,master发布,tags存档。你们能够在此分支策略基础上作任意变种,知足各个事业部不一样开发人员的工做习惯。
在出租车模式发布的各个环境里,使用了在敏捷阶段介绍的deploy,每一个环境推送,都必须指定一个deploy,这个deploy必须和你推送的项目工程有关:
deploy必须到了某个阶段,才能推送对应环境,而deploy的每一个阶段都有准出检查。
这就像一条河,河上有几个坝,每个坝都会拦截一部分河里的垃圾,那这条河的下游相对上游确定是更清澈干净一些,最终汇入大海的水才会清澈,海水就是咱们的生产环境。
每个节点(环境)又有各自的流水线,各节点下的流水线:
因此咱们的流水线是二级流水线:第一级流水线对应咱们的五大环境(测试环境用户能够自定义环境名称,因此又有子环境的概念);第二级流水线对应各环境所须要的原子任务组合。
全部功能咱们作成原子任务,包括校验类和执行类。每一个节点(环境)能够自由组合须要的原子任务(必须的原子任务由后台控制,非必须的原子任务由用户自行选择是否添加)。
校验类:咱们在执行任务以前,有不少校验(此类任务通常使用Java实现),包括前面提到的和敏捷关联的deploy的流程校验,以及安全扫描是否经过,配置中心是否配置,告警中心是否有对应告警等多达十几个校验项;
执行类:各类校验内容经过后,才进入到执行类任务,包括从GitLab拉代码,编译构建,上传制品库,发布到代码源服务器,Docker镜像制做,上传Harbor仓库,启动容器等,其中大部分功能是Jenkins来完成的。
为了保证流水线的高可用,设计了Jenkins的多Master + 多 Slave的架构,具体架构状况以下:
由于Jenkins的权限机制没法知足公司业务需求,因此咱们将Jenkins放在了后台,用户不能直接接触到Jenkins,而是使用DevOps做为用户入口进行调度。
DevOps集群随机调度到对应的Master上,当DevOps在建立Jenkins的Job的时候会在全部Master上面建立;当DevOps在触发Jenkins构建的时候会随机选择一个Master执行(当某个Master异常,DevOps不会调度到该Master,当Master恢复正常后,后台任务会自动将多个Master间的任务置为一致),Slave放在Kubernetes集群中,当Slave队列满的状况下可自动增长Slave节点(构建Docker镜像的节点仍然在虚拟机中)。
Jenkins上的任务首先以项目工程为单位创建folder,再在folder下创建对应的执行类任务。咱们没有使用Jenkins的Pipeline的缘由,就是由于Pipeline统一维护困难,且没有层级划分。Jenkins在面向企业级方面还须要提供更丰富的功能。
每日构建次数:每日构建次数包括全部环境的发布次数,平均每日大概在1500次左右。
每日上线次数:每次上线次数为项目发布到生产环境的次数,平均每日大概100次左右,同时支持hotfix发布,随时回滚等。
由于咱们开发语言的缘由,因此不一样开发语言有对应的组件仓库,这在前面的发布API里面已经讲过,主要是Java的Nexus仓库、PHP的PPKG仓库、Node.js的NPM仓库,这里就不重复了
制品库分两种,虚拟机和Docker发布,其中虚拟机发布的咱们直接将编译构建好的内容保存起来,供推送其余环境时可直接使用,达到一次构建,到处运行的目的(和环境有关的配置统一放在配置中心,每次发布前经过校验类流水线任务,校验完成配置后方可发布)。
Docker的是直接构建成镜像,上传到Harbor镜像仓库,在触发Kubernetes容器集群启动容器时从镜像仓库获取镜像启动。
虚拟机发布是使用Rsync服务进行文件同步,将代码从制品库同步到对应服务器,而后服务器上有一个守护进程,会实时监测文件是否更新,如有代码更新则进行重启操做。
Docker发布是调用Kubernetes进行发布,将事先生成好的yml文件传递给Kubernetes,而后在对应数据中心启动容器,并经过zbjcheck服务校验功能确保服务启动正常后,再删除老的容器,达到不停机升级的目的。
目前DevOps集成了单元测试(包括自动生成单元测试用例)、接口测试、性能测试的功能。单元测试大部分状况下仍是须要开发人员写用例,自动生成单元测试用例的功能并非那么好用,因此用户较少,但在流水线上会自动进行单元测试,并将结果反馈给用户:
单测结果是基于Sonar的,在Jenkins上执行完单测后连同静态检测结果一块儿发布到Sonar,在Sonar上配置了通用的过滤条件,能够过滤掉部分不须要统计单测的代码(如框架自动生成的代码不计入单测覆盖率),用户能够在此基础上配置其余过滤条件。
接口测试和性能测试方面,咱们在DevOps平台上作了一个关联的功能,每个接口测试或者性能测试用例,都对应一个项目工程,关联关系梳理好后能够实如今发布流水线的任意环节触发接口测试或者性能测试。
和项目工程关联:
发布流水线触发接口测试:
发布流水线触发性能测试:
自动化测试的结果展现方面目前作的不够好,只是在日志中提供连接,用户点击连接进去查看结果。
CMDB做为底层的统一资源管理中心,负责跨数据中心的混合云管理,提供统一的资源管理平台,无论私有云仍是公有云,无论虚拟机仍是Docker都统一管理,同时提供对底层服务的访问支持。提供机器与宿主机的拓补图关系等,对基础设施的管理提供了便利。
一套OpenStack表示一个虚拟化集群,一套Kubernetes表示一个容器云集群,每一个数据中心有一套或多套OpenStack和Kubernetes。CMDB经过数据中心和可用区来标示不一样的集群。任何须要和虚拟机和容器对接的功能统一由CMDB提供接口管理。
DNS做为附加的功能,可由用户直接点击一个按钮实现域名解析:
域名解析是一个比较复杂的过程,它须要和后台不少系统交互,还须要根据事先定义好的Nginx模版生成配置,Docker的服务还须要进行动态服务发现,最终将域名信息注册到DNS中。
DevOps平台同时支持对虚拟机和Docker的扩缩容功能,只要对应数据中心存在对应的服务,就能够进行扩缩容,一次扩容节点不能超过10个,缩容节点数最少保留一个。
咱们能对不一样数据中心的服务进行扩缩容,而且全部的操做都有事件机制,能将每一个服务所使用的资源进行归档管理,最终能够对各个部门所使用的资源进行服务器成本费用结算。
从浏览器进入服务器,且经过权限控制,有权限人员才能进入,更加方便排查问题:
DevOps已经集成了监控的部分功能,包括接口调用状况、全站可用性、监控数据排行榜、金丝雀分析等。
可用性监控
监控数据排行榜
接口调用状况
金丝雀分析
金丝雀分析主要用于在代码发布到灰度环境时,分析灰度环境和线上环境的相关指标值对比,以确保新版本代码质量没必要老版本差。
目前只有如下几个指标数据,后续将不断完善指标内容:
灰度环境和线上环境都承担用户流量,经过Nginx的Upstream进行权重设置,咱们能够根据金丝雀结果作一次上线发布前的质量评估。
虽然咱们完成了DevOps的大部分功能,要讲到技术细节,上面的每个小节都能用一篇文章来说解,因此之后咱们会不断分享咱们在DevOps中的一些技术细节,固然咱们也还有不少须要优化和改进的。需求搜集和规划、项目管理和发布关联、自动化测试、金丝雀分析的改进、自助做业平台、CMDB对混合云的管理等都是后续须要改进的,总体的规划图以下:
DevOps平台功能架构分布中,还有不少工具以及功能未描述,上面讲到的每个点均可以展开为一篇文章作详细介绍,这里主要为2017年作一个总结。
以上内容为猪八戒网最近几年来整个DevOps的发展演进史,公司的规模不一样,总体架构以及方法可能不一样,对于猪八戒来讲,DevOps还在继续演进,同时也会不断学习业界优秀实践,为业务发展提供最基础的保障。