运维行业发展至今,从最初的人肉运维、脚本时代,到后期的平台化阶段、以及现在很火的AIOps的概念。都绕不过一个主题——资源管理。

无论是健全而人性化的发布体系、灵敏强大的监控体系、还是稳定高效的服务发现,都需要我们有一种可以很灵活的管理资源的模型。
这个模型,应该有如下两个特点

  • 支持业务分级,可以与业务形态灵活对应
  • 筛选能力灵活,可以支持多个维度灵活精确的匹配与筛选

这就是服务树概念的由来。接下来笔者会将我们在服务树的建设过程中的一些思考和遇到的问题,分享给大家。
此篇文章专注介绍服务树模型的设计与实现。用于资源管理的CMDB系统,机器上下线、报修、借用归还相关的资源全流程闭环,此篇文章不做探讨。

什么是服务树

服务树,一言以蔽之,是一个将业务映射成树形结构,然后与资源对应起来的模型
通俗且狭义地讲,服务树维护着,哪个业务线下有哪几台机器、哪几个VIP等资源。
与传统意义的CMDB系统不同的是,服务树专注于解决**业务与资源的映射关系,而传统的CMDB系统更多的关注于资源本身的属性与状态**。
比如,一个公司下有N个事业群,每个事业群下有N个部门,每个部门内有N个服务,每个服务有N个模块,每个模块又有N个集群。边说着,是不是你的脑中,就已经出现了一棵树?

服务树——灵活强大的运维资源管理体系 - 图1

接着我们可以想,每一个树节点,都是一个单独的空间,可以放一些机器、VIP之类的资源。当我们把所有的资源,根据使用情况分别放置到树的不同节点上时,这就是一棵服务树啦。
树的节点之间,天然就有继承的关系,正好与业务的组织架构对应。
每一个树的节点,我们称之为 NS(NameSpace)。是不是有点类似编程语言的命名空间?

服务树的由来

最初的时候,我们只有一个CMDB系统,当然这个系统可能只是一个excel表格。
后来我们要对机器进行批量操作,可能是某个服务的一批机器,可能是某个集群的一批机器,也有可能是某个产品线的所有机器,于是我们开始维护各种各样的资源列表。
再后来,大家想,能不能搞个平台,把所有的资源列表都管理起来。也就是,分组功能服务化。
然后就有了服务树。

服务树——灵活强大的运维资源管理体系 - 图2

其实服务树的发展过程,与运维系统平台化的发展是基本同步的。因为越先进的运维系统,就要求越强大越高效的资源管理系统。

服务树的日常应用

在我看来,服务树的作用只有一个:灵活的筛选业务与资源的关联关系
在服务树接管资源的管理之后,我们来看下如何利用服务树更好的进行运维操作:

  • 发布一个服务的时候,我可以指定将此服务发布至【服务树某个节点】。
  • 监控一个进程是否存活,我可以指定,只采集【服务树某个节点】的进程数据并报警。
  • 一台机器是混部的,很多业务线在共用。我可以查询【该机器存在于哪几个服务树节点】,就能知道哪几个业务线在使用。
  • 我要给某个人授权,可以不需要指定机器列表,可以只给他服务树节点的权限即可。

上述这些情况,使用服务树节点代替机器列表,带来的好处有:

  • 无需关心琐碎的资源列表,所有操作对节点生效,简洁明了,提高人员效率。
  • 无需人工指定机器列表,由服务树来补全,减少误操作。
  • 当节点下机器发生变更,将直接在所有周边系统生效,不需要人为干预。

服务树节点规范的制定

服务树的模型,说来并不算复杂。但是确实整个运维平台最核心的地方。
当我们做服务树的时候,更多的,是做一个规范。
规范的制定,一定要非常慎重,因为规范一旦确定,模型就确定了,再改起来就会非常困难。
首先是层级的划分,要根据公司的实际情况,与业务紧密关联起来。最好有对公司体系架构非常熟悉的人来帮忙review。
其次要考虑如何同时满足各种灵活的筛选和调整。考虑当前公司的各种系统对资源的检索需求,设计模型是否可以满足。
最后,服务树模型的设计者一定要想明白这个模型,要在最大程度满足业务需求的前提下,保留服务树的灵活性。不要完全被业务所左右,要给我们的想象和未来留一点空间。
一般来讲,服务树规范分为命名规范使用规范两方面。

命名规范

命名规范主要是用来约束节点的命名。这些规则,是构建一棵服务树的具体规则。根据公司业务情况的不同所不同。
比如:

  • 服务树的节点必须有层级的概念,必须从上到下有【公司】【部门】【产品线】【service】不能缺省、其他的【servicegroup】可以缺省。
  • 【servicegroup】层级可以嵌套和级联。
  • 【idc】【status】等在一台机器上,必须唯一。

使用规范

使用规范用来约束服务树的使用,同时约束周边系统的行为。可以与各个周边系统的负责人来商量敲定
比如:

  • 监控系统指标只允许上报至叶子节点。
  • 部署服务必须在【service】节点维度进行。

服务树的实践

这一部分,分享一个笔者老东家的一个服务树的实践,可谓是小巧灵活、弹性十足。
小巧,从逻辑上,核心的服务树模型与机器全流程的运转,做了隔离。服务树可以更好地专注于映射关系的处理。
灵活,这棵服务树的层级之间的关系并不是固定的,而是由一个一个的标签组合而来。比如,我一台机器,在【部门A-业务线B-集群C】,并不是做了这样的绑定关系。而是分别给这台机器打了【部门A】【业务线B】【集群C】三个关联标签
这样,就可以随意的组合各种标签,用来筛选资源,比如:【部门A-集群C】所有机器,可以筛选出【部门A】下所有业务线【集群C】的机器。
弹性,除了维护逻辑的关系之外,同时支持另一类标签,用来标示资源的属性。比如【机器状态】【机器idc】等。可以支持更多维度的筛选。
并且,允许用户自定义服务树视图。比如,一个sys主机组的同学,并不关心机器的所属部门和业务情况,只关心坏掉的机器。那就可以将视图设置为【公司X-状态trouble】,这样,看到的树,只有两级,并且可以完全的满足他的筛选需求。

这棵树的实现方式,比较简单:一张资源表,一张节点表,一张关联表。
节点表存的是排过序的tag组合串。平时的tag筛选,通过数据库的like操作来实现。
资源相关的属性标签,直接放在资源表里。
说来这个实现方式其实比较trick,只是打擦边球实现了服务树的各种功能。
不过服务树的数据体量一般不会太大,因此这个问题暴露的也不算太明显。有查询的瓶颈也可以通过加cache来解决。不过一旦机器量到达10W+,很可能就要从模型上来重构了。

服务树模型当前的问题与瓶颈

问题一:与周边的关联

周边系统要与服务树打通,有两种方式:

  • 节点串关联:与周边系统弱耦合。如果节点改名,需要有一个触发式的通知机制,由周边系统来订阅。不利于解耦。
  • ID关联:与周边系统强耦合。使用服务树的节点串唯一ID来做关联,改名可以不用通知。但是周边系统每次都需要用ID向服务树动态解析,一旦服务树出现故障,很可能导致大量周边系统不可用。

上述已知的两种方式,都存在问题,目前也没有很好的解决方式。笔者公司目前是使用的第一种方式,一旦服务树出现问题,起码可以保证周边系统可用。

问题二:关联了节点,却失去了对资源本身的关注

笔者公司目前遇到了这样的一种情况,机器A同时挂载到了两个节点,监控与服务树是弱关联。
因此监控数据分为两份,分别与两个节点关联。如果是业务数据,那没问题。但是由于我们监控系统根据服务树节点做了分片。基础指标,也分了两份,推往了不同的节点。
当我配置一条大节点的策略:cpu.idle小于10的时候,报警出来。但是却同时收到了两条报警,因为节点不同,监控系统认为,这是两条监控数据。
那么问题来了,用户视角:“为什么,同一台机器,同一条监控策略,你要给我发两条报警??
哑口无言。
虽然这个问题,通过报警的收敛可以解决。但是模型的不支持,却让我们耿耿于怀。

脑洞 & 思考

服务树的本质

服务树,本质上应该只是一种视图,而不应该是一个实体。
关于资源本身的属性,更多的应该回归到资源的本身。
周边系统也是如此,应当对资源本身的属性与正常的服务树节点有所区分。

节点标签化

这篇文章介绍的一个实践,仍然是有树的实体的。在我的构想里,整个系统应该以资源为主体。
所有的服务树信息,都以标签的形式,标记在资源上。
只是标签需要分两类:

  • 一类标签,可以无限制标记到资源。(比如:部门、产品线、服务、集群)
  • 另一类标签,对应资源属性,必须唯一。(比如:IP、IDC、状态)

这样一来,树只是一种视图,每次对树的查询,都可以动态的从海量的标签中组合出一棵树。非常灵活。
只是这种设计,资源太多,海量的标签,计算与定制树的速度将大大变慢。
对性能是一个比较大的考验。笔者已经不做服务树很久了,一直也没有好的机会来实践,因此这个设想也一直没有落实。

功能拓展

服务树的职能其实很简单,基本也不用拓展。能做好最核心的映射工作已经非常好了。
在功能拓展的时候,更多的是要做减法。不能太过影响服务树的灵活性,服务树一旦变得臃肿,整个运维平台都会感觉很乱。

服务树——灵活强大的运维资源管理体系 - 图3