版权声明:本文为博主原创文章,转载请注明出处:https://twocups.cn/index.php/2021/06/28/43/

情况说明

Zabbix 是原生支持监控机器上的单个 Mysql 的,这个网上教程很多,可以自己去查阅一下。但是原生的 Zabbix 监控并不支持一台机器上的一些端口上都部署了 Mysql 实例的情况。比如,服务器上的20120、20121、20122等十几个端口都部署了 Mysql 实例。

Zabbix 版本:5.0 LTS

Mysql版本:任意

流程简介

Zabbix 服务端主动向 Zabbix 客户端发送监控请求,Zabbix 客户端收到请求后运行我们自定义的脚本,通过 socket 文件向本机内指定端口的 Mysql 实例发送请求。Zabbix 客户端得到 Mysql 返回的数据后,再将其发送给 Zabbix 服务端。

原理简介

可能现在看不懂,但把整个部署进行一遍之后就能看到这里在说什么了。

我们先在被监控的主机上定义宏 {$MYSQLPORT},宏的值就是这台主机部署了 Mysql 实例的端口们。Zabbix 服务端有了被监控主机的宏之后,就可以通过自动发现规则去访问被监控主机上的 Mysql 实例的端口们。这时,Zabbix 服务端再调用 Zabbix 客户端脚本,去逐个访问所有指定端口的 Mysql 实例,这样就能获得我们想要的数据了。

在多个Mysql中都新建监控账号

既然我们要访问 Mysql 实例,那么我们需要在每个 Mysql 实例中都创建监控账号。

以下账号为 zabbix_monitor,密码为0。

CREATE USER 'zabbix_monitor'@'%' IDENTIFIED BY '0';
GRANT USAGE,PROCESS,REPLICATION CLIENT,REPLICATION SLAVE,SUPER ON *.* TO 'zabbix_monitor'@'%';
FLUSH PRIVILEGES;

如果你不想设置密码,就这么写。但这样可能会出现一个问题,具体问题和规避方法我在下面说。

CREATE USER 'zabbix_monitor'@'%';
GRANT USAGE,PROCESS,REPLICATION CLIENT,REPLICATION SLAVE,SUPER ON *.* TO 'zabbix_monitor'@'%';
FLUSH PRIVILEGES;

提一句,不要将新建用户指令和赋权指令一起写,否则新一点的版本都会出现 Warning 的。

修改Zabbix客户端配置

首先,我们修改 zabbix-agent2 的配置文件。

vim /etc/zabbix/zabbix_agent2.conf

# 以下是配置文件/etc/zabbix/zabbix_agent2.conf中的内容
# 这条的意思是运行指定文件夹下所有的conf配置
Include=/etc/zabbix/zabbix_agent2.d/*.conf
# 这条的意思是允许用户自定义监控项
UnsafeUserParameters=1

接下来,我们新增配置文件 multi_mysql.conf。

vim /etc/zabbix/zabbix_agent2.d/multi_mysql.conf

# 以下是配置文件/etc/zabbix/zabbix_agent2.d/multi_mysql.conf中的内容
# mysql基础监控项
UserParameter=mysql_discovery[*],/etc/zabbix/bin/discovery_mysql.sh $1
UserParameter=mysql.test.status[*],/etc/zabbix/bin/mysql_status.sh $1 $2
UserParameter=mysql.test.ping[*],/etc/zabbix/bin/mysql_alive.sh $1
UserParameter=mysql.test.ms.check[*],/etc/zabbix/bin/mysql_slave_status.sh $1
UserParameter=mysql.test.ms.time[*],/etc/zabbix/bin/mysql_slave_time.sh $1
# mysql进程列表
UserParameter=mysql.test.processlist[*],/etc/zabbix/bin/mysql_processlist.sh $1
# mysql事务
UserParameter=mysql.test.innodb.trx[*],/etc/zabbix/bin/mysql_innodb_trx.sh $1

注意一下,里面有一个参数是“mysql.test.ping”。如果把它改成“mysql.ping”就会导致 zabbix-agent2 启动失败,报错原因是“用户参数mysql.ping[*]无法初始化,因为主键已经存在了”,所以我这里改成了“mysql.test.ping”,你要想改成其他的名字也可以。

从这个配置文件,我们能很容易看出来,当 Zabbix 服务端向 Zabbix 客户端请求指定参数的时候,Zabbix 客户端运行指定脚本。这其实就是 Zabbix 原生的监控自定义项的方法,格式如下。

UserParameter=参数名称,shell指令

如果你有其他想监控的参数,也可以按照这个格式写。不过如果与 Mysql 无关的话,最后新建一个 conf 配置文件,方便你后期好归类。

以上配置文件中的 shell 指令就是运行我们指定目录下的带参脚本,那么我们现在就要去创建这些脚本。

# 首先创建存放脚本的文件夹
mkdir /etc/zabbix/bin
cd /etc/zabbix/bin

脚本1:自动发现不同端口。

vim discovery_mysql.sh

# 以下是脚本 discovery_mysql.sh 的内容
res=`echo $1| sed "s/_/\n/g"`;
port=($res)
printf '{\n'
printf '\t"data":[\n'
for key in ${!port[@]}
do
if [[ "${#port[@]}" -gt 1 && "${key}" -ne "$((${#port[@]}-1))" ]];
then
printf '\t {\n'
printf "\t\t\t\"{#MYSQLPORT}\":\"${port[${key}]}\"},\n"
else [[ "${key}" -eq "((${#port[@]}-1))" ]]
printf '\t {\n'
printf "\t\t\t\"{#MYSQLPORT}\":\"${port[${key}]}\"}\n"
fi
done
printf '\t ]\n'
printf '}\n'

脚本2:监控 Mysql 性能。

vim mysql_status.sh

# 以下是脚本 mysql_status.sh 的内容
#!/bin/bash
var=$1
mysql=/usr/bin/mysql
MYSQL_USER="zabbix_monitor"
MYSQL_PASSWORD=0
MYSQL_SOCK_DIR="/tmp/mysql_$2.sock"
${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} -S ${MYSQL_SOCK_DIR} -e "show global status;" 2> /dev/null |grep -v Variable_name|grep "\b${var}\b"|awk '{print $2}'

脚本3:监控是否能连通 Mysql 实例。

vim mysql_alive.sh

# 以下是脚本 mysql_alive.sh 的内容
#!/bin/bash
mysqladmin=/usr/bin/mysqladmin
MYSQL_USER="zabbix_monitor"
MYSQL_PASSWORD=0
MYSQL_SOCK_DIR="/tmp/mysql_$1.sock"
${mysqladmin} -u${MYSQL_USER} -p${MYSQL_PASSWORD} -S ${MYSQL_SOCK_DIR} ping|grep -c alive

脚本4:监控从库 Mysql 性能。

vim mysql_slave_status.sh

# 以下是脚本 mysql_slave_status.sh 的内容
#!/bin/bash
#var=$1
mysql=/usr/bin/mysql
MYSQL_USER="zabbix_monitor"
MYSQL_PASSWORD=0
MYSQL_SOCK_DIR="/tmp/mysql_$1.sock"
${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} -S ${MYSQL_SOCK_DIR} -e "show slave status\G;" 2> /dev/null|grep -E 'Slave_IO_Running: Yes|Slave_SQL_Running: Yes'|grep -c Yes

脚本5:监控从库延迟情况。

vim mysql_slave_time.sh

# 以下是脚本 mysql_slave_time.sh 的内容
#!/bin/bash
#var=$1
mysql=/usr/bin/mysql
MYSQL_USER="zabbix_monitor"
MYSQL_PASSWORD=0
MYSQL_SOCK_DIR="/tmp/mysql_$1.sock"
${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} -S ${MYSQL_SOCK_DIR} -e "show slave status\G;" 2> /dev/null|grep -E 'Seconds_Behind_Master'|awk '{print $2}'

脚本6:监控 Mysql 进程列表。

vim mysql_processlist.sh

# 以下是脚本 mysql_processlist.sh 的内容
#!/bin/bash
mysql=/usr/bin/mysql
MYSQL_USER="zabbix_monitor"
MYSQL_PASSWORD=0
MYSQL_SOCK_DIR="/tmp/mysql_$1.sock"
${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} -S ${MYSQL_SOCK_DIR} -e "select * from information_schema.processlist order by time;" 2> /dev/null

脚本7:监控当前 Innodb 引擎内每个事物的情况。

vim mysql_innodb_trx.sh

# 以下是脚本 mysql_innodb_trx.sh 的内容
#!/bin/bash
mysql=/usr/bin/mysql
MYSQL_USER="zabbix_monitor"
MYSQL_PASSWORD=0
MYSQL_SOCK_DIR="/tmp/mysql_$1.sock"
${mysql} -u${MYSQL_USER} -p${MYSQL_PASSWORD} -S ${MYSQL_SOCK_DIR} -e "select * from information_schema.innodb_trx order by trx_started\G" 2> /dev/null

所有脚本创建好以后一定要给其运行权限,否则会报错“Permission denied”。

chmod 777 /etc/zabbix/bin/*.sh

注意点1:以上 mysqladmin 和 mysql 的地址是我机器上的地址,你机器上的地址自己先去查一下,然后替换掉。

# 查找机器上mysqladmin和mysql的地址
find / -name mysqladmin
find / -name mysql

注意点2:以上 socket 文件的地址我写的是“/tmp/mysql_$1.sock”,这是由于我机器上的 socket 文件叫这个名字,比如“/tmp/mysql_20120.sock”。你要自己去看看你机器上 socket 文件的目录和名称,然后替换掉。

# 查找机器上所有连接mysql的socket文件
find / -name mysql*.sock

注意点3:以上是之前我们创建的监控账号 zabbix_monitor 密码为0的情况。如果之前没有设置密码为空的话,不是去掉“MYSQL_PASSWORD=0”就行了,还要同时去掉最后一条实际 shell 语句中的“-p${MYSQL_PASSWORD}”才行。

我之前没有设置密码,只去掉了“MYSQL_PASSWORD=0”,而没有去掉“-p${MYSQL_PASSWORD}”。这就导致了 Zabbix 监控项返回数据不对的情况。

Mysql On 20120 status

返回数据:
Enter password: 1

正常情况下,返回数据应该是“1”,而这里返回数据就变成了“Enter password: 1”。先不说内容,这个参数的存储格式是无符号数字,这里返回了一个文本类型,肯定会报错。

这里就涉及到另一个问题了,为什么要新建监控账号?直接用 root 账户不好吗?

为什么要新建监控账号?

因为权限

在实际企业环境中,root 账号并不一定拥有全部的权限。所有的权限都在一个特殊账户上,我们一般都是用这个账户来登陆数据库的,而不是 root。

而我们做监控,就是要无论数据库出现什么情况,都对它进行实时监控。这又涉及到一个 Mysql 的账户权限,SUPER 权限。拥有 SUPER 权限的账户被称为 SUPER 账户,即使在数据库处于离线模式的时候也能连接上数据库,这是非常重要的一点。

离线模式(offline mode)是 Mysql 5.7版本的新特性,用于在管理员对数据库进行升级和维护工作时,阻止其他账户对数据库进行访问的。

所以在 root 账户没有 SUPER 权限的时候,我们需要创建一个有 SUPER 权限的账户 zabbix_monitor 来使 Zabbix 对 Mysql 进行监控,防止在数据库处理离线模式的时候拒绝 Zabbix 的访问。

但是,在实际的企业环境中,有些是不允许出现额外的 SUPER 账户的。我自己当时就创建了有 SUPER 权限的 zabbix_monitor 账户,结果反手就被系统下掉了该账户的 SUPER 权限。

所以我自己的解决方法就是直接用登陆数据库用到的特殊账户去访问数据库,毕竟系统不允许它以外的账户有 SUPER 权限,我用它来监控也是无奈之举。由于这个特殊账户是没有密码的,所以我之前才强调了监控账户没有密码的时候脚本如何改动。

Zabbix客户端配置完成

以上流程走完后,Zabbix 客户端的配置就完成了。我们重启 Zabbix 客户端。

systemctl restart zabbix-agent2

Zabbix前端页面配置

第一步,我们先添加主机宏。这个必须放在第一步,否则就会出现端口找不到的情况。

# 后添加主机宏的错误显示:“{}”里面应该显示端口号,但这里没有显示
mysql_discovery: Mysql On {} status

我们来到 Zabbix 前端页面,左侧栏“配置-主机”,选择需要监控的主机。再进入主机配置界面后,配置该主机的宏。

宏:{$MYSQLPORT},值:端口号(多端口号之间用下划线连接),例如20120_20121_20122。

第二步,我们导入模版 template multi MySQL.xml。

模版 template multi MySQL.xml 下载地址:https://twocups.cn/wp-content/uploads/2021/06/template-multi-MySQL.xml_.zip

由于网站里不好直接放 xml 文件,所以你们下载下来是个压缩包,解压一下就是模版 template multi MySQL.xml。

我们在左侧栏“配置-模版”页面的右上角导入模版。

之后,“配置-模版”页面就会出现我们刚刚导入的新模版“Template Multi Mysql”。

第三步,我们点进去,修改自动发现规则“mysql_discovery”。

名称:mysql_discovery
类型:Zabbix客户端(主动式)
键值:mysql_discovery[{#MYSQLPORT}]

第四步,给被监控的主机添加我们设置好的模版“Template Multi Mysql”。

在左侧栏“配置-主机”页面中,选择被监控的主机,然后在模版一栏,添加新的模版。

等待结果

到这里为止,所有的部署和配置都结束了。接下来需要等待一会儿,等 Zabbix 去收集数据,才会出现 Mutli Mysql 应用集和该应用集中的各种选项。整个等待时间大概五分钟左右吧。

结果展示

左侧栏“配置-主机”页面,指定主机,然后选择监控项-应用集 Multi Mysql,就能看到已经设置好的监控项。

左侧栏“监视-最新数据”页面,指定主机,选择应用集 Multi Mysql,就能看到监控到的数据。

如果等了一段时间之后,配置里面还是没有出现应用集 Multi Mysql 和相应的监控项的话,就可以着手开始排查错误。我们在 Zabbix 服务端机器上操作。

zabbix_get -s zabbix客户端ip -p 10050 -k mysql.test.ping[zabbix客户端上数据库端口]

这是测试 zabbix-server 能否连接到 zabbix-agent2 的指定端口数据库实例的,如果返回1,说明能连上;如果返回0,说明没连上客户端端口数据库。

那我们再去测试一下 Zabbix 客户端,看看是客户端出了问题,还是服务端有问题。

我们在 Zabbix 客户端机器上操作。先看看是不是脚本的问题。

sh /etc/zabbix/bin/mysql_alive.sh 客户端上数据库端口

如果返回1,说明脚本没问题,问题不在客户端这里,而是在服务端那里。如果返回0,那么再往下查。

/usr/bin/mysqladmin -uzabbix_monitor -p0 -S /tmp/mysql_客户端数据库端口.sock ping|grep -c alive

如果返回1,说明 shell 指令本身没问题,问题在上面的脚本哪里。如果返回0,或者其他具体的错误,就好好看看错误原因。到这一步,说明 Zabbix 客户端所在的机器自己都连接不上自己端口上的 Mysql 实例了,这就和 Zabbix 无关了。

手动添加新的Mysql监控项

接下来讲讲怎么添加新的关于 Mysql 的自定义监控项,就比如 processlist 和 innodb_trx 这两个监控项其实是我自定义的监控项。你们上面下载并导入的模版文件 template multi MySQL.xml 并不包含这两个监控项,所以需要我们手动添加。

我们就先在 Zabbix 客户端进行操作。

我们先将 shell 命令封装成脚本添加到目录 /etc/zabbix/bin 下,然后去配置文件 /etc/zabbix/etc/zabbix/zabbix_agent2.d/multi_mysql.conf 中添加相应的参数名称和脚本运行指令。都修改完别忘了重启 zabbix-agent2。

systemctl restart zabbix-agent2

然后,我们再在 Zabbix 前端页面上进行操作。

我们直接在“配置-模版”中添加新的监控项,这样就可以自动应用到所有使用了该模版的主机了。我们在左侧栏“配置-模版”页面选择模版“Template Multi Mysql”,然后选择它的自动发现规则“mysql_discovery”的监控项原型。

进入监控项原型界面后,我们点击右上角的创建监控项原型,然后填入相应的自定义监控项的信息。

# 监控项processlist
名称:Mysql On {#MYSQLPORT} processlist
类型:Zabbix客户端
键值:mysql.test.processlist[{#MYSQLPORT}]
信息类型:文本

# 监控项innodb_trx
名称:Mysql On {#MYSQLPORT} innodb_trx
类型:Zabbix客户端
键值:mysql.test.innodb.trx[{#MYSQLPORT}]
信息类型:文本

这些都配置完成之后,照样还是等待一段时间,大概五分钟左右就会在使用了该模版的主机中出现新的监控项了。

林皓伟

发表回复

您的电子邮箱地址不会被公开。