[Из песочницы] Мониторинг для бедных или SAR + MySQL + Gnuplot
Почему именно SAR? Я уже довольно давно занимаюсь мониторингом. Поэтому по роду своей деятельности частенько сталкиваюсь с нестандартными ситуациями, когда приходится придумывать различные «велосипеды», для того, чтобы мониторить хост. Например, мы будем рассматривать ситуацию, когда у нас есть сервер (виртуалки или VDS), который очень ограничен в ресурсах.Существует множество хороших систем мониторинга, таких как Zabbix, Nagios, Cacti и т.д. Но для нашей ситуации все они не подходят, в силу ясных причин — они сами потребляют ресурсы, которых у нас итак не очень много. Сразу возникает вопрос, как быть? И тут к нам на помощь спешит SAR.
Установка и настройка SAR SAR (System Activity Report) — это очень мощная утилита, для сбора статистической информации о производительности системы. Входит в пакет sysstat. Поэтому, если у вас на сервере еще нет пакета sysstat, устанавливаем его. Например, для Debian: # apt-get install sysstat Затем нам потребуется настроить сам SAR. Включаем sysstat, для этого правим файл: # vim /etc/default/sysstat И меняем строку ENABLED=«false» на ENABLED=«true». После чего нам нужно поправить задание в cron. # vim /etc/cron.d/sysstat Я собираю данные каждую минуту, поэтому в моей системе это выглядит так (у вас может быть немного иначе): # Activity reports every 1 minutes everyday * * * * * root command -v debian-sa1 > /dev/null && debian-sa1 1 1
# Additional run at 23:59 to rotate the statistics file 59 23 * * * root command -v debian-sa1 > /dev/null && debian-sa1 60 2 Перезапускаем сервис sysstat: # service sysstat restart На этом настройка окончена.Использование SAR Я не буду подробно описывать, как использовать SAR. Для этого существует множество статей в интернете, да и сам SAR предоставляет довольно обширную документацию. Все что вам нужно, это man sar, а там, думаю, разберетесь.Учим SAR заливать репорты в MySQL Да-да, вы все правильно прочитали. Конечно, мы можем использовать SAR по своему прямому назначению, вызывать его из консоли и получать репорты в таком виде: $ sar -s 07:00:00 -e 07:10:00 Linux 3.2.0–4-amd64 (mind-x) 02.03.2015 _x86_64_ (1 CPU)
07:00:01 CPU %user %nice %system %iowait %steal %idle 07:01:01 all 0,64 0,00 0,15 0,10 0,00 99,11 07:02:01 all 0,03 0,00 0,02 0,00 0,00 99,95 07:03:01 all 0,03 0,00 0,02 0,00 0,00 99,95 07:04:01 all 0,03 0,00 0,02 0,02 0,00 99,93 07:05:01 all 0,05 0,00 0,03 0,00 0,00 99,92 07:06:01 all 0,63 0,00 0,17 0,10 0,00 99,11 07:07:01 all 0,03 0,00 0,02 0,00 0,00 99,95 07:08:01 all 0,02 0,00 0,02 0,00 0,00 99,97 07:09:01 all 0,03 0,00 0,02 0,00 0,00 99,95 Среднее: all 0,17 0,00 0,05 0,02 0,00 99,76 Но согласитесь, смотреть в эти цифры после долгого рабочего дня совсем не хочется, глаза болят и т.д. Что же делать? Как работать со столь важной информацией? Признаюсь, я целый вечер думал над этой проблемой. Все решения мне казались странными. Возможно, решение, которое я придумал, тоже является странным, но почему я захотел подружить SAR с MySQL? Постараюсь объяснить далее.
Если вы внимательно читали часть про настройку SAR, то вы, наверно, заметили, что SAR ротирует свои журналы после полуночи. Сделано это специально, чтобы разбивать журналы по дням. Мне захотелось получать данные непрерывно (ведь далее мы будем строить по ним графики), чтобы я мог выбрать только нужный мне столбец, за определенное время и т.д. И тут я задумался, а почему не заливать все эти репорты в базу данных? Так как на сервере уже был MySQL, то выбор стал очевиден.
Итак, дружим SAR и MySQL Я перерыл весь интернет по этому поводу, но никакой информации практически нет, только пару статей, результатом прочтения которых стал скрипт. Но прежде чем мы его разберем, давайте подготовим базу.Создаем базу данных sysstat:
CREATE DATABASE `sysstat`; Создаем пользователя sysstat (вы можете дать этому пользователю любые другие права). CREATE USER 'sysstat'@'localhost' IDENTIFIED BY 'some_pass'; GRANT ALL PRIVILEGES ON sysstat.* TO 'sysstat'@'localhost'; Создаем таблицы, у меня это выглядит примерно так: CREATE TABLE `host_health_cpu` ( `datetime` datetime NOT NULL DEFAULT '0000–00–00 00:00:00', `pct_user` decimal (10,2) DEFAULT NULL, `pct_nice` decimal (10,2) DEFAULT NULL, `pct_system` decimal (10,2) DEFAULT NULL, `pct_iowait` decimal (10,2) DEFAULT NULL, `pct_steal` decimal (10,2) DEFAULT NULL, `pct_idle` decimal (10,2) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `host_health_memory` ( `datetime` datetime NOT NULL DEFAULT '0000–00–00 00:00:00', `kbmemfree` int (11) DEFAULT NULL, `kbmemused` int (11) DEFAULT NULL, `per_memused` decimal (10,2) DEFAULT NULL, `kbbuffers` int (11) DEFAULT NULL, `kbcached` int (11) DEFAULT NULL, `kbcommit` int (11) DEFAULT NULL, `per_commit` decimal (10,2) DEFAULT NULL, `kbactive` int (11) DEFAULT NULL, `kbinact` int (11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `host_health_la` ( `datetime` datetime NOT NULL DEFAULT '0000–00–00 00:00:00', `runq_sz` int (11) DEFAULT NULL, `plist_sz` int (11) DEFAULT NULL, `ldavg_1` decimal (10,2) DEFAULT NULL, `ldavg_5` decimal (10,2) DEFAULT NULL, `ldavg_15` decimal (10,2) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `host_health_net` ( `datetime` datetime NOT NULL DEFAULT '0000–00–00 00:00:00', `iface` varchar (7) DEFAULT NULL, `rxpck_persec` decimal (10,2) DEFAULT NULL, `txpck_persec` decimal (10,2) DEFAULT NULL, `rxbyt_persec` decimal (10,2) DEFAULT NULL, `txbyt_persec` decimal (10,2) DEFAULT NULL, `rxcmp_persec` decimal (10,2) DEFAULT NULL, `txcmp_persec` decimal (10,2) DEFAULT NULL, `rxcst_persec` decimal (10,2) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; Все, теперь у нас все готово, для того, чтобы заливать репорты в MySQL.Разбираем скрипт В скрипте мы будем использовать утилиту sadf, которая может отображать данные, собранные SAR, в различных форматах, например, в CSV, JSON, XML. Нам понадобится CSV. Сам скрипт не очень большой и не сложный для понимания, дополню лишь то, что я удаляю первые 2 столбца из вывода sadf, в них содержится информация о хосте и интервале между снятиями данных. Хост в нашем случае один, а интервал я и так знаю, поэтому эта информация мне не нужна. #!/bin/bash #Инициализируем переменные WORKDIR=/var/cache/sar FMATDIR=/var/cache/sar_data SADF=`which sadf` HEAD=`which head` AWK=`which awk` #Копируем последний журнал в рабочую директорию cd ${WORKDIR} COPY=`which cp` SAR_LOG=/var/log/sysstat cd ${SAR_LOG} LATEST_DATA=`ls -tlr ${SAR_LOG} | tail -1 | awk '{print $9}'` ${COPY} ${LATEST_DATA} ${WORKDIR}
for file in *; do #Выбираем репорты за последние 6 минут. Для этого создаем переменную $TIME UNIXTIME=$((`date +%s`-300)) TIME=`date -d@${UNIXTIME} +%H:%M:%S` #Статистика по CPU ${SADF} -d ${file} -s ${TIME} -t | cut -d ';' -f3,5- > »${FMATDIR}»/»${file}»-host_health_cpu.csv #Сетевая статистика ${SADF} -d ${file} -s ${TIME} -t — -n DEV | cut -d ';' -f3- > »${FMATDIR}»/»${file}»-host_health_net.csv #Размеры очередей и LA ${SADF} -d ${file} -s ${TIME} -t — -q | cut -d ';' -f3- > »${FMATDIR}»/»${file}»-host_health_la.csv #Статистика по использованию памяти ${SADF} -d ${file} -s ${TIME} -t — -r | cut -d ';' -f3- > »${FMATDIR}»/»${file}»-host_health_memory.csv done #Заливаем данные в MySQL cd ${FMATDIR} MYSQL=`which mysql` USER='user' PASS='some_pass' HOST='localhost' DB='sysstat' for file in *.csv; do ${MYSQL} -u${USER} -p${PASS} -h${HOST} -D${DB} -e «LOAD DATA LOCAL INFILE '${FMATDIR}/${file}' INTO TABLE `echo ${file} | sed 's/.csv//g' | awk -F'-' '{print $2}'` FIELDS TERMINATED BY ';' IGNORE 1 LINES;» done #Удаляем временные файлы rm -fr ${FMATDIR}/*.csv rm -fr ${WORKDIR}/sa* В общем, такой вот скрипт. Для того, чтобы заливка началась, добавляем его в cron. Вызывать будем раз в 5 минут. */5 * * * * bash /usr/local/sbin/sar.sh Интересной особенностью SAR является то, что когда мы вызываем его как sar -s, указывая время начала, то само это время не входит в репорт, поэтому вызывая в скрипте sar за последние 6 минут, в выводе мы получаем репорт за 5 минут. Это обязательно надо учитывать. Иначе будут «дырки» или дубли в MySQL.В результате у вас получится примерно следующее:
mysql> SELECT * FROM host_health_memory WHERE datetime > NOW () — INTERVAL 10 MINUTE; ±--------------------±----------±----------±------------±----------±---------±---------±-----------±---------±--------+ | datetime | kbmemfree | kbmemused | per_memused | kbbuffers | kbcached | kbcommit | per_commit | kbactive | kbinact | ±--------------------±----------±----------±------------±----------±---------±---------±-----------±---------±--------+ | 2015–03–02 08:36:01×1381896 | 679396×32.00×104044 | 155520×803420 | 38.00×484244 | 142688 | | 2015–03–02 08:37:01×1377476 | 683816×33.00×104068 | 155668×810284 | 39.00×487632 | 142808 | | 2015–03–02 08:38:01×1377476 | 683816×33.00×104096 | 155672×810284 | 39.00×487668 | 142804 | | 2015–03–02 08:39:01×1377476 | 683816×33.00×104120 | 155680×810524 | 39.00×487832 | 142804 | | 2015–03–02 08:40:01×1372416 | 688876×33.00×104160 | 155684×819104 | 39.00×490708 | 142816 | | 2015–03–02 08:41:01×1377104 | 684188×33.00×104276 | 155700×810524 | 39.00×488008 | 142808 | | 2015–03–02 08:42:01×1379228 | 682064×33.00×104288 | 155708×816640 | 39.00×486392 | 142632 | | 2015–03–02 08:43:01×1378980 | 682312×33.00×104328 | 155708×816744 | 39.00×486680 | 142628 | | 2015–03–02 08:44:01×1378608 | 682684×33.00×104356 | 155716×816932 | 39.00×486936 | 142636 | | 2015–03–02 08:45:01×1371564 | 689728×33.00×104392 | 155720×827704 | 40.00×491912 | 142648 | ±--------------------±----------±----------±------------±----------±---------±---------±-----------±---------±--------+ Что делать с этими данными? Вы можете делать с ними все, что угодно. Я чуть выше писал, что на основе этих данных мы будем рисовать графики. Сделать это можно любым доступным способом. Здесь все зависит лишь от вашей фантазии.Gnuplot Мой выбор выпал на Gnuplot. Это довольно удобный инструмент для построения графиков, диаграмм и т.д. По Gnuplot есть огромная документация на его родном сайте, поэтому часть про его возможности и как его использовать мы пропустим.Я написал вот такой скрипт:
#!/bin/bash sleep 10 # Параметры по умолчанию width=»640» high=»480» outfile=«graph.svg» format=«svg»
NO_ARGS=0 E_OPTERROR=65
if [ $# -eq »$NO_ARGS» ] # Сценарий вызван без аргументов? then echo «Скрипт запущен без параметров! Для правильной работы используйте параметры: -o Указывает имя файла графика (по умолчанию \«graph.svg\») -f Указывает формат файла графика (по умолчанию \«svg\») -w Ширина файла (по умолчанию \»640\») -h Высота файла (по умолчанию \»480\») -t Тип графика Повторите вашу попытку.» exit $E_OPTERROR fi #Выбираем необходимые параметры while getopts »: h: w: t: f: o:» Option do case $Option in h) high=»$OPTARG»;; w) width=»$OPTARG»;; f) format=»$OPTARG»;; o) outfile=»$OPTARG»;; t) type=»$OPTARG»;; esac done shift $(($OPTIND — 1))
#Записываем результат во временный файл /tmp/datatmp if [ ${type} == 'cpu' ] then #Создаем заголовок графика title=«Распределение нагрузки на CPU, %» QUERY=«select time (datetime), pct_idle as idle, pct_iowait as iowait, pct_system as system, pct_user as user from host_health_cpu where now () — interval 1 hour < datetime;" format_y='set format y "%.0f%%";' elif [ ${type} == 'mem' ] then title="Использование памяти, B" QUERY="select time(datetime),(kbmemfree * 1024) as Free,(kbmemused * 1024) as Used,(kbbuffers * 1024) as Buffers,(kbcached * 1024) as Cached from host_health_memory where now() - interval 1 hour < datetime;" format_y="set format y '%.1s%cB'" elif [ ${type} == "net" ] then title="Входящий и исходящий трафик, B/s" QUERY='select time(datetime), (rxbyt_persec * 1024) as Rx, (txbyt_persec * 1024) as Tx from host_health_net where now() - interval 1 hour < datetime and iface="eth0";' format_y="set format y '%.1s%cB/s'" elif [ ${type} == "la" ] then title="Load Average" QUERY="select time(datetime),ldavg_1 as LoadAvg1, ldavg_5 LoadAvg5,ldavg_15 as LoadAvg15 from host_health_la where now() - interval 1 hour < datetime;" format_y="set format y '%.2f'" fi
#Делаем выборку из базы и сохраняем во временный файл MYSQL=`which mysql` USER=«user» PASS=«some_pass» DB=«sysstat» ${MYSQL} -u${USER} -p${PASS} -D${DB} -B -r -e »${QUERY}» >> /tmp/datatmp_${type}
#Подсчитываем количество столбцов в файле. cols=`awk '{print NF}' /tmp/datatmp_${type} | sort -nu | tail -n 1` #Определяем временные промежутки hour_ago=`${MYSQL} -u${USER} -p${PASS} -D${DB} -N -e «select time (datetime) from host_health_cpu where now () — interval 1 hour < datetime limit 1;"` now=`${MYSQL} -u${USER} -p${PASS} -D${DB} -N -e "select time(datetime) from host_health_cpu where now() - interval 1 hour < datetime order by datetime desc limit 1;"`
#Рисуем график gnuplot << EOP #Указываем формат файла и его размер set terminal ${format} size ${width},${high}
#Указываем выходной файл set output ${outfile}
#Рисуем легенды set key autotitle columnhead set key outside center bottom set key horizontal #Рисуем заголовок set style fill transparent solid 0.5 noborder set title »${title}»
#Делаем ось Х в формате отображения дат set xdata time set timefmt »%H:%M:%S» set xrange [»${hour_ago}»:»${now}»] set xtics format »%H:%M»
#Указываем имена осей set xlabel «Время» set ylabel »${title}» set grid set yrange [0:*] ${format_y} #Получаем конечный результат. plot for [i=2:${cols}] »/tmp/datatmp_${type}» using 1: i smooth unique with filledcurve x1
EOP #Удаляем временный файл. rm /tmp/datatmp_${type} echo «Image write to \»${outfile}\» exit 0; Запускаем его примерно так: $ sar-plot.sh -t mem -o /path/to/memory.svg В результате получается вот такой график за 1 час.Если добавить этот скрипт в cron и вызывать его, например, раз в 5 минут, то у нас всегда будут свежие графики. Например у меня сделано вот так: */5 * * * * bash /usr/local/sbin/sar-plot.sh -t cpu -o /path/to/images/cpu.svg */5 * * * * bash /usr/local/sbin/sar-plot.sh -t mem -o /path/to/images/memory.svg */5 * * * * bash /usr/local/sbin/sar-plot.sh -t net -o /path/to/images/network.svg */5 * * * * bash /usr/local/sbin/sar-plot.sh -t la -o /path/to/images/la.svg Далее эти изображения можно добавить на HTML-страницу, сделать чтобы она автоматически обновлялась. Таким образом мы можем мониторить производительность хоста практически в реальном времени (с задержкой 5 минут). Чего для нас в принципе достаточно.Заключение SAR — очень удобный инструмент, незаменимый в работе системного администратора. Описанный мной способ мониторинга хорошо подходит для тех, кто очень ограничен в ресурсах, не хочет поднимать на сервере Zabbix или по различным другим причинам.Вы можете развить это решение под себя: Добавить другие метрики, которые не описаны в статье, например, можно добавить статистику по активности дисковой подсистемы. Вы можете рисовать графики любым другим способом, например, с использованием Javascript-библиотек. Вы можете доработать систему так, чтобы при достижении каких-нибудь критических значений, на вашей веб-странице отображались алерты, и, например, отправлялись сообщения себе на почту. Все зависит от вашего желания. Удачи!