当前位置: 首页 > 科技观察

这才是DevOps进化和CI-CD实践的正确打开方式!

时间:2023-03-20 22:43:05 科技观察

1.前言从2016年底发布第一个版本到现在能够全面支持猪八戒500+研发人员的日常研发工作,DevOps团队经历了不断的试错和改进总结。本文重点介绍解决方案,更多详情可咨询八戒技术团队公众号。希望对即将实践DevOps和正在实践DevOps的团队有所帮助。二、从0到1打造DevOps背景介绍2015年,经过10年的稳步发展,猪八戒的稳步发展积累了很多,迎来了业务的高速增长,随之而来的是公司人员的成长,而研发团队也从几十人扩大到上百人,正是人才的引进和业务增长的迫切需要,让猪八戒开始了一场轰轰烈烈的改革运动,而这样的运动已经进行了6在过去的十年中,由于公司的学习文化,我们将这种运动称为“腾云行动”。对于这次腾云运营,我们主要做了两件事:第一是服务拆解,将庞大的单体应用按照业务和模块功能进行拆分,拆解成独立的小应用进行部署;第二件事是服务重构,重构80%以上用Java编写的PHP程序,引入以SOA为核心框架的架构体系。而这两件事将交付周期从之前的几个月缩短到几周甚至几天。这无疑对我们的交付能力提出了严峻的考验。因此,经过充分的研究和准备,以及慎重的决策,2016年第三季度,研发团队抽调了部分运维人员和开发人员,组建了devops团队。这个团队只有一个目标,就是满足频繁的交付,随时随地的交付。为实现这一目标,必须做到以下几点:建立标准化的研发流程,使整个交付过程可靠、规范。一键生成可部署项目,避免重复开发,缩短开发周期,统一技术栈,规范研发,降低维护成本。打造自动化CI/CD流水线,替代人工部署,大幅提升交付效率。建立线网故障快速回滚机制,针对高速生产中可能出现的错误提供对策,提高整个站点的可用性。2.标准化的研发流程我们将猪八戒的业务拆分成业务条线。现在我们把这些业务线抽象成产品线,然后在产品线下面有子产品线,在子产品线下面有具体的产品,从而形成层次分明、业务清晰的产品树。然后我们引入了产品责任制的概念。我们可以看到每个产品都包含一些基本信息。这里需要注意的是,每个产品都必须有一个产品经理,产品经理也有一个部门。所以我们得到了一个责任链,产品-产品经理-归因部门。接着,我们引入了工程责任制的概念。同样的,我们的每一个项目也包含了一些信息,比如源码地址,开发语言,运维配置信息,还有我们的项目负责人。每个项目负责人也有一个归属部门,所以我们也得到一个责任链,工程-工程负责人-所属部门。我们现在把产品和项目关联起来,规定每个项目都必须关联一个产品,从而保证每个产品都能找到真正的生产源码。而做到这些还不够,我们还需要有东西来穿这一切,所以我们用jira搭建了四个标准的需求发布流程:评审、产品原型评审、安全评审、技术方案评审等产品大版本迭代上线流程:产品重大变更采用此流程,涉及需求评审、产品原型评审、安全评审、技术方案评审等迭代上线productfunctionsprocess:productfeatures使用这个流程进行模块的日常迭代使用Bugfixprocess:修复bug快速上线使用这个流程现在我们有了产品树,产品责任体系,工程责任体系,需求发布流程,以及我们终于建立了一条标准的需求-产品-工程研发生产线。3.一键生成可部署项目要实现这一点,我们需要实现四个功能:1)创建源代码仓库:根据用户填写的git祖先名称和项目名称,自动创建一个git仓库。2)提供各种技术栈的项目模板:根据用户填写的开发语言提供相应的项目模板,创建git仓库后,完成初始化提交到git仓库。3)生成部署配置信息:根据用户填写的基本信息和系统预设的配置,动态生成流水线配置信息。4)生成配置中心信息:为每个环境生成配置中心信息。4.CI/CD管道管道实际上做了四件事:拉取源码、编译构建、上传产品到产品库、部署产品到服务器。为了让这个过程可靠、可控、规范,我们增加了验证任务,对一些访问和退出进行验证。其次,增加了自动化测试等测试任务。那么就形成了这样一个pipeline:最后应用到各种环境之后,就变成了下面的pipeline:pipeline有以下功能:1)支持虚拟机容器和虚拟机发布两种发布方式。编译构建后,将生成的产品上传到文件服务器。这个文件服务器相当于虚拟机发布项目的产品库。本项目发布的历史产品版本保存在文件服务器上。上传到文件服务器后,产品会从文件服务器同步到代码最后,虚拟机服务器上的守护进程会检测代码的代码是否有变化,如果有变化,会主动拉取代码并重新启动服务。对于容器发布,编译构建完成后,会根据用户提供的dockerfile构建镜像,然后将镜像上传到公司内部的hub仓库,然后组装元数据,调用容器云接口部署到k8s集群。这里的容器云是猪八戒基于k8s做的二次封装。主要功能是对元数据进行处理,生成部署文件,然后调用k8s执行部署操作。容器发布&虚拟机发布构建打包示意图2)多分支开发,主干启动在测试阶段,可以使用各个分支进行开发测试。测试通过后,必须合并到主干中,然后使用主干发布上线。3)一次构建中处处使用考虑设置的分支策略,所以我们规定测试环境的产品只能在测试环境中使用。经过测试并合并到主线代码中,认为是稳定可靠的,所以在后续环境中,不需要再次构建,直接使用预发布生成的产品。4)使用Jenkins作为后台构建作业机,采用多master、多slave的Jenkins集群方案,master只做调度,slave执行某些任务。我们提前在jenkinsmaster上创建了pipeline对应的job。图中左边是我们自研的pipeline服务,用Java写的,通过调用jenkinsAPI触发构建,jenkinsmaster调度slave节点执行job,然后左边的pipeline服务定时调用JenkinsAPI获取构建状态和结果,实时更新推送记录的状态和日志。现在,我们将需求发布流程和流水线结合起来,得到如下图所示的标准生产流程。5.线网故障快速回滚机制上面我们讲到了管道。下面说说如果线路有问题怎么回滚。不知道大家有没有注意到上图中的一个细节,就是在预发布的时候,有一个任务——打标签,这个操作就是我们回滚的关键。这个tagging主要做了两件事:在git上生成一个tag,表示这次代码稳定,可以上线;保存一条记录,代码版本和产品版本,以及这个标签的记录。现在我们来看这种情况:比如现在我们发布了一个在线发布,发布的tag版本是v1.3.35,对应的代码版本是a,镜像是A,这次发布成功,没有问题。然后我们又在线发布了一个版本,v1.3.36,对应的版本是a,镜像是A。在线发布的时候发现服务异常,所以需要进行回滚操作,选择最后一个成功的版本v1.3.35,因为保存了这个版本对应的code信息和image信息,所以选择这个版本的时候,可以找到正确的产品,然后触发一次pipeline,回滚。整个过程可以控制在几十秒以内,将网络故障造成的损失降到最低。最后,我们来看一下整个devops生态链:至此,我们的devops第一阶段已经完成。1)带来的意义和价值:研发流程标准化,研发生产物料责任制管理,交付流程更可靠;提供多种项目模板,无需从头构建项目,降低开发成本,同时统一技术栈,规范代码研发;CI/CD自动化,支持高频构建(支持500+研发人员日常构建),降低运维成本(运维学员从40人减少到10人);网络故障快速回滚,提高整个站点的可用性。2)缺点:流水线的执行过程不够灵活,导致负载高,消耗资源多;项目生命周期管理缺乏关键路径,大量项目处于散养状态;基础服务和工具较多,需要在多个平台之间切换,增加了开发者的负担;没有高效的自主执行研发工作流程,大量实际工作需要人工处理;缺乏成本控制手段,服务器成本居高不下。3、从DevOps到一站式研发平台,针对以上不足,我们做了如下改造:1.重构流水线1)将流水线的任务拆解成独立的原子任务,将原子人拆分成学校任务根据他们的职能。测试和执行类。2)根据项目开发语言、发布方式、推送环境,预设一套流水线任务列表。可以看到,箭头有两种,代码同步任务和异步任务:同步任务串行执行,失败则阻塞进程;异步任务是并行执行的,失败了也不会阻塞进程。3)自研JenkinsrabbitMQ插件,通过消息队列实现管道服务与Jenkins的通信。重构前是通过调用JenkinsAPI实现的。重构后,管道服务组装构建信息并将消息发布到队列中。jenkins插件消费消息,然后调度slave执行任务,同时状态和结果生成消息也发布到队列中,管道服务消费消息更新日志和状态,大大提高了成功率。4)Jenkins从节点容器化改造前,所有从节点都是虚拟机,导致节点数量固定,要么造成资源浪费,要么不能满足高并发,维护成本高。一旦涉及变更,就需要人工对每个节点进行变更。重构之后,我们使用k8s插件链接我们的k8s集群,创建slave节点。利用k8s特性,可以动态调整节点数量,既满足高并发,又不会造成资源浪费,易于维护。一旦涉及变更,只需要重建slaveimage应用即可。重构后的流水线具有以下特点:流水线执行任务更加灵活,可以根据实际情况动态调整执行任务,实现“因地制宜”;提高流水线执行任务的成功率,实现高可用;k8s特性实现Jenkins从节点动态伸缩,满足高并发的同时节省服务器资源。2.项目生命周期管理1)项目创建阶段定义六大项目类型,完全覆盖所有研发需求,配置简单,一键创建。2)项目研发阶段,根据项目类型生成配套组件,研发阶段全面赋能。支撑组件包括工程权限管理、工程服务管理、工程资源管理、配置中心管理、调度任务管理、域名管理、安全管理等。3)项目启动阶段统一需求发布流程,cicd流水线标准生产,确保每一步的可靠性。4)项目运行阶段实时监控服务,多维度异常报警机制。5)项目下线阶段,智能检测中心检测无用项目,360度检测项目依赖,一键下线,操作简单。由此,我们实现了项目的全生命周期管理:3.整合基础服务和工具1)提供一站式查询和使用2)提供各种工具使用文档4.高效的研发工作流程1)三步定制工作流程模板首先定制流程信息,填写一些简单的信息工作流程;然后是自定义表单的内容,我们提供了大量丰富的表单组件,比如文本框、单选框、复选框等;定义反向节点,你可以为每个节点设置处理程序。如果由系统执行,则会根据工作流类型执行相应的后台任务。使用工作流模板,我们可以创建工作流。2)分三步创建工作流。首先,选择工作流模板;然后填写表格,就是工作流设置对应的表格;最后提交完成工作流的创建。3)实时记录工作流状态和执行过程。创建一个工作流后,这个工作流的所有执行状态和过程都会被清楚地记录下来,如图所示每个节点从启动到反转,以及执行结果和执行时间。4)数十个系统自动执行节点任务。如果handler是一个系统,那么会根据当前的工作流类型执行相应的系统任务。我们预设了数十个系统执行任务,基本涵盖了所有的研发需求。比如数据库相关操作,运维相关操作。5)实时通知负责人,进行提醒。当转向某个节点时,我们会通过系统通知和用户提醒来尽可能缩短工作流的处理时间。至此,我们有了一个高效的逆向研发流程。5.研发成本管理系统1)按产品纬度统计各部门服务器成本。前面我们提到,每个项目都与一个产品相关,每个产品都有一个部门,所以我们可以根据产品纬度统计部门的服务器成本。当然,不仅仅是服务器成本,其他的费用,比如代理运维费、开发者成本等等,都可以据此计算。2)监控各部门服务器费用是否超过预算,如果超过预算则不允许发布上线。至此,我们的devops第二阶段已经完成。总结一下成果和价值:Pipeline2.0丰富灵活的原子任务支持各种业务场景,在支持高并发和高可用的同时,不造成资源浪费;进行项目全生命周期管理,确保研发数据100%可控;一站式管理基础服务和工具,减轻开发者负担;强大高效的工作流系统,大幅提升研发效率;成本管理体系,在记录每个产品的研发费用的同时,严格控制研发成本。4.结语DevOps的实践之路还在继续,因为不同的公司有不同的业务场景,同一家公司的业务会随着时代的发展不断变化。只有适合自己的才是最好的,只有能够拥抱变化的才是最好的,但始终如一。我认为应该有以下几点:1)DevOps应该以提高研发效率为目标进行实践。2)DevOps应该和业务紧密相关,因为不同的业务需要不同的技术架构,因此需要的交付方式也会不同。3)DevOps应该以人为本。我们应该把所有繁琐的过程尽可能交给程序,人们只需要“坐享其成”或者做少量的决定。