第一章介绍的是运维的本质,开头以Netflix 公司(业界微服务架构的最佳实践者)为例,介绍了在其内部"运维工程师"的角色。在Netflix 内部没有运维工程师这一角色,取而代之的是SRE(site Reliability Engineer),SRE 不同于运维,其主要职责在于软件工程的方法重新设计和定义运维工作。为什么在Netflix 内部这种工作模式可以玩得转,其实跟其企业文化有关。Netflix 企业文化总结起来就是一句话:Freedom & Responsibility,体现在技术团队中,就是"You build it,You run it" ,也就是说,从产品开发设计阶段到后续交付、线上运维阶段都会由该团队来完成,而不是说产品开发设计由所谓的开发团队完成并交付给所谓的运维团队负责产品上线后的维护和服务保障。当然这些理念受限于各个公司的企业文化,还有就是需要非常强大的技术实力和人才储备,这里我不展开过多的讨论。

    书的第一章里面提到一个核心观念:以应用作为运维体系建设的核心

    

    下面我从what,why,how 的角度,尝试理解下作者的推崇的思想:

    一、"应用"是什么?

    微服务架构都是从单体工程拆分而来,每个产品设计初期都只有部分核心功能,随着时间推移与产品的不断迭代,产品本身会越来越臃肿,从初期一个解决某种特定场景,服务于特定人群的一个"工具",最终演变成为一个庞大的体系,甚至是一个生态。而一个产品一旦变得臃肿,后续的维护工作会变得越来越复杂,我能想到的最麻烦的一个问题可能就是发版本。假如所有服务都放在一个工程下面,某天A 团队为了紧急修复a 模块的bug,紧急发布,导致B团队的b模块也跟着重启,而实际上我们知道b模块跟这个bug本身无关,但放在一个单体工程下面,就会面临这种问题,牵一发动全身。所以文章里面提到的第一个观点就是"拆",将一个臃肿的应用拆解成为一个个的服务,每个服务又对外暴露API供其他服务调用,这样的架构就是我们常说的微服务架构。书里面给了一个范例图:

blob.png

    举一个具体一点的例子,以电商网站为例,我们知道电商网站包含很多功能,如用户登录注册、产品概览、产品详情、支付/充值、售后等等一系列服务,在应用的设计初期,就可以将一个庞大的工程拆解成一个个功能模块。

blob.png

    拆分后的模块数量与业务体量和复杂度相关,所以为了统一概念,我们将这些模块称之为"应用"。为了确保每个应用的唯一性,我们会给每个应用确定一个唯一的标示符,例如上图中的DetailServices,SKUService,TagService,TemplateService 等等,后续将通过这里定义的"应用名"贯彻整个产品的生命周期,将该产品设计到的方方面面都关联起来。


    二、为什么要以"应用"为核心?

    文中举了2个场景:

    场景一:研发团队出于业务上线需要,在运维平台申请了一些资源,比如说缓存或者消息队列(数据库、VIP、存储等等),一开始这些资源都是自己使用,所以很清楚这些资源的用途。随着业务发展,时间一长,申请的资源一多,慢慢的记不住了。后面业务交接给其他团队维护,或者原先申请资源的负责人离职,慢慢的这些资源就变得七零八碎,没有人清楚它的用途,没有人知道这个资源有没有用到,没有人能看清楚整个应用的全貌。


    前段时间,我们内部在做成本优化的时候,这个问题就特别的棘手。成本优化中有一部分工作就是梳理服务器,合理利用机柜,要知道每台服务器的成本不仅仅是服务器本身的价格,还有后续每年机柜的费用(托管机房都是这样)。所以有一段时间,我们都在推动业务方搬迁机器,说实话这是一个脏累活,不管是开发团队还是运维团队都不想做。为什么不想做,原因很简单,就是上面提到的问题,有些年代久远的服务器上面部署的服务,负责人已经转了几次手,甚至已经离职,现阶段的业务负责人根本不知道这个应用的用途,不知道机器上面跑的memcache、redis 有没有用,什么服务在用,甚至于有些负责人都不知道机器上面还跑了个memcache、redis。后果可想而知,我们在搬迁过程中遇到了各种阻力,毕竟出故障是大家都不想看到的结果。


    文中举的第二个场景是:同一个应用没有一个统一的应用名,没有以应用名贯穿整个应用的什么周期,通过应用名将所有与该应用相关的资源关联起来。开发团队认为自己只要按时按量完成产品的开发/上线即可,为了快速上线,草草的为产品或者应用起了随意起了一个名字,例如用户中心(User)。运维团队则从产品上线后的维护工作考虑,为了资源和应用配置管理方便,通常又会独立定义一套应用名体系,给产品取了另外一个名字,用户中心(UserCenter),如果后面还有配置管理、发布、监控系统,可能又各自维护了独立一套应用名体系,而实际上我们知道无论是开发团队定义的User 还是 运维团队定义的UserCenter 本质上都是对应着同一个应用下面的不同资源。最终的结果就是,通过应用下面的各自资源都成为一个个的孤岛,无法将彼此关联起来,如下图范例图所示:

blob.png

    

    近期我们在搞告警、监控梳理,也面临到这个问题。我们原先的告警非常零散,比如机器本身健康状况的告警(比如CPU、内存、IO等等),会由服务器告警出来;机房间网络有网络中断,网络丢包告警;各个基础组件也有各自的告警,比如进程存活告警等;如果是个web服务,还有URL探测的告警,服务异常的告警等等等等。我们初期想法是将这些告警汇总到一块,并尝试从这些告警中找出共性,缩小问题定位的范围,从而辅佐我们更快的定位问题根因以及后续的告警抑制,服务自愈等等。

    但是我们刚刚开展这项工作的时候,遇到的一个问题就是各种资源没有一个统一的"应用名"可以将彼此关联起来,举个例子,一台机器CPU告警了,告警出来只有一个IP还有一个业务模块的信息,如果告警的是个web的服务,那么在web管理系统里面我们有业务模块、域名的信息机器的信息,我们可以勉强的通过业务模块或者域名作为一个key展开,将告警关联起来。但来到发布系统里面,每个应用的应用名又变成了业务名、项目名,并没有所谓的域名(这个字段其实是有的,但这里的域名又不同于前面提到的域名,没办法关联起来),更没有关联的IP信息,内部自成一套应用名体系,这种时候想关联起来就相当麻烦。所以,如果要顺利的将监控/告警梳理这项工作顺利开展下去,第一步我们就是要将前面的坑填好,引导研发团队自行将应用名、域名、IP等等信息关联起来。


    三、以"应用"为核心应该怎么做?

    每个应用都有自己的职能,并依赖于各种与业务无直接关系的,相对独立的基础设施和组件,比如服务器资源,IP,域名,数据库,网络等等。所以,在产品的生命周期里面,除了应用本身这个实体以外,还有着各种基础组件实体,并且在应用上线后,还可能会不断的有新的组件产生,而新的组件不断产生,又会给后续的维护造成更大的困难。因此,以"应用"为核心就变得极其重要,通过应用模型和关系模型的梳理和建立,为后续持续交付、运维自动化奠定基础。

    应用模型的梳理,其实就是上面范例中提到的电商网站,将一个产品拆分成多个模块,不同功能模块暴露自己的API供其他模块调用。拆分的工作更多是由产品架构师来把控,我们不展开讨论,重点看看运维层面关心的 应用管理模型的梳理。

    应用管理模型:我们知道每个人都会有自己的各种属性,比如姓名,性别,职业,联系方式,家庭住址,×××号码等等,我们都知道每个人的名字并非唯一,同名同姓随处可见,而×××号码则是这个人唯一的标识。每个应用也有着自身的各种属性,比如应用名,功能,负责人,SVN地址,域名,部署架构,配置等等,而其中应用名就是该应用的唯一标识。

    每个应用依赖的组件和基础设施大概可以分为两类:

    资源层面:应用本身运行的载体,如物理服务器、容器、虚拟机,网络,以及对外提供服务的域名、IP等等。

    基础组件:应用依赖的中间件,如nginx、tomcat、java等基础组件,以及数据库、消息队列、缓存、存储等等。

    

    我们可以看到,这些基础设施/组件 本质上都是为上层的应用提供服务,抛开应用,这些基础设施/组件本身并没有单独存在的意义。


    文中建议我们可以按这个思路去梳理应用 与 基础设施/组件之间的关联关系。例如,在用户中心(User)在申请数据库资源的时候,在数据库平台肯定也会要求业务方提供一个数据库平台范畴内全局唯一的一个标识,这里我假定这个字段叫做服务名。那么业务方在申请数据库资源的时候,就可以将数据库里面的服务名赋值为应用名User,又或者添加一个应用名的字段,通过外链的方式将数据库与应用关联起来。

    同理,对于其他基础设施、基础组件也可以以类似的方法梳理。完成这一步之后,我们就会得到类似下面的一个以应用为核心的完整架构图,将应用、基础设施、服务、配置、运行载体等关联起来。

blob.png


以上是我刚读完《进化:运维技术变革与实践探索》第一章的一些总结,并结合自身实际工作中遇到的一些问题,展开的一些思考,篇幅比较长难免会有错漏,欢迎大家帮忙指正,也欢迎大家提出各自的观点,共同探讨这个话题,谢谢