Zabbix + PostgreSQL 16 + TimescaleDB 2.19.x 部署

Zabbix 支持 TimescaleDB 作为 PostgreSQL 扩展,用于大规模时间序列数据。

TimescaleDB 不支持给 Zabbix Proxy 当数据库 ,只能给中心 zabbix-server 的 PostgreSQL 后端使用。

Zabbix 7.0.6 开始把 TimescaleDB 最大支持版本提升到 2.17.x,7.0.13 提升到 2.19.x。

使用 Docker Compose 部署 PostgreSQL

  • pg16
  • timescaledb 2.19.x

目录结构示例:

.
├── config # postgresql 等配置文件路径
│ ├── pg_hba.conf
│ └── postgresql.conf
├── docker-compose.yaml
├── .env # 环境变量统一存储
├── initdb # 数据库初始化 sql,只有在数据库为空的情况下才会执行
│ ├── 01-create-zabbix-user.sql
│ ├── 02-create-timescaledb.sql
│ └── 03-create-db.sql
├── postgres-data # Postgresql/scaledb 持久化数据
│ └── pgdata
└── zabbix-data # zabbix 持久化数据
├── alertscripts
├── enc
├── export
├── externalscripts
└── ssl

10 directories, 6 files


.env 内容参考

.env
TZ=Asia/Shanghai

POSTGRES_DB=zabbix
POSTGRES_USER=postgres
POSTGRES_PASSWORD=ReplaceMe_SuperStrong_Zabbix

ZABBIX_DB_USER=zabbix
ZABBIX_DB_PASSWORD=ReplaceMe_SuperStrong_Zabbix

PGDATA=/var/lib/postgresql/data/pgdata

initdb 中的初始化 SQL

initdb/01-create-zabbix-user.sql
DO
$$
BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'zabbix') THEN
CREATE ROLE zabbix LOGIN PASSWORD 'ReplaceMe_SuperStrong_Zabbix';
END IF;
END
$$;

initdb/02-create-timescaledb.sql
CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;
initdb/03-create-db.sql
GRANT ALL PRIVILEGES ON DATABASE zabbix TO zabbix;
ALTER DATABASE zabbix OWNER TO zabbix;

Postgresql 主配置 config/postgresql.conf

config/postgresql.conf
listen_addresses = '*'
port = 5432
max_connections = 200

shared_buffers = 8GB
effective_cache_size = 24GB
work_mem = 32MB
maintenance_work_mem = 1GB

wal_level = replica
max_wal_size = 8GB
min_wal_size = 1GB
checkpoint_timeout = 15min
checkpoint_completion_target = 0.9
wal_compression = on

random_page_cost = 1.1
effective_io_concurrency = 200

default_statistics_target = 200
shared_preload_libraries = 'timescaledb'

autovacuum = on
autovacuum_max_workers = 5
autovacuum_naptime = 10s
autovacuum_vacuum_scale_factor = 0.02
autovacuum_analyze_scale_factor = 0.01

log_timezone = 'Asia/Shanghai'
timezone = 'Asia/Shanghai'
log_min_duration_statement = 1000
log_checkpoints = on
log_connections = off
log_disconnections = off
log_lock_waits = on

timescaledb.telemetry_level = off

config/pg_hba.conf 配置示例

# TYPE  DATABASE        USER            ADDRESS                 METHOD

local all all trust
host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256

# Docker 网段,仅示例
host zabbix zabbix 10.244.0.0/16 scram-sha-256
host zabbix zabbix 172.18.0.0/16 scram-sha-256

# 运维堡垒机
host all postgres 192.168.20.10/32 scram-sha-256

docker-compose.yaml 配置示例

docker-compose.yaml
services:
timescaledb:
image: timescale/timescaledb:2.19.3-pg16
container_name: zabbix-timescaledb
hostname: zabbix-timescaledb
restart: unless-stopped

env_file:
- .env

environment:
TZ: ${TZ}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
ZABBIX_DB_USER: ${ZABBIX_DB_USER}
ZABBIX_DB_PASSWORD: ${ZABBIX_DB_PASSWORD}
PGDATA: ${PGDATA}
POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256 --auth-local=trust --data-checksums"

ports:
- "5432:5432"

volumes:
- ./postgres-data:/var/lib/postgresql/data
- ./initdb:/docker-entrypoint-initdb.d:ro
- ./config/postgresql.conf:/etc/postgresql/postgresql.conf:ro
- ./config/pg_hba.conf:/etc/postgresql/pg_hba.conf:ro
- /etc/localtime:/etc/localtime:ro

command:
[
"postgres",
"-c", "config_file=/etc/postgresql/postgresql.conf",
"-c", "hba_file=/etc/postgresql/pg_hba.conf"
]

healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 12

ulimits:
nofile:
soft: 65536
hard: 65536

zabbix-server:
image: zabbix/zabbix-server-pgsql:alpine-7.4-latest
container_name: zabbix-server
hostname: zabbix-server
restart: unless-stopped

env_file:
- .env

environment:
TZ: ${TZ}
DB_SERVER_HOST: timescaledb
DB_SERVER_PORT: 5432
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${ZABBIX_DB_USER}
POSTGRES_PASSWORD: ${ZABBIX_DB_PASSWORD}
ENABLE_TIMESCALEDB: "true"

depends_on:
timescaledb:
condition: service_healthy

ports:
- "10051:10051"

volumes:
- ./zabbix-data/alertscripts:/usr/lib/zabbix/alertscripts:ro
- ./zabbix-data/externalscripts:/usr/lib/zabbix/externalscripts:ro
- ./zabbix-data/export:/var/lib/zabbix/export
- ./zabbix-data/enc:/var/lib/zabbix/enc
- /etc/localtime:/etc/localtime:ro

zabbix-web:
image: zabbix/zabbix-web-nginx-pgsql:alpine-7.4-latest
container_name: zabbix-web
hostname: zabbix-web
restart: unless-stopped

env_file:
- .env

environment:
DB_SERVER_HOST: timescaledb
DB_SERVER_PORT: 5432
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${ZABBIX_DB_USER}
POSTGRES_PASSWORD: ${ZABBIX_DB_PASSWORD}
ZBX_SERVER_HOST: zabbix-server
PHP_TZ: ${TZ}

depends_on:
- zabbix-server

ports:
- "8080:8080"

volumes:
- ./zabbix-data/ssl:/etc/ssl/nginx:ro
- /etc/localtime:/etc/localtime:ro


常用操作

从 Zabbix Server 测试 Zabbix Agent 连通性

以下命令可以用于在 Zabbix Server 检查到 Zabbix Agent 的连通性,连接 Agent 正常会返回 1

docker compose exec -T zabbix-server zabbix_get -s 172.247.1.1 -p 10050 -k agent.ping

如果防火墙已经放通,却依然无法连接,很可能是 zabbix-agent2 配置中的 Server= 配置的 IP 不是 Zabbix Server 实际使用的 IP。此时可以通过 tcpdump 抓包确定请求 Zabbix Agent 的 Zabbix Server IP

# tcpdump -n dst port 10050
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes

12:39:34.936583 IP 172.18.0.3.37688 > 172.247.2.14.10050: Flags [S], seq 1718798137, win 64240, options [mss 1460,sackOK,TS val 2935844814 ecr 0,nop,wscale 7], length 0
12:39:35.946554 IP 172.18.0.3.37688 > 172.247.2.14.10050: Flags [S], seq 1718798137, win 64240, options [mss 1460,sackOK,TS val 2935845824 ecr 0,nop,wscale 7], length 0