快速构建Zabbix7.0高可用监控方案

背景

​ 随着公司业务的不断发展,系统规模和客户群体日益庞大,传统的监控系统已经无法满足公司对于系统稳定性、安全性和可维护性的需求。为了解决这些问题,决定基于Zabbix7.0开源监控系统来构建全新的监控体系。本文将详细介绍基于Zabbix7.0+PostgreSQL+TimescaleDB开源监控系统建设过程中的实践经验,包括系统架构设计、proxy接入配置、数据采集等方面的内容。

架构图

whiteboard_exported_image

组件

Zabbix

Zabbix 是一款监控众多参数的网络以及服务器、虚拟机、应用程序、服务、数据库、网站、云等的健康和完整性的软件。Zabbix 使用灵活的通知机制,允许用户为几乎任何事件配置基于电子邮件的告警,以实现对服务器问题做出快速反应。Zabbix 基于存储的数据提供出色的报告和数据可视化功能。这使得 Zabbix 成为容量规划的理想选择。同时Zabbix 是一个企业级的开源分布式监控解决方案。

​ zabbix7中通过引入proxy groups来实现proxy的负载均衡。Proxy groups可以自动将主机分配给proxy,当proxy离线时,其监控的主机将立即被分配到组内的其他proxy,实现proxy负载均衡和高可用。

Pigsty

PostgreSQL In Great STYle”: Postgres, Infras, Graphics, Service, Toolbox, it’s all Yours.

—— 开箱即用、本地优先的 PostgreSQL 发行版,开源 RDS 替代

banner.zh

Pigsty可以让您立刻在本地拥有生产级的PostgreSQL数据库服务!

​ PostgreSQL 是一个足够完美的数据库内核,但它需要更多工具与系统的配合才能成为一个足够好的数据库服务(RDS),Pigsty 帮助 PostgreSQL 完成这一步飞跃。 Pigsty 为您解决使用 PostgreSQL 中会遇到的各种难题:内核扩展安装,连接池,负载均衡,服务接入,高可用 / 自动故障切换,日志收集,指标监控,告警,备份恢复,PITR,访问控制,参数调优,安全加密,证书签发,NTP,DNS,参数调优,配置管理,CMDB,管理预案… 您无需再为这些细节烦心劳神!

安装pigsty

1
2
curl -fsSL https://repo.pigsty.cc/get | bash -s v3.1.0
./install.yml
组件端口域名说明Demo地址
Nginx80/443h.pigstyWeb 服务总入口,本地YUM源home.pigsty.cc
AlertManager9093a.pigsty告警聚合/屏蔽页面a.pigsty.cc
Grafana3000g.pigstyGrafana 监控面板demo.pigsty.cc
Prometheus9090p.pigstyPrometheus 管理界面p.pigsty.cc

安装完之后可通过配置本地host访问相关组件

部署pgsql集群

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#### pigsty.yml
    pg-cu1:
      hosts:
        10.30.35.3: { pg_seq: 1, pg_role: primary } 
        10.30.35.4: { pg_seq: 2, pg_role: replica } 
        10.30.35.5: { pg_seq: 3, pg_role: replica } 
      vars: 
        pg_cluster: pg-cu1
        pg_databases:
          - name: zabbix
            pgbouncer: true
            extensions:
              - { name: timescaledb }
            owner: zabbix
        pg_users:
          - name: zabbix
            password: xxxxxxx
            pgbouncer: true
            roles: [dbrole_admin]
        pg_hba_rules:
          - { user: 'zabbix'  ,db: all ,addr: 0.0.0.0/0    ,auth: pwd ,title: 'zabbix用户不限制登录'}
        pgb_hba_rules: 
          - { user: 'zabbix'  ,db: all  ,addr: 0.0.0.0/0   ,auth: pwd ,title: 'zabbix用户不限制登录'}
        pg_libs: 'timescaledb, pg_stat_statements, auto_explain'
        pg_vip_enabled: true
        pg_vip_address: 10.30.35.10/24
        pg_vip_interface: ens192

TimescaleDB

​ Zabbix支持TimescaleDB,这是一种基于PostgreSQL的数据库解决方案,可自动将数据分为基于时间的块,以支持更快的大规模性能。

​ 数据库启用 TimescaleDB 扩展

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
CREATE OR REPLACE FUNCTION cuid_timestamp(cuid varchar(25)) RETURNS integer AS $$
DECLARE
        base36 varchar; 
        a char[];
        ret bigint;
        i int;
        val int;
        chars varchar;
BEGIN
        base36 := substring(cuid FROM 2 FOR 8);

        chars := '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

        FOR i IN REVERSE char_length(base36)..1 LOOP
                a := a || substring(upper(base36) FROM i FOR 1)::char;
        END LOOP;
        i := 0;
        ret := 0;
        WHILE i < (array_length(a, 1)) LOOP
                val := position(a[i + 1] IN chars) - 1;
                ret := ret + (val * (36 ^ i));
                i := i + 1;
        END LOOP;

        RETURN CAST(ret/1000 AS integer);
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE;
DROP FUNCTION IF EXISTS base36_decode(character varying);

DO $$
DECLARE
        minimum_postgres_version_major          INTEGER;
        minimum_postgres_version_minor          INTEGER;
        current_postgres_version_major          INTEGER;
        current_postgres_version_minor          INTEGER;
        current_postgres_version_full           VARCHAR;

        minimum_timescaledb_version_major       INTEGER;
        minimum_timescaledb_version_minor       INTEGER;
        current_timescaledb_version_major       INTEGER;
        current_timescaledb_version_minor       INTEGER;
        current_timescaledb_version_full        VARCHAR;

        current_db_extension                    VARCHAR;
BEGIN
        SELECT 10 INTO minimum_postgres_version_major;
        SELECT 9 INTO minimum_postgres_version_minor;
        SELECT 2 INTO minimum_timescaledb_version_major;
        SELECT 0 INTO minimum_timescaledb_version_minor;

        SHOW server_version INTO current_postgres_version_full;

        IF NOT found THEN
                RAISE EXCEPTION 'Cannot determine PostgreSQL version, aborting';
        END IF;

        SELECT substring(current_postgres_version_full, '^(\d+).') INTO current_postgres_version_major;
        SELECT substring(current_postgres_version_full, '^\d+.(\d+)') INTO current_postgres_version_minor;

        IF (current_postgres_version_major < minimum_postgres_version_major OR
                        (current_postgres_version_major = minimum_postgres_version_major AND
                        current_postgres_version_minor < minimum_postgres_version_minor)) THEN
                RAISE EXCEPTION 'PostgreSQL version % is NOT SUPPORTED (with TimescaleDB)! Minimum is %.%.0 !',
                                current_postgres_version_full, minimum_postgres_version_major,
                                minimum_postgres_version_minor;
        ELSE
                RAISE NOTICE 'PostgreSQL version % is valid', current_postgres_version_full;
        END IF;

        SELECT extversion INTO current_timescaledb_version_full FROM pg_extension WHERE extname = 'timescaledb';

        IF NOT found THEN
                RAISE EXCEPTION 'TimescaleDB extension is not installed';
        ELSE
                RAISE NOTICE 'TimescaleDB extension is detected';
        END IF;

        SELECT substring(current_timescaledb_version_full, '^(\d+).') INTO current_timescaledb_version_major;
        SELECT substring(current_timescaledb_version_full, '^\d+.(\d+)') INTO current_timescaledb_version_minor;

        IF (current_timescaledb_version_major < minimum_timescaledb_version_major OR
                        (current_timescaledb_version_major = minimum_timescaledb_version_major AND
                        current_timescaledb_version_minor < minimum_timescaledb_version_minor)) THEN
                RAISE EXCEPTION 'TimescaleDB version % is UNSUPPORTED! Minimum is %.%.0!',
                                current_timescaledb_version_full, minimum_timescaledb_version_major,
                                minimum_timescaledb_version_minor;
        ELSE
                RAISE NOTICE 'TimescaleDB version % is valid', current_timescaledb_version_full;
        END IF;

        SELECT db_extension FROM config INTO current_db_extension;

        PERFORM create_hypertable('history', 'clock', chunk_time_interval => 86400, migrate_data => true, if_not_exists => true);
        PERFORM create_hypertable('history_uint', 'clock', chunk_time_interval => 86400, migrate_data => true, if_not_exists => true);
        PERFORM create_hypertable('history_log', 'clock', chunk_time_interval => 86400, migrate_data => true, if_not_exists => true);
        PERFORM create_hypertable('history_text', 'clock', chunk_time_interval => 86400, migrate_data => true, if_not_exists => true);
        PERFORM create_hypertable('history_str', 'clock', chunk_time_interval => 86400, migrate_data => true, if_not_exists => true);
        PERFORM create_hypertable('history_bin', 'clock', chunk_time_interval => 86400, migrate_data => true, if_not_exists => true);
        PERFORM create_hypertable('auditlog', 'auditid', chunk_time_interval => 604800,
                        time_partitioning_func => 'cuid_timestamp', migrate_data => true, if_not_exists => true);
        PERFORM create_hypertable('trends', 'clock', chunk_time_interval => 2592000, migrate_data => true, if_not_exists => true);
        PERFORM create_hypertable('trends_uint', 'clock', chunk_time_interval => 2592000, migrate_data => true, if_not_exists => true);

        IF (current_db_extension = 'timescaledb') THEN
                RAISE NOTICE 'TimescaleDB extension is already installed; not changing configuration';
        ELSE
                UPDATE config SET db_extension='timescaledb',hk_history_global=1,hk_trends_global=1;
                UPDATE config SET compression_status=1,compress_older='7d';
        END IF;

        RAISE NOTICE 'TimescaleDB is configured successfully';
END $$;

部署

Zabbix Server 7.0

部署zabbix 7.0 参考 install

​ Zabbix提供了一个本地的高可用性解决方案,方便设置,不需要任何HA专业知识也可以完成。本地Zabbix HA对于防止Zabbix server的软件/硬件故障或减少维护停机时间是有用的。

Zabbix高可用模式下,多台Zabbix server作为集群中的节点运行。 当集群中的一个Zabbix server 处于active 时,其他服务器处于standy,随时准备在必要时接管。

zabbix_ha

zabbix server 配置

#### zabbix_server-1.conf

## pgsql conf
DBHost=10.20.3.x
DBPort=5436
DBName=zabbix
DBUser=zabbix
DBPassword=xxxx
### Zabbix Ha conf
HANodeName=zabbix-server-01 
NodeAddress=10.20.3.130

#### zabbix_server-2.conf
## pgsql conf
DBHost=10.20.3.x
DBPort=5436
DBName=zabbix
DBUser=zabbix
DBPassword=xxxx
### Zabbix Ha conf
HANodeName=zabbix-server-02
NodeAddress=10.20.3.131

Zabbix Proxy

​ 对于主动代理,节点名称必须列在 proxy 服务器参数中,以分号分隔。

Server=zabbix-server-01;zabbix-server-02

在zabbix web配置proxy为proxy组,后将节点加入到proxy组

image-20241216154812172

Zabbix Agent

zabbix_ha_agent

Server=zabbix-proxy-01,zabbix-proxy-02 				# 
ServerActive=zabbix-proxy-01;zabbix-proxy-02  # 对于主动检查agent,节点与其他server之间必须用逗号分隔,而节点本身必须用分号分隔

高可用测试

pgsql高可用测试

手动关闭pgsql master节点,观察告警和数据收集情况

结论: master节点触发异常告警,zabbix访问正常,数据收集正常,启动master1,节点服务正常

zabbix server 高可用测试

00e4d87d-e5c1-468c-bf78-90076b40986a

1.手动关闭01节点server服务

7e7f6220-d9a6-429b-a15b-847c73f5ea91

2.访问zabbix web节点正常,数据收集正常

1fbde61d-d807-4190-a310-4abf608afc51

3.另一台server 状态为stop,手动开启server,节点状态变更为standby

4b84049c-a67d-4c16-94f8-3dd54d1b76a6

总结

​ 通过配置Zabbix高可用方案,主节点发生故障时可以迅速切换到备用节点,确保监控系统不间断。使用TimescaleDB的分片技术和Zabbix的分布式架构,Zabbix Proxy部署在各个分支节点或边缘设备上,负责将采集到的数据传输到Zabbix Server,减轻主节点的负担。可以大幅提升系统的可扩展性和容灾能力,可以有效提升企业监控系统的可靠性和稳定性,确保业务系统的持续健康运行。

引用

zabbix: https://www.zabbix.com/documentation/7.0/zh/manual pigsty: https://pigsty.cc