Ganglia+Nagios监控系统

  1. 简介

ganglia是一款为HPC(高性能计算) 集群设计的可扩展性 的分布式监控系统,它可以监视和显示集群中节点的各种状态信息,他由运行在各个节点上的gmond守护进程来采集 CPU、内存、磁盘利用率、I/O负载、网络流量情况等方面的数据。然后汇总到gmetad守护进程下,使用rrdtool存储数据,然后将历史数据以曲线方式通过PHP页面呈现。

ganglia作为一款用于Linux环境中的监控软件,它擅长的的是从节点中按照用户的需求以较低的代价采集数据。但是ganglia在预警以及发生事件后通知用户上并不擅长。最新的ganglia已经有了部分这方面的功能。但是更擅长做警告的还有Nagios。Nagios,就是一款精于预警、通知的软件。通过将Ganglia和Nagios组合起来,把Ganglia采集的数据作为Nagios的数据源,然后利用Nagios来发送预警通知,可以完美的实现一整套监控管理的系统。

 

  1. Ganglia三大组件

  2. Gmond

gmond类似于传统监控系统中的代理,需要安装在每台主机上,负责和操作系统交互以获得需要关注的指标数据。 gmond在内部采用模块化设计,采用基于C语言编写、根据操作系统定制的插件进行监控。gmond为指标提供了大部分标准插件,而且可以增加更多的用C、C++或Python等语言编写的插件来支持新的指标。此外,内置的gmetric工具可以用来报告用任何语言编译的自定义指标数据。

gmond根据自身本地配置文件定义的调度方案进行轮询。监听数据时使用简单的监听/通告协议,通过XDR (xml的压缩格式)或者XML格式在集群内的主机之间共享监控数据。这些通告默认使用多播,而集群是由共享同一多播地址的主机所构成的。当然gmond也可以使用单播,将数据都汇聚到同一台中心节点。因为每台gmond主机将指标数据多播到集群内的其他主机,每台gmond主机也记录了集群内其他主机的指标数据。因此,Ganglia集群内的每个节点都知道同一集群内所有主机的当前指标数据。远程轮询器可以通过端口8649向集群内任意节点请求获得该集群XML格式的所有数据。

如果服务器主机过多,因为只要轮询集群中任意节点就能获取所有集群内其他主机的性能指标数据,所以我们可以将众多的主机划分到不同的组里面,这样一来,收集数据的工作量将得到大大的减轻。

  1. Gmetad

gmetad是一个简单的轮询器,对网络中每个集群进行轮询,并将每台主机上返回的所有指标数据写入各个集群对应的轮询数据库RRD。轮询器对集群的"轮询"只需要打开一个用于读取的套接字,连接到目标gmond节点的8649端口即可,通过远程非常容易实现。

作为数据存储的一种流行的解决方案,RRDtool是很好的选择。指标数据存储于轮询数据库(Round Robin Database),这种数据库包含了多个时间块内静态分配的数值。如果每10秒进行一次轮询,每次数据都进行存储,一天将需要8640次存储。考虑到数据保留需求, RRDtool 内部以"循环覆盖"的方式管理数据,将新数据的值叠加到原来的数值上来覆盖原有数据。

gmetad还有一些其他特性,如可以从其他的gmetad中轮询数据,gmetad通过tcp端口8651侦听远程gmetad连接,并且向授权主机提供XML格式的网格状态。从而构成一种联合层次结构。gmetad具有交互式查询功能,外部监控系统可以通过TCP 8652端口用简单文本协议进行轮询。gmetad也可以通过配置gmetad将指标数据转送到诸如Graphite,Nagios外部系统发送数据。

  1. Gweb

ganglia可视化工具。显示ganglia收集的主机各项指标。gweb允许在图标中通过点击-拖拽改变时间周期,包含从不同文本格式(CSV,JSON等)中便捷提供数据的工具,显示完整、使用的URL接口,使用户可以通过预知的URL将感兴趣的图表嵌入其他程序。

gweb是一种PHP程序,因为需要与轮询器创建的RRD数据库交互,所以gweb通常安装在和gmetad相同的物理硬件上。

  1. ganglia监控架构图

  1. Ganglia工作模式

Ganglia收集数据可以工作在单播或多播模式下,默认在多播模式。本系统采用多播模式。

单播:发送自己收集到的监控数据到特定的一台或几台服务器上,可以跨网段。

多播:发送自己收集到的监控数据到同一网段所有的服务器上,同时收集同一网段的所有服务器发送过来的监控数据。因为是以广播的形式发送,因此需要在同一网段内,但同一网段内,又可以定义不同的发送信道。

Gmond之间通过udp通信,传递的文件格式为xdl。收集的数据供gmetad读取,默认监听的端口8649,监听到gmetad的请求后发送xml格式的文件。在监控系统中gmetad会周期性的到各个datasource收集各个cluster的数据,并更新到rrd数据库中,datasource是指被监控的一个集群。

 

  1. 安装Ganglia(基于Centos7)

  2. Server端安装

1.安装httpd和php

yum -y install httpd php

 

2.安装依赖包

yum -y install apr-devel apr-util check-devel cairo-devel pango-devel libxml2-devel rpm-build glib2-devel dbus-devel freetype-devel fontconfig-devel gcc gcc-c++ expat-devel python-devel libXrender-devel

yum -y install libart_lgpl-devel pcre-devel libtool rsync

yum -y install rrdtool rrdtool-devel #时序数据库

 

3.安装confuse

wget http://savannah.nongnu.org/download/confuse/confuse-2.7.tar.gz

tar xf confuse-2.7.tar.gz

cd confuse-2.7/

./configure --prefix=/usr/local/confuse CFLAGS=-fPIC --disable-nls --libdir=/usr/local/confuse/lib64

make && make install

 

4.安装ganglia

wget https://sourceforge.net/projects/ganglia/files/ganglia%20monitoring%20core/3.7.2/ganglia-3.7.2.tar.gz

tar xf ganglia-3.7.2.tar.gz

cd ganglia-3.7.2/

./configure --prefix=/usr/local/ganglia --enable-gexec --with-python --enable-status --with-gmetad --with-libconfuse=/usr/local/confuse
#Ganglia在安装时默认不安装gmetad,所以需要在configure时指定:--with-gmetad

make && make install

cp gmetad/gmetad.init /etc/init.d/gmetad

cp gmond/gmond.init /etc/init.d/gmond

/usr/local/ganglia/sbin/gmond -t >/usr/local/ganglia/etc/gmond.conf #生成gmond.conf配置文件

ln -s /usr/local/ganglia/sbin/gmetad /usr/sbin/gmetad

ln -s /usr/local/ganglia/sbin/gmond /usr/sbin/gmond

 

5.安装gweb

wget https://sourceforge.net/projects/ganglia/files/ganglia-web/3.7.2/ganglia-web-3.7.2.tar.gz

tar xf ganglia-web-3.7.2.tar.gz -C /var/www/html/

mv /var/www/html/ganglia-web-3.7.2 /var/www/html/ganglia

cd /var/www/html/ganglia

sed -i 's/www-data/apache/' Makefile #用户默认为www-data,修改为apache

make install

 

6.修改配置

(1). 修改gmetad启动脚本

# vim /etc/init.d/gmetad

[ -f /usr/local/ganglia/etc/gmetad.conf ] || exit 6 #这里将配置文件改成现在的位置,不然启动没反应

(2). 修改gmond启动文件

vim /etc/init.d/gmond

[ -f /usr/local/ganglia/etc/gmond.conf ] || exit 6 #这里将配置文件改成现在的位置,不然启动没反应

(3). 创建rrds目录

# mkdir /var/lib/ganglia/rrds -p #ganglia默认指定的rrds路径

# chown -R nobody:nobody /var/lib/ganglia/rrds

(4.) 创建pid文件目录

# mkdir -p /usr/local/ganglia/var/run/

 

7.gweb 添加密码认证

(1). 生成账号密码

htpasswd -c /etc/httpd/auth.basic adminganglia

(2). vim /etc/httpd/conf/httpd.conf #在配置文件末尾加上下面这些:

Alias /ganglia "/var/www/html/ganglia"

<Directory "/var/www/html/ganglia">

AuthType Basic

Options None

AllowOverride None

Order allow,deny

Allow from all

AuthName "ganglia Access"

AuthUserFile/etc/httpd/auth.basic

Require valid-user

</Directory>

 

8.启动服务

# systemctl start gmond.service

# systemctl start gmetad.service

# systemctl start httpd.service

 

  1. Client端安装

(1). 安装epel源

wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

yum clean all

yum makecache

(2). 下载并启动

yum install -y ganglia-gmond ganglia-gmond-python #默认不支持自定义python监控,所以要添加。

systemctl start gmond.service

 

  1. Web页面展示效果

  1. 配置文件说明

  2. gmetad配置文件

gmetad.conf 配置文件是由单行属性及相应值组成。属性名不区分大小写,但属性值区分大小写。

#vim /usr/local/ganglia/etc/gmetad.conf

1.data_source属性

每一行data_source描述一个gmetad收集信息的gmond集群或gmetad网格。当gmetad检测到data_source引用一个集群时,gmetad将为data_source保留一整套轮询数据库(Round Robin Database)。然而,当gmetad检测一个data_source引用一个网格时,gmetad将只保留概要性的RRD。

设置scalable属性为off时,gmetad 将强制为网格data_source保留一整套RRD文件,该值默认为on。

下面是默认配置中的data_source配置示例:

# data_source "my cluster" 10 localhost my.machine.edu:8649 1.2.3.5:8655

# data_source "my grid" 50 1.3.4.7:8655 grid.org:8651 grid-backup.org:8651

# data_source "another source" 1.3.4.7:8655 1.3.4.8

每个data_source有3个字段组成。第一个字段为唯一标识data_source的字符串;第二个字段为指定轮询间隔(单位是秒,默认为15秒,不应大于80秒);第三个字段是以空格分开的所要轮询数据的主机列表,可以以IP地址或主机名的形式指定,同时可以指定端口号。如果未指定端口号,默认连接tcp/8649。

2.gridname属性

能唯一标识网格的字符串。该字符串应该与网络中其他gmetad所设置的标识符不同。

3.authority(URL)

网格的授权URL,被其他gmetad用来找到当前gmetad数据源的图表位置。默认值为"http://hostname/ganglia/"

4.trusted_hosts(文本格式)

允许其他gmetad获取本机8152端口的xml访问权限的主机列表,以空格作为分隔。Localhost总是可信的。

5.all_trusted(on|off)

当该值设置为on时,将重写trusted_hosts属性,允许数据和任意主机共享,默认不允许。

6.setuid_username(UID)

gmetad设置UID的用户名。默认为nobody。

7.setuid(on|off)

当该值设置为off时,将不能设置UID,使用当前用户。

8.xml_port(数字)

gmetad侦听端口(监听其他gmetad),默认为8651。

9.umask(数字)

指定已创建RRD文件及其目录(/var/lib/ganglia/rrds)的umask。默认为022。

10.interactive_port(数字)

gmetad交互式应答端口,默认为8652。 #暂时没有验证

11.server_threads(数字)

允许同时连接到侦听端口的连接数,默认为4。

12.case_sensitive_hostnames(1|0)

在gmetad之前版本中,RRD文件区分主机名大小写,但是现在已经有所改变。如果希望继续使用Ganglia 3.2之前版本创建的RRD文件,将该值设置为1。从Ganglia 3.2开始,该值默认设置为0。

13.RRA(文本格式)

该选项代表自定义的罗宾环存档(Round Robin Archive)值。默认为(15秒步进):

"RRA:AVERAGE:0.5:1:5856" "RRA:AVERAGE:0.5:4:20160" "RRA:AVERAGE:0.5:40:52704"

14.rrd_rootdir(路径)

指定RRD文件在本地文件系统存储的基本目录(默认:/var/lib/ganglia/rrds)。

 

 

  1. gmond配置文件

gmond.conf配置文件由大括号括起来的几section组成。这些section可以粗略的划分为两个逻辑分类。第一类的section处理主机和集群的配置,第二类中section处理指标数据收集和调度的特定问题。所有的section名和属性不区分大小写。配置文件的section包括globals、cluster、host、udp_send_channel、udp_recv_channel、tcp_accept_channel、sflow、modules、collection_group。

#vim /usr/local/ganglia/etc/gmond.conf

globals {

daemonize = yes #以后台的方式运行

setuid = yes #这是gmond将user属性指定的特定用户的UID作为有效UID;值为false时,gmond将不会改变其有效用户。

user = nobody #运行gmond的用户

debug_level = 0 #值为0,gmond正常运行,大于0,gmond前台运行并输出调试信息。debug_level值越大,输出越详细。

max_udp_msg_len = 1472 #gmond发送包所能包含的最大长度。

mute = no #设置为no,gmond就是可以发送数据到其他gmond。设置为yes,就是单收,但是仍然会相应诸如gmetad的外部轮询器。

deaf = no #当值为true时,gmond将不能接收数据。设置no就是可以接收数据。

allow_extra_data = yes #当值为false时,gmond将不会发送XML的EXTRA_ELEMENT和EXTRA_DATA部分。默认是发送

host_dmax = 86400 #设置为0,gmond不会从队列中删除不在报告的主机。这里的意思是在86400秒内,接收不到某台主机的数据,web页面上会删除此gmond。

host_tmax = 20 #当gmond等到20秒*4的时间内,接收不到某台主机的任何消息,gmond就认为该主机已经崩溃。

cleanup_threshold = 300 #gmond清除过期数据的最小时间间隔为300秒。

gexec = no #当值为true时,gmond将允许主机运行gexec任务。这种方式需要允许gexecd并安装合适的验证码

send_metadata_interval = 0 #这是设置gmond两次发送元数据包的时间间隔。单位是秒。默认设置为0,表示gmond只有在启动和收集到其他远程允许的gmond节点请求时才会发送元数据包。但是如果单播环境下必须设置重发间隔

}

cluster { #每个gmond守护进程会使用在cluster section中定义的属性来报告它所属集群的信息。

name = "unspecified" #指定集群名称。当轮训节点的集群状态的XML集合时,把该名称插入CLUSTER元素内。轮询该节点的gmetad会使用该值来命名存储集群数据的RRD文件。该指令将取代gmetad.conf配置文件中指定的集群名称。

owner = "unspecified" #指定集群管理员

latlong = "unspecified" #指定该集群在地区上的GPS坐标的经纬度。

url = "unspecified" #指定接待集群特定信息(如集群用途和使用细节)的URL

}

#注意: 多播地址和UDP端口指定一个主机是否在某个集群中,name属性只是充当轮询时的标识符。

host { #section:host提供运行gmond主机的相关信息。目前只支持地址字符串属性。

location = "unspecified" #用来描述主机位置,描述的格式一般与站点位置有关,如:rack,U[,blade]

}

udp_send_channel {

#gmond集群内每个节点默认通过UDP将自身指标数据多播或单播至其他节点,如果是多播的形式的话还会侦听其他节点的类似UDP多播。

#bind_hostname = yes #通知gmond使用源地址解析主机名

mcast_join = 239.2.11.71 #gmond将创建udp套接字并加入由239.2.11.71指定的多播组。该选项与host相互排斥。

port = 8649 #gmond接收数据的端口号。未指定的话默认是8649

ttl = 1 #该设置在多播环境比较重要,当该值设置的比实际所需的更大时,指标数据将能够通过WAN连接传输到多个站点。

host #gmond将向已命名主机发送数据,这就是单播,与mcast_join相互排斥。

}

udp_recv_channel {

mcast_join = 239.2.11.71 #gmond侦听指定IP的多播组所发送的多播数据包。如果未指定多播属性,gmond将在指定端口创建单播UDP服务器。

port = 8649 #gmond接收数据的端口号。未指定的话默认是8649

bind = 239.2.11.71 #当指定该选项时,gmond将捆绑到指定的本地地址。

retry_bind = true #绑定失败后重试绑定

# buffer = 10485760 #UDP缓冲区大小,如果你正在处理大量的指标应该将它向上 10MB甚至更高。

注:还有几个参数

family (inet4|inet6) #默认版本为inet4.如果用户对一个特殊的端口进行IPV4和IPV6侦听,为此端口定义两个分离的接收通道。

mcast_if 网卡名称#gmond将侦听指定接口(例如eth0)数据

acl #通过指定接入控制列表(ACL)可以对接收通道进行精细的接入控制。

}

tcp_accept_channel {

#TCP接收通道是gmond节点创建向gmetad或其他外部轮询器汇报集群状态的通道,用户可以配置多选项。

port = 8649 #gmond接收连接的端口号。

gzip_output = no #对XML输出不进行压缩

注:另外还有几个参数

bind IP地址 #gmond将捆绑到指定的本地地址

family (inet4|inet6) #默认版本为inet4.如果用户对一个特殊的端口进行IPV4和IPV6侦听,为此端口定义两个分离的接收通道。

interface 网卡名称 #gmond将侦听指定接口(例如eth0)数据

acl #通过指定接入控制列表(ACL)可以对接收通道进行精细的接入控制。

}

modules {

#包含了加载指定模块的必要参数。指标模板是动态可加载的共享目标文件,用于扩展gmond可收集的指标。如果模块已经与gmond静态链接,它会不需要加载路径。 但是所有动态可加载模块必须包括负载路径。每个modules必须包含至少一个module subsection。

module {

name = "core_metrics"

}

module {

name = "cpu_module"

path = "modcpu.so"

}

...

属性说明:

name #模块如果由python开发,模块名与源文件名相同。如果用C/C++开发,则模块名由模块结构所决定。

language #如果未指定开发模块的源代码语言,默认为C/C++。如:language = "C/C++"

enabled #通过配置文件设置模块可用或不可用,如果enabled指令不包含在模块配置中,则默认为yes。

path #gmond预设的加载模块路径,默认在ganglia安装目录的lib64/ganglia/下。

}

collection_group {

#collection_group实体指定了gmond包含的指标及gmond收集和广播这些指标的周期。用户可以定义任意多的collection_group,每个collection_group至少包含一种metric section。

collect_once = yes #有些指标重启也是不变化的,如系统CPU数量等,只在初始启动时手机一次,设置为yes,与collect_every相互排斥。

time_threshold = 20

metric {

name = "heartbeat"

}

}

collection_group {

collect_every = 60 #收集组的轮询间隔为60秒,默认CPU,内存等指标数据收集间隔时间是60s。

time_threshold = 60 #gmond发送collection_group所指定的指标数据到所有已配置的udp_send_channels的最大时间。

metric {

name = "cpu_num" #指标收集模块定义的单个指标标准名称,可以使用gmond -m 获取可用指标名列表。

title = "CPU Count" #用于Web前端的指标名称。

#额外的属性:

value_threshold = "1.0" #每次收集到指标数据时,会将新值与上一次的数值进行比较。当二者差别大于value_threshold时,整个收集组被发送至已定义的udp_send_channels。在不同的指定模块中该值表示不同的指标单位。例如,对于CPU统计,该值代表百分比,网络统计则将该值理解为原始字节数。

}

注: 默认ganglia-web 显示的节点名称是主机名,可以通过在客户端添加/etc/hosts来自定义返回名称。

  1. 集群的分组部署

默认配置下,Ganglia会把所有东西放在一个Grid里面,也就是一个网格。大的集群,不分组。但是真实的服务器集群有各种功能,每个群分管不同的事务,全放一起就太乱了,也不好识别。所以需要分组使用。其实Ganglia的分组很简单,就是分端口,不同的组配置不同的监听端口就完事了。

  1. gmetad.conf 添加一行配置配置

[root@nagios ~]# vim /usr/local/ganglia/etc/gmetad.conf

data_source "my cluster" localhost #默认的

data_source "Portal" 192.168.109.128:8650 #新添加的端口不能与当前网络已有端口相同。

 

  1. gmond要修改集群名称和upd,tcp端口

[root@python3 ~]# vim /etc/ganglia/gmond.conf

cluster {

name = 'Portal' #对应gmetad配置文件中新添加的集群名称

owner = "unspecified"

latlong = "unspecified"

url = "unspecified"

}

udp_send_channel {

mcast_join = 239.2.11.71

port = 8650 #修改udp发送端口

ttl = 1

}

udp_recv_channel {

mcast_join = 239.2.11.71

port = 8650 #修改udp接收端口

bind = 239.2.11.71

retry_bind = true

}

tcp_accept_channel {

port = 8650 #修改gmetad连接gmond,获取信息的端口。

gzip_output = no

}

 

  1. 重启gmetad与gmond

#systemctl restart gmond

#/etc/init.d/gmetad restart

  1. 自定义metric监控

首先要确保gmond机器上已经有了"modpython.so"模块,否则gmond无法调用python。可以使用yum -y install ganglia-gmond-python 来下载modpython.so模块。

  1. 测试metric: 获取随机值

    1. 编写python脚本,用来获取随机值。

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import random

import time

def random_number_1(name): #ganglia调用此函数时会带上name实参,必须有一个行参。

return int(random.uniform(5, 50)) + 10

def random_number_2(name):

return int(random.uniform(50, 100)) + 10

def metric_init(params): #必须带有一个参数

d1 = { #特定格式

'name': 'random_number_1', #度量名称,接下来的配置文件中调用的就是这个度量名称

'call_back': random_number_1, #在收集度量数据时被调用的函数

'time_max': 90,

'value_type': 'uint', #值类型,string|uint|float|double

'units': 'C', #度量单位,%|GB|MB|KB

'slope': 'both',

'format': '%u', #必须符合value_type,否则你的度量就会未知(参考: http://docs.python.org/library/stdtypes.html#string-formatting)

'description': 'Random a number', #度量的描述,在前台网页中,在划过主机度量图形时被呈现。

'groups': 'example random' #相同分组的度量在前台网页中会被关联在一起。

}

d2 = {

'name': 'random_number_2',

'call_back': random_number_2,

'time_max': 90,

'value_type': 'uint',

'units': 'C',

'slope': 'both',

'format': '%u',

'description': 'Random a number',

'groups': 'example random'

}

descriptors = [d1,d2] #多个值使用列表返回

return descriptors

def metric_cleanup():

pass

注: Ganglia运行的时候会调用metric_init和metric_cleanup两个函数,从这两个函数的名字我们就能得知前一个是做初始化工作,后面一个是做结束资源清理工作的。在Ganglia加载相关模块来运行时,只会调用这两个函数。

  1. 添加配置文件,应用自定义的metric。

在/etc/ganglia/conf.d/中创建random_number.conf文件,并添加如下内容。

modules {

module {

name = "random_number" #需要和random_number.py名称一致

language = "python"

path = "/usr/lib64/ganglia/python_modules/random_number.py"

}

}

collection_group {

collect_every = 30

time_threshold = 30

metric {

name = "random_number_1" #这里的name值需要与random_number.py里的d1中的name一致。

title = "random 2" #title 是指标的描述信息

value_threshold = 0

}

metric {

name = "random_number_2"

title = "random 2"

value_threshold = 0

}

}

  1. 重启启动gmond 

[root@gitlab ganglia]# systemctl restart gmond.service

  1. 自定义metric,监听服务器端口

    1. 编写python脚本,监听本机端口

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import os

import re

 

def listen_port(name):

count=0

with open('/proc/net/tcp','r') as f:

for i in f:

if not i.strip().startswith('s') and int(name) == int(re.split('[: ]+',i)[3],16):

count+=1

return 1 if count > 0 else 0

 

def metric_init(params):

descriptors = []

for i in params.values():

descriptors.append({

'name': i,

'call_back': listen_port,

'time_max': 90,

'value_type': 'uint',

'units': 'units',

'slope': 'both',

'format': '%d',

'description': 'TCP_'+str(i),

'groups': 'Listen Port'

})

return descriptors

def metric_cleanup():

pass

  1. 添加配置文件,应用自定义的metric。

modules {

module {

name = "listen_port"

language = "python"

path = "/usr/lib64/ganglia/python_modules/listen_port.py"

param mysql_port {

value = 3306

}

param nginx_port {

value = 80

}

param tomcat_port {

value = 8080

}

}

}

collection_group {

collect_every = 30

time_threshold = 90

 

metric {

name = 80 #metric名称需要与value值相同。

title = "TCP_80"

value_threshold = 0

}

metric {

name = 3306

title = "TCP_3306"

value_threshold = 0

}

metric {

name = 8080

title = "TCP_8080"

value_threshold = 0

}

}

注: 主要思路就是:通过传入的参数值来生成多个函数,然后metric在调用这个函数。

  1. 重启启动gmond

[root@gitlab ganglia]# systemctl restart gmond.service

  1. Web页面查看监控值

  1. 自定义metric,监控网站的验证码

    1. 编写python脚本,获取验证码

[root@nagios python_modules]# vim captcha.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import os

import re

import copy

import urllib2

captcha_address={}

def get_captcha(name):

url=captcha_address[name]

response=urllib2.urlopen(url)

return 1 if len(response.read()) > 100 else 0 #根据验证码的长度来返回指标

def metric_init(params):

global captcha_address

captcha_address=copy.copy(params)

descriptors = []

for i in params.keys():

descriptors.append({

'name': i,

'call_back': get_captcha,

'time_max': 90,

'value_type': 'uint',

'units': 'units',

'slope': 'both',

'format': '%d',

'description': 'jinyunhui'+i,

'groups': 'captcha'

})

return descriptors

def metric_cleanup():

pass

  1. 添加配置文件,应用自定义的metric。

[root@nagios python_modules]# vim /usr/local/ganglia/etc/conf.d/verification_code.conf

modules {

module {

name = "captcha"

language = "python"

path = "/usr/local/ganglia/lib64/ganglia/python_module/captcha.py"

param frond {

value = 'http://jyh.xxx-cloud.com/api/admin/captcha.jpg'

}

param back {

value = 'http://ht.xxx-cloud.com/api/admin/captcha.jpg'

}

}

}

collection_group {

collect_every = 30

time_threshold = 90

 

metric {

name = frond

title = "frond captcha"

value_threshold = 0

}

metric {

name = back

title = "back captcha"

value_threshold = 0

}

}

注: 主要思路就是:通过传入的键值来生成多个函数,然后metric在调用这个函数。

  1. 重启启动gmond

[root@gitlab ganglia]# systemctl restart gmond.service

  1. Web页面查看监控值

  1. 使用自带的Python Metric,监控MySQL。

首先要有确保MySQL模块文件要存在,如果不存在要下载(yum -y install ganglia-gmond-python)。

[root@jenkins_test ~]# ll /lib64/ganglia/python_modules/mysql.py

-rw-r--r--. 1 root root 38472 4月 8 17:20 /lib64/ganglia/python_modules/mysql.py

  1. 添加配置文件,应用自带的metric。

[root@iZbp1bmji0bwyxg4zamhzhZ ~]# vim /etc/ganglia/conf.d/mysql.pyconf

 

modules {

module {

name = "mysql"

language = "python"

param user {

value = root #数据库用户

}

param passwd {

value = 123456 #数据库密码

}

param host {

value = localhost #连接的主机,默认

}

}

} #具体有哪些参数可以到py文件中查看。

collection_group {

collect_every = 60

time_threshold = 60

 

metric {

name = "mysql_threads_connected" #具体有那些metric,可以手动执行py文件来查看。

title = "ClientConnNum"

#value_threshold = 1.0

}

}

  1. 安装MySQLdb模块

注意:执行py文件时有可能会报缺少"MySQLdb"模块,安装上即可。

wget http://sourceforge.net/projects/mysql-python/files/mysql-python/1.2.3/MySQL-python-1.2.3.tar.gz

tar zxvf MySQL-python-1.2.3.tar.gz

cd MySQL-python-1.2.3/

python setup.py build

yum -y install python-devel

python setup.py build

python setup.py install

  1. 重启启动gmond

[root@gitlab ganglia]# systemctl restart gmond.service

  1. Web页面查看监控值

  1. 自定义metric,获取阿里云主机外网网卡流量

    1. 安装依赖包(需要Python2.7以上)

#pip2.7 install aliyun-python-sdk-cms==6.0.11

#pip2.7 install aliyun-python-sdk-core==2.8.5

 

 

  1. 编写python脚本,获取网卡流量值

#vim /usr/lib64/ganglia/python_modules/Monitor_NetworkIO.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-

from aliyunsdkcore import client

from aliyunsdkcore.profile import region_provider

from aliyunsdkcms.request.v20180308 import QueryMetricLastRequest

def NetIn(name):

clt = client.AcsClient('AccessKeyID','AccessKeySecret','cn-hangzhou')

request = QueryMetricLastRequest.QueryMetricLastRequest()

request.set_accept_format('json')

request.add_query_param('Project', 'acs_ecs_dashboard')

request.add_query_param('Period', '60')

request.add_query_param('Dimensions', '{"instanceId":"xxx"}')

request.add_query_param('Metric', 'VPC_PublicIP_InternetInRate')

response = clt.do_action(request)

return eval(eval(response.decode())['Datapoints'])[0]["Average"]

def NetOut(name):

clt = client.AcsClient('AccessKeyID','AccessKeySecret','cn-hangzhou')

request = QueryMetricLastRequest.QueryMetricLastRequest()

request.set_accept_format('json')

request.add_query_param('Project', 'acs_ecs_dashboard')

request.add_query_param('Period', '60')

request.add_query_param('Dimensions', '{"instanceId":"xxx"}')

request.add_query_param('Metric', 'VPC_PublicIP_InternetOutRate')

response = clt.do_action(request)

return eval(eval(response.decode())['Datapoints'])[0]["Average"]

def metric_init(params):

d1={

'name': 'NetIn',

'call_back': NetIn,

'time_max': 90,

'value_type': 'uint',

'units': 'units',

'slope': 'both',

'format': '%d',

'description': 'NetworkIO_NetIn',

'groups': 'NetworkIO'

}

d2={

'name': 'NetOut',

'call_back': NetOut,

'time_max': 90,

'value_type': 'uint',

'units': 'units',

'slope': 'both',

'format': '%d',

'description': 'NetworkIO_NetIn',

'groups': 'NetworkIO'

}

descriptors=[d1,d2]

return descriptors

def metric_cleanup():

pass

  1. 添加配置文件,应用自定义的metric。

modules {

module {

name = "Monitor_NetworkIO"

language = "python"

path = "/usr/lib64/ganglia/python_modules/Monitor_NetworkIO.py"

}

}

collection_group {

collect_every = 30

time_threshold = 90

metric {

name = "NetIn"

title = "NetworkIO_In"

value_threshold = 0

}

metric {

name = "NetOut"

title = "NetworkIO_Out"

value_threshold = 0

}

}

  1. 重启启动gmond

[root@gitlab ganglia]# systemctl restart gmond.service

  1. Web页面查看监控值

  1. ganglia metric默认监控项说明

监控项

说明

Load_one

每分钟的系统平均负载

Load_five

每5分钟的系统平均负载

Load_fifteen

每15分钟的系统平均负载

mem_buffers

内核缓存的内存总量

mem_cached

缓存内存大小

mem_free

空闲内存大小

mem_shared

共享内存大小

swap_free

空闲交换分区空闲大小

cpu_idle

空闲CPU百分比

cpu_system

内核空间占用CPU百分比

cpu_user

用户空间占用CPU百分比

disk_free

磁盘剩余大小

disk_total

磁盘总大小

part_max_used

所有分区使用的最大百分比

pkts_in

每秒进来的包

pkts_out

每秒出去的包

bytes_in

每秒进来字节数

bytes_out

每秒出去字节数

proc_run

运行的总进程(不准)

proc_total

总进程数(不准)

  1. 注意: ganglia-web 显示的度量单位指标

  • 1m=0.001
  • 1k=1000 #注意不是1024
  • 1M=1000000

注: 下图显示的值其实为1800000KB

  1. 配置ganglia连接nagios

  2. 复制check_ganglia.py脚本到nagios的模块目录中

[root@nagios python_modules]# cp /root/ganglia-3.7.2/contrib/check_ganglia.py /usr/local/nagios/libexec/

  1. 修改service.cfg,配置相应的ganglia的监控服务。

[root@nagios ~]# cat /usr/local/nagios/etc/objects/services.cfg

define servicegroup { #定义相应的服务组

servicegroup_name ganglia-metrics

alias Ganglia Metrics

}

 

define host { #定义监控的主机

use linux-server

host_name node4

address 192.168.18.181

}

 

define host {

use linux-server

host_name node3

address 192.168.18.227

}

 

define host {

use linux-server

host_name aliyun_test

address 47.98.117.8

}

 

define hostgroup { #定义监控组,包含监控的主机

hostgroup_name rimi-servers

members node4,node3,aliyun_test

}

define command { #定义获取ganglia监控数据的命令

command_name check_ganglia

command_line $USER1$/check_ganglia.py -h $HOSTADDRESS$ -m $ARG1$ -w $ARG2$ -c $ARG3$

} #-h 为你定义的主机IP,-m 为获取主机的metric值,-w 为警告值,-c 为临界值。

 

 

define service {

use generic-service

name ganglia-service

hostgroup_name rimi-servers

service_groups ganglia-metrics

notifications_enabled 0

}

 

define service {

use ganglia-service

service_description load_one

check_command check_ganglia!load_one!4!5

}

 

 

define service {

use ganglia-service

service_description cpu_idle

check_command check_ganglia!cpu_idle!30!15

}

 

define service {

use ganglia-service

service_description part_max_used

check_command check_ganglia!part_max_used!80!90

}

 

define service { #定义监控Nginx端口

use generic-service

host aliyun_test

service_description Nginx_Port

check_command check_ganglia!80!0.5!0

}

 

define service {

use generic-service

host aliyun_test

service_description MySQL_Port

check_command check_ganglia!3306!0.5!0

}

define service { #定义监控网卡流量

use generic-service

host aliyun_test

service_description NetIn

check_command check_ganglia!NetIn!102400!204800

}

define service {

use generic-service

host aliyun_test

service_description NetOut

check_command check_ganglia!NetOut!102400!204800

}

define service { #定义监控MySQL指标

use generic-service

host aliyun_test

service_description mysql_threads_connected

check_command check_ganglia!mysql_threads_connected!3!5

}

  1. 修改gmetad配置 

默认情况下,ganglia的gmetad服务不会监控指标给网络上的其他机器,默认只能把数据传输到localhost,所以需要做相应的配置,使其可以监控数据给其他机器。主要是考虑nagios的主机与ganglia的主机没在同一台机器上。

#vim /usr/local/ganglia/etc/gmetad.conf

trusted_hosts 192.168.18.188

  1. 修改check_ganglia.py脚本的端口号和ip地址 

因为check_ganglia.py脚本默认只会从localhost去获得ganglia中gmetad的监控数据,所以此处需要修改脚本,使其可以从集群中某一台主机获取监控指标。

#vim /usr/local/nagios/libexec/check_ganglia.py

ganglia_host = '192.168.18.188'

ganglia_port = 8651

  1. .修改check_ganglia.py脚本

监控只对大于等于设定值的情况可以进行报警提示,没有对等于小于的情况做报警提示(可以根据自己应用场景考虑是否修改脚本)

[root@nagios python_modules]# tail -20 /usr/local/nagios/libexec/check_ganglia.py

if critical > warning:

if value >= critical:

print "CHECKGANGLIA CRITICAL: %s is %.2f" % (metric, value)

sys.exit(2)

elif value >= warning:

print "CHECKGANGLIA WARNING: %s is %.2f" % (metric, value)

sys.exit(1)

else:

print "CHECKGANGLIA OK: %s is %.2f" % (metric, value)

sys.exit(0)

else:

if critical >= value:

print "CHECKGANGLIA CRITICAL: %s is %.2f" % (metric, value)

sys.exit(2)

elif warning >= value:

print "CHECKGANGLIA WARNING: %s is %.2f" % (metric, value)

sys.exit(1)

else:

print "CHECKGANGLIA OK: %s is %.2f" % (metric, value)

sys.exit(0)

#主要是通过critical和warning来比对。critical大于warning则比较的是大于,否则比较的是小于。

  1. 重启nagios,Web页面查看。

  1. 配置gmond为单播模式(可选)

  2. 接收者

要配置成为单播你应该指定一个(或者多个)接受的主机,比如我将要挑选本机主机(192.168.18.213)作为接收者,本地主机的gmond.conf应该看起来像这样。

[root@nagios ~]# vim /usr/local/ganglia/etc/gmond.conf

udp_send_channel {

host = 192.168.18.213

port = 8649

ttl = 1

} #发送数据到本机

udp_recv_channel {

port = 8649

retry_bind = true

bind = 192.168.18.213

}#接收本机8649端口的数据

  1. 发送者

在其他的所有主机上,你只需要配置这个:

[root@gitlab ~]# vim /etc/ganglia/gmond.conf

globals {

daemonize = yes

setuid = yes

user = ganglia

debug_level = 0

max_udp_msg_len = 1472

mute = no

deaf = yes #修改为不接收数据

allow_extra_data = yes

host_dmax = 86400 /*secs. Expires (removes from web interface) hosts in 1 day */

host_tmax = 20 /*secs */

cleanup_threshold = 300 /*secs */

gexec = no

send_metadata_interval = 30 /*secs */ #定期的发送元数据。

}

udp_send_channel {

host = 192.168.18.213

port = 8649

ttl = 1

}

请注意send_metadata_interval被设置为30秒。Ganglia的度量指标从他的元数据间隔发送得到的。元数据包含诸如度量分组,类型等等。假如你重启了接收的gmond主机,那么元数据就会丢失,gmond就不知道如何处理度量数据,因此会把他们抛弃。这会导致生成空白的图表。在组播模式下,gmonds可以和其他任意一台主机通信,在元数据丢失情况请求重新获取。但这在单播模式下是不可能的,因此你需要命令gmond定期的发送元数据。

  1. 重启所有

包括gmetad,接收端与发送端的gmond。

  1. 配置层级gmetad

  2. 子节点配置

首先安装好gmetad和httpd(可选)

[root@ganglia_test ganglia]# vim /usr/local/ganglia/etc/gmetad.conf

gridname "AliyunGanglia" #这里要设置成其他的名称,多个gmetad之间名称不能相同

authority http://47.98.197.7/ganglia/ #修改选择Grid时,跳转的url。默认是主机名

trusted_hosts 127.0.0.1 61.130.182.122 #让61.130.182.122拥有对8651端口的xml的访问权限

  1. 父节点配置

[root@nagios ganglia-3.7.2]# vim /usr/local/ganglia/etc/gmetad.conf

data_source "aliyunClient" 47.98.197.7:8651 #添加监听子节点

  1. 重启所有

重启所有节点的gmetad和httpd

  1. Web页面查看

 

注:当选择Grid后成功跳转到对应的页面

  1. 只保留其他gmetad节点内的节点数据

注: 如果你想的是从其他gmetad节点,将其内部的节点数据都收集过来进行汇总。

  1. 修改父节点配置

[root@nagios ganglia-3.7.2]# vim /usr/local/ganglia/etc/gmetad.conf

scalable off #将注释去掉重启gmetad服务

  1. 查看页面效果

上一篇:Nagios安装-钉钉报警


下一篇:C和指针笔记-第1、2章 基本概念