前期规划 ********************************************************************************************************************** 注 :该教程参考了如下内容 : A )官方文档 :http://oss.oetiker.ch/rrdtool/doc/index.en.html B )abel 兄的大作 :http://bbs.chinaunix.net/viewthread.php?tid=552224&highlight=rrdtool http://bbs.chinaunix.net/viewthread.php?tid=552220&highlight=rrdtool 作者 :ailms <ailms{@}263{dot}net> 版本 :v1 最后修改 :2006/11/18 0:06 ********************************************************************************************************************** 可能大家会觉得奇怪,做个 RRDtool 还要规划什么?俗话说:磨刀不误砍柴工。好的规划必须具备灵活性、可扩展性,否则会给 将来的使用带来不少的麻烦。我们先谈一下 MRTG 的规划,再谈 RRDtool 的规划。 一)MRTG 的前期规划 A )想要监测监测什么对象? 并列出一个清单; B )想要以什么方法来取得数据? 是通过 SNMP 还是 shell 、perl 。如果使用 SNMP ,监测对象所在主机 的 SNMP 服务安装了吗?是否配置完毕; C )每个对象的监测时间是多长时间一次? 并以此对监测对象进行分类。例如笔者本人共用 MRTG 监测了 80 多个对象,并根据 内容分成四类 : 重要状态方面 : 例如 HACMP 的切换动作监控;Oracle 服务的状态;LVM 中的 vg 是否在线;服务器是否宕机等。这些监 测对象对于一个系统的运行来说都是十分重要的,一旦发生故障,需要立即处理的。所以对于这类对象,按最 小时间间隔(5 分钟一次)设置 I/O 性能方面 : 主要是 I/O 吞吐量、I/O 服务时间方面的监测。这类对象是7 分钟一次 次要状态方面 : 例如 cpu 利用率、内存利用率、在线人数、温度、拨号用户人数等。20 分钟一次 利用率方面 : 由于实际应用的问题,所以对利用率比较关心。单独拎出来做一块监测。主要是监控Oracle 的各个表空间的利 用率,以及LVM 磁盘系统各个分区的利用率。每25 分钟一次 监控机本身 : 负责监控的监控机本身也需要监控。主要监控当前监测的对象数量,以及系统负荷。这类就30 分钟一次。 D )每个对象一个 cfg 文件?还是全部集中在一个 cfg 文件中呢? 我本人还是比较倾向于每个 Target 一个 cfg 文件,每个 cfg 中都定 义 Workdir 、Language 这两个选项。针对上面的5 个分类,建立5 个 “ 大的”cfg 文件,再利用 MRTG 中的 Include 功能导入一个个 “ 小的” 、具体的 cfg 文件。这样当日后对某个监测对象进行修改时(例如修改数据的获取脚本,或者修改图片的外观),可以单独测试 该对象。不用连同其他对象也一起跑一次,节省不少时间。如果想取消那个对象的监测,在前面提到的那个“ 大的”cfg 文件中,把对应 的 Include 语句注释掉就可以了,是不是更方便呢? E )为个监控对象起一个合适的名称 。一般用 <host_iterm> 的方式。这一步也满重要的。一开始不注意,随便给个名字,等到后来自己都 搞不清楚了,建议一开始就规划好。如果要使用 MRTG 的告警功能,就更应该好好规划了,要不然收到告警邮件都不知道是那个对象,那个机 器出现问题,白白浪费时间。 F )是否需要用到 MRTG 的告警功能。 MRTG 有告警功能,可以设置输入/ 出的最大值,最小值。超过限制就会调用 ThreshProgI 和 ThreshProgO 选项指定的程序。我一般用发送邮件和HTML 配合的方式。下面是告警部分的截图 : 差不多也就这些了,就可以开始动手写 script 了。 二)RRDtool 的前期规划 RRDtool 的前期规划相对多一点,因为 RRDtool 很多东西需要自己设定。除了上述 MRTG 考虑的几点之外,我一般还考虑以下几点 : A )是一个 RRD 文件中包括多个监测对象(DS ),还是分成多个 RRD 文件 ? RRDtool 提供了 tune 操作,可以增加监测对象或者删除 RRD 文 件中的某个对象,而且绘图时也可以指定要画的是那个对象,这点看个人喜欢而定。 B )如何统计取得的数据 : MRTG 是固定的,5 分钟、20 分钟、2 小时、1 天。RRDtool 则可以自己设置 C )如何保存/ 统计这些数据 : 这是和 MRTG 不同的地方。MRTG log 的建立和维护是自动的,RRDtool 的数据存放 则需要自己定义。但我们可以参照 MRTG 的方式: 每日统计图(5 分钟平均) : 600 个,大约2 天的时间 每周统计图(20 分钟平均) : 600 个,大约8 天的时间 每月统计图 (2 小时平均) : 600 个,50 天的时间 每年统计图 (1 天平均) :730 个, 2 年的时间 D 要以什么方式绘图 : MRTG 只有曲线(LINE )和方块(AREA )两种;RRDtool 除了这两种外,还有一种是 STACK 方式。就是在前一个曲线或者方 块的基础上绘图图,而不是直接从 X 轴开始绘图。这样绘制出来的图比较清晰,不会出现交叉的现象,但此时 Y 轴的值等于当前对象的值加上前一 个绘图对象的值。例如前一个对象(cpu 的系统进程利用率)的值是10 ,采用的是 AREA 方式绘图。当前对象(cpu 的用户级进程的利用率)是5 , 采用的是 STACK 方式,则“cpu 的用户级进程利用率” 对应的Y 轴刻度是10+5=15 ;所以如果不加说明,别人可能会误解。 三)实际例子 A )搞清楚究竟想要监测什么对象 : 监测本地主机的网络流量。包括 eth0 和 lo 接口的流量。 B )想要以什么方法来取得数据 : sar 也可以统计网卡接口的流量。但这里我们用 SNMP ,访问 ifInOctets 和 ifOutOctets 。 假设脚本名称是 get_eth0_traffic.sh 和 get_lo_traffic.sh C )每个对象的监测时间是多长时间一次 : 5 分钟 D )是采用一个 RRD 文件还是多个 : 2 个 RRD 文件,一个是 eth0.rrd ,一个是 lo.rrd E )为每个监测对象起名 : 分别是 eth0_in ,eth0_out ,lo_in ,lo_out F )统计频率 : 5 分钟、20 分钟、2 小时、1 天 G )如何保存统计数据 : 600 个、600 个、600 个、730 个 H )要以什么方式绘图 : 目前暂不考虑该问题。等到实际绘图时再体验。 注 :实际上我们可以把数据的插入、绘图一起做到 get_eth0_traffic.sh 和 get_lo_traffic.sh 中,但目前这两个脚本只是负责取数据并输出而已, 到最后我们再把这些功能合并到一起。 四)下面是脚本的内容
[Copy to clipboard]
CODE:
[root@dns1 bob]# cat get_eth0_traffic.sh #!/bin/bash # 首先取得 eth0 接口的 ifIndex index=$(snmpwalk -IR localhost RFC1213-MIB::ifDescr |grep eth0|cut -d '=' -f 1|cut -d '.' -f 2) # 再通过 snmp 协议取得 ififInOctets 和 ifOutOctets 的值 # 由于在 /etc/snmp.conf 中配置了 defVersion 和 defCommunity ,所以 snmpget 命令不用指定这两个参数 eth0_in=$(snmpget -IR -Os localhost ifInOctets.${index}|cut -d ':' -f 2|tr -d '[:blank:]') eth0_out=$(snmpget -IR -Os localhost ifOutOctets.${index}|cut -d ':' -f 2 |tr -d '[:blank:]') echo $eth0_in echo $eth0_out [root@dns1 bob]#
[Copy to clipboard]
CODE:
[root@dns1 bob]# cat get_lo_traffic.sh #!/bin/bash # 首先取得 eth0 接口的 ifIndex index=$(snmpwalk -IR localhost RFC1213-MIB::ifDescr |grep lo|cut -d '=' -f 1|cut -d '.' -f 2) lo_in=$(snmpget -IR -Os localhost ifInOctets.${index}|cut -d ':' -f 2|tr -d '[:blank:]') lo_out=$(snmpget -IR -Os localhost ifOutOctets.${index}|cut -d ':' -f 2 |tr -d '[:blank:]') echo $lo_in echo $lo_out [root@dns1 bob]#
再把这2 个脚本放入 crontab 中,每5 分钟执行一次
[Copy to clipboard]
CODE:
*/5 * * * * /home/bob/get_eth0_traffic.sh */5 * * * * /home/bob/get_lo_traffic.sh
不过这样会有讨厌的邮件产生,也可以在脚本中用 while true 循环,配合 sleep 300 让脚本一直运行,而不是重复启动脚本。具体选择那样你自己决定。 当所有的准备工作都完成后,就可以开始考虑建库了。 建立 RRD 数据库 ********************************************************************************************************************** 注 :该教程参考了如下内容 : A )官方文档 :http://oss.oetiker.ch/rrdtool/doc/index.en.html B )abel 兄的大作 :http://bbs.chinaunix.net/viewthread.php?tid=552224&highlight=rrdtool http://bbs.chinaunix.net/viewthread.php?tid=552220&highlight=rrdtool 作者 :ailms <ailms{@}263{dot}net> 版本 :v1 最后修改 :2006/11/17 17:35 ********************************************************************************************************************** 准备工作都做完了,脚本也写完了,就可以开始建库了。建库实际上就是建立后缀名为 .rrd 的 RRD 文件。 一)语法格式
[Copy to clipboard]
CODE:
rrdtool create filename [--start|-b start time] [--step|-s step] [DS:ds-name:DST:dst arguments] [RRA:CF:cf arguments]
其中 filename 、DS 部分和 RRA 部分是必须的。其他两个参数可免。 二)参数解释 A )<filename> : 默认是以 .rrd 结尾,但也以随你设定。 B ) --step : 就是 RRDtool “ 期望” 每隔多长时间就收到一个值。和 MRTG 的 interval 同样含义。默认是5 分钟。我们的脚本也应该是 每5 分钟运行一次。 C ) --start : 给出 RRDtool 的第一个记录的起始时间。RRDtool 不会接受任何采样时间小于或者等于指定时间的数据。也就是说 –-start 指定了数据库最早的那个记录是从什么时候开始的。如果 update 操作中给出的时间在 –-start 之前,则 RRDtool 拒绝接受。--satrt 选项也是 可选的。按照 我们在前一篇中的设定,则默认是当前时间减去 600*300 秒,也就是50 个小时前。 如果你想指定--start 为1 天前,可以用
[Copy to clipboard]
CODE:
--start $(date -d '1 days aog' +%s)
注意,--start 选项的值必须是 timestamp 的格式。 D ) DS : DS 用于定义 Data Soure 。也就是用于存放脚本的结果的变量名(DSN) 。 就是我们前面提到的 eth0_in ,eth0_out, lo_in , lo_out 。DSN 从 1-19 个字符,必须是 0-9,a-z,A-Z 。 E ) DST : DST 就是 Data Source Type 的意思。有 COUNTER 、GUAGE 、DERIVE 、ABSOLUTE 、COMPUTE 5 种。 由于网卡流量属于计数器型,所以这里应该为 COUNTER 。 F ) RRA : RRA 用于指定数据如何存放。我们可以把一个RRA 看成一个表,各保存不同 interval 的统计结果 G )PDP : Primary Data Point 。正常情况下每个 interval RRDtool 都会收到一个值;RRDtool 在收到脚本给来的值后 会计算出另外 一个值(例如平均值),这个 值就是 PDP ;这个值代表的一般是“xxx/ 秒” 的含义。注意,该值不一定等于RRDtool 收到的那个值。除非是 GAUGE ,可以看下面的例子就知道了 H ) CF : CF 就是 Consolidation Function 的缩写。也就是合并(统计)功能。有 AVERAGE 、MAX 、MIN 、LAST 四种 分别表示对多个PDP 进行取平均、取最大值、取最小值、取当前值四种类型。具体作用等到 update 操作时 再说。 I ) CDP :Consolidation Data Point 。RRDtool 使用多个 PDP 合并为(计算出)一个 CDP 。也就是执行上面 的CF 操作后的结果。这个值就是存入 RRA 的数据,绘图时使用的也是这些数据。 三)再说 DST DST 的选择是十分重要的,如果选错了 DST ,即使你的脚本取的数据是对的,放入 RRDtool 后也是错误的,更不用提画出来的图是否有意义了。 如何选择 DST 看下面的描述 : A )COUNTER :必须是递增的,除非是计数器溢出(overflows )。在这种情况下,RRDtool 会自动修改收到的值。例如网络接口流量、收到的 packets 数量都属于这一类型。 B )DERIVE :和 COUNTER 类似。但可以是递增,也可以递减,或者一会增加一会儿减少。 C )ABSOLUTE :ABSOLUTE 比较特殊,它每次都假定前一个interval 的值是0 ,再计算平均值。 D )GAUGE :GAGUE 和上面三种不同,它没有“ 平均” 的概念,RRDtool 收到值之后字节存入 RRA 中 E )COMPUTE :COMPUTE 比较特殊,它并不接受输入,它的定义是一个表达式,能够引用其他DS 并自动计算出某个值。例如
[Copy to clipboard]
CODE:
DS:eth0_bytes:COUNTER:600:0:U DS:eth0_bits:COMPUTE:bytes,8,*
则 eth0_bytes 每得到一个值,eth0_bits 会自动计算出它的值:将 eth0_bytes 的值乘以 8 。不过 COMPUTE 型的 DS 有个限制,只能应用 它所在的 RRD 的 DS ,不能引用其他 RRD 的 DS 。 COMPUTE 型 DS 是新版本的 RRDtool 才有的,你也可以用 CDEF 来实现该功能。 F )AVERAGE 类型适合于看“ 平均” 情况,例如一天的平均流量,。所以 AVERAGE 适用于需要知道 ‘xxx/ 秒’ 这样的需求。但采用 AVERAGE 型时,你并不知道 在每个 CDP 中(假设30 分钟平均,6 个PDP 组成)之中,流量具体是如何变化的,什么时候高,什么时候低。这于需要用到别的统计类型了 G )MAXIMUM 、MINIMUM 不适用想知道“xxx/ 秒” 这样的需求,而是适用于想知道某个对象在各个不同时刻的表现的需求,也就是着重点在于各个时间点。 也就是所谓的“ 趋势” 了,还是上面的例子,如果采用 MAXIMUM 或者 MINIMUM 的 CF ,可以看出接口在每个 CDP 的周期内最高是达到多少,最低又是多 少,如果是 AVERAGE 的话,有可能前5 个 PDP 都很均匀,但最后一个 PDP 的值发生很大的突变。这时候如果用 AVERAGE 可能是看不出来的,因为突变的部 分被平均分配到整个时间段内了,所以看不出突变这一现象;但如果用 MAXIMUM 就可以清楚的知道在该 CDP 的周期内,曾经有达到某个值的时候。所以用 MAXIMUM 或者 MINIMUM 就可以知道某个对象在某个时间段内最大达到多少,最低低到什么程度。 例如要看某个接口在一天内有没有超过50Mb 流量的时候就要用 MAXIMUM 例如要看磁盘空间的空闲率在一天内有没有低于 20% 的时候就要用 MINIMUM H )LAST 类型适用于 “ 累计” 的概念,例如从xxx 时候到目前共累计xxxx 这样的需求。例如邮件数量,可以用 LAST 来表示 30 分钟内总共收到多少个邮件,同 样 LAST 也没有平均的概念,也就是说不适用于 ‘xxx/ 秒’ 这样的需求,例如你不能说平均每秒钟多少封邮件这样的说法;同样也不适用于看每个周期内的变化, 例如30 分钟内共收到100 封邮件,分别是 :第一个5 分钟20 封,第二个5 分钟30 封,第三个5 分钟没有,第4 个5 分钟10 封,第5 个5 分钟也没有,第6 个5 分钟 40 封。如果用 MAXIMUM 或者 MINIMUM 就不知道在30 分钟内共收到100 封邮件,而是得出30 和0 。所以 LAST 适用于每隔一段时间被观察 对象就会复位的 情况。例如每30 分钟就收一次邮件,邮件数量就是 LAST 值,同时现有的新邮件数量就被清零;到下一个30 分钟再收一次邮件,又得到一个 30 分钟的 LAST 值。 这样就可以得得出“ 距离上一次操作后到目前为止共xxx” 的需求。(例如距离上一次收取邮件后又共收到100 封新邮件) 四)DST 实例说明 这样说可能还是比较模糊,可以看下面的例子,体会一下什么是 DST 和 PDP :
QUOTE:
Values = 300, 600, 900, 1200 # 假设 RRDtool 收到4 个值,分别是300 ,600 ,900 ,1200 Step = 300 seconds # step 为 300 COUNTER = 1,1, 1,1 # (300-0 )/300 ,(600-300 )/300 ,(900-600 )/300 ,(1200-900 )/300 ,所以结果为 1 ,1 ,1 ,1 DERIVE = 1,1,1,1 # 同上 ABSOLUTE = 1,2,3,4 # (300-0)/300,(600-0)/300 , (900-0)/300, (1200-0)/300 ,所以结果为 1 ,2 ,3 ,4 GAUGE = 300,600,900,1200 # 300 , 600 ,900 ,1200 不做运算,直接存入数据库
所以第一行的 values 并不是 PDP ,后面4 行才是 PDP 五)开始建库
[Copy to clipboard]
CODE:
[root@dns1 root]# rrdtool create eth0.rrd / > --start $(date –d ‘1 days ago’ +%s) / > --step 300 / > DS:eth0_in:COUNTER:600:0:12500000 / # 600 是 heartbeat ;0 是最小值;12500000 表示最大值; > DS:eth0_out:COUNER:600:0:12500000 / # 如果没有最小值/ 最大值,可以用 U 代替,例如 U:U > RRA:AVERAGE:0.5:1:600 / # 1 表示对1 个 PDP 取平均。实际上就等于 PDP 的值 > RRA:AVERAGE:0.5:4:600 / # 4 表示每4 个 PDP 合成为一个 CDP ,也就是20 分钟。方法是对4 个PDP 取平均, > RRA:AVERAGE:0.5:24:600 / # 同上,但改为24 个,也就是24*5=120 分钟=2 小时。 > RRA:AVERAGE:0.5:288:730 # 同上,但改为288 个,也就是 288*5=1440 分钟=1 天 [root@dns1 root]#
注:上面第2-4 个 RRA 的记录数实际上应该是 700 ,775 ,790 ,而不是 600 ,600 ,730 。 600 samples of 5 minutes (2 days and 2 hours)= 180000 秒 (2.08 天) 700 samples of 30 minutes (2 days and 2 hours, plus 12.5 days)= 1260000 秒 (14.58 天 ,2 周) 775 samples of 2 hours (above + 50 days) = 5580000 秒 (64.58 天,2 个月) 797 samples of 1 day (above + 732 days, rounded up to 797) = 68860800 秒(2 年) 可以看出每个 RRA 都存储了相应单位2 倍时间的数据,例如每天的 RRA 存储2 天的数据,每周的 RRA 存储2 周的数据,每月的 RRA 存储2 个月的数据,每年的 RRA 存储2 年的数据 检查一下结果
[Copy to clipboard]
CODE:
root@dns1 bob]# ll -h eth0.rrd -rw-r--r-- 1 root root 41K 11 月 19 23:16 eth0.rrd [root@dns1 bob]#
有的人可能会问,上面有两个 DS ,那 RRA 中究竟存的是那个 DS 的数据呢?实际上,这些 RRA 是共用的,你只需建立一个 RRA ,它就可以用于全部的 DS 。 所以在定义 RRA 时不需要指定是给那个 DS 用的。 六)什么是 CF 以第2 个RRA 和 4 ,2 ,1 ,3 这4 个 PDP 为例 AVERAGE :则结果为 (4+2+1+3)/4=2.5 MAX :结果为4 个数中的最大值 4 MIN :结果为4 个数中的最小值1 LAST :结果为4 个数中的最后一个 3 同理,第三个RRA 和第4 个RRA 则是每24 个 PDP 、每288 个 PDP 合成为1 个 CDP 七)解释度(Resolution ) 这里要提到一个 Resolution 的概念,在官方文档中多处提到 resolution 一词。Resolution 究竟是什么?Resolutino 有什么用? 举个例子,如果我们要绘制1 小时的数据,也就是60 分钟,那么我们可以从第一个RRA 中取出12 个 CDP 来绘图;也可以从第2 个 RRA 中取出2 个 CDP 来绘图。到底 RRDtool 会使用那个呢? 让我们看一下 RRA 的定义 :RRA:AVERAGE:0.5:4:600 。 Resolution 就等于 4 * step = 4 * 300 = 1200 ,也就是说 ,resolution 是每个CDP 所代表的时间范围,或者说 RRA 中每个 CDP (记录) 之间的时间间隔。所以第一个 RRA 的 resolution 是 1* step=300 ,第2 是 1200 ,第三个是 24*300=7200 ,第4 个 RRA 是 86400 。 默认情况下,RRDtool 会自动挑选合适的 resolution 的那个 RRA 的数据来绘图。我们大可不必关心它。但如果自己想取特定 RRA 的数据,就需要用到它了。 关于 Resolution 我们还会在 fetch 和 graph 操作中提到它。 八)xff 字段 细心的朋友可能会发现,在 RRA 的定义中有一个数值,固定是 0.5 ,这个到底是什么东东呢? 这个称为 xff 字段,是 xfile factor 的缩写。让我们来看它的定义 :
QUOTE:
The xfiles factor defines what part of a consolidation interval may be made up from *UNKNOWN* data while the consolidated value is still regarded as known. It is given as the ratio of allowed *UNKNOWN* PDPs to the number of PDPs in the interval. Thus, it ranges from 0 to 1 (exclusive)
这个看起来有点头晕,我们举个简单的例子 :例如
[Copy to clipboard]
CODE:
RRA:AVERAGE:0.5:24:600
这个 RRA 中,每24 个 PDP (共两小时)就合成为一个 CDP ,如果这 24 个 PDP 中有部分值是 UNKNOWN (原因可以很多),例如1 个,那么这个 CDP 合成的结果如何呢?是否就为 UNKNOWN 呢? 不是的,这要看 xff 字段而定。Xff 字段实际就是一个比例值。0.5 表示一个 CDP 中的所有 PDP 如果超过一半的值为 UNKNOWN ,则该 CDP 的值就被标为 UNKNOWN 。也就是说,如果24 个 PDP 中有12 个或者超过12 个 PDP 的值是 UNKNOWN ,则该 CPD 就无法合成,或者合成的结果为 UNKNOWN ; 如果是11 个 PDP 的值为 UNKNOWN ,则该 CDP 的值等于剩下 13 个 PDP 的平均值。 如果一个 CDP 是有2 个 PDP 组成,xff 为 0.5 ,那么只要有一个 PDP 为 UNKNOWN ,则该 PDP 所对应的 CDP 的值就是 UNKNOWN 了