首页 > 代码库 > Zabbix 的自动监控项目监控Nginx各hostname配置 - Low Level Discovery

Zabbix 的自动监控项目监控Nginx各hostname配置 - Low Level Discovery

Zabbix演示版本:2.4.4

涉及到的脚本语言:PHP

技术分享


low-level discovery的意思是“低层次的自动发现”,检查lld。 lld并不似因为功能简单或者不重要而被称为“低层次的”,而是因为相对于服务器的自动发现,low-level discovery是针对服务器上设备的自动发现。


Zabbix 原生支持针对三种(文件系统、网卡、SNMP OIDs)自动发现来配套自动添加Items、Triggers 和 Graphs等。在lld中它们被称为Item原型、Trigger原型 和 Graph原型。


因为low-level discovery是基于Template或者Host的。一个low-level discovery由以下两部分组成。

  1. 探测部件(文件系统或者网卡)的Item,比如 net.if.discovery。

  2. 基于Item创建的Triggers 和 Graphs。


low-level discovery 的 Item比较特殊,普通的Item返回的可能是数字、字符串等的监控数据,lld的Item返回的是一个JSON对象,其中包含了探测到的部件列表。以net.if.discovery为例,它会返回一些键值对,比如"{#IFNAME}" - "lo",和 "{#IFNAME}" - "eth0"。


lld会发现很多不同的部件,比如多块网卡,这些变量(网卡名称,eth0,eth1等)会绑定在宏上。定义Triggers或者Items的时候使用这些宏来代替变量名就行了。针对侦测到的网卡的监控就可以是 net.if.out[{#IFNAME}]。


技术分享

单击模板后面的“Discovery”链接进入Template OS Linux 的 lld界面,接下来可以看到我们想看到的lld。

技术分享

在显示的界面中个,每一行里除了lld的名字外,显示了Item原型、Trigger原型、Graph原型 和 Host原型,因为作为例子的lld没有Host原型,所以笔者会在例子后面单独介绍它。“Key”就是执行lld的Item key(也就是那个需要返回JSON数据的key)。


技术分享

其中

  1. Type:和配置Item时的Type的含义一致。

  2. Key:和配置Item时的key含义一致。

  3. Update interval (in sec):表示更新该lld发现规则的间隔时间。

  4. Flexible intervals:弹性的间隔时间。

  5. Keep lost resources period (in days):lld侦测到的新部件在各种原型保留多少天。 比如设置为10,那么在侦测到一块磁盘后的原型会连续监控10天,如果在10天内这块硬盘还被侦测到了,那么这个时间会顺延。设置这个参数的目的是当服务器上的部件发生变化时,能够将不用的部件禁用。注意,这里设置为0,并不是永远不停止,而是立刻删除。 

  6. Filter选项卡:lld的Item会返回JSON对象,其中通常只有一部分是我们需要的。比如,vfs.fs.discovery返回的JSON是这样的:

{"data":[{"{#FSNAME}":"/","{#FSTYPE}":"rootfs"},{"{#FSNAME}":"/proc","{#FSTYPE}":"proc"},{"{#FSNAME}":"/boot","{#FSTYPE}":"ext4"},{"{#FSNAME}":"/data","{#FSTYPE}":"xfs"},{"{#FSNAME}":"/proc/sys/fs/binfmt_misc","{#FSTYPE}":"binfmt_misc"},{"{#FSNAME}":"/nfs","{#FSTYPE}":"nfs"}]}

    而你只想要监控nfs的,那么就需要对{#FSTYPE}进行过滤,简单来说,需要{#FSTYPE}符合一些条件。这里所说的条件是在“Administration → General”的Regular Expressions中配置的,它对{#FSTYPE}进行了过滤。

技术分享

1  ^(btrfs|ext2|ext3|ext4|jfs|reiser|xfs|ffs|ufs|jfs|jfs2|vxfs|hfs|ntfs|fat32|zfs)$[Result is TRUE]



下面来创建 Item原型:

技术分享

Item原型的配置和普通的Item是差不多的,唯一不同的就是key中使用了特殊的宏来替代lld发现的部件的变量。 比如图中的{#FSNAME}就是磁盘路径。 Trigger原型 和 Graph原型都是类似的情况。



-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

实际操作:结合Nginx的两个第三方模块实现Nginx单独虚拟主机的并发监控

第三方模块1:ngx_req_status GitHub 

第三方模块2:ngx_realtime_request_module GitHub 

这两个模块功能差不多,但还是有那一点小区别。


大致上分为以下几个步骤:

  • 编译Nginx 添加支持查询虚拟主机状态数据的第三方模块。

  • zabbix agent端添加自定义key

    • 编写自定义key的数据采集脚本

    • 并且该脚本支持单独主机的数据抽样采集

  • zabbix 编写lld模板配置

  • 关联实体监控主机并测试


首先需要在编译Nginx的时候添加第三方模块。(省略)


web访问测试。

realtime_request

技术分享


req_status

技术分享

我这里使用的php写的两个简单的脚本。源码如下(这里只讲req_status模块)

// ngx_req_status 模块
<?php
/**
 * Created by PhpStorm.
 * User: Eric
 * Date: 2016/09/20
 * Time: 21:20
 */
/** 此模块适用于 ngx_req_status 统计模块 */
// bugfix

$URL = ‘http://localhost/req_status?l‘;
$CONTENT = explode("\n", file_get_contents($URL));

function handle_req_status_to_hostArray($subject, $argv) {
    function sub_explode($value) {
        return explode("\t", $value);
    }

    function sub_filter($value) {
        if (is_array($value) && count($value) > 1) {
            return $value;
        }
    }

    function sub_combine($value) {
        $item_name = array(‘zone‘, ‘{#KEY}‘, ‘max_active‘, ‘max_bandwidth‘, ‘traffic‘, ‘request‘, ‘current_active‘, ‘current_bandwidth‘);
        return array_combine($item_name, $value);
    }

    if (count($argv) == 2) {
        $split = explode(" ", $argv[2]);
        $argv[1] = $split[0];
        $argv[2] = $split[1];
    }

    if (is_array($subject)) {
        $result = array_map(‘sub_explode‘, $subject);
        $result = array_filter($result, ‘sub_filter‘);
        $result = array_map(‘sub_combine‘, $result);
        array_shift($result);

        if (count($argv) > 1) {
            while ($item = each($result)) {
                if ($item[‘value‘][‘{#KEY}‘] == $argv[1]) {
                    return $item[‘value‘][$argv[2]];
                }
            }
        }
        //return $result;
        return array(‘data‘ => $result);
    } else {
        return $subject;
    }
}

if (!isset($argv)) {
    $argv = false;
}
// web浏览不报错

$test = handle_req_status_to_hostArray($CONTENT, $argv);
if (count($argv) > 1) {
    echo $test;
} else {
    echo json_encode($test);
}
?>

req_status模块的nginx配置如下

http {
    req_status_zone    server_name    "$server_name:$server_port"    256k; // key值是基于server_name和server_port的组合值
    req_status    server_name;
    .....
    
    server {
        .....
        location = /req_status {
            req_status_show  on;
        }
    }
}

技术分享

这个就是ngx_req_status返回的数据格式,然后利用php处理该数据返回位JSON对象。

而且该脚本也能根据提供两个参数取出特定的值。如图

技术分享

最后做好测试工作(通过zabbix_get方式获取例如该key的值)。


回到正题,配置 Zabbix 模板

技术分享

根据如图配置新生成一个新的空模板。


点击模板的 Discovery rules → Create discovery rules 创建一个新的 lld 发现规则。

技术分享

如图,配置好lld发现规则。

技术分享

这里的 key 就是需要在zabbix_agentd中配置的自定义key,对应的是那个php脚本。

由于我没有需要过滤的数据,所以Filter页面就留空。


点击上面的 Item prototypes 进入到Item原配置界面。

技术分享

按照如图,配置好6个根据{#KEY}迭代的key值。(注意区分大小写,特殊的{#KEY}宏是需要特定的格式,而且全大写字母


比如 req_status current Request 这个监控项

技术分享


然后创建图形源模板

技术分享

比如 Nginx_req_status - {#KEY} - Current Data 这个图形源的配置

技术分享

这些都配置好过后,那么接下来就可以关联那台nginx主机了。


关联该模板过后,大约在lld发现规则周期之内就会根据定义查询指定主机的 ngx_req_status key值返回的JSON数据了。


如果配置都正常,那么就会陆续自动添加很多监控项,然后生成图形。



注意事项:

  1. lld discovery自动发现的key的返回值必须是指定格式的JSON对象数据。 比如格式为

{"data":[{"{#HOST}":"  "request":"1024", "active":"512"}, {"{#HOST}":"static.bdimg.com", "request":"4051", "active":"2415"}]}

其中还有一点是需要注意的,稍不注意就容易掉坑里。作为lld发现key的特殊宏的格式是特定的,上例中的格式中只有{#HOST}这个特殊宏才能作为lld发现key,而且key的字母必须为全大写。


B. lld的发现key的间隔时间与该发现规则的 Item原型的间隔时间是不相干的,前者可以设置的间隔时间稍大,后者就相当于一个普通的Item项,根据你业务的需求设置监控粒度。


C. UserParameter=ngx_req_status[*],php /tmp/req_status.php $1 $2 这样可以让php脚本接收两个命令行参数,但是在zabbix web端配置的时候,有个坑,, 如图

技术分享

模板Item原型中的key参数之间不能有空格。(我当时在逗号后面接了个空格,导致zabbix_get始终无法测试出带两个参数的key值获取,捣鼓了好久,才看到这个坑技术分享


本文出自 “Professor哥” 博客,请务必保留此出处http://professor.blog.51cto.com/996189/1855620

Zabbix 的自动监控项目监控Nginx各hostname配置 - Low Level Discovery