在前文中,我们通过一个实例配置对Sensu有了初步地了解,但是对其中的一些概念只是有一个模糊的印象,本文将对Sensu中的几个重要概念或者说是术语,进行详尽的介绍。
Sensu的设计中涵盖了一些自定义的概念,比如check、event、Handler
、Filter
等。
Check
Check是指在客户端运行的可执行程序,用于检测和监控客户端上的各种服务、资源和应用程序的运行状态等,比如监控HTTP的运行状态,或者收集机器的可用内存值。Check实际上是一个可执行的脚本,它的输出数据是STDOUT
或者STDERR
,并且在执行后会返回一个值来表示所检测内容的状态。通常使用0
表示OK
,1
表示WARNING
,2
表示CRITICAL
,3
以及更大的值表示UNKNOWN
或其他用户自定义状态。Sensu的check配置和Nagios是相同的,因此Nagios中的Check插件可以直接在Sensu中使用。
根据Check的调度方式不同,可以分为发布/订阅
模式,即由服务端来调度和推送check的执行请求,发布/订阅模式下的check则是在服务器端配置,在配置的时候需要为check设置订阅主题。当要执行该check时,服务器会根据订阅主题分发执行请求,所有订阅了相应主题的客户端会收到执行的请求,从而运行check程序。同样的,执行的返回结果也会通过消息队列返回给服务器;
另外一种是Standalone
模式,该模式下的check直接在客户端进行配置,不需要服务器端发出执行的请求,可以根据配置的时间间隔在客户端自主执行,每次执行后会将结果通过消息队列返回给服务器。
Check定义参数
参数名称 | 描述 | 必填 | 类型 | 默认值 | 示例 |
---|---|---|---|---|---|
type | Check类型,standard /metric |
no | String | standard | "type": "metric" |
command | 执行的check命令 | true(除非配置了extension ) |
String | "command": "check-process.rb -p cron" |
|
extension | 可以替换command使用,不常用 | true(除非配置了command ) |
String | "extension": "system_profile" |
|
standalone | 是否是standalone模式 | false | Boolean | false | "standalone": true |
subscribers | 订阅者 | true(除非配置了standalone ) |
Array |
"subscribers": ["test"] |
|
publish | 是否发布 | false | Boolean | true | "publish": false |
interval | 执行周期 | true(除非publish 配为false ,或者配置了cron ) |
Integer | "interval": 60 |
|
cron | 执行周期可以配置为cron表达式 | true(除非publish 配为false ,或者配置了interval ) |
String | "cron": "0 0 * * *" |
|
timeout | 超时时间 | false | Integer | "timeout": 30 |
|
stdin | 是否将检查结果写入到进程STDIN | false | Boolean | false | "stdin": true |
auto_resolve | 当Check由CRITICAL 或者WARNING 切换到OK 状态时,是否自动清除之前产生的event,当需要手动清除时可以设置为false时 |
false | Boolean | true | "auto_resolve": false |
force_resolve | 强制将event置为解决状态 | false | Boolean | false | "force_resolve": true |
handle | 是否处理Check产生的event | false | Boolean | true | "handle": true |
handler | 用来指定处理Check产生的event的handler的名称 | false | String | "handler": "file" |
|
handlers | 可以同时指定多个handler | false | Array |
"handlers": ["file", "email" |
|
truncate_output | 是否对output进行截短,对metric类型的check默认为true,其他默认为false | false | Boolean | false | "truncate_output": false |
truncate_output_length | 设置output的最大长度,超过部分会截短 | false | Integer | 255 | "truncate_output_length": 1024 |
其他高级参数配置可以参考官方文档。
Check配置
安装检测插件
脚本check-process.rb
可以用于检测服务进程是否在运行,可以使用下面的命令在客户端进行安装。
1 | sensu-install -p process-checks |
发布/订阅模式示例
在服务端新建文件/etc/sensu/conf.d/check_cron.json
,文件内容如下:1
2
3
4
5
6
7
8
9
10
11{
"checks": {
"cron": {
"command": "check-process.rb -p cron",
"subscribers": [
"test"
],
"interval": 60
}
}
}
该Check会发送到test
订阅客户端上运行。
在上一篇文章中已经使用了发布/订阅模式,这里基于之前搭建的系统,我们主要来讲下Standalone模式的Check。
Standalone模式示例
在客户端新建文件/etc/sensu/conf.d/check_cron.json
,文件内容如下:1
2
3
4
5
6
7
8
9{
"checks": {
"cron": {
"command": "check-process.rb -p cron",
"standalone": true,
"interval": 60
}
}
}
通过配置"standalone": true
表明这是一个Standalone模式的Check,该Check会在客户端每60s运行一次。
不像发布/订阅模式,Standalone模式的Check在uchiwa
页面是看不到的,只有在Check状态不正常时,在页面才会收到告警。
正常情况下的可以通过client端的日志查看Check的执行过程:
我们将Check中的cron
进程修改为一个不存在的进程,再次观察,可以发现uchiwa页面可以收到Check告警信息:
指标采集
Check还可以分为两种类型:标准采集standard
和指标采集metric
。
- 对于标准类型的check来说,Sensu不会在每次执行后都生成event,而只是在check所返回的结果为
非0
或者是从非0
变为0
的时候才会生成event。这样带来的好处是降低了负载,适用于那些只关注于非正常状态,而在正常的状态无需采取措施的监控场景。 - 指标采集类型的check则会在每次执行后,无论其返回的结果是什么都会生成event。此类型的check一般用于获取监控指标的信息,除了check所返回的状态值,还有一些其它的输出信息可以通过event进行收集,然后返回给Sensu服务器。
之前我们接触的一致都是standard类型的check,比如HTTP状态、cron服务状态的监控等。下面我们来配置一个metric采集的Check。
安装采集插件
脚本metrics-cpu.rb
用来采集和输出CPU
指标,可以在客户端执行如下命令进行安装:
1 | sensu-install -p cpu-checks |
Check定义
在客户端新建文件/etc/sensu/conf.d/cpu_metrics.json
,内容如下:1
2
3
4
5
6
7
8
9
10
11
12{
"checks": {
"cpu_metrics": {
"type": "metric",
"command": "metrics-cpu.rb",
"interval": 10,
"standalone": true,
"truncate_output": false,
"handler": "debug"
}
}
}
这里采用Standalone模式进行配置,另外参数truncate_output
的设置为false
的目的是不用截短output。因为指标采集的输出通常较长,默认会对output进行截短。也可以通过"truncate_output_length": 666
设置output的长度。
指标采集结果
重启sensu-client
服务后,可以在uchiwa页面看到指标采集结果。
Check结果
Check结果结果是客户端再check执行完成后推送到Sensu transport
中的JSON格式的数据,一般包含如下信息:
- check定义相关,如command,subscribers,interval,name等,以及check输出
客户端名称
check结果示例
1
2
3
4
5
6
7
8
9
10
11
12
13{
"client": "client66",
"check": {
"command": "/usr/lib64/nagios/plugins/check_http -I 127.0.0.1",
"handler": "file",
"name": "check_http",
"issued": 1517317008,
"executed": 1517317024,
"duration": 0.006,
"output": "HTTP OK: HTTP/1.1 200 OK - 289 bytes in 0.001 second response time |time=0.000647s;;;0.000000 size=289B;;;0\n",
"status": 0
}
}
其中各个字段的含义为:
issued
- check请求发出的时间executed
- 客户端执行check的时间duration
- 客户端执行check所耗时长output
- check命令的输出status
- check运行的退出状态码
Event
Sensu使用event来通知所监控内容的状态变化。比如当check执行后返回2
,这表示所监控的内容出现了较为严重的问题,那么Sensu会生成event来报告这个问题,event会绑定一个或多个handler
来对所报告的问题进行处理。event包含有一些上下文信息,即event data
,主要包括执行check的客户端信息和check运行后的结果信息。通常event数据是以JSON
格式传递的,以下是一个event的示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33"event": {
"client": {
"name": "client66",
"address": "192.168.2.196",
"subscriptions": ["test",
"client:client66"],
"version": "1.2.0",
"timestamp": 1517148354
},
"check": {
"command": "/usr/lib64/nagios/plugins/check_http -I 127.0.0.1",
"interval": 10,
"subscribers": ["test"],
"name": "check_http",
"issued": 1517066088,
"executed": 1517148355,
"duration": 0.005,
"output": "connect to address 127.0.0.1 and port 80: 拒绝连接\nHTTP CRITICAL - Unable to open TCP socket\n",
"status": 2,
"type": "standard",
"history": ["2","2"],
"total_state_change": 0
},
"occurrences": 33,
"occurrences_watermark": 34,
"action": "create",
"timestamp": 1517066088,
"id": "9287299a-cebc-4708-893f-213257d105ca",
"last_state_change": 1517065768,
"last_ok": 1517065428,
"silenced": false,
"silenced_by": []
}
可以看到,event数据包含了Sensu客户端的基本信息,包括名称、IP等,同时也包含了所执行的check信息,客户端执行了该check并返回了状态值为2,同时输出内容HTTP CRITICAL: HTTP/1.1 503 Service Temporarily Unavailable
,可以用来帮助handler对问题进行处理。
Event属性
属性 | 描述 | 类型 | 可取值 | 默认值 |
---|---|---|---|---|
id | event的唯一id | String | 任意的uuid | |
timestamp | event的发生时间 | Integer | ||
action | event动作 | String | create /resolve /flapping |
create |
occurrences | 已发生次数 | Integer | 1 | |
check | check结果和check相关属性 | Hash | ||
check.history | check的历史退出状态,最多21个 | Array | ||
client | 客户端属性 | Hash | ||
silenced | 是否沉默 | Boolean | ||
silenced_by | 匹配该event的沉默的、条目ID列表 | Array |
Handler
Sensu handler
用于处理Sensu event
,例如发生告警邮件,将采集指标存放到时序数据库等。Handler在check的配置文件中指定,可以同时指定多个handler对event进行处理。Sensu包括以下几种类型的handler
:
Pipe handler
- 最常用,将event数据通过STDIN
传递给处理程序;TCP/UDP handler
- 将event数据发送给一个远程的socket
,如外部API;Transport handler
- 将数据发送给Sensu transport
(默认为RabbitMQ
)Set handler
- 用于组成一个event handler
集合,使得能够同时管理多个特定类型的event
默认handler
当check中没有指定handler时,Sensu会尝试使用default
的handler,若没有定义名为default
的handler,Sensu会在日志中报错。
handler配置
安装插件
1 | wget -O /etc/sensu/plugins/event-file.rb http://sensuapp.org/docs/1.2/files/event-file.rb |
由于event-file.rb
需要Ruby
运行环境,因此需要安装相关依赖:1
yum install ruby ruby-devel
定义handler
这里以pipe类型为例,新增文件/etc/sensu/conf.d/event_file.json
,内容如下:1
2
3
4
5
6
7
8
9
10{
"handlers": {
"file": {
"command": "/etc/sensu/plugins/event-file.rb",
"type": "pipe",
"timeout": 10,
"severities": ["critical", "unknown"]
}
}
}
TCP/UDP handler示例
下面的示例定义了一个TCP handler,会将event数据转发到定义的socket上。1
2
3
4
5
6
7
8
9
10
11
12{
"handlers": {
"example_tcp_handler": {
"type": "tcp",
"timeout": 30,
"socket": {
"host": "10.0.1.99",
"port": 4444
}
}
}
}
Transport handler示例
该handler会将event数据推送到名为example_handler_queue
的Sensu transport,其他组件可以通过订阅该消息队列来处理该event。1
2
3
4
5
6
7
8
9
10
11{
"handlers": {
"example_transport_handler": {
"type": "transport",
"pipe": {
"type": "direct",
"name": "example_handler_queue"
}
}
}
}
Set handler示例
相当于一个handler的结合,在check中引用时就可以通过notify_all_the_things
来引用其中定义的多个handler。1
2
3
4
5
6
7
8
9
10
11
12{
"handlers": {
"notify_all_the_things": {
"type": "set",
"handlers": [
"file",
"example_tcp_handler",
"example_transport_handler"
]
}
}
}
handler属性
属性 | 描述 | 是否必须 | 类型 | 可取值 | 默认值 |
---|---|---|---|---|---|
type | 类型 | true | String | pipe /tcp /udp /transport /set |
|
filter | 过滤器 | false | String | ||
filters | 可以同时配置多个过滤器 | false | Array |
||
severities | 定义处理哪个级别的event | false | Array |
ok /warning /critical /unknown |
|
mutator | 转换器 | false | String | ||
timeout | 超时时长,只在pipe 和tcp 中适用 |
false | Integer | 10 | |
handle_silenced | 是否处理沉默的event | false | Boolean | false | |
handle_flapping | 是否处理跃动状态的event | false | Boolean | false | |
command | handler的执行命令 | true(type==pipe ) |
String |
Filter
Sensu Filter用来过滤一些Sensu event。Filter会检查event中的数据和定义的过滤规则是否匹配,然后判断是否将event发送给handler。需要注意的是filter只能针对单个的handler配置有效,在handler set配置中是无效的。
Filter处理流程
- Sensu在处理event时,会检查handler的定义文件,在执行handler之前,会先执行该handler配置的filter,若配置了多个filter,会顺序执行;
- 将filter属性和event数据进行比较;
- 若filter将event删除了,那么之后就不会有的分析和处理
Filter分类
Sensu filter包含两种过滤方式:Inclusive
包含和Exclusive
排除。
- 包含式:默认的处理方式,只有符合filter定义的event才会被处理,可以用个参数
"negate": false
设置,如果同时使用多个,需要同时满足(x AND y AND z
)才会处理 - 排除式:会过滤掉符合filter定义的event,可以用个参数
"negate": true
设置
包含方式指定的是含有相应信息的event才会被发送至handler
排除方式则相反,含有指定信息的event会被过滤掉,不会被发送到handler
进行处理。值得注意的是,可以同时指定多个filter
,此时event需要同时匹配所有指定的filter
规则。
Filter示例
Filter属性直接比较
该filter会匹配数据中包含客户端属性"environment": "test"
的event。1
2
3
4
5
6
7
8
9
10
11
12{
"filters": {
"production_filter": {
"negate": false,
"attributes": {
"client": {
"environment": "test"
}
}
}
}
}
处理状态改变的event
下面定义的filter可以用来匹配状态变化的event,因为在每次event状态改变时,occurrences
的数值都会被重置,或者event的action
是resolve
状态,因为当check结果状态由非0
到0
时出action会切换到resolve状态。1
2
3
4
5
6
7
8
9
10{
"filters": {
"state_change_only": {
"negate": false,
"attributes": {
"occurrences": "eval: value == 1 || ':::action:::' == 'resolve'"
}
}
}
}
重复event的处理
下面的filter用来匹配check时间间隔是60s,并且occurrences!=1
,即不是第一次发生(或者发生次数不能被60整除)。需要注意的是这里配置的是一个Exclusive
类型的filter,即匹配的将会被过滤。即该过滤器的目的是对check间隔是60s并且在第一次发生时以及每小时进行处理。1
2
3
4
5
6
7
8
9
10
11
12
13{
"filters": {
"filter_interval_60_hourly": {
"negate": true,
"attributes": {
"check": {
"interval": 60
},
"occurrences": "eval: value != 1 && value % 60 != 0"
}
}
}
}
还有我们之前用的例子,仅处理出现次数大于5的event:1
2
3
4
5
6
7
8
9{
"filters": {
"recurrence": {
"attributes": {
"occurrences": "eval: value > 5"
}
}
}
}
仅处理工作时间的event
仅处理周一到周五9点到17点的event。1
2
3
4
5
6
7
8
9
10{
"filters": {
"nine_to_fiver": {
"negate": false,
"attributes": {
"timestamp": "eval: [1,2,3,4,5].include?(Time.at(value).wday) && Time.at(value).hour.between?(9,17)"
}
}
}
}
Filter配置属性
属性 | 描述 | 是否必须 | 类型 | 默认值 |
---|---|---|---|---|
negate | 配置是否会移除符合filter的event | false | Boolean | false |
attributes | 用来和event数据比较的属性 | true | Hash | |
when | 何时使用该filter | false | Hash |
when使用示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27{
"filters": {
"offhours": {
"attributes": {
"client": {
"environment": "production"
}
},
"when": {
"days": {
"all": [
{
"begin": "5:00 PM",
"end": "8:00 AM"
}
],
"friday": [
{
"begin": "12:00 PM",
"end": "5:00 PM"
}
]
}
}
}
}
}
Mutator
Sensu Mutators
用来转换event数据,然后将转换后的数据传递给event handler
。通过使用Mutator对event数据进行处理,可以减少重复代码,简化事件处理过程。Mutator在Sensu服务器端执行,从STDIN
接收JSON
格式的event数据,并将转换后的数据写入STDOUT
。Mutator会返回一个退出状态码用于标识转换是否成功。如果Mutator执行失败,事件将不会被handler处理,并且会将错误信息记录到日志中。
Sensu监控处理流程
如图所示,Sensu的监控流程如下:
Sensu Server
或Sensu Client
一个Service Check
请求Sensu Client
来执行Service Check
Service Check
会发出状态信息和检测数据作为check结果Sensu Client
将check结果发送到Sensu Transport
(如redis, rabbitmq)Sensu Server
会对check结果进行处理,并将check的最新结果写入到Data Store
,同事创建相应的eventSensu Server
会通过Event Handler
来处理event- 通过
Handler
上定义的Filter
对Handler
进行过滤 - 处理
Handler
所绑定的Mutator - 最终执行
Event Handler
- 通过