Почему появилась эта статья
В мире администрирования linux есть два замечательных проекта, OpenVZ и Zabbix.
OpenVZ — система виртуализации на уровне операционной системы для ОС linux, благодаря низкому потреблению ресурсов и другим плюшкам обрела огромную популярность.
Zabbix — система мониторинга «всего», стремительно вытесняет постаревший и обросший надстройками nagios с пьедестала почета.
Тем не менее, на просторах интернета не нашлось ни одного решения что бы нормально их подружить, а именно:
1) Один агент на физический сервер.
2) Мониторинг и UBC и дискового пространства всех VE.
3) Гибкость решения.
И так, основные проблемы:
1) UBC массив текста, который нужно парсить.
Решается как не странно парсером.
2) Количество виртуальных систем на физической машине динамически меняется, поэтому очень сложно привязать к чему-то данные.
Решается отсылкой в теле уведомления vzid виртуальной системы и hostname физической.
3) Zabbix_agent будет бесполезен, если потребуется снять данные другой системой мониторинга.
Решается использованием SNMP.
Конфиги и комментарии к ним:
Настройка сервера snmpd на сервере OpenVZ:
В конфигурационный файл snmp (как правило — /etc/snmp/snmpd.conf) необходимо добавить строки:
## разрешаем доступ к оидам UBC и VZQUOTA
view systemview included .1.3.6.1.4.1.2021.51
view systemview included .1.3.6.1.4.1.2021.52
## привязываем команды
extend .1.3.6.1.4.1.2021.51 beancounters /bin/cat /proc/user_beancounters
extend .1.3.6.1.4.1.2021.52 vzquota /bin/cat /proc/vz/vzquotaНастройка системы Zabbix:
Скрипт для обработки значений, его нужно поместить в /etc/zabbix/externalscripts/check_ubc_vzquota.sh и не забыть про права на выполнение:
#!/bin/bash
HOST=$1
COMMUNITY=$2
export FILE=/tmp/$HOST.beancounters
RET=0
RET1=0
RET2=0
if [ $# == 0 ]; then
echo "Usage: $0 hostname community_string"
exit 1
fi
DATA_TMP=`snmpwalk -v 2c -c $COMMUNITY $HOST .1.3.6.1.4.1.2021.51.4`
if [ "$?" != "0" ]; then
echo "Unknown snmp error"
exit 1
fi
DATA=`echo "$DATA_TMP"| perl -ne '/"(.*)"/ ; print "$1\n" ;'`
if [ -f $FILE ]; then
echo "$DATA" | perl -n -e'
use Data::Dumper;
my $file=$ENV{"FILE"};
my $ret=0 ;
my $vid ;
my $resource ;
my $held ;
my $maxheld ;
my $barrier ;
my $limit ;
my $failcnt ;
my %beancounters ;
my %beancounters_old ;
while(<STDIN>){
my %vmachine;
if ( /\D*(\d+):.*/ ){ $vid=$1; $beancounters{$vid}=\%vmachine ; }
if ( /^[\W\d]+([a-z]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+).*/ ) {
$resource=$1 ;
$held=$2 ;
$maxheld=$3 ;
$barrier=$4 ;
$limit=$5 ;
$failcnt=$6 ;
${beancounters{$vid}}{$resource}=[$held , $maxheld , $barrier , $limit ,$failcnt ];
if ( ($held > $barrier) && ($barrier != 0) ) {
print "WARNING: Limits on $vid: $resource held->$held , barrier->$barrier ( limit->$limit ) " ;
$ret=1;
}
}
}
# read and parse old data
open(MYINPUTFILE, "<$file");
while(<MYINPUTFILE>){
my %vmachine;
if ( /\D*(\d+):.*/ ){ $vid=$1; $beancounters_old{$vid}=\%vmachine ; }
if ( /^[\W\d]+([a-z]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+).*/ ) {
$resource=$1 ;
$held=$2 ;
$maxheld=$3 ;
$barrier=$4 ;
$limit=$5 ;
$failcnt=$6 ;
${beancounters_old{$vid}}{$resource}=[$held , $maxheld , $barrier , $limit ,$failcnt ];
}
}
foreach my $vmachine_id (keys %beancounters) {
foreach my $resource (keys %{$beancounters{$vmachine_id}} ) {
if ( defined($beancounters{$vmachine_id}{$resource}[4]) && defined($beancounters_old{$vmachine_id}{$resource}[4]) ){
my $failcnt=$beancounters{$vmachine_id}{$resource}[4];
my $failcnt_old=$beancounters_old{$vmachine_id}{$resource}[4];
my $held=$beancounters{$vmachine_id}{$resource}[0];
my $maxheld=$beancounters{$vmachine_id}{$resource}[1];
my $barrier=$beancounters{$vmachine_id}{$resource}[2];
my $limit=$beancounters{$vmachine_id}{$resource}[3];
if ( $failcnt_old < $failcnt ){
print "CRITICAL: Incrased failcnt $vmachine_id: $resource from $failcnt_old to $failcnt (held->$held , maxheld->$maxheld , barrier->$barrier , limit->$limit ) " ;
$ret=2;
}
}
}
}
# if ($ret == 0 ) { print "Ok. \n" ; }
# print Dumper(%beancounters_old) ;
# print "\n";
exit($ret);
'
RET1=$?
fi
echo "$DATA" > $FILE
#####################################################################################
######### quota check
#####################################################################################
DATA=`snmpwalk -v 2c -c $COMMUNITY $HOST .1.3.6.1.4.1.2021.52.4 \
| perl -ne '/"(.*)"/ ; print "$1\n" ;'`
if [ "$?" != "0" ]; then
echo "Unknown snmp error"
exit 1
fi
echo "$DATA" | perl -n -e'
my $vid ;
my $ret=0 ;
while(<STDIN>){
my %vid;
if ( /\D*(\d+):.*/ ){ $vid=$1; }
if ( /\s*(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+).*/ ){
$resource=$1 ;
$usage=$2 ;
$softlimit=$3 ;
$hardlimit=$4 ;
$time=$5 ;
$expire=$6 ;
if ( $usage >= $softlimit ){
print "WARNING: VZquota limit exceeded on $vid: $resource usage->$usage, softlimit->$softlimit, hardlimit->$hardlimit, time->$time, expire->$expire " ;
$ret=1;
}
}
}
exit($ret);
'
RET2=$?
#####################################################################################
########### return
#####################################################################################
if [ $RET1 -gt $RET2 ]; then
RET=$RET1
else
RET=$RET2
fi
if [ $RET = 0 ]; then
echo Ok.
fi
exit $RET
* This source code was highlighted with Source Code Highlighter.
Шаблон для item и trigger в Zabbix (если у вас используется другой community string, необходимо поменять его в теле шаблона в двух местах, в нем прописан public).
<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export version="1.0" date="05.01.11" time="07.22">
<hosts>
<host name="snmp_ubc_vzquota">
<proxy_hostid>0</proxy_hostid>
<useip>1</useip>
<dns></dns>
<ip>127.0.0.1</ip>
<port>10050</port>
<status>3</status>
<useipmi>0</useipmi>
<ipmi_ip>127.0.0.1</ipmi_ip>
<ipmi_port>623</ipmi_port>
<ipmi_authtype>0</ipmi_authtype>
<ipmi_privilege>2</ipmi_privilege>
<ipmi_username></ipmi_username>
<ipmi_password></ipmi_password>
<groups>
<group>Templates custom</group>
</groups>
<triggers>
<trigger>
<description>UBC and VZQUOTA trigger</description>
<type>0</type>
<expression>{snmp_ubc_vzquota:check_ubc_vzquota.sh[public].str(Ok.)}=0</expression>
<url></url>
<status>0</status>
<priority>5</priority>
<comments></comments>
</trigger>
</triggers>
<items>
<item type="10" key="check_ubc_vzquota.sh[public]" value_type="4">
<description>UBC and VZQUOTA check1</description>
<ipmi_sensor></ipmi_sensor>
<delay>30</delay>
<history>90</history>
<trends>365</trends>
<status>0</status>
<data_type>0</data_type>
<units></units>
<multiplier>0</multiplier>
<delta>0</delta>
<formula>0</formula>
<lastlogsize>0</lastlogsize>
<logtimefmt></logtimefmt>
<delay_flex></delay_flex>
<authtype>0</authtype>
<username></username>
<password></password>
<publickey></publickey>
<privatekey></privatekey>
<params></params>
<trapper_hosts>localhost</trapper_hosts>
<snmp_community></snmp_community>
<snmp_oid></snmp_oid>
<snmp_port>161</snmp_port>
<snmpv3_securityname></snmpv3_securityname>
<snmpv3_securitylevel>0</snmpv3_securitylevel>
<snmpv3_authpassphrase></snmpv3_authpassphrase>
<snmpv3_privpassphrase></snmpv3_privpassphrase>
<applications/>
</item>
</items>
<templates/>
<graphs>
</graphs>
<macros/>
</host>
</hosts>
<dependencies/>
</zabbix_export>
* This source code was highlighted with Source Code Highlighter.
Уведомления:

Привязываем шаблон к серверу и можно создавать VE для тестов!