# 定期巡检(扁鹊)

## 扁鹊（定期巡检功能）

* [1 项目概述](#1-项目概述)
  * [1.1 背景介绍及目标](#11-背景介绍及目标)
  * [1.2 名词说明](#12-名词说明)
  * [1.3 Roadmap](#13-roadmap)
* [2 需求分析](#2-需求分析)
  * [2.1 功能需求](#21-功能需求)
  * [2.2 非功能需求](#22-非功能需求)
  * [2.3 调研](#23-调研)
    * [2.3.1 zabbix](#231-zabbix)
    * [2.3.2 openstack ceilometer](#232-openstack-ceilometer)
    * [2.3.3 小型项目（星络）](#233-小型项目星络)
    * [2.3.4 shinken](#234-shinken)
    * [2.3.5 StackStorm](#235-stackstorm)
* [3 总体设计](#3-总体设计)
  * [3.1 系统架构](#31-系统架构)
  * [3.2 模块简介](#32-模块简介)
  * [3.3 设计与折衷](#33-设计与折衷)
    * [3.3.1 规则引擎](#331-规则引擎)
  * [3.4 潜在风险](#34-潜在风险)
* [4 详细设计](#4-详细设计)
  * [4.1 模块 xx](#41-模块-xx)
    * [4.1.1 交互流程](#411-交互流程)
    * [4.1.2 数据库设计](#412-数据库设计)
    * [4.1.3 接口形式](#413-接口形式)
* [5 传送门](#5-传送门)

## 1 项目概述

### 1.1 背景介绍及目标

* 对管理的服务进行定期巡检，早期发现隐患
* 巡检服务与监控服务很类似

目标

* 方便添加巡检项

### 1.2 名词说明

### 1.3 Roadmap

## 2 需求分析

> 需求分析重点是需求

### 2.1 功能需求

### 2.2 非功能需求

### 2.3 调研

#### 2.3.1 zabbix

> trigger

```
{<server>:<key>.<function>(<parameter>)}<operator><constant>


{www.zabbix.com:system.cpu.load[all,avg1].last(0) }> 5
它指定的服务器是'www.zabbix.com'，Items 是'system.cpu.load[all,avg1]'，使用函数'last()'
取最近一次获取到的值，'>5'表示来自 www.zabbix.com 主机最后负载值大于 5 时触发器进入异常状态
```

#### 2.3.2 openstack ceilometer

<https://github.com/openstack/ceilometer>

#### 2.3.3 小型项目（星络）

```
基于 socket 自己封装协议，详细可以看 x-luo（星络）
    +---------------------------+
    | +---------+               |
    | |my_sender|               | alarm
    | +---------+               |
    +------|--------------------+
    +------|--------------------+
    |   +------+     +-----+    |
    |   |filter|     |saver|    |
    |   +------+     +-----+    |
    |        \        /         |  server
    |         +-------+         |
    |         |trans  |         |
    |         +-------+         |
    +---------------------------+
            ^          ^
           /            \
          /              \
    +---------------------------+
    |   +------+     +------+   |
    |   |agent1|     |agent2|   |  agent
    |   +------+     +------+   |
    +---------------------------+
```

只能由 agent 往 trans 进行发送数据，当监控项需要变更时，需要在 agent 侧进行变更，即监控项的管理缺失

#### 2.3.4 shinken

#### 2.3.4.1 shinken 架构

```
组件间使用 http 协议


    +--------------------------------------------------------------+
    | +----------------------+   +-------------------------------+ |
    | |Reactionner(Satellite)|   |Broker                         | |
    | |* send notifications  |   |* manage broks                 | |
    | |                      |   |* send check results to backend| |
    | +----------------------+   +-------------------------------+ |         +---------+ * Load configuration
    |                      \           /                           |  server | Arbiter | * Dispath configuration
    |                   +------------------+                       |         +---------+
    |                   |Scheduler         |                       |
    |                   | * schedule checks|                       |
    |                   +------------------+                       |
    +--------------------------------------------------------------+
                            ^          ^
             Active check  /            \ passive check
                          V              \
    +-------------------------------------------------------------+
    |   +------------------------+    +------------------------+  |
    |   |Poller(Satellite)       |    |Receiver(Satellite)     |  |  agent
    |   |* execute check commands|    |* receive passive checks|  |
    |   +------------------------+    +------------------------+  |
    +-------------------------------------------------------------+
```

#### 2.3.4.2 shinken 组件

> * Arbiter（仲裁）: Arbiter 节点读取本地的配置，然后将配置切分之后分发到多个合适的 schedulers 节点。
> * Scheduler（调度）: scheduler 节点负责分别管理 poller 和 reactionner 节点的任务调度。
> * Poller（轮询）: poller 节点通过各类插件执行 scheduler 节点的任务，获取各种健康指标。
> * Reactionner（响应）: reactionner 节点的任务是一旦满足要求将触发 event\_handlers 机制（比如发送通知等）。
> * Broker（中间人）: broker 节点的任务真的是中间人——导出和管理 scheduler 节点中的数据。
> * Receiver （接收人）: 可选节点，在某些特定场景下可以通过 reciver 节点汇总数据（比如汇总私网内部数据，统一转发）

> 主动监控与被动监控（对象都指的服务端）

```
Active  check:（主动检查）
--- Scheduler 主动发起命令给 Poller，然后 Poller 回调 Scheduler 写入数据
--- shinken.daemons.pollerdaemon:Poller


Passive check:（被动检查）
--- Receiver 主动将数据上报到 Scheduler
--- shinken.daemons.receiverdaemon.py:Receiver

Reactionner: (动作)
--- shinken.daemons.receiverdaemon.py:reactionnerdaemon.py
```

> * 除了 Arbiter 节点之外，任何的节点都可以不是唯一的。节点之间的关系也都是多对多的。
> * 每一个节点都支持 / 依赖插件，或者说 Shinken 本身只是一个插件的框架而已。
> * 保障性能和可靠性——根据 CAP 法则，放弃了一致性。

#### 2.3.4.3 shinken 代码

> Satellite（shinken/satellite.py）--卫星

```
```

#### 2.3.5 StackStorm

![st2](https://github.com/meetbill/meetbill_static/blob/master/st2/st2_flow.png?raw=true)

> * 主要角色
>   * 传感器（Sensors）是用于分别接收或监视事件的入站或出站集成的 Python 插件。 当来自外部系统的事件发生并由传感器处理时，StackStorm 触发器将发射到系统中。
>   * 触发器（Triggers）是外部事件的 StackStorm 表示形式。 有通用触发器（例如定时器，webhooks）和集成触发器（例如，Sensu 告警，JIRA 问题更新）。 通过编写传感器插件可以定义新的触发器类型。
>   * 动作（Actions）是 StackStorm 出站集成。 有通用动作（ssh，REST 调用），集成（OpenStack，Docker，Puppet）或自定义操作。 动作是 Python 插件或任何脚本，通过添加几行元数据将其消耗到 StackStorm 中。 动作可以由用户通过 CLI 或 API 直接调用，或者作为规则和工作流程的一部分使用和调用。
>   * 规则（Rules）将触发器映射到动作（或工作流），应用匹配条件并将触发器加载到动作输入中。
>   * 工作流（Workflows）将动作拼接成“超级动作”，定义顺序，转换条件以及传递数据。 大多数自动化不止一步，因此需要多个动作。 工作流就像“原子”动作一样，可在 Action 库中使用，并且可以手动调用或由规则触发。
>   * 包 (Packs) 是内容部署的单位。 它们通过对集成（触发器和动作）和自动化（规则和工作流）进行分组，简化了 StackStorm 可插拔内容的管理和共享。 StackStorm Exchange 上有越来越多的包可用。 用户可以创建自己的包，在 Github 上共享它们，或者提交给 StackStorm Exchange.
>   * 审计跟踪（Audit Trail）记录并存储手动或自动操作执行的审计跟踪，并存储触发上下文和执行结果的全部细节。 它还被记录在审计日志中，用于集成外部日志记录和分析工具：LogStash，Splunk，statsd，syslog
> * 大概执行流程
>   * 从各个服务系统通过 push 或 pull 的方式把 event 传给 sensors， sensors 会产生一个 trigger
>   * 到规则配置中查询该 trigger 对应的动作或者工作流
>   * 将来自工作流的 Action 发送到消息队列（内置 rabbitmq）中
>   * Actions 到达外部的系统后就执行相应的动作
>   * 日志和审计历史被推送到数据库进行存储（Mongodb）
>   * 处理后的结果被发送回规则引擎进行进一步处理

## 3 总体设计

> 总体设计重点是设计与折衷

### 3.1 系统架构

> 一般来说会有个简单的架构图，并配以文字对架构进行简要说明；

### 3.2 模块简介

> 架构图中如果有很多模块，需要对各个模块的功能进行简要介绍；

### 3.3 设计与折衷

> 设计与折衷是总体设计中最重要的部分；

#### 3.3.1 规则引擎

<https://github.com/zeroSteiner/rule-engine>

> * 需要 Python3 支持

```
import rule_engine
# match a literal first name and applying a regex to the email
rule = rule_engine.Rule(
    'first_name == "Luke" and email =~ ".*@rebels.org$"'
) # => <Rule text='first_name == "Luke" and email =~ ".*@rebels.org$"' >
rule.matches({
    'first_name': 'Luke', 'last_name': 'Skywalker', 'email': 'luke@rebels.org'
}) # => True
rule.matches({
   'first_name': 'Darth', 'last_name': 'Vader', 'email': 'dvader@empire.net'
}) # => False
```

```
import rule_engine
# define the custom context with two symbols
context = rule_engine.Context(type_resolver=rule_engine.type_resolver_from_dict({
    'first_name': rule_engine.DataType.STRING,
    'age': rule_engine.DataType.FLOAT
}))

# receive an error when an unknown symbol is used
rule = rule_engine.Rule('last_name == "Vader"', context=context)
# => SymbolResolutionError: last_name

# receive an error when an invalid operation is used
rule = rule_engine.Rule('first_name + 1', context=context)
# => EvaluationError: data type mismatch
```

### 3.4 潜在风险

## 4 详细设计

> // 详细设计重点在“详细”

### 4.1 模块 xx

> （有了数据库 + 接口 + 流程，别的同学拿到详设文档，基本也能够搞定了）

#### 4.1.1 交互流程

> 简要的交互可用文字说明，复杂的交互建议使用流程图，交互图或其他图形进行说明

#### 4.1.2 数据库设计

#### 4.1.3 接口形式

## 5 传送门

> * [yzhao062/pyod](https://github.com/yzhao062/pyod) --- 异常检测算法库
> * [redis](https://github.com/meetbill/op_practice_book/blob/master/doc/db/redis.md)
> * graphite(Python)
> * [o/simmetrica](https://github.com/o/simmetrica)
> * [cloud-custodian/cloud-custodian](https://github.com/cloud-custodian/cloud-custodian) 适配了 AWS
