简述
在工作中对自动化运维建设接触较多,日常都忙于解决具体的问题少有时间做一个沉淀和积累,现在想通过写文章的方式整理一下在做自动化运维过程中的一些思考,希望这个分享能对大家有所帮助。
建设目的
自动化运维自从云相关技术的成熟逐渐火热,行业对自动化的呼声越来越高。从宏观上看是业务发展越来越快,对技术的要求也越来越高:自助的资源使用、CICD流水线自动化等等,反映出自助和自动趋势。接触过较多的客户,对于做自动化运维的主要动机是不尽相同的,有的团队是希望通过自动化建设实现团队能力转型,有的团队是希望提供一个知识的沉淀让能力的迭代有一个工作基础,有的团队是有一体化运维建设战略。
自动化运维建设的目的可以有很多角度的答案,但是最直接和根本的作用就是达到更短的 MTTR(平均故障恢复时间).
更长的MTTF(平均失效时间,表示一个系统预计持续运行直到失败的时长).
以及影响衡量体现预期性能的MTBF(总运行时间/总的失败次数;平均无故障时间).
业务特点
大规模下显著特征就是管理维护的服务器数量巨大,服务器数达到成百上千台,服务器上的业务更迭频繁,运维需要对接多个业务终端,协同压力较大。一般能达到大规模服务器群的企业都按照用途划分了环境,比如生产环境、测试环境、预生产环境(一部分可能没有)、生产环境,进一步增加了运维的工作量。大量的工作计划、沟通计划穿插其中,各种工作数据散布在工作流程的各个环节,在大规模运维场景下对运维管理也是一个不小的挑战
解决方案
目前市面上有很多自动化运维的工具,例如SaltStack、Ansible、Puppet、Chef等百花齐放非常繁荣,不同的工具都有其特点,要建设大规模自动化运维系统的第一步就是要选择合适的工具,对于市面上较主流工具主要考虑两点:agent是否必须、是否有大规模的用户在使用。
agent重点考虑的原因是在于服务器规模较大的企业的业务相对来说已经较为复杂了,不是所有业务系统的服务器都欢迎安装agent、特别是金融类客户几乎是不允许以agent方式操作业务服务器。而考虑是否有大规模的用户基础则是考虑其稳定性,在有足够的用户群体时其产品的使用性已经达到相对稳定。
从这两点出发筛选出来就Ansible比较符合,使用ssh协议无需要在服务器上安装代理,而且也有很活跃的用户群在使用例如openstack社区的kolla项目就是完全基于ansible。
但是Ansible也有自身设计带来的问题,资源使用会随着规模增长,当然要是能接受也可以用时间换空间,通过配置fork数来分组执行。这个问题在小规模时感受并不明显,一旦直接运维的服务器规模成百上千,执行时间长或者资源开销大总是要占一个,所以在大规模自动化运维场景下不能只依靠Ansible,而是要在使用过程中扬长避短
在大规模使用Ansible过程中首先要补足的就是执行效率问题,比较常见的做法就是建设执行器群来形成二级结构把压力分散开,也把资源需求分散开,当没有执行任务时只需要维持很少的固定开销,当有自动化任务需要执行时,执行的资源开销转移到各个执行器上,当有业务系统新上线时也可以为其设定执行器或者把其中一台服务器设定为执行器来适应要运维的业务规模。
选择Ansible还有一些软性的点在建设时需要长远考虑来进行补足,Ansible的初衷之一就是让运维的知识module化之后降低使用难度来减少重复造轮子,从Ansible的module库的数量变化和使用热度上看,这个定位无疑是非常成功,其声明式语法和幂等的执行特性非常强大,也确实为写Ansible脚本的运维开发减少了很多难度和工作量的同时提高了脚本运维质量。从企业内部运维团队的知识积累角度也有类似的诉求,期望各个具体的运维问题能可迭代可积累地开展自动化,以更简单的交互方式交付给用户自助服务。
技术选型
为了满足二级的执行架构势必要引入分布式任务调度组件,从模式上看任务的分发模型有两种,即推模式与拉模式。推模式是中心向执行器直接推送任务,理解起来很简单,使用任务少,执行器端执行效率高对即时性要求高的场景,基于推模式的任务分发不方便控制执行速率;拉模式则是任务执行端主动去中心拉取任务来执行,执行完成后再主动拉取,任务在中心不被执行器拉取就不会被执行,这种模式的好处是可以自适应执行器的执行能力。考虑到自动化运维任务在执行时并没有统一的尺度,例如备份文件或者进行文件内容的比较等场景其执行市场、资源开销都是无法统一定义的,所以对执行器的要求对很高,综合考虑在自动化运维场景更适合采用拉模式的任务分发。但是市面上使用拉模式的调度组件较少,常见的xxl-job都是基于推模式。
为了在ansible之上进行可迭代的自动化需要再加一层抽象即流程编排,把ansible的脚本作为一个原子任务,这个原子任务就是团队的一个知识积累。例如应用配置变更、应用系统巡检、应用配置备份、多环境一致性比较等。一个自动化场景均由这些原子任务组成,拿一次大规模的服务器变更来说,在创建这个变更流程时中间有很多步骤穿插,例如变更前巡检系统稳定性判断是否具备变更条件,变更前重要配置备份、变更后巡检业务是否正常、变更成功后提交新配置到中心库等操作,真正执行变更的只是众多任务节点的一个。运维是一个严肃严谨的活动,这样做并不为过。如果没有流程编排意味着每次都将重复大量的开发劳动,而且散落在各个操作上的实践反馈无法可视化展示和分析,例如备份的文件在某次变更后有增加删除那么以后所有的执行脚本涉及到备份的都应该更新,例如巡检项有发生变化意味着之前的巡检脚本已经过期需要更新,如果没有流程编排将意味着较低的复用性和陡峭的维护难度。
之前我们使用activit+xxl-job来构建自动化运维系统,直到建木的出现,更完美地契合了自动化运维场景下的诉求。同时具备了基于拉模式的分布式任务调度、声明式的流程编排,我们当即就使用建木在自动化运维领域做了一些尝试。尝试之后有更令人欣喜的发现,建木官方提供docker的worker,在执行任务时是以注入docker环境变量+docker镜像方式来执行,这意味着更宽松的开发条件和更优雅的执行。
建木印象
这个设计让我回想到两个印象很深的案例,第一个案例是要做从DB2数据库读取数据来比对的脚本,写完测试没有问题但到来执行时发现代理机上已经有安装了client且有另外的任务会周期性用到,这个事就是运维脚本工具和他们依赖的运行环境分离了带来的;另外一个案例就是使用Ansible的异步模块时,在一些特定的情况下中断,这时在目标主机上和运维Ansible脚本的机器上都会有文件残留,当任务执行率大的时候逐步积累最终导致触发了磁盘空间的警报,这个意味着一些自动化任务中止后的残留是非常隐蔽的得了解到相当的实现细节才能做到,但这又违背了使用Ansible降低技术难度的初衷。
能理解这两个真实案例再回过来看建木在执行设定上的设计,虽然技术实现上不一定复杂,但是在效用上是极度符合自动化运维的需要,即脚本工具和它的执行环境打包在一起,利用了容器技术执行完成或者中止后删除。对于运维开发来说测试环境的测试结果和生产环境的运行结果有了依照,减少了“意外”。
我们截至目前已经使用建木配合自研的应用配置管理组件以及大量的内置运维自动化流程封装了运维产品AutoOps实现了自动化运维的场景化和基础设施运维知识的迭代积累,运维的云平台数量达到300+,管理服务器的规模达到了数千。一次针对全部服务器的变更仅需5个工作日就可以,积累了诸如openstack巡检、变更、openstack实施标准检查等场景和运维制度落地方面的积累。
最后
建木作为一个流程编排调度引擎属于是通用技术可以在各自场景被使用到,对建木感兴趣的小伙伴可以加入建木社区一起探索这个领域,喜欢我们在做的事就点个star吧,点击这里直达===>建木。