控平臺:從配置到告警的完整實踐)
想了很久在監(jiān)控工具里到底該選誰最后還是把 Zabbix 7.4 用 Docker 跑了起來。這套組合不是靈光一閃而是因為 Zabbix 本身是開源監(jiān)控里功能最完整的那一檔加上 7.4 這個版本在可視化、告警和采集性能上都做了不少優(yōu)化Docker 又能把部署成本壓到最低。這篇東西就是記錄我實際部署的全過程包括 compose 文件的寫法、環(huán)境變量怎么配、踩過哪些坑適合正在做監(jiān)控選型、或者剛接手 Zabbix 的人直接抄作業(yè)。1. 為什么要用 Docker 跑 Zabbix 7.41.1 Zabbix 7.4 解決了什么問題Zabbix 7.4 給我的第一感覺是“終于把界面和配置邏輯理順了”。老版本里常用的儀表盤、主機組、模板關(guān)聯(lián)都藏在多級菜單里新版本明顯做了一次收攏很多操作不用再跳來跳去。另一個比較實在的變化是監(jiān)控項的處理效率官方給出的數(shù)據(jù)是單臺 server 可以支撐的監(jiān)控項數(shù)量比之前版本更進一步實際用下來同一套配置下歷史數(shù)據(jù)查詢的響應(yīng)速度也要快一些。不過選 7.4 最重要的原因是它對容器環(huán)境更友好。官方鏡像倉庫里提供了 server、web、agent 的全套鏡像tag 直接對應(yīng)版本號不再需要自己用源碼編譯或者手工改配置文件。這一點對中小團隊尤其關(guān)鍵監(jiān)控系統(tǒng)本身越省事才越有精力去整理業(yè)務(wù)側(cè)的告警規(guī)則。1.2 Docker 部署與裸機部署的取舍如果只有兩三臺服務(wù)器很多人會覺得直接裝個 RPM 包就夠了。確實單機部署 Zabbix 的安裝過程也不算復(fù)雜但一旦涉及升級、回滾、遷移問題就來了。我見過不止一個團隊因為服務(wù)器上殘留著舊版本的依賴庫導(dǎo)致升級到新版本時數(shù)據(jù)庫 schema 遷移失敗最后只能重新部署。Docker 把運行環(huán)境和依賴一起打包很大程度上規(guī)避了這類問題。容器化也讓“一個監(jiān)控平臺同時跑多個監(jiān)控場景”變得更簡單。比如需要臨時測試告警規(guī)則可以在同一臺宿主機上再起一個隔離的實例想升級版本把鏡像 tag 改掉重啟 compose 項目不行就切回舊 tag整個過程對現(xiàn)有監(jiān)控數(shù)據(jù)的影響很小。當(dāng)然代價也有Docker 網(wǎng)絡(luò)、存儲卷、容器日志這些概念需要額外理解但相比之下收益遠大于學(xué)習(xí)成本。1.3 整體架構(gòu)與運行原理Zabbix 7.4 的 Docker 部署通常拆成三個核心容器數(shù)據(jù)庫、Zabbix Server、Zabbix Web另外再加一個 Agent2 容器用于采集宿主機自身狀態(tài)。數(shù)據(jù)庫負責(zé)存配置和監(jiān)控歷史數(shù)據(jù)Server 是邏輯大腦負責(zé)輪詢、數(shù)據(jù)處理、觸發(fā)告警Web 是前面的界面層負責(zé)渲染儀表盤和接受操作指令。三個容器各司其職通過一個自定義 bridge 網(wǎng)絡(luò)互相通信。Agent2 的作用容易被低估。它不只是“裝在被監(jiān)控機器上”的東西在 Docker 部署場景里還可以把宿主機本身納入監(jiān)控順便通過主動模式匯報數(shù)據(jù)。這樣即便被監(jiān)控網(wǎng)絡(luò)的防火墻限制比較嚴(yán)格只要宿主機能出站到 Server 的 10051 端口監(jiān)控鏈路仍然是通的。2. 部署前的規(guī)劃與關(guān)鍵決策2.1 數(shù)據(jù)庫選型PostgreSQL 還是 MySQLZabbix 7.4 官方支持 PostgreSQL 和 MySQL 兩種主流數(shù)據(jù)庫。我的建議是新部署無腦選 PostgreSQL。原因不是 MySQL 不能用而是 Zabbix 在 PostgreSQL 上的分區(qū)表、歷史數(shù)據(jù)批量清理機制支持得更成熟遇到大規(guī)模監(jiān)控項時不容易出現(xiàn)鎖表現(xiàn)象。此外官方鏡像里zabbix/zabbix-server-pgsql和zabbix/zabbix-web-nginx-pgsql的 tag 維護最及時避坑概率更高。如果團隊里已經(jīng)有成熟的 MySQL 運維體系也不是不能選 MySQL但要注意字符集和時區(qū)設(shè)置避免寫入中文亂碼或者時間偏移。真要我給一個硬性建議只要不是歷史包袱太重數(shù)據(jù)庫就選 PostgreSQL后續(xù)備份、調(diào)優(yōu)、遷移都會輕松不少。2.2 鏡像 tag 與版本配套Docker 部署最容易犯的錯誤是亂用 tag導(dǎo)致 server 是 7.4 而 web 是 7.2數(shù)據(jù)庫 schema 直接不兼容。官方鏡像倉庫里 7.4 對應(yīng)的核心鏡像如下組件鏡像名推薦 tag數(shù)據(jù)庫postgres16-alpineServerzabbix/zabbix-server-pgsql7.4-latestWebzabbix/zabbix-web-nginx-pgsql7.4-latestAgentzabbix/zabbix-agent27.4-latest這里有個細節(jié)Web 鏡像里其實已經(jīng)內(nèi)置了 Nginx 和 PHP-FPM不需要額外再裝一個 Nginx外部訪問直接映射 Web 容器的 8080 端口即可。數(shù)據(jù)庫鏡像我選了 Alpine 版體積小不少對監(jiān)控系統(tǒng)這類長時間運行的服務(wù)來說也更干凈。2.3 數(shù)據(jù)持久化方案Zabbix 的數(shù)據(jù)安全完全依賴于持久化配置做對了沒有。最穩(wěn)妥的方案是數(shù)據(jù)庫用 Docker volume而 server 和 web 容器不需要持久化任何數(shù)據(jù)因為真正的狀態(tài)都在數(shù)據(jù)庫里。有人習(xí)慣用宿主機目錄 bind mount 來存數(shù)據(jù)庫也可以但要注意目錄權(quán)限PostgreSQL 容器內(nèi)的postgres用戶 UID 是 70權(quán)限不對會出現(xiàn)“Permission denied”導(dǎo)致數(shù)據(jù)庫起不來。建議在部署前就定義好 volume 的命名后續(xù)做備份和遷移時可以直接用docker run --volumes-from或者pg_dump從容器里把數(shù)據(jù)導(dǎo)出來避免跟不同項目的掛載點搞混。3. 基于 Docker Compose 的一鍵部署實操3.1 準(zhǔn)備工作與目錄規(guī)劃我先在一臺干凈的 Linux 服務(wù)器上做演示系統(tǒng)是 CentOS 7.9 的內(nèi)核層面兼容方案但實際用的發(fā)行版是 Debian 系原因不再展開重點是想說明這個方案跟發(fā)行版關(guān)系不大只要 Docker Engine 和 Compose 插件可用就行。安裝 Docker 后先建好項目目錄mkdir -p /opt/zabbix在/opt/zabbix下放一個docker-compose.yml以及后續(xù)會用到的.env文件。為什么要單獨建目錄因為 compose 項目名稱默認以目錄名命名后續(xù)執(zhí)行docker compose down時只會影響這個項目內(nèi)的容器不會誤傷其他服務(wù)。3.2 完整 compose 文件直接貼出我實際使用的 compose 配置services: zabbix-db: image: postgres:16-alpine container_name: zabbix-db environment: POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pwd POSTGRES_DB: zabbix volumes: - zabbix-db-data:/var/lib/postgresql/data networks: - zabbix-net restart: unless-stopped healthcheck: test: [CMD-SHELL, pg_isready -U zabbix -d zabbix] interval: 5s timeout: 3s retries: 10 zabbix-server: image: zabbix/zabbix-server-pgsql:7.4-latest container_name: zabbix-server environment: DB_SERVER_HOST: zabbix-db DB_SERVER_PORT: 5432 POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pwd POSTGRES_DB: zabbix ZBX_CACHESIZE: 128M ZBX_HISTORYCACHESIZE: 128M ZBX_TRENDCACHESIZE: 64M ports: - 10051:10051 volumes: - zabbix-server-alertscripts:/usr/lib/zabbix/alertscripts networks: - zabbix-net depends_on: zabbix-db: condition: service_healthy restart: unless-stopped zabbix-web: image: zabbix/zabbix-web-nginx-pgsql:7.4-latest container_name: zabbix-web environment: ZBX_SERVER_HOST: zabbix-server ZBX_SERVER_PORT: 10051 POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pwd POSTGRES_DB: zabbix PHP_TZ: Asia/Shanghai ports: - 8080:8080 networks: - zabbix-net depends_on: - zabbix-server restart: unless-stopped zabbix-agent2: image: zabbix/zabbix-agent2:7.4-latest container_name: zabbix-agent2 environment: ZBX_SERVER_HOST: zabbix-server ZBX_SERVER_PORT: 10051 ZBX_HOSTNAME: Docker Host pid: host privileged: true networks: - zabbix-net depends_on: - zabbix-server restart: unless-stopped volumes: zabbix-db-data: networks: zabbix-net: driver: bridge幾個關(guān)鍵點我單獨說一下。ZBX_CACHESIZE這些緩存參數(shù)初始環(huán)境用默認值也能跑但我給的是適合幾千個監(jiān)控項的經(jīng)驗值后續(xù)監(jiān)控項增加后可以按需調(diào)整。zabbix-server-alertscripts卷是給自定義告警腳本預(yù)留的一開始就掛出來后面要做 Webhook 或發(fā)短信腳本時不用動容器。Agent2 容器加了privileged: true是因為我想讓它通過 mount 方式采集宿主機的磁盤和進程數(shù)據(jù)如果只是采基本 CPU、內(nèi)存指標(biāo)這個權(quán)限可以不開放。3.3 啟動與日志檢查在/opt/zabbix目錄下執(zhí)行docker compose up -d第一次啟動會因為拉鏡像和初始化數(shù)據(jù)庫花一兩分鐘不要急著看頁面。用下面的命令觀察 server 是否正常docker compose logs -f zabbix-server正常日志里會出現(xiàn)類似server #0 started [Zabbix Server]的字樣這時候再去訪問 Web 端。數(shù)據(jù)庫初始化過程最怕 server 容器在數(shù)據(jù)庫未就緒時反復(fù)重啟我的 compose 里已經(jīng)用 healthcheck 加了依賴等待所以基本不會出現(xiàn)這個問題。如果日志一直在報連接拒絕優(yōu)先查數(shù)據(jù)庫容器狀態(tài)。3.4 Web 界面初始化與中文設(shè)置瀏覽器打開http://服務(wù)器IP:8080第一次訪問會進入安裝向?qū)?。過程很簡單確認數(shù)據(jù)庫連接信息無誤后Zabbix 會自動執(zhí)行 schema 導(dǎo)入完成后跳轉(zhuǎn)到登錄頁默認賬號是Admin默認密碼是zabbix。進來后第一件事是把界面語言改成中文。點右上角頭像進入 User settings把 Language 改為Chinese (zh_CN)。這里有個常見坑如果PHP_TZ環(huán)境變量沒設(shè)置或設(shè)置錯誤中文界面下時間會偏移告警時間對不上號所以我在 Web 容器的環(huán)境變量里已經(jīng)寫好了PHP_TZ: Asia/Shanghai。4. 常見故障與排查實錄4.1 數(shù)據(jù)庫連接不上的連鎖反應(yīng)剛部署完最容易遇到的現(xiàn)象是zabbix-server容器每隔幾秒重啟一次日志顯示failed to connect to database。多數(shù)原因是 server 啟動時數(shù)據(jù)庫還沒 ready或者 compose 里的depends_on條件寫得太簡單。我現(xiàn)在的寫法是讓 server 依賴數(shù)據(jù)庫的 healthcheck 結(jié)果只有pg_isready返回成功才開始拉 server。如果已經(jīng)把 compose 文件改成這樣還重啟那就手工進數(shù)據(jù)庫容器驗證docker exec -it zabbix-db psql -U zabbix -d zabbix -c select 1能返回1說明數(shù)據(jù)庫本身沒問題問題大概率在密碼或者 host 配置。環(huán)境變量里的POSTGRES_PASSWORD必須和數(shù)據(jù)庫初始化時保持一致改密碼后要同步改 compose 里的所有引用位置。4.2 Agent 顯示不可達的問題監(jiān)控宿主機時如果 Agent2 容器已經(jīng)跑了但 Web 界面上主機狀態(tài)一直是紅色先別急著懷疑網(wǎng)絡(luò)。Zabbix 的主機名匹配機制是常見原因Agent 上報的Hostname要和主機配置里的名字一致不一致時 server 會把數(shù)據(jù)當(dāng)未知來源丟掉。我在 Web 上配置主機時主機名寫的是“Docker Host”Agent2 容器的ZBX_HOSTNAME也必須是“Docker Host”。同時要把主機類型改成主動或被動對應(yīng)模式默認的 Agent 模式是主動檢查如果 Agent 配成被動檢查但對端端口不通界面一樣顯示不可達。4.3 容器重啟后數(shù)據(jù)全丟這個問題多半是沒掛 volume。數(shù)據(jù)庫容器如果沒掛zabbix-db-datadocker compose down之后容器刪除數(shù)據(jù)跟著就沒了。驗證方法很簡單docker volume ls | grep zabbix能查到對應(yīng) volume 才說明持久化正常。備份時直接用pg_dump導(dǎo)出數(shù)據(jù)庫內(nèi)容不需要整個 volume 快照但如果是遷移服務(wù)器還是建議用 volume 快照加pg_dump雙保險。4.4 時區(qū)錯亂引發(fā)的告警誤差PHP 默認時區(qū)是 UTC國內(nèi)服務(wù)器如果不顯式設(shè)置PHP_TZ頁面上的時間會比北京時間慢 8 小時。這個問題的隱蔽之處在于Zabbix Server 內(nèi)部的告警判斷是基于 UTC 的Web 端展示時間會通過 PHP 時區(qū)轉(zhuǎn)換所以最后看到的就是“告警時間對不上”。排查技巧先在數(shù)據(jù)庫里查now()和current_timestamp確認數(shù)據(jù)庫時區(qū)正常再看 Web 容器環(huán)境變量是否有PHP_TZ。修改環(huán)境變量后不需要重建容器只需要docker compose up -d重新創(chuàng)建 Web 容器即可。5. 上線后的配置、備份與加固5.1 基礎(chǔ)監(jiān)控模板與告警通道Zabbix 7.4 自帶了很多官方模板比如 Linux 主機模板、Windows 主機模板、SNMP 設(shè)備模板。建議先把宿主機通過 Agent2 接入跑一遍自帶模板確認監(jiān)控項數(shù)據(jù)正常后再擴展其他設(shè)備。告警通道方面先配置一個最簡單的郵件告警確認觸發(fā)鏈路通再去搞 Webhook 或釘釘機器人。在配置告警媒介時千萬不要只在 Media type 里填寫服務(wù)器地址還要在 Users 里給用戶添加“告警媒介”。我見過很多新手卡在這一步告警動作配置了媒介也配置了但用戶沒有綁定媒介結(jié)果一條告警都收不到。5.2 數(shù)據(jù)庫的備份策略Docker 部署環(huán)境的備份比物理機簡單。我推薦每天凌晨用 cron 執(zhí)行一次pg_dump到宿主機備份目錄保留最近 7 天docker exec zabbix-db pg_dump -U zabbix zabbix | gzip /backup/zabbix_$(date \%F).sql.gz find /backup -name zabbix_*.sql.gz -mtime 7 -delete執(zhí)行前確保宿主機libpq客戶端可用或者直接在容器內(nèi)執(zhí)行并掛載備份目錄?;謴?fù)時先用gunzip解壓再通過psql導(dǎo)入到新數(shù)據(jù)庫注意導(dǎo)入順序要保證目標(biāo)庫是空的否則會有主鍵沖突。5.3 安全加固的幾個動作默認密碼Admin/zabbix上線后必須第一時間改掉。其次是把 Guest 用戶禁用這個用戶默認存在但基本用不上留著只會增加暴露面。Web 容器如果只在內(nèi)網(wǎng)訪問建議端口映射時綁定內(nèi)網(wǎng) IPports: - 127.0.0.1:8080:8080需要從公網(wǎng)訪問時前面加一層帶有 HTTPS 證書的反向代理不要直接暴露 Zabbix Web 的 8080 端口。數(shù)據(jù)庫 5432 端口不需要映射到宿主機compose 里只放在自定義網(wǎng)絡(luò)內(nèi)即可外部連不上反而安全。最后再分享一個小技巧Zabbix Server 容器日志默認是標(biāo)準(zhǔn)輸出長時間運行會積累不少數(shù)據(jù)建議在運行 Docker 的宿主機上配置 log rotation。/etc/docker/daemon.json里加上log-driver和max-size配置避免/var/lib/docker/containers目錄被日志撐爆。這個坑是我在監(jiān)控平臺跑了三個月之后才遇到的提前配置好能省掉不少清理工作。