运维知识
悠悠
2025年9月17日

别再说监控难搭了!手把手教你玩转Zabbix,从入门到放弃再到真香

之前有分享Beszel轻量监控,但是在使用过程中还是发现有些不足。多用户管理不方便,监控不够细致和灵活还有告警不支持钉钉!!!还是打算迁移到zabbix,顺便重温下zabbix!Zabbix这个老牌监控系统,虽然界面看起来有点"复古",但功能是真的强大。我记得刚开始用的时候还嫌弃它界面丑,现在用习惯了反而觉得挺顺手的,人就是这么奇怪。

为什么选择Zabbix

市面上监控系统那么多,Prometheus、Grafana、Nagios为啥偏偏选Zabbix?说白了就是因为它"傻瓜式"操作,而且免费。

Zabbix最大的优势就是开箱即用,安装完基本不用怎么配置就能跑起来。而且它的告警功能做得特别好,可以发邮件、短信,甚至还能调用API做一些自动化操作。

不过话说回来,Zabbix也不是完美的。界面确实有点老土,而且在处理大量数据时性能会有些吃力。但对于中小型企业来说,这些都不是问题。

文档地址:https://www.zabbix.com/documentation/current/zh/manual

安装

下载源码包,准备编译环境

[root@zabbixserver nginx-1.12.2]# yum install -y gcc pcre-devel openssl-devel

####安装nginx
##配置nginx支持https
[root@zabbixserver nginx-1.12.2]# ./configure --with-http_ssl_module

##编译安装
[root@zabbixserver nginx-1.12.2]# make && make install

 ###配置nginx支持php,配置php可以连接mysql
 [root@web1 ~]# yum install -y php php-fpm php-mysql mariadb-server mariadb-devel 

修改配置文件

[root@zabbixserver ~]# cat /usr/local/nginx/conf/nginx.conf

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    fastcgi_buffers 8 16k; 
    fastcgi_buffer_size 32k;
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ \.php$ {
            root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            include        fastcgi.conf;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

开启服务

[root@zabbixserver ~]# systemctl enable mariadb.service --now
Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service.


###启动php
[root@zabbixserver ~]# systemctl enable php-fpm --now
Created symlink from /etc/systemd/system/multi-user.target.wants/php-fpm.service to /usr/lib/systemd/system/php-fpm.service.


###启动nginx
[root@zabbixserver ~]# /usr/local/nginx/sbin/nginx 
[root@zabbixserver ~]# ss -antlp|grep "80"
LISTEN     0      128          *:80                       *:*                   users:(("nginx",pid=14854,fd=6),("nginx",pid=14853,fd=6))

###设置开机自动启动
[root@zabbixserver ~]# echo '/usr/local/nginx/sbin/nginx' >> /etc/rc.d/rc.local
[root@zabbixserver ~]# chmod +x /etc/rc.d/rc.local

编译安装zabbix

###安装zabbixserver依赖包
[root@zabbixserver ~]# yum install -y net-snmp-devel curl-devel autoconf libevent-devel

 ###编译安装zabbix
 [root@zabbixserver ~]# tar xf zabbix-3.4.4.tar.gz 
 [root@zabbixserver ~]# cd zabbix-3.4.4/
 ###生成安装配置文件
  [root@zabbixserver zabbix-3.4.4]# ./configure --enable-server --enable-agent --with-mysql=/usr/bin/mysql_config --with-net-snmp --with-libcurl
##--enable-server  安装服务器端
##--enable-agent 安装被控端
##--with-mysql 指定mysql数据库配置程序
##--with-net-snmp 配置可以通过snmp收集数据
--with-libcurl 启用curl库,以便zabbix可以通过curl连接web服务
##--enable-proxy:启动proxy代理,不必安装
##
##make安装
[root@zabbixserver zabbix-3.4.4]# make && make install

创建存zabbix数据的数据库

[root@zabbixserver database]# mysql

###创建一个名为zabbix的数据库, 
##default charset utf8 字符集utf-8
MariaDB [(none)]> create database zabbix default charset utf8;
##创建zabbix用户
 MariaDB [(none)]> grant all on zabbix.* to zabbix@'%' identified by 'zabbix';
##本机ip加上访问权限
MariaDB [(none)]> grant all on zabbix.* to zabbix@'localhost' identified by 'zabbix';

##切换到zabbix数据库
 MariaDB [(none)]> use zabbix;
 
 #切换到mysql脚本目录
  [root@zabbixserver mysql]# pwd
/root/zabbix-3.4.4/database/mysql

  ##执行zabbix创建数据库脚本,注意安装先后顺序
  #执行schema.sql脚本
  [root@zabbixserver mysql]# mysql -uzabbix -pzabbix zabbix< schema.sql
  ##执行images.sql脚本
  [root@zabbixserver mysql]# mysql -uzabbix -pzabbix zabbix< images.sql  
    ##执行data.sql脚本
  [root@zabbixserver mysql]# mysql -uzabbix -pzabbix zabbix< data.sql 
  

创建zabbix运行用户

##-s /sbin/nolog 设置不能登录
[root@zabbixserver zabbix-3.4.4]# useradd -s /sbin/nolog zabbix

启动zabbix服务器

[root@zabbixserver ~]# vim /usr/lib/systemd/system/zabbix_server.service
#####文件内容######
[Unit]
Description=zabbix server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/tmp/zabbix_server.pid
ExecStart=/usr/local/sbin/zabbix_server
ExecStop=/bin/kill ${MAINPID}
# We want systemd to give httpd some time to finish gracefully, but still want
# it to kill httpd after TimeoutStopSec if something went wrong during the
# graceful stop. Normally, Systemd sends SIGTERM signal right after the
# ExecStop, which would kill httpd. We are sending useless SIGCONT here to give
# httpd time to finish.

[Install]
WantedBy=multi-user.target


###############3
##重新加载systemct
[root@zabbixserver ~]# systemctl daemon-reload

##设置开机自启
[root@zabbixserver system]# systemctl enable zabbix_server.service

##启动
[root@zabbixserver system]# systemctl start zabbix_server.service

 ##查看服务状态
[root@zabbixserver system]# ss -tnlp|grep "10051"

配置agent,自己被监控

[root@zabbixserver system]# vim /usr/local/etc/zabbix_agentd.conf

image-20250917221601358

配置被监控端server启动

##打开
[root@zabbixserver ~]# vim /usr/lib/systemd/system/zabbix_agentd.service 
###########配置内容##########3
[Unit]
Description=zabbix agent
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/tmp/zabbix_agentd.pid
ExecStart=/usr/local/sbin/zabbix_agentd
ExecStop=/bin/kill ${MAINPID}
# We want systemd to give httpd some time to finish gracefully, but still want
# it to kill httpd after TimeoutStopSec if something went wrong during the
# graceful stop. Normally, Systemd sends SIGTERM signal right after the
# ExecStop, which would kill httpd. We are sending useless SIGCONT here to give
# httpd time to finish.

[Install]
WantedBy=multi-user.target

####################################
##重新加载配置
[root@zabbixserver ~]# vim /usr/lib/systemd/system/zabbix_agentd.service 
[root@zabbixserver ~]# systemctl enable zabbix_agentd.service
[root@zabbixserver ~]# systemctl start zabbix_agentd.service
[root@zabbixserver ~]# ss -tlnp|grep "10050"
LISTEN     0      128          *:10050                    *:*                   users:(("zabbix_agentd",pid=1778,fd=4),("zabbix_agentd",pid=1777,fd=4),("zabbix_agentd",pid=1776,fd=4),("zabbix_agentd",pid=1775,fd=4),("zabbix_agentd",pid=1774,fd=4),("zabbix_agentd",pid=1773,fd=4))


Web界面配置

### 复制php web文件到nginx中的html目录,-r 递归复制,可复制文件夹,-f 强制覆盖,因为cp有别名,所以cp -rf还会有提示,需要绝对路径执行,注释别名
[root@zabbixserver ~]# /bin/cp -rf zabbix-3.4.4/frontends/php/* /usr/local/nginx/html/
##安装php,会自动创建apache账号
 [root@zabbixserver ~]# id apache
uid=48(apache) gid=48(apache) 组=48(apache)
##修改所属组 权限
 [root@zabbixserver ~]# chown -R apache:apache /usr/local/nginx/html/
###访问地址,打开安装页面

image-20250917221710604

zabbix网页出现错误,需要修改php配置文件

image-20250917221734007

需要做以下配置

[root@zabbixserver ~]# yum install -y php-gd php-xml php-bcmath php-mbstring

重启服务,页面正常

image-20250917221812848

配置web1环境

上传zabbix源码包

配置编译安装环境

###配置编译安装环境
[root@web1 zabbix-3.4.4]# yum install -y gcc pcre-devel autoconf

###安装zabbix客户端
[root@web1 zabbix-3.4.4]# ./configure --enable-agent

####编译安装
[root@web1 zabbix-3.4.4]# make && make install

修改配置文件

image-20250917222014255

##添加zabbix用户
[root@web1 zabbix-3.4.4]# useradd -s /sbin/nologin zabbix

###拷贝zabbix_agentd.service文件到被监控端
 [root@zabbixserver ~]# scp /usr/lib/systemd/system/zabbix_agentd.service 192.168.4.100:/usr/lib/systemd/system/
 
 
 #设置开机自启,并重启
  [root@web1 zabbix-3.4.4]# systemctl enable zabbix_agentd.service --now
Created symlink from /etc/systemd/system/multi-user.target.wants/zabbix_agentd.service to /usr/lib/systemd/system/zabbix_agentd.service.

 
  ##检查是否运行成功
[root@web1 zabbix-3.4.4]# ss -tlnp|grep "10050"
LISTEN     0      128          *:10050                    *:*                   users:(("zabbix_agentd",pid=9003,fd=4),("zabbix_agentd",pid=9002,fd=4),("zabbix_agentd",pid=9001,fd=4),("zabbix_agentd",pid=9000,fd=4),("zabbix_agentd",pid=8999,fd=4),("zabbix_agentd",pid=8998,fd=4),("zabbix_agentd",pid=8997,fd=4))


在zabbix web管理平台中配置监控

  • 主机:安装了agent,被监控的主机
  • 主机组:根据需求,将多台主机加入到一个主机组中,方便管理。系统默认已经创建了一些主机组。
  • 模板:是监控项的集合。将模板应用到主机,主机就可以直接拥有模板中的所有监控项。系统中默认已经创建了一些模板

添加被监控的主机

http://192.168.4.5/index.php

image-20250917222117503

image-20250917222127884

image-20250917222144920

image-20250917222200683

常用的监控指标:

  • CPU idle time:CPU空闲时间。不宜过低。
  • Processor load(1 min average per core) / Processor load(5 min average per core) / Processor load(15 min average per core):每核心1分钟、5分钟、15分钟的平均负载。这个值不应长期大于1。
  • Free disk sapce on /:根分区剩余的空间
  • Free disk sapce on /(percentage):根分区剩余的空间百分比
  • Available memory:可用内存
  • Incoming network traffic on eth0:eth0网卡进入的流量
  • Outgoing network traffic on eth0:eth0网卡外出的流量
  • Maximum number of processes:系统最多运行的进程数
  • Number of logged in users:已登陆的用户数

实现监控web1用户数量的监控项

  1. 在被控端创建key。被控端被监控的内容叫作key,可以理解为它就是一个变量名,具体的名字自己决定。
  2. 在web页面中创建监控项。监控项对应key值。
  3. 监控项存在应用集中。应用集就是相似监控项的集合。
  4. 应用集存在模板中。一个模板可以包含多个应用集。\

image-20250917222236360

在被控端创建key

UserParameter=自定义key值,命令
# 命令的执行结果,是key的value

#####配置文件
###vim 后面+264 是直接跳到264
[root@zabbixserver ~]# vim +264 /usr/local/etc/zabbix_agentd.conf

###创建文件
 [root@zabbixserver ~]# vim /usr/local/etc/zabbix_agentd.conf.d/conunt.line.passwd
 
  ###在文件中写入这一行
  UserParameter=count.line.passwd,sed -n '$=' /etc/passwd


 ###改完重启服务
[root@web1 ~]# systemctl restart zabbix_agentd.service
###
###在被控端验证服务是否能正常获取数据
[root@web1 ~]# zabbix_get -s 127.0.0.1 -k count.line.passwd
22

 ###在监控端验证服务是否能正常获取数据
[root@zabbixserver ~]# zabbix_get -s 192.168.4.100 -k count.line.passwd
22


配置告警

  • 默认情况下,监控项不会自动发送告警消息
  • 需要配置触发器与告警,并且通过通知方式发送信息给联系人
  • 触发器:设置条件,当条件达到时,将会执行某个动作
  • 动作:触发器条件达到之后要采取的行为,比如发邮件或执行命令

用户超过35时,发送告警邮件

  • 当web1的用户数超过35时,认为这是一个问题(Problem)
  • 当出现问题时,将会执行动作。
  • 执行的动作是给管理员发邮件。
  • 给管理员发邮件,还要配置邮件服务器的地址,以及管理员的email地址

实施

配置-->模板-->触发器

表达式语法:

{<server>:<key>.<function>(<parameter>)}<operator><constant>
{<主机>:<key>.<函数>(<参数>)}<操作符><常量>
{count.line.passwd:count.line.passwd.last()}>35
# count.line.passwd是模板
# count.line.passwd是在被控端上定义的key
# last是函数,表示最近的一次取值
# > 是操作符
# 35 是常量
# 以上表达式的含义是:应用count.line.passwd模板的主机,它的count.line.passwd最近一次取值大于35,则状态为“问题”,即Problem

配置邮箱告警

image-20250917222417254

image-20250917222428386

模板的使用

Zabbix最强大的地方就是模板系统。官方提供了很多现成的模板,基本覆盖了常见的监控需求。

给主机关联模板很简单,编辑主机配置,在Templates标签页搜索并添加需要的模板。比如Linux主机可以添加"Linux by Zabbix agent"模板。

这个模板包含了CPU、内存、磁盘、网络等基础监控项,还有相应的触发器。添加后等几分钟就能看到监控数据了。

我记得第一次看到那些花花绿绿的图表时还挺兴奋的,感觉自己瞬间变成了运维大神。不过后来发现,看图表容易,分析问题才是真功夫。

自定义监控项

虽然模板很方便,但有时候还是需要自定义一些监控项。比如监控某个特定的进程或者自定义的脚本输出。

创建监控项的步骤:

  1. 进入Configuration -> Hosts
  2. 点击主机名进入详情
  3. 点击Items标签页
  4. 点击"Create item"

关键参数说明:

  • Name: 监控项名称
  • Type: 监控类型,常用的有Zabbix agent、SNMP、SSH等
  • Key: 监控项的键值,这个很重要
  • Type of information: 数据类型
  • Update interval: 更新间隔

举个例子,监控系统负载:

Name: System load 1 minute
Type: Zabbix agent
Key: system.cpu.load[all,avg1]
Type of information: Numeric (float)
Update interval: 1m

Key是Zabbix预定义的,文档里有完整列表。也可以自定义Key,但需要在agent配置文件中定义相应的脚本。

分布式监控架构

如果监控的主机比较多,单台Zabbix server可能扛不住。这时候就需要用到Zabbix proxy了。

Proxy相当于一个中转站,负责收集一部分主机的数据,然后统一上报给Zabbix server。这样可以减轻server的压力,也能解决网络隔离的问题。

安装Proxy的步骤和Server类似,只是配置文件不同:

yum install -y zabbix-proxy-mysql

配置文件 /etc/zabbix/zabbix_proxy.conf 主要参数:

Server=zabbix-server-ip
Hostname=zabbix-proxy-01
DBHost=localhost
DBName=zabbix_proxy
DBUser=zabbix
DBPassword=password

Proxy需要单独的数据库,但不需要导入完整的数据结构:

zcat /usr/share/doc/zabbix-sql-scripts/mysql/proxy.sql.gz | mysql -uzabbix -p zabbix_proxy

在Zabbix server的Web界面添加proxy:Administration -> Proxies -> Create proxy。

然后在配置主机时选择对应的proxy就行了。

我之前在一个项目中用过这种架构,总共监控了200多台服务器,分布在3个机房。每个机房部署一个proxy,效果还不错。

常见问题排查

用Zabbix这么久,踩过的坑也不少。分享几个常见问题的解决方法:

Agent连接不上

这个最常见,一般是防火墙或者配置问题。先检查agent是否正常运行:

systemctl status zabbix-agent

然后检查端口是否监听:

netstat -tlnp | grep 10050

如果都正常,就检查防火墙设置。还有就是确认agent配置文件中的Server参数是否正确。

监控项变成不支持状态

这种情况通常是Key写错了,或者agent版本不支持某个Key。可以在agent主机上手动测试:

zabbix_get -s 127.0.0.1 -k system.cpu.load

如果返回错误信息,就知道问题出在哪了。

数据库连接失败

检查数据库服务是否正常,用户权限是否正确。还有就是确认配置文件中的数据库连接参数。

Web界面访问慢

通常是数据库查询慢导致的,可以开启慢查询日志分析一下。或者检查是否有大量历史数据没有清理。

高级功能探索

Zabbix还有一些高级功能,虽然平时用得不多,但关键时刻很有用。

网络发现

可以自动发现网络中的设备并添加监控。配置起来有点复杂,但对于大规模环境很有用。进入Configuration -> Discovery,创建发现规则。

低级发现

这个功能很强大,可以自动发现文件系统、网络接口等。比如自动监控所有挂载点的磁盘使用率,不用手动一个个添加。

Web监控

可以监控网站的可用性和响应时间,支持复杂的场景,比如模拟用户登录流程。

SNMP监控

对于网络设备监控很有用,交换机、路由器基本都支持SNMP。配置相对简单,主要是MIB的理解需要一些网络基础。

与其他工具的集成

现在很少有系统是完全独立的,Zabbix也需要和其他工具配合使用。

和Grafana集成

虽然Zabbix自带图形功能,但Grafana的展示效果确实更好。可以通过Zabbix插件让Grafana读取Zabbix的数据。

和自动化工具集成

可以通过Zabbix的API实现和Ansible、Puppet等工具的集成。比如发现问题后自动执行修复脚本。

和日志系统集成

虽然Zabbix不是专门的日志分析工具,但可以监控日志文件中的关键字。配合ELK这样的日志系统使用效果更好。

安全考虑

监控系统本身也需要考虑安全问题,毕竟它能看到整个基础设施的状态。

首先是访问控制,Zabbix支持用户组和权限管理。不同的人员应该只能看到相关的监控数据。

然后是网络安全,agent和server之间的通信可以配置加密。虽然会有一些性能损失,但在安全要求高的环境中是必要的。

还有就是定期更新,Zabbix的安全补丁还是比较及时的。我一般会关注官方的安全公告,有重要更新就及时升级。

数据库安全也很重要,不要用默认密码,定期备份数据。我见过有公司的监控数据被删了,几个月的历史数据全没了,那叫一个惨。

实际应用案例

说了这么多理论,来个实际案例。我之前负责一个电商网站的监控,大概50台服务器,包括Web服务器、数据库、缓存、消息队列等。

监控架构是这样的:

  • 1台Zabbix server,配置比较高
  • 2台Proxy,分别负责不同机房
  • 所有服务器安装agent

重点监控项目:

  • 基础资源:CPU、内存、磁盘、网络
  • 应用服务:Nginx、PHP-FPM、MySQL、Redis
  • 业务指标:订单量、支付成功率、页面响应时间

告警策略比较严格,CPU超过80%就告警,内存超过85%告警。磁盘空间低于20%就发短信,低于10%直接打电话。

效果还不错,基本能在问题影响用户之前发现并解决。有一次数据库主从同步出问题,通过监控及时发现,避免了数据不一致的问题。

当然也有翻车的时候,有次配置触发器时写错了表达式,结果半夜疯狂发告警短信,把整个技术团队都吵醒了。第二天被骂得狗血淋头,从此配置告警都格外小心。


如果这篇文章对你有帮助,别忘了点赞转发支持一下!想了解更多运维实战经验和技术干货,记得关注微信公众号@运维躬行录,领取学习大礼包!!!我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习,共同进步!

公众号:运维躬行录

个人博客:躬行笔记

文章目录

博主介绍

热爱技术的云计算运维工程师,Python全栈工程师,分享开发经验与生活感悟。
欢迎关注我的微信公众号@运维躬行录,领取海量学习资料

微信二维码