2010年11月01日 星期一 14:03
简介: 集群管理人员经常需要知道集群中各种资源(CPU,内存,硬盘,网络带宽等)的使用情况。现在有许多通用的集群管理工具,如 Ganglia,Performance Co- Pilot,Nagios,Cacti 等都可以实现这一目的,但没有一个工具可以监控管理人员所需要的所有内容。本文介绍了一种简单的方法利用 RSCT 和 RRDtool 来实现定制的集群监控 。并通过一个简单的示例来说明这种方法,读者可以直接使用文中提供的自动化监控脚本或是编写自己的脚本来实现所需的监控软件。此外,使用 RSCT 来完成监控对于使用 AIX 作为操作系统的集群管理人员是非常方便的。AIX 系统自带 RSCT 软件,所有你不需要在节点上安装额外的软件,只需要在管理节点上安装 RRDtool 就可以实现集群监控。
RSCT(Reliable Scalable Cluster Technology)是一组为提高集群可用性,扩展性以及易用性提供底层支持的软件。IBM 的许多产品都依赖它,例如:HACMP, TSA, CSM 等等。RSCT 中的 RMC(Resource Monitoring and Control)子系统提供了用于管理集群或单机资源的一个通用框架,这个框架为集群管理软件提供底层的监控,查询,修改和控制集群资源的功能。
RRDtool 源于 MRTG(多路由器流量绘图器 ),是一个为监控而开发的数据库。
本文要介绍的方法就是利用 RMC 查询集群资源的功能来取得实时的监控数据,在处理完数据后,把结果保存在 RRDtool 数据库中。
要使用 RSCT,首先必须理解什么是 RSCT 的资源。在 RSCT 中,资源代表系统中物理或逻辑上可为其他组件提供服务的实体。所有的操作都是对资源进行的。一个资源可以是一个特定的文件系统、主机、网卡或进程等。相同类型的资源组成资源类。每个资源有一个或多个属性。属性有两种,静态属性和动态属性。静态属性指的是资源相对稳定的一些属性。经常可能变化的属性被称为动态属性。动态属性常常是被监控的对象。例如:IBM.EthernetDevice 是系统中以太网设备资源组成的资源类。清单 1 和清单 2 使用 lsrsrc 显示了该资源类中资源信息。
# lsrsrc -Ap "IBM.EthernetDevice"
Resource Persistent Attributes for IBM.EthernetDevice
resource 1:
Name = "ent0"
ActivePeerDomain = ""
NodeNameList = {"master.domain"}
resource 2:
Name = "ent1"
ActivePeerDomain = ""
NodeNameList = {"master.domain"}
|
# lsrsrc -Ad "IBM.EthernetDevice"
Resource Dynamic Attributes for IBM.EthernetDevice
resource 1:
RecErrorRate = 0
RecDropRate = 0
XmitDropRate = 0
XmitErrorRate = 0
XmitOverflowRate = 0
RecByteRate = 1547
RecPacketRate = 7
XmitByteRate = 83
XmitPacketRate = 0
RecErrors = 0
RecDrops = 0
XmitDrops = 0
XmitErrors = 0
XmitOverflows = 0
RecBytes = 490999495
RecPackets = 4212256
XmitBytes = 8422514234
XmitPackets = 5859387
resource 2:
…
|
其中,以太网设备的名称和所属的节点名是静态属性,收发速率和字节数是动态属性。RSCT 提供了许多常用的资源类。通过这些资源类,用户可以方便地查看集群中各种资源的信息,通过收集这些信息实现集群监控。此外,用户还可以自定义 RSCT 中没有的资源。
根据需要 , 可以将集群中的节点分配给不同的 RSCT 域。RSCT 域有两种,管理域(management domain) 和对等域 (peer domain)。管理域中,有一个节点是管理控制点(MCP, Management Control Point),只有 MCP 知道域中其他节点的信息。对等域中没有所谓的管理节点,所有的节点都是对等的,每一个都知道其它节点的信息。如果是出于管理的目的,可以将多个节点配置为一个 RSCT 的管理域。对等域通常被用来提供高可用性 (HA,High Availability)。出于监控目的,需要选择一个节点被选择为管理节点,并将集群中的所有需要监控节点配置在与这个管理节点同一个管理域中。这样,管理员就可以在这个管理节点上通过 RSCT 查询命令看到域中其他节点的信息,取得监控数据。
管理域资源管理器定义的资源类有:
IBM.MngNode- 在管理控制点上定义被管理节点。
IBM.MCP- 在被管理节点上定义管理控制点的信息。IBM.MCP 资源被定义后会自动进行管理控制点与被管理节点之间的公钥交换,所以最好是先在管理控制点上为被管理节点创建 IBM.MngNode 资源。
IBM.MngNodeNetIF- 定义被管理节点与管理控制点通讯的网络接口信息。该类资源会随着 IBM.MngNode 类资源的创建,修改和删除被自动创建,修改和删除。每个被管理节点配置一个 IP 地址。
IBM.PublicKeyExchange- 用于交换公钥。正常情况下,在被管理节点上成功创建 IBM.MCP 资源后,管理域资源管理器会自动发起公钥交换协议(PKE,public key exchange)协议。在被管理节点上执行 refrsrc IBM.MCP 命令也可以重新发起与所有 IBM.MCP 定义的管理控制点之间的公钥交换。
IBM.MngNodeNetIF 和 IBM.PublicKeyExchange 是被自动创建的,所以要建立 RSCT 管理域,只要在 IBM.MngNode 和 IBM.MCP 类中定义相应资源。命令 mkrsrc/chrsrc/rmrsrc/lsrsrc 用于定义 / 修改 / 删除 / 显示资源。此外,RSCT 中有 4 个为脚本使用而设计的新命令来执行相似的功能,这 4 个命令分别是 mkrsrc-api,chrsrc-api,rmrsrc-api,lsrsrc-api。与原来的命令相比,这四个命令有以下特点:
所以在脚本操作 RSCT 资源,建议使用这 4 个命令。
创建 RSCT 管理域的步骤如下:
#mkrsrc-api IBM.MngNode::Name::"$node"::KeyToken::"$node"::IPAddresses::
{"$node_ip"}::NodeID::$node_id
|
其中,$node 指的是节点的主机名 ,$node_ip 是节点与 MCP 相连的 IP 地址,$node_id 是 RSCT 中标志一个节点 ID 号,可以通过在节点上执行 /usr/sbin/rsct/bin/lsnodeid 取得。
#mkrsrc-api IBM.MCP::MNName::"$node"::KeyToken::"$ms"::IPAddresses::{"$ms_ip"}
::NodeID::$ms_node_id`
|
其中,$ms 是 MCP 的主机名 ,$ms_ip 是 MCP 与被管理节点相连的 IP 地址,$ms_node_id 是 MCP 的 ID 号。
例如:集群里有三个节点,hostname/IP/nodeID 分别为 master/192.168.0.1/0x1B04866DD460924C,node1/192.168.0.2/0x1B04866DD460924D, node2/192.168.0.2/0x1B04866DD460924E. 其中,master 节点作为 MCP。
清单 3.在 master 上创建 IBM.MngNode 资源
#mkrsrc-api IBM.MngNode::Name::"node1"::KeyToken::"node1"::IPAddresses::
{"192.168.0.2"}::NodeID:: 0x1B04866DD460924D
#mkrsrc-api IBM.MngNode::Name::"node1"::KeyToken::"node2"::IPAddresses::
{"192.168.0.3"}::NodeID:: 0x1B04866DD460924E
# lsrsrc -Ap IBM.MngNode
Resource Persistent and Dynamic Attributes for IBM.MngNode
resource 1:
Name = "node1"
NodeID = 1946828745203552845
KeyToken = "node1"
Aliases = {}
IPAddresses = {"192.168.0.2"}
ActivePeerDomain = ""
NodeNameList = {"master.domain"}
resource 2:
Name = "node2"
NodeID = 1946828745203552846
KeyToken = "node2"
Aliases = {}
IPAddresses = {"192.168.0.3"}
ActivePeerDomain = ""
NodeNameList = {"master.domain"}
|
#mkrsrc-api IBM.MCP::MNName::"node1"::KeyToken::"master"::IPAddresses::
{"192.168.0.1"}::NodeID::0x1B04866DD460924C
# lsrsrc -Ab IBM.MCP
Resource Persistent and Dynamic Attributes for IBM.MCP
resource 1:
MNName = "node1"
NodeID = 1946828745203552844
KeyToken = "master"
IPAddresses = {"192.168.0.1"}
ActivePeerDomain = ""
NodeNameList = {"node1.domain"}
|
#mkrsrc-api IBM.MCP::MNName::"node2"::KeyToken::"master"::IPAddresses::
{"192.168.0.1"}::NodeID::0x1B04866DD460924C
# lsrsrc -Ap IBM.MCP
Resource Persistent and Dynamic Attributes for IBM.MCP
resource 1:
MNName = "node2"
NodeID = 1946828745203552844
KeyToken = "master"
IPAddresses = {"192.168.0.1"}
ActivePeerDomain = ""
NodeNameList = {"node2.domain"}
|
完成后,在 master 上执行 lsrsrc -Ap -a IBM.Host,可以看到被管理节点 node1,node2 的信息,表示管理域建立成功。
#lsrsrc -Ap -a IBM.Host
Resource Persistent Attributes for IBM.Host
resource 1:
Name = "node1.domain"
NumProcessors = 6
RealMemSize = 11811160064
OSName = "AIX"
KernelVersion = "5.3"
DistributionName = "IBM"
DistributionVersion = "5300-12-01-1016"
Architecture = "ppc"
NumOnlineProcessors = 6
EntProcCapacity = 300
NumOnVProcessors = 3
NumActPProcessors = 32
ActivePeerDomain = ""
NodeNameList = {"node1.domain"}
resource 2:
Name = "node2.domain"
…
|
如果你的集群装有 CSM 软件,也可以通过 CSM 的 updatenode 命令来创建管理域。
RRDtool(Round Robin Database Tool)是一个用来处理定量数据的开源高性能数据库。
由于 RRDtool 设计的初衷就是为监控开发的,所以与其他的数据库相比,RRDtool 有以下特性:
图 1. 最近一小时的网卡收发速率
图 2. 最近一天的网卡收发速率
图 3. 最近一年的网卡收发速率
RRD 数据库存储的值并不一定等于更新时提供的值。这个值是根据数据库设定对提供的值进行计算得到的。计算过程可以分为三个步骤:
| 数据类型 | 计算方法 |
|---|---|
| GAUGE | 等于提供的值,适用于提供值为速度计,温度或人数等 |
| COUNTER | 当前值与前一个值的变化速度,要求递增的值,如计数器,里程表等。如果计数器溢出,RRDtool 会检查溢出是 32 位还是 64 位的,并相应地加上合适的值。 |
| DERIVE | 当前值与前一个值的变化速度,不要求递增。除了不进行溢出处理之外,该类型的内部处理机制与 COUNTER 相同。 |
| ABSOLUTE | 假定前一个值始终为 0,求变化速度。可用来存储读取后复位的计数器。 |
输入的时间经常会不在时间间隔的边界,所以需要根据前后两个有效的更新进行线性整形。(有效时间是被 heartbeat 设定控制的 )假定你在监视一个增长速度不均匀的计数器,每分钟检查一次,在 4:30 是 2,5:30 是 4,那么第 5 分钟的变化速度为 3。整形后得到的值称为 PDP(Primary Data Points)。
RRDtool 最终会根据设定对 PDP 进行合并,得到 CDP(Consolidated Data Point)。CDP 可以是多个(可以是一个)PDP 的平均值、最小值、最大值以及最近的值。CDP 是 RRD 数据库中最终存储的数据。这对于输出监控数据时是非常有利的。假设每个 PDP 的时间间隔是 1 分钟,如果你想查看 1 天的数据,而且你不需要查看每一分钟具体的监控数据,只是想看一下这一个天中每半个小时的监控数据。如果 RRD 中存储的是 PDP, 在输出时就需要对当天的 PDP 每 30 个进行合并。合并需要时间,如果你需要合并的数据量更大,如 1 个月或是 1 年,那这个合并的时间会非常长。所以 RRDtool 选择在数据库更新时对 PDP 进行合并,保存 CDP。用户可以根据需要设定如何对 PDP(非 UNKNOWN)进行合并。
| 合并方式 | 计算方法 |
|---|---|
| AVERAGE | 取平均值 |
| MIN | 取最小值 |
| MAX | 取最大值 |
| LAST | 取最近的值 |
1. 创建 RRD 数据库
语法:
rrdtool create filename [--start|-b start time] [--step|-s step] [--no-overwrite] [DS:ds-name:DST:dst arguments] [RRA:CF:cf arguments]
参数:
create 关键字,用于创建一个 RRD 数据库文件。
filename 文件名,扩展名最好是 .rrd
--start|-b start time 第一个记录的开始时间,默认是当前时间减 10 秒。表示方法为从 1970-01-01 UTC 到指定时间的秒数
--step|-s step 每条记录的时间间隔,默认为 300 秒
--no-overwrite 不覆盖同文件名的数据库文件
DS:ds-name:DST:dst arguments
DS 关键字,用于定义数据源。一个 RRD 文件可以有多个 DS。
ds-name 数据源名称,可以是 1 ~ 19 个 [a-zA-Z0-9_] 中的任意字符,一个 RRD 数据库文件可以有多个数据源。
DST 数据类型。支持的数据类型有:
GAUGE, COUNTER, DERIVE, ABSOLUTE,COMPUTE
DS:ds-name:GAUGE | COUNTER | DERIVE | ABSOLUTE:heartbeat:min:max
DS:ds-name:COMPUTE:rpn-expression
COMPUTE 存放对其他数据源进行公式计算的结果。
Heartbeat 心跳,两次数据源更新之间将数据源的数值确定为 UNKNOWN 前所允许的最大秒数。Min:max PDP 的最小值 / 最大值。
Rpn-expression
RRA:CF:cf arguments
RRA 关键字,用于定义 RRA(round robin archive) 档。一个 RRD 数据库文件有至少一个的 RRA 档。CDP 就被保存于 RRA 中。
CF 合并方式,可以是 AVERAGE,MIN,MAX,LAST
RRA:AVERAGE | MIN | MAX | LAST:xff:steps:rows
xff 定义合并时间间隔内允许的 PDP 为 UNKNOWN 的比例,超过这个比例时,CDP 被置为 UNKNOWN。
steps 定义多少个 PDP 合并一个 CDP。
rows 定义一个 RRA 档保存有多少条记录。
2. 更新 RRD 数据库
语法:
rrdtool {update | updatev} filename [--template|-t ds-name[:ds-name]...] [--daemon address] [--] N|timestamp:value[:value...] at-timestamp@value[:value...] [timestamp:value[:value...] … ]
参数:
update/updatev 关键字,用于更新数据库。updatev 会输出磁盘上数据库文件更新后输出更新信息。由于 updatev 需要直接的磁盘访问,所有不能与 --daemon 共用。
filename 需要更新的 RRD 数据库的文件名
--template|-t ds-name[:ds-name]...
默认情况下,需要按照数据源定义的顺序更新。该参数允许你指定要更新的数据。
--daemon address
使用缓存后台程序更新数据库,而不直接访问磁盘。
N|timestamp:value[:value...]
更新时间及数据。时间格式可以是 N| 时戳;N 表示现在;时戳以自 1970-01-01 以来的秒数来表示。 如果使用负数时间(当前时间之前多长时间),需要使用—与其它选项区分开。用 U 表示数据的值为 UNKNOWN。
at-timestamp@value[:value...]
更新时间也可以使用 AT 风格表示。
环境变量 RRDCACHED_ADDRESS 与 --daemon 选项的作用是一样的,如果两者都出现的话,前者优先。
3. 读取数据
语法:
rrdtool fetch filename CF [--resolution|-r resolution] [--start|-s start] [--end|-e end] [--daemon address]
参数:
fetch 关键字,用于取数据。
filename 需要读取的文件的文件名
CF 需要读取数据的合并方式 (AVERAGE,MIN,MAX,LAST)
--resolution|-r resolution (default is the highest resolution)
解析度,也就是你要取数据的时间间隔(单位:秒);rrdfetch 会尽量找到最匹配的 RRA。默认为数据库文件支持的最高解析度,即时间间隔最短的;如果想取的不是最高解析度的 RRA,假设要取得的是解析度为 x 的 RRA,开始时间和结束时间必须落在期望解析度的边界点上,即需要满足以下条件:
a.start 时间和 end 时间都是 x 的倍数
b.start 时间和 end 时间都在 RRA 记录的时间范围内。
--start|-s start (default end-1day)
开始时间;支持时戳和 AT 风格;默认是 1 天前。
--end|-e end (default now)
结束时间;格式与开始时间相同;默认是现在;
--daemon address
缓存后台程序地址。如果指定的话,在读取之前,会发 flush 指令给缓存后台程序将缓存的数据同步到磁盘。
2010年11月01日 星期一 14:04
在了解了 RSCT 和 RRDtool 的用法之后,本章将用一个实际的例子来说明如何实现自动化的集群监控。首先,选一个节点作为管理节点,这个节点负责收集处理其他被监控节点的信息,并向管理员提供可视的监控数据。所有的监控数据都保存在管理节点的本地的 RRD 数据库中。
在所有节点上安装 RSCT 软件,在管理节点上安装 RRDtool 软件。RSCT 有分别支持 AIX 和 Linux 的两个版本。AIX V5 和 AIX V6 上默认安装 RSCT 软件。Linux 用户可以从
http://www14.software.ibm.com/webapp/set2/sas/f/rsct/rmc/download/home.html
下载并安装 RMC。
然后,将管理节点作为 MCP,把需要监控的节点与管理节点配置到同一个 RSCT 管理域中。
编写脚本 getmetrics 收集集群中各节点信息,并把数据保存到系统的 /var/rrd 目录下。本脚本在 AIX5.3 上测试通过,读者可以直接使用或根据需要进行修改。
脚本用法:getmetrics 资源类名 属性列表 采样时间间隔
示例:取得集群中所有节点以太网卡收发数率
#getmetrics IBM.EthernetDevice RecByteRate,XmitByteRate 1
清单 7 为脚本声明全局变量及分析参数的部分。其中哈希数组 %metrix 有三个键值,依次为 { 属性名 }{ 节点名 }{ 资源名 },用来保存收集到的各节点监控数据。
#!/usr/bin/env perl
@attrs = ();
$attr = undef;
$nnlist = undef;
$ret = undef;
$cmd = undef;
%metrix={};
($rsrc, $attrlist, $minute) = @ARGV;
@attrs = split /,/, $attrlist;
$attr = join '::', @attrs;
|
在示例中,RRD 数据库文件被分为两类,一类保存的是单个资源的数据,另一个保存的是多个资源数据的和。如果一个 RRD 数据库文件保存的是多个资源数据的和,那么该数据库文件中有两个数据源,sum 和 num,sum 用来记录值,num 保存资源数;如果文件只保存单个资源数据,则数据库文件只有一个数据源 sum。清单 8 封装了 rrdtool create 和 update 命令。
#---------------------------------------------------------------
# 函数名:RRD_create
# 描 述 : 创建 RRD 数据库文件,会覆盖已有文件
# 输 入 :
# $rrd 文件名
# $sum 如果 $sum!=0 会创建数据源 num
# $step 每条 RRD 记录的时间间隔
# $start_time 记录开始时间
# $ds_type ds-name:GAUGE | COUNTER | DERIVE | ABSOLUTE
# 返回值 :
# 0 成功 !0 失败
#---------------------------------------------------------------
sub RRD_create
{
my ($rrd, $sum, $step, $start_time, $ds_type) = @_;
my $output = [];
my $heartbeat = 8 * $step;
my $cmd = "create $rrd --start $start_time --step $step \
DS:sum:$ds_type:$heartbeat:U:U";
if($sum){
$cmd = $cmd." DS:num:$ds_type:$heartbeat:U:U";
}
$cmd = $cmd." RRA:AVERAGE:0.5:1:244 RRA:AVERAGE:0.5:24:244 \
RRA:AVERAGE:0.5:168:244 RRA:AVERAGE:0.5:672:244 RRA:AVERAGE:0.5:5760:374";
@$output = `rrdtool $cmd`;
my $line = pop(@$output);
if($line =~ /ERROR/){
return -1;
}
return 0;
}
#---------------------------------------------------------------
# 函数名:RRD_update
# 描 述 : 更新已有的 RRD 数据库文件
# 输 入 :
# $rrd 文件名
# $sum 数据源 sum 的值
# $num 数据源 num 的值
# $process_time 更新时间
# 返回值 :
# 0 成功 !0 失败
#---------------------------------------------------------------
sub RRD_update
{
my ($rrd, $sum, $num, $process_time) = @_;
my $output = [];
my $cmd = "update $rrd";
if($num ne "null"){
$cmd = $cmd." $process_time:$sum:$num";
} else {
$cmd = $cmd." $process_time:$sum";
}
@$output = `rrdtool $cmd`;
my $line = pop(@$output);
if($line =~ /ERROR/){
return -1;
}
return 0;
}
#---------------------------------------------------------------
# 函数名:push_data_to_rrd
# 描 述 : 将数据保存到 RRD 数据库
# 输 入 :
# $rrd 文件名
# $sum 数据源 sum 的值
# $num 数据源 num 的值
# $step 每条 RRD 记录的时间间隔
# $process_time 更新时间
# $ds_type ds-name:GAUGE | COUNTER | DERIVE | ABSOLUTE
# 返回值 :
# 0 成功 !0 失败
#---------------------------------------------------------------
sub push_data_to_rrd
{
my $ret = 0;
my($rrd, $sum, $num, $step, $process_time, $ds_type) = @_;
my $summary = $num eq 'null' ? 0 : 1;
if(! -f $rrd){
$ret = RRD_create($rrd, $summary, $step, $process_time-$step, $ds_type);
if($ret != 0){
return $ret;
}
}
$ret = RRD_update($rrd, $sum, $num, $process_time);
return $ret;
}
|
清单 9 所示的 updaterrd 函数的功能是在 /var/rrd 下创建 RRD 数据库文件,并将 %metrix 中保存的数据更新到数据库中。保存的数据库文件在 /var/rrd 下的目录结构如下:
|--summary
|-- 属性名 .rrd
|--...
|-- 节点名
|-- 属性名 .rrd
|-- 属性名 _ 资源名 .rrd
|--...
|
其中,summary 目录保存的是整个集群的监控数据,在示例脚本中,是对所有节点监控数据求和。
#---------------------------------------------------------------
# 函数名:updaterrd
# 描 述 : 将 %metrix 中保存的监控数据更新到 RRD 数据库
# 输 入 :
# $step 每条 RRD 记录的时间间隔
# 返回值 :
# 0 成功 !0 失败
#---------------------------------------------------------------
sub updaterrd
{
my $step = shift @_;
my $ret = 0;
my $attr;
my $nnlist;
my $name;
my $value;
my $rmcrrdroot = "/var/rrd";
my $rrddir = undef;
my $rrd = undef;
my $process_time = `date +%s`;
$process_time = (int $process_time/$step)*$step;
my $temp = undef;
while(($attr, $nnlist) = each %metrix){
while(($nnlist, $name) = each %{$metrix{$attr}}){
if($nnlist eq 'number'){
next;
}
$rrddir = "$rmcrrdroot/$nnlist";
if(! -d $rrddir){
`mkdir -p $rrddir`;
}
if($nnlist eq 'summary'){
$rrd = "$rrddir/"."$attr.rrd";
$temp = $metrix{$attr}{summary};
$ret = push_data_to_rrd
($rrd, $temp, $metrix{$attr}{number}, $step, $process_time, 'GAUGE');
if($ret != 0){
return $ret;
}
} else {
while(($name, $value) = each %{$metrix{$attr}{$nnlist}}){
if($name eq 'number'){
next;
}
if($name eq 'summary'){
$rrd = "$rrddir/$attr.rrd";
$temp =
$metrix{$attr}{$nnlist}{summary}/$metrix{$attr}{$nnlist}{number};
$ret = push_data_to_rrd($rrd,$temp,\
$metrix{$attr}{$nnlist}{number},$step,$process_time,'GAUGE');
if($ret != 0){
return $ret;
}
} else {
$rrd = "$rrddir/$attr"."_$name.rrd";
push_data_to_rrd($rrd, $metrix{$attr}{$nnlist}{$name}, \
'null', $step, $process_time, 'GAUGE');
if($ret != 0){
return $ret;
}
}
}
}
}
}
return 0;
|
}
#---------------------------------------------------------------
# 函数名:parse_lsrsrc_output
# 描 述 : 解析 lsrsrc-api 的输出结果保存到 %metrix
# 输 入 :
# $pattr RSCT 资源类属性
# $output lsrsrc-api 的输出结果
# 返回值 :
# 0 成功 !0 失败
#---------------------------------------------------------------
sub parse_lsrsrc_output
{
my ($pattr, $output) = @_;
my $nnlist = undef;
my $name = undef;
my $line = undef;
my $attr = undef;
my @value = ();
my $i = undef;
foreach $line (@$output){
@value = split /::/, $line;
$name = $value[0];
$name =~ s/[^A-Za-z0-9]+/'.'/;
$value[1] =~ /{(\w+)}/;
$nnlist = $1;
$i = 2;
foreach $attr (@$pattr){
$metrix{$attr}{$nnlist}{$name} = $value[$i];
$metrix{$attr}{$nnlist}{summary} += $value[$i];
$metrix{$attr}{$nnlist}{number} += 1;
$i++;
}
}
return 0;
}
|
主函数调用 lsrsrc-api 取得监控数据,解析保存到 /var/rrd 下的数据库文件中。
$cmd =
"CT_MANAGEMENT_SCOPE=3 lsrsrc-api -i -s ${rsrc}::::Name::NodeNameList::$attr";
@output = `$cmd`;
if($? != 0){
exit ($? >> 8);
}
&parse_lsrsrc_output(\@attrs, \@output);
foreach $attr (keys %metrix){
foreach $nnlist (keys %{$metrix{$attr}}){
if(($nnlist ne 'summary') && ($nnlist ne 'number')){
$metrix{$attr}{summary} += $metrix{$attr}{$nnlist}{summary};
$metrix{$attr}{number} += $metrix{$attr}{$nnlist}{number};
}
}
}
$step = $minute * 60;
&updaterrd($step);
1;
|
最后,使用 crontab 周期性的执行该脚本监控集群。清单 12 是一个监控集群收发速率的示例。
#crontab -e
* * * * * getmetrics IBM.EthernetDevice RecByteRate,XmitByteRate 1
|
当脚本第一次执行后,你就可以在 /var/rrd 目录下看到下列文件:
|--summary
|--RecByteRate.rrd
|--XmitByteRate.rrd
|--nodename
|--RecByteRate.rrd
|--RecByteRate_ent0.rrd
|--RecByteRate_ent1.rrd
|--XmitByteRate .rrd
|--XmitByteRate_ent0.rrd
|--XmitByteRate_ent1.rrd
|
监控的最终目的是为了方便管理员查看集群的状态。RRDtool 提供了文本和图形两种方式显示数据库内容。清单 13 示例的脚本使用 rrdtool fetch 命令用文本方式显示监控数据的方法。
#!/usr/bin/env perl
#---------------------------------------------------------------
# 函数名:RRD_fetch
# 描 述 : 从数据库中取数据
# 输 入 :
# $rrd 文件名
# $start_time 开始时间
# $end_time 结束时间
# 返回值 :
# 0 成功 !0 失败
#---------------------------------------------------------------
sub RRD_fetch
{
my ($rrd, $start_time, $end_time) = @_;
my $output = [];
my $resolution = undef;
my $cmd = undef;
$cmd = "fetch $rrd AVERAGE -s $start_time -e $end_time";
@$output = `rrdtool $cmd`;
return $output;
}
#---------------------------------------------------------------
# 主函数
#---------------------------------------------------------------
($node, $attrs, $time) = @ARGV;
$output = undef;
@files = ();
$file = undef;
@attrlist = split /,/,$attrs;
$attr = undef;
$line = undef;
@namelist = ();
@timelist = ();
%hash = {};
$name = undef;
$timestamp = undef;
$sum = undef;
$num = undef;
$end_time = `date +%s`;
if($time =~ /(\d+)-(\d+)/){
$start_time = $end_time - $1 * 60;
$end_time = $end_time - $2 * 60;
}else {
$start_time = $end_time - $time * 60;
}
$rrddir="/var/rrd/$node";
foreach $attr (@attrlist) {
@namelist = ();
@timelist = ();
%hash = {};
$output = `ls -A $rrddir/$attr*`;
@files = split /\n/, $output;
foreach $file (@files) {
if($file =~ /$attr\.rrd$/){
$name = "$attr";
} elsif ($file =~ /${attr}_(\S+)\.rrd$/) {
$name = $1;
}
push @namelist, $name;
$output = RRD_fetch($file, $start_time, $end_time);
$line = pop(@$output);
if($line =~ /ERROR/){
next;
} else {
push @$output, $line;
}
foreach $line (@$output){
if($line =~ /[NaNQ|nan]/){
next;
} elsif ($line =~ /^(\d+): (\S+)/){
$timestamp = $1;
$sum = $2;
if(! grep {/$timestamp/} @timelist){
push @timelist, $timestamp;
}
$hash{$name}{$timestamp} = sprintf "%.4f", $sum;
}
}
}
$line = join "\t", (@namelist);
$line = " ".$line;
print "$line\n";
@timelist = sort @timelist;
foreach $timestamp (@timelist){
$line = localtime($timestamp)." ";
foreach $name (@namelist){
if(exists $hash{$name}{$timestamp}){
$line =$line."$hash{$name}{$timestamp}\t";
} else {
$line = $line."-\t";
}
}
print "$line\n";
}
}
|
如果集群中有大量的节点,为了减少单个管理节点的负担,可以将集群划分为多个子管理域,使用多个管理节点进行层次的集群管理。如图 4 所示,Master 是主管理节点,它监控整个集群,管理员的所有的监控操作都在 Master 上进行。Sub-Master 监控 Node1 与 Node2. Sub-Master 定期收集处理 Node1 与 Node2 的监控数据并被保存在本地数据库。Master 上不直接监控 Node1,Node2,也不保存 Node1 和 Node2 的具体监控数据。当管理员需要查询 Node1 或 Node2 的监控数据时,Master 通过 Sub-Master 上的 RRD server 服务获取 Node1 或是 Node2 的信息。另外,Master 定期通过 Sub-Master 上的 RRD server 从 Sub-Master 获取该子管理域保存于 summary 目录中的数据。并将其与 Node3,Node4 的信息进行合并,形成整个集群的监控 summary 信息保存在本地 RRD 数据库中。
RRD server 是 RRDtool 提供的一个支持远程控制的功能。RRD server 不仅可以接受 rrdtool 的所有命令还支持 cd/mkdir/pwd/ls/quit 命令。具体操作步骤如下:
rrdsrv 13900/tcp
|
rrdsrv stream tcp nowait root $rrddir/rrdtool rrdtool - /var/rrd
|
需要先创建 /var/rrd 目录,读者可以根据需要自定义路径。
通过 RRD server,用户可以像操作本地数据库一样操作在 Sub-Master 上的数据库信息,实现层次的集群监控。
本文介绍了利用 RSCT 和 RRDtool 实现集群自动化监控的一种方法。文中提供了一个完整的例子来说明这种方法,读者可以直接使用它,也可以根据自己的需要进行更改,实现自己的集群监控软件
Zeuux © 2025
京ICP备05028076号