• 构建资源的弹性伸缩


    在前面的文章中,我已经介绍了构建在整个持续交付过程中扮演的重要角色,并且详细讨论了依赖管理和构建检测等方面的内容。在这篇文章中,我将带你搭建一套高可用、高性能的构建系统。

    持续集成工具

    目前市面上已经有很多持续集成工具了,它们已经替我们解决了很多实际问题,所以我们也就没有必要去再重复造轮子了。这些持续集成工具,最流行的应属Travis CI、Circle CI、Jenkins CI这三种。

    第一,Travis CI

    Travis Cl是基于GitHub的CI托管解决方案之一,由于和GitHub的紧密集成,在开源项目中被广泛使用。

    TravisCl的构建,主要通过travisyml文件进行配置。这个travisyml文件描述了构建时所要执行的所有步骤。

    另外,TravisCl可以支持市面上绝大多数的编程语言。但是,因为Travis只支持GitHub,而不支持其他代码托管服务,所以官方建议在使用前需要先具备以下几个条件:

    1.能登录到GitHub;

    2.对托管在GitHub上的项目有管理员权限;

    3.项目中有可运行的代码;

    4.有可以工作的编译和测试脚本。

    TravisCl的收费策略是,对公共仓库免费,对私有仓库收费。

    第二,Circle CI

    CircleCl是来自GitLab公司的一款云端的持续集成管理工具。CircleCl目前也仅支持GitHub和Bitbucket管理。

    CircleCI与其他持续集成工具的区别在于,它们提供服务的方式不同。CircleCl需要付费的资源主要是它的容器。

    你可以免费使用一个容器,但是当你发现资源不够需要使用更多的容器时,你必须为此付费。你

    也可以选择你所需要的并行化级别来加速你的持续集成,它有5个并行化级别(1x、4x、8x.12x,和16x)可供选择,分别代表利用几个容器同时进行一个项目的构建,如何选择就取决于你了。

    第三,Jenkins Cl

    Jenkins是一款自包含、开源的用于自动化驱动编译、测试、交付或部署等一系列任务的自动化服务,它的核心是Jenkins Pipline。Jenkins Pipline可以实现对持续交付插件的灵活组合,以流水线的方式接入到Jenkins服务。

    Jenkins还提供了一整套可扩展的工具集,程序员可以通过代码的方式,定义任何流水线的行为。另外,经过多年的发展,Jenkins已经包含了很多实用的第三方插件,覆盖了持续交付的整个生命周期。

    目前,绝大多数组织都选择了Jenkins作为内部的持续集成工具,主要原因是:

    代码开源,插件完善,系统稳定;

    社区活跃,成功实践与网上资源比较丰富;

    Jenkins Pipeline非常灵活好用。

    大致了解了集成工具之后,携程和绝大部分企业一样,选择了最开放、最易于扩展的Jenkins作为集成构建的引擎,而且分别从实现横向的Master高可用和纵向的Slave弹性伸缩两方面,使构建系统更为强大和高效。

    Jenkins Master高可用架构的

    目前普遍的Jenkins搭建方案是:一个Jenkins Master搭配多个Jenkins Slave大多数情况下,这种方案可以很好地工作,并且随着构建任务的增加,无脑扩容JenkinsSlave也不是一件难事。另外,不管是Linux Slave还是WindowsSlave,Jenkins都可以很好地支持,并且非常稳定。

    但是,随着业务的增长,微服务架构的流行,持续交付理念的深入人心,构建会变得越来越多,越来越频繁,单个JenkinsMaster终究会成为系统中的瓶颈。

    遗憾的是,开源的Jenkins并没有给我们提供一个很好的Master高可用方案,CloudBees公司倒是提供了一个高可用的插件,但是价格不菲。

    所以,为了鱼与熊掌兼得,最终携程决定自己干。下面是我们构建系统的基本架构:

     

    携程的解决思路是在Jenkins上面再封装两层:BuildService暴露构建的HTTP接口,接收请求后将任务丢给异步队列 BuildWorker,BuildWorker根据不同的策略将任务分发给符合条件的Jenkins Master。

    这里的分发条件,可以是编译任务的平台或语言,比如可以将基于Windows和Linux的任务分别放在不同的JenkinsMaster上,也可以将Java构建和NodeJS构建任务放在不同的 Jenkins Master上。

    除此之外,携程的这个构建系统还可以满足的一种需求是:一些比较复杂目重要的业务线,有时也会提出独立构建资源的需求,以达到独占编译资源的目的。

    总而言之,构建任务分发的策略可以是非常灵活的:构建Worker和JenkinsMaster之间有“心跳监测”,可以时刻检查JenkinsMaster是否还健康,如果有问题就将任务分发到其他等价的JenkinsMaster上,并给相关人员发送告警通知。

    这种拆解JenkinsMaster主要有以下几个好处:

    1.每个Job都可运行在至少两个JenkinsMaster之上,保证高可用;

    2.根据不同的策略将Job做Sharding,避免积压在同一个Master上,

    3.JenkinsMaster按需配置,按需安装不同的插件,便于管理。

    利用这套方案,携程就可以做到Master层面的伸缩了。这套方案的实现成本并不是很大,简单易懂,小团队也完全可以掌握和实施。

    Jenkins Slave 弹性伸缩方案

    解决了Jenkins Master的高可用问题,接着就要去思考如何才能解决Slave资源管理和利用率的问题了。因为,你会发现一个组织的集成和构建往往是周期性的,高峰和低谷都比较明显,而且随着组织扩大,幅度也有所扩大。所以,如果按照高峰的要求来配备Slave实例数,那么在低谷时,就很浪费资源了。反之,又会影响速度,造成排队。

    因此,我们需要整个Slave集群具有更优的弹性:既要好管理,又要好扩展。在携程,我们尝试过多种虚拟机方案,比如全Windows类型、金映象方案等等。最后,根据容器的特性,选择了容器作为解决方案。期间也经历了Mesos到K8s的两套方案。

    第一,最初的虚拟机

    在最初构建种类不多并且场景不复杂的情况下,我们的Slave全部使用Windows虚拟机。

    我们把所需的构建软件像大杂烩一样一股脑地安装在虚拟机上,比如,编译NET所需的MSBuild编译Java所需的Maven。我们维护着一份啰嗦冗长的安装手册,并小心翼翼地这些文档保存在服务器上。

    这时,最怕的就是构建环境的变更,比如某个软件要升级,要添加对某个新软件的支持。这些变更需要我们对所有机器的操作都重来一遍,甚至还需要关机重启,十分费时折腾。

    后来,我们尝试了将虚拟机维护成镜像,并使用SaltStack做自动化变更。虽然日子好过了点,但升级一次环境还是需要投入不少人工成本。另外,文档的更新始终一件苦差事,从来不敢怠慢就怕某次变更没有记录在案。

    你我都清楚,写文档从来都不像写代码那么舒服。程序员最讨厌的两件事也都和文档相关:一是给自己的软件写文档,二是别人的软件没有文档。

    这让我们非常困扰,我们做的是DevOps与持续交付,但是自己的工具管理却如此混乱无章,这也使我们感觉十分蒙羞与窘迫。

    第二,容器化的甜头

    随着容器越来越流行,我们发现:使用容器镜像保存构建环境是一个非常不错的选择。相对于虚拟机,容器技术主要有以下几个优势:

    1.使用Dockerfile描述环境信息相对于之前的文档更加直观,并且可以很自然地跟Git结合做到版本化控制,先更新Dockerfile再更新镜像是很自然的事。

    2.镜像更容易继承,你可以配置一个Base镜像,然后根据不同的需求叠加软件。比如,你的所有构建都需要安装Git等软件,那么就可以把它写到Base镜像里面。

    3.Docker镜像可以自由控制,开发人员可以自己推送镜像,快速选代。重建容器的代价比重建虚拟机小得多,容器更加轻量,更容易在本地做测试。

    目前,携程的构建系统已经支持了包括:Java,NodeJS,Golang,Erlang,Python等多种语言的构建,并且维护起来非常轻松,完全没有负担。

    在尝到了nux容器带来的甜头之后,我们毅然决然地开始研究Windows容器技术,经过不断地尝试与探索,终于把它应用到了生产环境,并且取得了非常不错的效果,目前为止运行也十分稳定。

    第三,让资源弹起来

    容器化在很大程度上解决了运维成本的问题,虽然通过Docker管理容器比虚拟机要方便一些但是管理大量的容器却也没那么得心应手。

    此外,我们之前使用容器的方式几乎和使用虚拟机一样,也就是所谓的“胖容器”,一旦创建,不管用不用,它都在那里。而构建是一个周期性的行为,一般跟着程序员的工作时间走:工作日比周末多,白天比晚上多,甚至还有明显的午饭和晚饭空闲期。

    后来Mesos与Kubernetes等主流的容器集群管理工具渐渐浮出水面,出现在我们的视野中。

    基于Borg成熟经验打造的Kubernetes,为容器编排管理提供了完整的开源方案,并且社区活跃,生态完善,积累了大量分布式,服务化系统架构的最佳实践。在2017年,携程尝试将Jenkins和Kubernetes集成在了一起。

    目前,Jenkins社区已经提供了一个Kubernetes插件,而且是免费的,使得Jenkins与K8s的集成变得非常简单轻松。

     

    上图就是我们某台宿主机24小时的构建数量与所创建容器的对比图,可以看出两条曲线呈现的趋势基本是一致的。我们在夜晚闲置的资源上,调度了一些其他的离线Job,大幅提升了资源利用率。

    所以,携程利用容器技术,也顺利实现了Slave节点的弹性伸缩。对于中小型企业,初期完全可以利用Jenkins及其 Kubernetes插件,做到Slave节点的资源弹性伸缩。至于与离线Job混部,因为要考虑的因素较多,可以在应用容器化之后再考虑。

    总结与实践

    我主要介绍了几种流行的持续集成工具,以及基于Jenkins的高可用构建系统的一些基本设计理念和我们系统的演变过程。

    1.通常建议使用成熟的CI产品(比如,TravisCl、Circle CI、JenkinsCI)来作为平台的基础;

    2.虽然这些CI工具是成熟产品,但面对日新月异的技术需求,高可用和伸缩问题还是要自己解决;

    3.通过请求分发等设计,可以实现Master节点的横向伸缩及高可用问题;

    4.利用容器技术,可以解决Salve节点的弹性伸缩和资源利用率问题。

    最后,你可以尝试搭建一套Jenkins与Kubernetes服务,让你的任务跑在动态创建出来的容器上,并思考一下这个方案有没有什么缺点和不足。

  • 相关阅读:
    JS逆向之巨量创意signature签名
    vue——前端发展、vue介绍、mvvm模式、组件化开发、单页面开发、模板插值语法、文本指令、事件指令、属性指令
    C语言双向链表
    笙默考试管理系统-MyExamTest----codemirror(27)
    河南发文明确!这类企业数字化转型有了“时间表”
    图文手把手教程--ESP32 一键配网(Smartconfig、Airkiss)
    Linux 进程信号
    SpringBoot 集成 kaptcha 验证码
    Spring Cloud【为什么需要监控系统、Prometheus环境搭建、Grafana环境搭建 、微服务应用接入监控 】(十七)
    react源码中的hooks
  • 原文地址:https://blog.csdn.net/weixin_36691991/article/details/126262210