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:

apt-get install ruby1.9.3 ruby-bundler rubygems
wget http://nginx.com/download/newrelic/newrelic_nginx_agent.tar.gz
tar -xzvf newrelic_nginx_agent.tar.gz
cd newrelic_nginx_agent
bundle install

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

server {
	listen *:8899;

	location / {
	    stub_status on;
	    access_log off;
	    allow 10.0.0.0/8;
	    deny all;
	}
} 

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

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

agents:
  nginx_status_agent:
    -
      instance_name: Nginx1
      status_url: http://url1:8899/
    -
      instance_name: Nginx2
      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 пишем имя приложения (если плагин крутится на отдельном сервере, то параметров надо будет подкинуть).

varnish = [
        {
                name = Curacao.Varnish
        }
]

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

{
	cassandra = false
	varnish = true
}

На данном этапе плагин можно сразу же запустить и посмотреть, как он работает. Делать это можно, например, через 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

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

sudo gem install newrelic_haproxy_agent
sudo newrelic_haproxy_agent install

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

agents:
  HAproxy1:
    uri: http://url1:1936/;csv
    proxy: web
    proxy_type: BACKEND
  HAproxy2:
    uri: http://url2:1936/;csv
    proxy: app
    proxy_type: BACKEND

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

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

nohup newrelic_haproxy_agent run &

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

listen stats
        bind *:1936
        stats enable
        stats uri       /
        stats refresh   15s
        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:

java.util.logging.FileHandler.level = FINE
	java.util.logging.FileHandler.pattern = newrelic.log
	java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
	java.util.logging.FileHandler.append = true

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

#! /bin/sh
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="NewRelic 3legs plugin"
NAME=java
DAEMON=/usr/bin/$NAME
DAEMON_ARGS="-jar /root/newrelic/varnish/newrelic_3legs_plugin-0.0.2.jar"
PIDFILE=/var/run/newrelic-varnish-plugin.pid
SCRIPTNAME=/etc/init.d/newrelic-varnish-plugin
CHDIR=/root/newrelic/varnish

[ -x "$DAEMON" ] || exit 0

do_start()
{
        start-stop-daemon --start --quiet --background --chdir $CHDIR --make-pidfile --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
                || return 1
	start-stop-daemon --start --quiet --background --chdir $CHDIR --make-pidfile --pidfile $PIDFILE --exec $DAEMON -- \
		$DAEMON_ARGS \
		|| return 2	
}
do_stop()
{
	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
	RETVAL="$?"
        rm -f $PIDFILE
        return "$RETVAL"
}
case "$1" in
  start)
	[ "$VERBOSE" != no ] && echo "Starting $DESC"
	do_start
	case "$?" in
                0|1) [ "$VERBOSE" != no ] && echo "Successfully started $DESC" ;;
                2) [ "$VERBOSE" != no ] && echo "Could not start $DESC" ;;
	esac
	;;
  stop)
	[ "$VERBOSE" != no ] && echo "Stopping $DESC" "$NAME"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && echo "Successfully stopped $DESC" ;;
		2) [ "$VERBOSE" != no ] && echo "Could not stop $DESC" ;;
	esac
	;;
  restart)
	echo "Restarting $DESC"
	do_stop
	case "$?" in
	  0|1)
		do_start
	esac
	;;
  *)
	echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
	exit 3
	;;
esac

:

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

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

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

А вот для Nginx:

DESC="Nginx New Relic plugin"
NAME=newrelic_nginx_agent
DAEMON=/root/newrelic/nginx/$NAME
DAEMON_ARGS=""
PIDFILE=/var/run/newrelic-nginx-plugin.pid
SCRIPTNAME=/etc/init.d/newrelic-nginx-plugin
CHDIR=/root/newrelic/nginx

 

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

Результаты

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

nr-varnish

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

Comments

Leave a comment

 Comment Form