Enterprise Infrastructure Telemetry: Zabbix 7 LTS, TimescaleDB Hypertables, Zabbix Agent 2 & PSK Encryption
Executive Summary: While synthetic ping monitors tell you whether an endpoint responds, true infrastructure observability requires deep kernel, storage, SMART, systemd, and SNMP hardware telemetry correlated with predictive anomaly triggers. This architectural reference details the production deployment of Zabbix 7.0 LTS backed by PostgreSQL 17 + TimescaleDB hypertable compression, Go-based Zabbix Agent 2 with TLS Pre-Shared Key (
PSK) encryption, SNMPv3 network switch polling, and hysteresis trigger engineering.
-
TimescaleDB Hypertable Compression
Partition
historyandtrendstables into time-series chunks with native columnar compression (~90% disk reduction) and instant chunk drops instead of slow SQLDELETEloops. -
Zabbix Agent 2 (Go Architecture)
Replace legacy C agents with the concurrent Go-based
zabbix-agent2supporting native Docker, systemd, SMART (smartctl), PostgreSQL, and Redis plugins. -
TLS-PSK Encrypted Active Checks
Authenticate and encrypt all agent-to-server telemetry over port
10050/10051using 256-bit Pre-Shared Keys (TLSConnect=psk). -
Predictive & Hysteresis Triggers
Eliminate flapping alerts using recovery expressions,
timeleft()disk-exhaustion forecasting, and Low-Level Discovery (LLD) prototypes.
1. Architecture: Zabbix Server Pollers, Active/Passive Agents & TimescaleDB
Zabbix 7 LTS operates a multi-process C server engine (zabbix_server) with dedicated internal worker pools (Poller, Trapper, HistorySyncer, Preprocessor, LLDManager) writing high-velocity metric streams into PostgreSQL + TimescaleDB:
%%{init: {'flowchart': {'wrappingWidth': 600, 'subGraphTitleMargin': {'top': 15, 'bottom': 15}}}}%%
flowchart TB
subgraph MonitoredFleet["Monitored Infrastructure Fleet"]
LinuxHost["Linux Nodes (Zabbix Agent 2)<br/>Systemd + SMART + Docker<br/>TLS-PSK :10050/:10051"]
Switch["Managed Core Switches<br/>SNMPv3 authPriv (SHA/AES)"]
end
subgraph ZabbixCore["Zabbix 7.0 LTS Core Engine"]
Pollers["Poller & Trapper Pool<br/>Preprocessors + LLD Engine"]
VCache["ValueCache & HistoryCache<br/>Shared Memory Buffers"]
WebUI["Zabbix Web Frontend<br/>Nginx + PHP-FPM"]
end
subgraph StorageTier["Time-Series Storage Backend"]
TSDB[("PostgreSQL 17 + TimescaleDB<br/>Compressed Hypertable Chunks")]
end
LinuxHost <-->|"Encrypted TLS-PSK"| Pollers
Switch -->|"SNMPv3 BulkWalk"| Pollers
Pollers --> VCache
VCache -->|"Batch Insert"| TSDB
WebUI <--> TSDB
Why TimescaleDB Eliminates the Zabbix "Housekeeper" Bottleneck
In a standard relational database, Zabbix's internal Housekeeper process periodically executes massive DELETE FROM history WHERE clock < ... queries to purge expired metrics. On large installations, this causes severe PostgreSQL table bloat, high I/O wait, and autovacuum thrashing. With TimescaleDB, the history, history_uint, and trends tables are partitioned into time chunks (e.g., 1-day intervals). Dropping 90-day-old data becomes an instantaneous drop_chunks() metadata operation requiring zero row-by-row deletion.
2. Production Stack: Zabbix 7.0 LTS + PostgreSQL 17 TimescaleDB
services:
postgres-tsdb:
image: timescale/timescaledb-ha:pg17
container_name: zabbix-timescaledb
restart: unless-stopped
shm_size: "1g"
environment:
POSTGRES_USER: zabbix
POSTGRES_PASSWORD: "${ZBX_DB_PASSWORD}"
POSTGRES_DB: zabbix
command:
- "postgres"
- "-c"
- "shared_buffers=1GB"
- "-c"
- "work_mem=32MB"
- "-c"
- "maintenance_work_mem=256MB"
- "-c"
- "max_connections=200"
volumes:
- ./pgdata:/home/postgres/pgdata/data:Z
networks:
- zbx_net
zabbix-server:
image: zabbix/zabbix-server-pgsql:alpine-7.0-latest
container_name: zabbix-server
restart: unless-stopped
depends_on:
- postgres-tsdb
ports:
- "10051:10051/tcp"
environment:
DB_SERVER_HOST: postgres-tsdb
POSTGRES_USER: zabbix
POSTGRES_PASSWORD: "${ZBX_DB_PASSWORD}"
POSTGRES_DB: zabbix
ZBX_ENABLE_SNMP_TRAPS: "false"
# Tune Internal Pollers and Shared Memory Caches
ZBX_STARTPOLLERS: 10
ZBX_STARTPREPROCESSORS: 8
ZBX_STARTLLDPROCESSORS: 4
ZBX_CACHESIZE: 64M
ZBX_HISTORYCACHESIZE: 64M
ZBX_HISTORYINDEXCACHESIZE: 32M
ZBX_TRENDCACHESIZE: 32M
ZBX_VALUECACHESIZE: 128M
networks:
- zbx_net
zabbix-web:
image: zabbix/zabbix-web-nginx-pgsql:alpine-7.0-latest
container_name: zabbix-web
restart: unless-stopped
depends_on:
- postgres-tsdb
- zabbix-server
ports:
- "127.0.0.1:8085:8080/tcp"
environment:
ZBX_SERVER_HOST: zabbix-server
DB_SERVER_HOST: postgres-tsdb
POSTGRES_USER: zabbix
POSTGRES_PASSWORD: "${ZBX_DB_PASSWORD}"
POSTGRES_DB: zabbix
PHP_TZ: "Europe/Berlin"
networks:
- zbx_net
networks:
zbx_net:
driver: bridge
Enable the TimescaleDB extension and initialize Zabbix's hypertable schema after initial startup:
# 1. Create the TimescaleDB extension inside the zabbix database
docker exec -i zabbix-timescaledb psql -U zabbix -d zabbix \
-c "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;"
# 2. Apply the official Zabbix TimescaleDB schema migration script
docker exec -i zabbix-server cat /usr/share/doc/zabbix-sql-scripts/postgresql/timescaledb/schema.sql \
| docker exec -i zabbix-timescaledb psql -U zabbix -d zabbix
3. Deploying Zabbix Agent 2 with TLS-PSK Encryption & SMART/Docker Plugins
On every monitored Linux host, install zabbix-agent2 (written in Go) rather than the legacy zabbix-agent package. Generate a 256-bit hexadecimal Pre-Shared Key (PSK):
# 1. Generate a 256-bit (32-byte hex) Pre-Shared Key
sudo mkdir -p /etc/zabbix/psk
openssl rand -hex 32 | sudo tee /etc/zabbix/psk/agent.psk
sudo chown -R zabbix:zabbix /etc/zabbix/psk
sudo chmod 0400 /etc/zabbix/psk/agent.psk
# 2. Grant zabbix user access to Docker socket and NVMe/SATA SMART telemetry
sudo usermod -aG docker zabbix
cat << 'EOF' | sudo tee /etc/sudoers.d/zabbix-smartctl
zabbix ALL=(ALL) NOPASSWD: /usr/sbin/smartctl
EOF
sudo chmod 0440 /etc/sudoers.d/zabbix-smartctl
Configure /etc/zabbix/zabbix_agent2.conf to enforce psk encryption for both passive and active checks:
Server=192.168.10.25
ServerActive=192.168.10.25
Hostname=proxmox-node-01.lan.nejat-hakan.de
# Enforce TLS-PSK for both incoming (Passive) and outgoing (Active) connections
TLSConnect=psk
TLSAccept=psk
TLSPSKIdentity=PSK_PROXMOX_NODE_01
TLSPSKFile=/etc/zabbix/psk/agent.psk
# Enable built-in Go plugins for Systemd, Docker, and SMART disk health
Plugins.Smart.Path=/usr/sbin/smartctl
4. Engineering Flapping-Resistant Triggers (Hysteresis & Forecasting)
Naive threshold triggers (last(/host/system.cpu.util) > 85) fire and resolve repeatedly whenever a metric hovers between 84.9% and 85.1%. In Zabbix 7 expression syntax, combine time-window averages, Hysteresis recovery expressions, and linear regression forecasting (timeleft):
# 1. Hysteresis Trigger: Alert when 5m CPU load > 85%, resolve only when 10m CPU load drops < 70%
Problem Expression: avg(/Linux by Zabbix agent/system.cpu.util, 5m) > 85
Recovery Expression: avg(/Linux by Zabbix agent/system.cpu.util, 10m) < 70
# 2. Predictive Disk Exhaustion: Alert if linear regression predicts filesystem will hit 100% within 24h
Problem Expression: last(/Linux by Zabbix agent/vfs.fs.dependent.size[/,pused]) > 80
and timeleft(/Linux by Zabbix agent/vfs.fs.dependent.size[/,pused], 6h, 100) < 24h
# 3. NVMe / SATA SMART Critical Warning (Immediate Hardware Replacement Required)
Problem Expression: last(/SMART by Zabbix agent 2/smart.disk.critical_warning[{#NAME}]) > 0
5. Verification & Remote Agent Diagnostics
Use zabbix_get from the Zabbix server to verify TLS-PSK negotiation and test live zabbix-agent2 plugin keys:
# 1. Test local Agent 2 plugin keys directly on the monitored node
sudo zabbix_agent2 -t smart.disk.get
sudo zabbix_agent2 -t docker.containers
# 2. Query remote Agent 2 over TLS-PSK from the Zabbix server
docker exec zabbix-server zabbix_get \
-s 192.168.10.20 -p 10050 \
--tls-connect psk \
--tls-psk-identity "PSK_PROXMOX_NODE_01" \
--tls-psk-file /var/lib/zabbix/enc/agent.psk \
-k "system.uname"