Ceilometer Alarm是H版新添加的功能,监控报警是云平台不可缺少的部分,Ceilometer已经实现了比较完善的监控体系,报警怎么能缺少呢?用过AWS CloudWatch Alarm的人应该不会对Ceilometer的Alarm感到陌生,Ceilometer实现的Alarm和CloudWatch的Alarm很像,概念基本上都一样,Alarm的逻辑也基本上一样,可以说是一个开源版的CloudWatch Alarm,但是它进行了一些“微创新”,实现了一些比较有意思的小功能,而且代码写的也非常不错,是一个不错的学习素材。
下面我们从功能,实现,以及它目前存在的问题三个方面介绍一下Ceilometer的Alarm。
简单来说,Alarm的功能其实很简单,监控某一个或多个指标的值,若高于或者是低于阈值,那么就执行相应的动作,比如发送邮件短信报警,或者是直接调用某个接口进行autoscaling操作,像Heat就是依赖Ceilometer的Alarm实现Auto Scaling的操作。
Ceilometer中,实现了2种alarm:一种是threshold,一种是combination。顾名思义,threshold就是我们熟悉的根据监控指标的阈值去判断alarm的状态,它只是针对某一个监控指标建立alarm,而combination则可以理解为alarm的alarm,它是根据多个alarm的状态来判断自己的状态的,多个alarm之间是or/and的关系,这相当于是对多个监控指标建立了一个alarm。一般情况下,我们只需要threshold类型的alarm就足够了,但是一些特殊情况,比如Heat要执行auto scaling操作,可能就要对多个监控指标进行衡量,然后再采取操作。
下面,我们来分析一下Alarm的API,看它到底提供了哪些不一样的功能:
1. POST /v2/alarms
创建一个alarm,详细的参数见下表:
参数 | 类型 | 解释 |
---|---|---|
name | str | name是project唯一的 |
description | str | 描述 |
enabled | bool | alarm的一个开关,可以停止/启动该alarm,默认是True |
ok_actions | list | 当alarm状态变为ok状态时,采取的动作,默认是[] |
alarm_actions | list | 当alarm状态变为alarm状态时,采取的动作,默认是[] |
insufficient_data_actions | list | 当alarm状态变为insufficient data状态时,采取的动作,默认是[] |
repeat_actions | bool | 当alarm被触发时,是否重复执行对应的动作,默认是False |
type | str | alarm类型,目前有threshold和combination两种,必填 |
threshold_rule | AlarmThresholdRule | 当alarm类型为threshold时,制定的threshold规则 |
combination_rule | AlarmCombinationRule | 当alarm类型为combination时,制定的combination规则 |
time_constraints | list(AlarmTimeConstraint) | 约束该alarm在哪些时间段执行,默认是[] |
state | str | alarm的状态,默认是insufficient data |
user_id | str | user id,默认是context user id |
project_id | str | project id, 默认是context project id |
timestamp | datetime | alarm的定义最后一次被更新的时间 |
state_timestamp | datetime | alarm的状态最后一次更改的时间 |
这里主要说下面几个参数:
AlarmThresholdRule:
AlarmCombinationRule:
AlarmTimeConstraint:
举两个例子:
{ "name": "ThresholdAlarm1", "type": "threshold", "threshold_rule": { "comparison_operator": "gt", "evaluation_periods": 2, "exclude_outliers": false, "meter_name": "cpu_util", "period": 600, "query": [ { "field": "resource_id", "op": "eq", "type": "string", "value": "2a4d689b-f0b8-49c1-9eef-87cae58d80db" } ], "statistic": "avg", "threshold": 70.0 }, "alarm_actions": [ "http://site:8000/alarm" ], "insufficient_data_actions": [ "http://site:8000/nodata" ], "ok_actions": [ "http://site:8000/ok" ], "repeat_actions": false, "time_constraints": [ { "description": "nightly build every night at 23h for 3 hours", "duration": 10800, "name": "SampleConstraint", "start": "0 23 * * *", "timezone": "Europe/Ljubljana" } ] }
{ "name": "CombinationAlarm1", "type": "combination", "combination_rule": { "alarm_ids": [ "739e99cb-c2ec-4718-b900-332502355f38", "153462d0-a9b8-4b5b-8175-9e4b05e9b856" ], "operator": "or" }, "alarm_actions": [ "http://site:8000/alarm" ], "insufficient_data_actions": [ "http://site:8000/nodata" ], "ok_actions": [ "http://site:8000/ok" ] }
这个接口用来查询某个alarm发生的历史事件,记录的事件有:alarm被创建,alarm被更新,alarm被删除,alarm的状态被更新。
举个例子,比如我创建了一个alarm,然后又删除了,调用这个接口返回的结果是:
[ { "on_behalf_of": "2c35166baba84f46b1c5b093f02747fa", "user_id": "778a4ae5d8904a41b00c4e0f5734bcfd", "event_id": "dc5583ac-7ac8-4f4e-b8f7-edaa04522945", "timestamp": "2014-07-26T16:50:59.387923", "detail": "xxx", "alarm_id": "697a05df-d704-46a4-a0bd-1591c6588a17", "project_id": "2c35166baba84f46b1c5b093f02747fa", "type": "deletion" }, { "on_behalf_of": "2c35166baba84f46b1c5b093f02747fa", "user_id": "778a4ae5d8904a41b00c4e0f5734bcfd", "event_id": "d09fe2c3-37a8-4b19-9729-ccb2664a1116", "timestamp": "2014-07-26T16:50:27.315824", "detail": "xxx", "alarm_id": "697a05df-d704-46a4-a0bd-1591c6588a17", "project_id": "2c35166baba84f46b1c5b093f02747fa", "type": "creation" } ]
Alarm还有其它一些接口,这里就不说了,更多见alarm-api文档。
对于Alarm的实现,值得一说的就是Alarm的分布式实现,也就是文章的标题,Distributed Alarm。Ceilometer提供了两种方式的Alarm服务,一种是单进程的(SingletonAlarmService),一种是分布式的(PartitionedAlarmService),可以通过evaluation_service这个配置项进行配置。
前者没啥可说的,就是在一个进程中去检查所有的alarm,这种方式主要的缺点是处理能力弱,当量稍微大的时候,就会有延时,而且也没法做高可用,当他挂掉之后,alarm整个service就挂掉了,所以不推荐在生产环境中使用这个SingletonAlarmService的方式。
对于PartitionedAlarmService,它通过rpc实现了一套多个evaluator进程之间的协作协议(PartitionCoordinator),使得可以通过水平扩展来不断增大alarm service的处理能力,这样不仅实现了一个简单的负载均衡,还实现了高可用。下面我们就重点来说一下PartitionCoordinator这个协议。
PartitionCoordinator允许启动多个ceilometer-alarm-evaluator进程,这多个进程之间的关系是互相协作的关系,他们中最早启动的进程会被选为master进程,master进程主要做的事情就是给其他进程分配alarm,每个进程都在周期性的执行三个任务:
当一个进程被确定为master之后,如果它不挂掉,那么它的master是不会被抢走的,该进程就会一直在履行master的职责:
通过这个协议,就实现了一个简单的分布式alarm服务,其中的进程之间的相互协调,master的选举都值得去学习。
本文从三个方面大概描述了一下Ceilometer Alarm功能,功能篇主要从API入手,介绍Alarm都提供了哪些细枝末节的参数,实现篇主要描述了分布式Alarm协议的原理,很值得学习,问题篇其实没什么大问题,现在的alarm功能还是比较稳定的。