Crmgo Blog

Zabbix-agent + monitoring of MySQL, Nginx, php-fpm on CentOS

Zabbix-agent + monitoring of MySQL, Nginx, php-fpm on CentOS

chkconfig zabbix-agent on vim /etc/zabbix/zabbix_agentd.conf #Server=zabbix.domain.ua #ServerActive=zabbix.domain.ua #Hostname=MyServer #Include=/usr/local/etc/zabbix2/zabbix_agentd.d/ mkdir /etc/zabbix/zabbix_agentd.d/ service zabbix-agent start MYSQL mysql> GRANT USAGE ON *.* TO 'zabbix'@'%' IDENTIFIED BY 'mypass'; FLUSH PRIVILEGES; vim /etc/zabbix/zabbix_agentd.d/userparameter_mysql.conf UserParameter=mysql.status[*],echo "show global status where Variable_name='$1';" | HOME=/var/lib/zabbix mysql -N |…

Zabbix-agent + monitoring of MySQL, Nginx, php-fpm on CentOS
cat /etc/redhat-release
CentOS/RHEL 7:
# rpm -Uvh http://repo.zabbix.com/zabbix/3.2/rhel/7/x86_64/zabbix-release-3.2-1.el7.noarch.rpm
yum install zabbix-agent

 

chkconfig zabbix-agent on

vim /etc/zabbix/zabbix_agentd.conf

#Server=zabbix.domain.ua

#ServerActive=zabbix.domain.ua

#Hostname=MyServer

#Include=/usr/local/etc/zabbix2/zabbix_agentd.d/

mkdir /etc/zabbix/zabbix_agentd.d/

service zabbix-agent start

MYSQL

mysql> GRANT USAGE ON *.* TO 'zabbix'@'%' IDENTIFIED BY 'mypass';
FLUSH PRIVILEGES;

vim /etc/zabbix/zabbix_agentd.d/userparameter_mysql.conf

UserParameter=mysql.status[*],echo "show global status where Variable_name='$1';" | HOME=/var/lib/zabbix mysql -N | awk '{print $$2}'
UserParameter=mysql.size[*],bash -c 'echo "select sum($(case "$3" in both|"") echo "data_length+index_length";; data|index) echo "$3_length";; free) echo "data_free";; esac)) from information_schema.tables$([[ "$1" = "all" || ! "$1" ]] || echo " where table_schema=\"$1\"")$([[ "$2" = "all" || ! "$2" ]] || echo "and table_name=\"$2\"");" | HOME=/var/lib/zabbix mysql -N'

UserParameter=mysql.ping,HOME=/var/lib/zabbix mysqladmin ping | grep -c alive
UserParameter=mysql.version,mysql -V

vim /etc/zabbix/.my.cnf

[mysql]
user=zabbix
password=*****
[mysqladmin]
user=zabbix
password=*****

service zabbix-agent restart

NG

 

The nginx server is capable of providing part of the information about its state that we need. To do this, it must be properly configured. Open the server configuration file and add the following block:

server {
        listen localhost;
        server_name status.localhost;
        keepalive_timeout 0;
        allow 127.0.0.1;
        deny all;
        location /server-status {
                 stub_status on;
        }
        access_log off; 
}

Save the configuration and restart nginx, having first checked the configuration file for errors:

# nginx -t
# systemctl restart nginx

Check whether we can retrieve the required information:

# wget http://localhost/server-status

nginx server status

A file named server-status should appear in the current directory with content similar to the following:

# cat server-status
Active connections: 3
server accepts handled requests
156171 156171 318790
Reading: 0 Writing: 1 Waiting: 2

If you see the same, everything is fine and you can proceed. If something is not working, check the configuration files and review the logs. This is standard functionality, so it should be configured and work without issues.

Configuring Zabbix monitoring for nginx

We will parse the obtained server-status file using a script. To run it, you need to install a couple of packages:

#  yum -y install curl zabbix-sender

Create a directory where our monitoring scripts will be stored:

# mkdir /etc/zabbix/scripts

And place the nginx.sh script with the following content there:

#!/bin/sh

PREFIX='nginx'
URL='http://127.0.0.1/server-status'

CURL='/usr/bin/curl'
TMP='/tmp/nginx-ping.tmp'
SENDER='/usr/bin/zabbix_sender'
CONFIG='/etc/zabbix/zabbix_agentd.conf'

if [ ! -x ${CURL} ]
then echo Seems, path to curl is incorrect or not installed. && exit 0
else if [ ! -x ${SENDER} ]
then echo Seems, path to zabbix_sender is incorrect or not installed. && exit 0
else if [ ! -f ${CONFIG} ]
then echo Seems, path to zabbix_agentd.conf is incorrect && exit 0
fi fi fi

read -a s <<< `(time ${CURL} --no-keepalive -s -m 9 ${URL}) 2>$TMP`

if [[ "${s[7]}" =~ ([0-9]+) ]]
then
echo "\
- ${PREFIX}.accepts ${s[7]}
- ${PREFIX}.connections.active ${s[2]}
- ${PREFIX}.connections.reading ${s[11]}
- ${PREFIX}.connections.waiting ${s[15]}
- ${PREFIX}.connections.writing ${s[13]}
- ${PREFIX}.handled ${s[8]}
- ${PREFIX}.requests ${s[9]}" | ${SENDER} -c ${CONFIG} -i - >/dev/null 2>&1
awk '/real/{split($2,a,"[ms]");print a[1]*60+a[2];}' $TMP
else
echo '-0.001'
fi
rm $TMP
exit 1

Make it executable:

# chmod 0645 nginx.sh

Now open the Zabbix agent configuration file and add a user parameter:

# mcedit /etc/zabbix/zabbix_agentd.conf
UserParameter=nginx.ping,/etc/zabbix/scripts/nginx.sh

Restart the agent:

# systemctl restart zabbix-agent

Next, we need to add a new monitoring template. Download it from nginx.xml and open the Zabbix web interface. Go to the Configuration -> Templates section and click Import:

import template into zabbix

Select the file and click Import again:

select template for import

Almost everything is ready. Now we need to attach the added template to the web server we are monitoring. Go to Configuration -> Hosts, select the required server, open the Templates tab, and link the template:

link template to server

Click Update and wait for new data to arrive. You can check it in Monitoring -> Latest Data:

view incoming data

The template already includes several triggers and graphs. You can view and edit them in the template properties or in the properties of an individual host. I prefer to create Screens with the necessary set of graphs. Here is what my nginx monitoring dashboard looks like:

nginx monitoring in zabbix

This completes the nginx monitoring setup; you can now use it.

Preparing php-fpm for monitoring

We will monitor the following php-fpm parameters:

php-fpm monitoring
active processes count Number of active processes
connections per sec Number of connections per second
idle processes count Number of idle processes
latency Response time in milliseconds
length of listen queue Size of the pending connections queue
max children reached Number of times the process limit was reached
max length of listen queue Maximum size of the connections queue

A few words on why this is needed and how to use the collected data. This monitoring is relevant if you have dynamic process creation in php-fpm. For example, if the value of max children reached is regularly greater than one, it is recommended to increase the limit on the maximum number of processes, provided that the server resources allow it. The same applies to the length of listen queue parameter. If it is greater than zero, a queue of requests is created that the server cannot process in time. You need to increase the number of processes that can handle pending connections.

You should pay attention to the latency parameter. If it is regularly greater than 10-20 ms, you need to figure out why the server is responding so slowly. The rest of the information is just for statistics.

Let's start configuring. Install fcgi:

# yum -y install fcgi

Now prepare php-fpm to collect statistics. For this, we will use nginx again. Edit its configuration file, adding the following structure to the same server section as in the previous step:

location /status {
access_log off;
allow 127.0.0.1;
deny all;
include fastcgi_params;
fastcgi_pass unix:/var/run/php-fpm/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Please note that in my configuration, I use a connection to php-fpm via a unix socket. This is handled by the fastcgi_pass configuration parameter. If you use a tcp/ip port, usually 127.0.0.1:9000, you need to specify it instead of the socket, like this: fastcgi_pass 127.0.0.1:9000

Restart nginx:

# systemctl restart nginx

Make the necessary changes to the php-fpm configuration file — add one line:

# mcedit /etc/php-fpm.d/www.conf
pm.status_path = /status

Restart php-fpm:

# systemctl restart php-fpm

Check that we get php-fpm statistics at the specified address:

# wget http://127.0.0.1/status

php-fpm status

Look at the contents of the status file:

# cat status

pool: www
process manager: dynamic
start time: 10/Nov/2015:00:44:55 +0300
start since: 257703
accepted conn: 47066
listen queue: 0
max listen queue: 0
listen queue len: 0
idle processes: 7
active processes: 1
total processes: 8
max active processes: 40
max children reached: 1
slow requests: 0

If you have approximately the same output, then everything is fine, php-fpm is providing information about its state.

Configuring php-fpm monitoring in Zabbix

Now prepare a script for Zabbix to process the collected status:

# mcedit /etc/zabbix/scripts/php-fpm.sh
#!/bin/sh

PREFIX='php.fpm'
URL='http://127.0.0.1/status'

CURL='/usr/bin/curl'
TMP='/tmp/php-fpm-ping.tmp'
SENDER='/usr/bin/zabbix_sender'
CONFIG='/etc/zabbix/zabbix_agentd.conf'

if [ ! -x ${CURL} ]
then echo Seems, path to curl is incorrect or not installed. && exit 0
else if [ ! -x ${SENDER} ]
then echo Seems, path to zabbix_sender is incorrect or not installed. && exit 0
else if [ ! -f ${CONFIG} ]
then echo Seems, path to zabbix_agentd.conf is incorrect && exit 0
fi fi fi

(time ${CURL} --no-keepalive -sm3 ${URL}) 2>$TMP | awk --assign pr="- ${PREFIX}." '
/^accepted c/ {print pr"accepted_conn "$3}
/^active proc/ {print pr"active_processes "$3}
/^idle proc/ {print pr"idle_processes "$3}
/^listen queue:/ {print pr"listen_queue_len "$3}
/^max children reach/ {print pr"max_children_reached "$4}
/^max listen queue:/ {print pr"max_listen_queue_len "$4}' | ${SENDER} -c ${CONFIG} -i - 2>/dev/null | awk --assign t="${TMP}" '/^sent/{if($6==0){print"-0.001";print>t}}'
awk '/real/{split($2,a,"[ms]");print a[1]*60+a[2];}' $TMP
rm $TMP
exit 1

Make it executable:

# chmod 0645 php-fpm.sh

Add another user parameter to the Zabbix agent configuration:

# mcedit /etc/zabbix/zabbix_agentd.conf
UserParameter=php.fpm.ping,/etc/zabbix/scripts/php-fpm.sh

Restart the agent:

# systemctl restart zabbix-agent

Next, as in the case with nginx, go to the web interface and import the php-fpm.xml template. Add this template to the required server and wait for the data to update. Check for their arrival as usual in Monitoring -> Latest Data:

php-fpm monitoring data

If everything is in order, check the graphs and create the Screen you need. Mine looks like this:

php-fpm monitoring setup in Zabbix

The template already has 3 triggers configured, which activate when:

  • the php-fpm service goes down
  • the number of worker processes is less than 3
  • the response time is less than 10 ms over the last 10 measurements

The second trigger can be removed or modified if you have fewer than the minimum number of worker processes.

Conclusion

Let's summarize what we have done:

  1. Configured the nginx server to provide information about its status and the status of the php-fpm service.
  2. Created scripts to process information from the web server and pass it to Zabbix.
  3. Configured the Zabbix agent to send processed data to the server using user parameters.
  4. Created the necessary templates on the monitoring server and attached them to the monitored servers.
  5. Combined the monitored parameters into a Screen for convenient observation.

In other words, we performed the entire set of actions required to organize full-fledged monitoring of a web server based on nginx + php-fpm in Zabbix.

One application of such monitoring is choosing a faster hosting provider for your website. For example, some time ago I needed to change hosting. But how to find out if it will be faster than the current one or not? The specifications are roughly the same for everyone. I simply took a trial period, configured everything I needed on the server, including web server monitoring, moved the site there, and observed it for a day. Based on the response times of nginx and php-fpm, it became clear to me that the new hosting was faster:

Comparison of hosting speed

Note: This post may be AI-assisted and then human-edited. Editorial responsibility: Dmytro Lomaka, Kaltenkirchen.