Nginx, HAProxy, Varnish: мониторинг в New Relic

Date October 15th, 2013 Author Vitaly Agapov

Простейшие движения ума, к которым прибегал этот человек, чтобы заслониться от безнадежности человеческой судьбы, поражали своей абсурдной эффективностью.

Виктор Пелевин «Бэтман Аполло»

nr-hnv

Не так давно я писал статью по увязыванию в единое целое Nginx, Varnish и HAProxy и хотел рассмотреть также вопрос с мониторингом всего этого добра. Но пришла мне в голову идея расписать не общие возможности по мониторингу, а способы мониторить и собирать статистику по этим приложениям в довольно известном SaaS-сервисе под названием New Relic. New Relic умеет работать с помощью своих агентов практически в любых приложениях (Java, Ruby, PHP и ещё многих разных словах). Но главная вкусность таится в большом количестве отдельных плагинов для мониторинга практически чего угодно – от нашей тройки героев до Hadoop и RabbitMQ.

Nginx

Для Nginx у New Relic есть целых два плагина: официальный от Сысоевской команды Nginx, Inc и неофициальный от MeetMe, Inc. Со вторым баловаться не будем, а вот первый запустим. Крутить плагин можно на любом сервере, с которого есть HTTP-доступ на все Nginx'ы, которые мы хотим мониторить. Вариант для Ubuntu:

1.apt-get install ruby1.9.3 ruby-bundler rubygems
3.tar -xzvf newrelic_nginx_agent.tar.gz
4.cd newrelic_nginx_agent
5.bundle install

Чтобы плагин мог собирать информацию с сервера Nginx, надо создать примерно такой виртуал-хост:

01.server {
02.    listen *:8899;
03. 
04.    location / {
05.        stub_status on;
06.        access_log off;
07.        allow 10.0.0.0/8;
08.        deny all;
09.    }
10.}

Само собой nginx должен быть собран с опцией –with-http_stub_status_module.

Дальше переходим к конфигурированию (допустим, файлы плагин мы установили в /root/newrelic/nginx). В конфиге config/newrelic_plugin.yml надо вставить свой ключ от NR-аккаунта и вписать свои Nginx'ы в виде:

1.agents:
2.  nginx_status_agent:
3.    -
4.      instance_name: Nginx1
5.      status_url: http://url1:8899/
6.    -
7.      instance_name: Nginx2
8.      status_url: http://url2:8899/

При необходимости можно добавить авторизацию.

Запускать плагин на этом этапе можно скриптом newrelic_nginx_agent.daemon, но при этом пропадают логи, которые плагин умеет слать исключительно в stdout. Поэтому в начале для отладки можно пользоваться вариантом:
nohup ./newrelic_nginx_agent &

Логи при этом будут сыпаться в nohup.out

Varnish

Для Varnish у New Relic тоже есть два плагина: от Varnish Software (написанные на Ruby) и от разработчика 3legs (написанный на Java). Разбираться в тонкостях каждого из них у меня не было времени, поэтому я выбрал вариант от 3legs. Главным стимулом тут было то, что написан он на Java, при том, что запускать его в идеале надо на сервере с самим Varnish'ем (нужен доступ к varnishstat), на котором Ruby у меня нет и ставить не хочется.

В общем качаем newrelic_3legs_plugin-0.0.2, распаковываем. Внутри архива лежат конфиги и jar-ник. Конфиги тут более приличные, в logging.properties, например, можно задать уровень логирования (ставим в FINE на первое время) и файл для записи этих логов (если стандартный вывод нам не подходит). В newrelic.properties – пишем ключ от аккаунта NR. В application.conf пишем имя приложения (если плагин крутится на отдельном сервере, то параметров надо будет подкинуть).

1.varnish = [
2.        {
3.                name = Curacao.Varnish
4.        }
5.]

А в activation.conf оставить:

1.{
2.    cassandra = false
3.    varnish = true
4.}

На данном этапе плагин можно сразу же запустить и посмотреть, как он работает. Делать это можно, например, через nohup:

nohup java -jar newrelic_3legs_plugin-0.0.2.jar &

HAProxy

Продолжаем забег. Для HAProxy есть только один плагин от конторы Railsware LLC. Он написан на Ruby, и вот его проект на гитхабе: https://github.com/railsware/newrelic_platform_plugins/tree/master/newrelic_haproxy_agent

На гитхабе всё и написано:

1.sudo gem install newrelic_haproxy_agent
2.sudo newrelic_haproxy_agent install

Правим конфиг /etc/newrelic/newrelic_haproxy_agent.yml.Вписываем ключ, ставим для начала verbose: 1 (лог выплёвывать он опять умеет только в stdout) и настраиваем агенты:

01.agents:
02.  HAproxy1:
03.    uri: http://url1:1936/;csv
04.    proxy: web
05.    proxy_type: BACKEND
06.  HAproxy2:
07.    uri: http://url2:1936/;csv
08.    proxy: app
09.    proxy_type: BACKEND

Для запуска используем команду: newrelic_haproxy_agent run

А если хотим почитать логи, то можно воспользоваться nohup:

nohup newrelic_haproxy_agent run &

Чтобы на нужном порту HAProxy отдавал статистику, нужно в его конфиге вставить соответствующие директивы:

1.listen stats
2.        bind *:1936
3.        stats enable
4.        stats uri       /
5.        stats refresh   15s
6.        stats realm Haproxy\ Statistics

Init-скрипты и автозапуск

Если оставить всё как есть, то через какое-то время (дни, а то и недели) метрики у плагина для Varnish перестают посылаться, а в лог валятся ошибки:

[2013-10-01 00:46:21 -0400] com.newrelic.metrics.publish.Runner$PollAgentsRunnable | FINE | Harvest and report data
java.io.IOException: Cannot run program "varnishstat": java.io.IOException: error=24, Too many open files

lsof -n -p <pid> показывает, что процесс наоткрывал тучу файлов, из которых большинство примерно такие:

java      31849        root   19w     FIFO                0,8        0t0 1727914522 pipe

То есть открыты FIFO пайпы, у всех известны файловые дескрипторы и inode. А это значит, что jar-ник не закрывает свои открываемые потоки. В общем, плагин скорее всего представляет из себя быдлокод.

Workaround такой. Сделаем init.d скрипт и cron-задачу, которая будет, скажем, раз в день плагин перезагружать.

Для начала приведём в порядок logging.properties: уберём там java.util.logging.ConsoleHandler и раскомментируем FileHandler:

1.java.util.logging.FileHandler.level = FINE
2.    java.util.logging.FileHandler.pattern = newrelic.log
3.    java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
4.    java.util.logging.FileHandler.append = true

Создадим скрипт /etc/init.d/newrelic-varnish-plugin (за основу можно взять стандартный skeleton):

01.#! /bin/sh
02.PATH=/sbin:/usr/sbin:/bin:/usr/bin
03.DESC="NewRelic 3legs plugin"
04.NAME=java
05.DAEMON=/usr/bin/$NAME
06.DAEMON_ARGS="-jar /root/newrelic/varnish/newrelic_3legs_plugin-0.0.2.jar"
07.PIDFILE=/var/run/newrelic-varnish-plugin.pid
08.SCRIPTNAME=/etc/init.d/newrelic-varnish-plugin
09.CHDIR=/root/newrelic/varnish
10. 
11.[ -x "$DAEMON" ] || exit 0
12. 
13.do_start()
14.{
15.        start-stop-daemon --start --quiet --background --chdir $CHDIR --make-pidfile --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
16.                || return 1
17.    start-stop-daemon --start --quiet --background --chdir $CHDIR --make-pidfile --pidfile $PIDFILE --exec $DAEMON -- \
18.        $DAEMON_ARGS \
19.        || return 2
20.}
21.do_stop()
22.{
23.    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
24.    RETVAL="$?"
25.        rm -f $PIDFILE
26.        return "$RETVAL"
27.}
28.case "$1" in
29.  start)
30.    [ "$VERBOSE" != no ] && echo "Starting $DESC"
31.    do_start
32.    case "$?" in
33.                0|1) [ "$VERBOSE" != no ] && echo "Successfully started $DESC" ;;
34.                2) [ "$VERBOSE" != no ] && echo "Could not start $DESC" ;;
35.    esac
36.    ;;
37.  stop)
38.    [ "$VERBOSE" != no ] && echo "Stopping $DESC" "$NAME"
39.    do_stop
40.    case "$?" in
41.        0|1) [ "$VERBOSE" != no ] && echo "Successfully stopped $DESC" ;;
42.        2) [ "$VERBOSE" != no ] && echo "Could not stop $DESC" ;;
43.    esac
44.    ;;
45.  restart)
46.    echo "Restarting $DESC"
47.    do_stop
48.    case "$?" in
49.      0|1)
50.        do_start
51.    esac
52.    ;;
53.  *)
54.    echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
55.    exit 3
56.    ;;
57.esac
58. 
59.:

Дальше сделаем автозапуск:

update-rc.d newrelic-varnish-plugin start 70 2 3 4 5 . stop 20 0 1 6 .

А в crontab добавляем строчку вроде такой:

20 03 * * * /etc/init.d/newrelic-varnish-plugin restart > /dev/null

Вроде бы всё, но самое обидное, что почему-то проблемы с передачей метрик в New Relic периодически вылезают и у двух остальных плагинов: Nginx и HAProxy. Они почему-то могут внезапно взять и перестать отправлять метрики, ничего толкового не написав в логе. Процесс висит, но ничего не делает. Поэтому аналогичную схему с init-скриптом можно реализовать для всех плагинов. Отличаться скрипты будут фактически только путями и аргументами.

Вот кусок для HAProxy

1.DESC="HAProxy New Relic plugin"
2.NAME=newrelic_haproxy_agent
3.DAEMON=/usr/local/bin/$NAME
4.DAEMON_ARGS="run"
5.PIDFILE=/var/run/newrelic-haproxy-plugin.pid
6.SCRIPTNAME=/etc/init.d/newrelic-haproxy-plugin
7.CHDIR=/root/newrelic/haproxy

А вот для Nginx:

1.DESC="Nginx New Relic plugin"
2.NAME=newrelic_nginx_agent
3.DAEMON=/root/newrelic/nginx/$NAME
4.DAEMON_ARGS=""
5.PIDFILE=/var/run/newrelic-nginx-plugin.pid
6.SCRIPTNAME=/etc/init.d/newrelic-nginx-plugin
7.CHDIR=/root/newrelic/nginx

 

И по аналогии делаем автозапуск и периодический рестарт.

Результаты

New Relic обладает достаточно мощью и гибкостью. Он собирает большое количество метрик и удобно предоставляет их в графическом виде. Не буду расписывать всё, что мы можем получить с помощью описанных выше плагинов, но приведу пример всего лишь одной из страниц, которые мы можем получить для Varnish:

nr-varnish

Tags: , ,
Category: HAProxy, Nginx, Varnish | No comments »

Comments

Leave a comment

 Comment Form 

Rich Text Editor, comment