Ceilometer项目的初衷是作为Openstack的计费系统。众所周知,计费系统在云计算系统特别是公有云中起着重要的作用。这也意味着Ceilometer项目是Openstack走向成熟商业产品的标志。但可能是因为当时的核心开发人员对计费也没有想得特别清楚,以至于现在的Ceilometer更像是一个监控系统,而且是一个性能比较慢的监控系统。不过这也给了很多开发人员展示拳脚的机会。


Ceilometer的概念


1. Meters(计量),可以简单理解为需要被计量、监控的事物,比如用户比较关心的虚拟机的cpu使用率、内存使用率以及镜像的大小等。 它的结构如下:


+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(255) | NO   | MUL | NULL    |                |
| type  | varchar(255) | YES  |     | NULL    |                |
| unit  | varchar(255) | YES  |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+


包括名字、类型和单位,其中类型又分为以下三种:

         1)cumulative:表示递增的数据

 

         3) gauge:表示值的变化没有规律


2. Resources(资源),表示Openstack中的资源包括:images、volumes、instances等。它的结构如下:


+-------------------+--------------+------+-----+---------+----------------+
| Field             | Type         | Null | Key | Default | Extra          |
+-------------------+--------------+------+-----+---------+----------------+
| internal_id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| resource_id       | varchar(255) | YES  | MUL | NULL    |                |
| user_id           | varchar(255) | YES  |     | NULL    |                |
| project_id        | varchar(255) | YES  |     | NULL    |                |
| source_id         | varchar(255) | YES  |     | NULL    |                |
| resource_metadata | text         | YES  |     | NULL    |                |
| metadata_hash     | varchar(32)  | YES  |     | NULL    |                |
+-------------------+--------------+------+-----+---------+----------------+


其中resource_metadata表示资源的详细信息,比如如果是一个镜像资源则会包含该镜像的名字、状态、格式等信息。

metadata_hash表示resource_metadata的hash值,主要是为了提高查询的效率。


3. Samples(样本), 主要代表被计量的事物在具体某一个时刻的值(datapoints)。它的结构如下:


+-------------------+---------------+------+-----+---------+----------------+
| Field             | Type          | Null | Key | Default | Extra          |
+-------------------+---------------+------+-----+---------+----------------+
| id                | int(11)       | NO   | PRI | NULL    | auto_increment |
| volume            | double        | YES  |     | NULL    |                |
| message_signature | varchar(1000) | YES  |     | NULL    |                |
| message_id        | varchar(1000) | YES  |     | NULL    |                |
| timestamp         | decimal(20,6) | YES  | MUL | NULL    |                |
| recorded_at       | decimal(20,6) | YES  |     | NULL    |                |
| meter_id          | int(11)       | YES  | MUL | NULL    |                |
| resource_id       | int(11)       | YES  | MUL | NULL    |                |
+-------------------+---------------+------+-----+---------+----------------+


其中volume为sample的值。


4. Statistics(统计), sample表示在一个时间点的值,而statistics表示在某一段时间范围内的聚合值,目前Ceilometer提供了类似于数据库中的聚合函数: count、max、min、avg、sum。

statistics中duration和period的概念比较容易混淆,其中duration表示统计的总体时间范围,而period又可以把duration分成更小的时间片进行聚合。


lan@lan-pc:~$ ceilometer statistics -m image -p 10
+--------+---------------------+---------------------+-----+-----+-----+-----+-------+----------+---------------------+---------------------+
| Period | Period Start        | Period End          | Max | Min | Avg | Sum | Count | Duration | Duration Start      | Duration End        |
+--------+---------------------+---------------------+-----+-----+-----+-----+-------+----------+---------------------+---------------------+
| 10     | 2015-01-18T07:44:48 | 2015-01-18T07:44:58 | 1.0 | 1.0 | 1.0 | 4.0 | 4     | 0.0      | 2015-01-18T07:44:48 | 2015-01-18T07:44:48 |
| 10     | 2015-01-18T07:54:48 | 2015-01-18T07:54:58 | 1.0 | 1.0 | 1.0 | 4.0 | 4     | 0.0      | 2015-01-18T07:54:48 | 2015-01-18T07:54:48 |
| 10     | 2015-01-18T08:04:48 | 2015-01-18T08:04:58 | 1.0 | 1.0 | 1.0 | 4.0 | 4     | 0.0      | 2015-01-18T08:04:48 | 2015-01-18T08:04:48 |
| 10     | 2015-01-18T08:14:48 | 2015-01-18T08:14:58 | 1.0 | 1.0 | 1.0 | 4.0 | 4     | 0.0      | 2015-01-18T08:14:48 | 2015-01-18T08:14:48 |
| 10     | 2015-01-18T08:24:48 | 2015-01-18T08:24:58 | 1.0 | 1.0 | 1.0 | 4.0 | 4     | 0.0      | 2015-01-18T08:24:48 | 2015-01-18T08:24:48 |
| 10     | 2015-01-18T08:34:48 | 2015-01-18T08:34:58 | 1.0 | 1.0 | 1.0 | 4.0 | 4     | 0.0      | 2015-01-18T08:34:48 | 2015-01-18T08:34:48 |
+--------+---------------------+---------------------+-----+-----+-----+-----+-------+----------+---------------------+---------------------+


每次进行统计时都会进行所有的聚合运算,但由于ceilometer采用了map-reduce模型来计算这些值,所以也不容易产生多余的比较。


5. Pipeline(传递途径), 通常称为管道。因为ceilometer获取的数据中,有些可能是比较初始的数据,需要经过一些转换才能成为用户能够理解的数据。所以就有了pipeline的概念,pipeline定义了一个计量数据在发送出去之间经历的一系列变化。

常用的转换(transformers)有以下三种:

1). unit_conversion: 单位转换,传入一个scale值。

2). rate_of_change:  将当前值和前一个值比较并除以时间差:

volume_delta = (s.volume - prev_volume
                            if (prev_volume <= s.volume or
                                s.type != sample.TYPE_CUMULATIVE)
                            else s.volume)
            rate_of_change = ((1.0 * volume_delta / time_delta)
                              if time_delta else 0.0)


如果sample的类型不是cumulative,则volume_delta直接采用当前值 -  前一个值,这种情况允许负值。

如果sample的类型是cumulative,而且当前值 > 前一个值, 则取差, 如果当前值<前一个值,则将delta重置为当前值。

3). accumulator: 在传递出去之前能够收集多个sample数据。

4). aggregator:  聚合一段时间或者一个阀值内的sample。

当sample类型为cumulative时,返回最后一个sample值。

当sample类型为gauge时,返回所有sample的平均值。

5). arithmetic: 可以对多个meter进行算数运算:


- name: "arithmetic"
      parameters:
        target:
          name: "memory_util"
          unit: "%"
          type: "gauge"
          expr: "100 * $(memory.usage) / $(memory)"

pipeline中还有一个很重要的概念publisher,Ceilometer没有强制将数据发送到MQ中,它可以将数据灵活的发送到其他监控系统或者文件中。当前存在的publisher有:

1)rpc: 将sample数据以rpc的方式发送到MQ中

        2)notifier: 将sample数据以notifier的方式发送到MQ中

        3)udp: 将sample数据以socket的方式发送到udp server中

        4)direct: 将sample数据直接存到数据库中

5)file: 将sample数据存到文件中


ceilometer中提供的dispatcher功能和publisher有点类似,只不过publisher根据不同的meter可能不通,而ceilometer会采用唯一的dispatcher。当前存在的dispatcher有:

1)database: 将publisher过来的sample数据直接存入数据库中

2)file:将publisher过来的sample数据存入文件中

3)http: 将publisher过来的sample数据以http的形式发送出去


由于ceilometer的数据会逐步的增长,相应的查询性能也会越来越差,目前的dispatcher已经不能满足快速查询的需求。同时,针对ceilometer存储的关键数据中时间作为很重要的一个查询条件,ceilometer的开发大牛们为了提交查询效率,提出了一个新的dispatcher: Gnocchi. 它为Openstack提供了TDBaaS(Time Series Database as a service)服务。感兴趣的话可以看一下Julien Danjou的blog: 

https://julien.danjou.info/blog/2014/openstack-ceilometer-the-gnocchi-experiment


6. Alarms(报警),  这为Openstack提供了面向用户的MaaS(Monitoring-as-a-service). 它使得Ceilometer可以监控数据转为为一些自动化的控制行为,在Openstack中最常用的场景是结合Heat autoscaling功能。Alarms体现为一个个规则,定义了当资源处于一种状态时需要触发某种行为。alarm的结构如下:


+---------------------------+---------------+------+-----+---------+-------+
| Field                     | Type          | Null | Key | Default | Extra |
+---------------------------+---------------+------+-----+---------+-------+
| alarm_id                  | varchar(255)  | NO   | PRI | NULL    |       |
| enabled                   | tinyint(1)    | YES  |     | NULL    |       |
| name                      | text          | YES  |     | NULL    |       |
| description               | text          | YES  |     | NULL    |       |
| user_id                   | varchar(255)  | YES  | MUL | NULL    |       |
| project_id                | varchar(255)  | YES  | MUL | NULL    |       |
| state                     | varchar(255)  | YES  |     | NULL    |       |
| ok_actions                | text          | YES  |     | NULL    |       |
| alarm_actions             | text          | YES  |     | NULL    |       |
| insufficient_data_actions | text          | YES  |     | NULL    |       |
| type                      | varchar(50)   | YES  |     | NULL    |       |
| rule                      | text          | YES  |     | NULL    |       |
| timestamp                 | decimal(20,6) | YES  |     | NULL    |       |
| state_timestamp           | decimal(20,6) | YES  |     | NULL    |       |
| repeat_actions            | tinyint(1)    | YES  |     | 0       |       |
| time_constraints          | text          | YES  |     | NULL    |       |
+---------------------------+---------------+------+-----+---------+-------+

其中rule表示alarm被触发的规则;evaluation_period表示需要触发规则的次数;

ok_actions表示当alarm进入ok状态需要触发的操作(webhooks);相应的,alarm_actions和insufficient_data_action分别表示当alarm进入alarm和insufficient状态时需要触发的操作。
repeat_actions: 表示alarm是否需要重复触发动作。


lan@lan-pc:~/stack/devstack$ ceilometer alarm-list
+--------------------------------------+----------+-------------------+---------+------------+---------------------------------+------------------+
| Alarm ID                             | Name     | State             | Enabled | Continuous | Alarm condition                 | Time constraints |
+--------------------------------------+----------+-------------------+---------+------------+---------------------------------+------------------+
| fa2b4aac-f8c7-4ec6-9208-71dcd1b0f51f | cpu_high | insufficient data | True    | False      | cpu_util > 70.0 during 3 x 600s | None             |
+--------------------------------------+----------+-------------------+---------+------------+---------------------------------+------------------+



7 Event(事件) , event表示Openstack中资源状态的变化,比如虚拟机的启动,镜像的删除等。event的结构如下:


+---------------+---------------+------+-----+---------+----------------+
| Field         | Type          | Null | Key | Default | Extra          |
+---------------+---------------+------+-----+---------+----------------+
| id            | int(11)       | NO   | PRI | NULL    | auto_increment |
| message_id    | varchar(50)   | YES  | UNI | NULL    |                |
| event_type_id | int(11)       | YES  | MUL | NULL    |                |
| generated     | decimal(20,6) | YES  | MUL | NULL    |                |
+---------------+---------------+------+-----+---------+----------------+

event_type表示事件的类型,由点来分隔,如“compute.instance.update” 表示虚拟机状态的改变。

message_id表示消息的唯一标识id

generated表示事件发生的时间

其中Event中还有Traits的概念,它是一些键值对,描述了这个事件的详情,同事trait还有类型,当前支持 strings、ints、floats和datetimes.

它的结构如下:


+---------------+---------------+------+-----+---------+----------------+
| Field         | Type          | Null | Key | Default | Extra          |
+---------------+---------------+------+-----+---------+----------------+
| id            | int(11)       | NO   | PRI | NULL    | auto_increment |
| t_string      | varchar(255)  | YES  | MUL | NULL    |                |
| t_float       | double        | YES  | MUL | NULL    |                |
| t_int         | int(11)       | YES  | MUL | NULL    |                |
| event_id      | int(11)       | YES  | MUL | NULL    |                |
| trait_type_id | int(11)       | YES  | MUL | NULL    |                |
| t_datetime    | decimal(20,6) | YES  | MUL | NULL    |                |
+---------------+---------------+------+-----+---------+----------------+