先说结论:这套方案我已经在OpenEuler22.03 LTS上完整跑通了。如果你正在给国产化环境选监控系统,或者公司有信创要求必须用OpenEuler,又想用上Zabbix 7.0的新特性,那这一篇你直接抄作业就行。真要用起来,最大的感受是:Zabbix 7.0的容器化部署并没有想象中那么复杂,但坑是真不少。特别是OpenEuler和CentOS的细微差异、Docker-Compose的安装方式、数据库初始化时区这些细节,官方文档基本不会告诉你,等到你踩进去,一个晚上就没了。
这篇文章我会从环境准备、镜像选型、Compose配置、初始化落地、常见故障排查五个方面完整展开,每个步骤都给出我实测过的配置和参数,并解释为什么这么写。适合有一定Linux基础、用过Docker、想尽快把Zabbix 7.0跑起来的运维同学,也适合正在做信创迁移、需要在OpenEuler上落地监控体系的项目组参考。
1. 环境准备:OpenEuler上Docker与Compose的安装细节
1.1 OpenEuler 22.03 LTS的软件源与基础环境
OpenEuler 22.03 LTS的底层兼容性做得比很多人想象中好,官方文档说它和CentOS生态兼容,实际用下来yum仓库里的软件包确实和RHEL系列高度重叠。但这不代表直接yum install docker就能完美跑起来,我遇到的第一个坑就在这里。
OpenEuler默认没有启用Docker官方源,系统自带的仓库里虽然有docker相关的包,但是版本比较旧,而且依赖的容器运行时组件(containerd、runc)可能和最新的Docker Engine不匹配。我的建议是直接通过dnf安装基础依赖,然后从官方源装最新版本:
sudo dnf install -y yum-utils device-mapper-persistent-data lvm2 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install -y docker-ce docker-ce-cli containerd.io sudo systemctl enable --now docker这里有个关键点:在OpenEuler上添加Docker官方源时,地址要使用centos仓库路径,不要用openeuler路径。因为Docker官方并没有单独为OpenEuler发布仓库,而OpenEuler 22.03 LTS与CentOS 8系列在glibc和内核特性上兼容性很好,直接用centos8的源安装不会有问题。我一开始自作聪明去网上找所谓“OpenEuler专用源”,反而装出来一堆依赖问题,来回折腾了两小时。
装完之后一定要验证一下:
sudo docker run hello-world如果这一步能跑通,说明Docker daemon、镜像加速、内核网络都正常。另外建议顺手配置一下镜像加速器,国内网络环境拉取Docker Hub镜像经常超时,这一点尤其影响后面Zabbix和PostgreSQL镜像的拉取速度。修改/etc/docker/daemon.json:
{ "registry-mirrors": ["https://docker.m.daocloud.io"] }修改后重启Docker生效:
sudo systemctl restart docker1.2 Docker-Compose的安装方式选择:在线与离线
Docker-Compose的安装可以说是整个环境准备阶段最容易踩坑的环节,尤其是在内网环境或没有外网权限的服务器上。OpenEuler默认仓库里其实有一个docker-compose包,但版本是2.x还是1.x因系统版本而异,而且很多情况下版本太老,根本不适配Zabbix 7.0的compose文件格式。
我实测下来最稳定的安装方式是从GitHub官方仓库下载二进制文件。在OpenEuler x86_64环境下:
sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.0/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose如果要部署的机器是在完全离线内网,那需要在一台能上外网的机器上下载好二进制包,然后通过U盘或内网传输工具拷过去,放到/usr/local/bin/docker-compose并赋可执行权限即可。这里没有额外依赖,一个单文件就能跑,所以在离线环境下反而比用系统包管理安装要省事得多。
验证安装:
docker-compose --version这里给一个我的切身体会:不要把docker-compose和docker compose(Docker 26+内置的插件形式)混为一谈。OpenEuler自带的Docker版本如果是20.10或更旧,可能不支持docker compose子命令,而docker-compose独立二进制兼容性更好,推荐在脚本和自动化工具里统一用docker-compose。等到后面要上systemd管理容器生命周期的时候,命令一致性会让配置简单很多。
1.3 重点:为什么我推荐在OpenEuler上优先用容器化部署Zabbix 7.0
很多从传统运维转过来的同学习惯在宿主机上直接装Zabbix,rpm包一装、数据库一建、web一配,思路清晰。但我在OpenEuler 22.03上走了一轮原生部署以后,发现容器化几乎是最优解。
首先,OpenEuler的软件包版本和Zabbix官方仓库的匹配度不算高。Zabbix官方为RHEL/CentOS提供了rpm仓库,但OpenEuler虽然兼容,官方并不保证可以直接用。我尝试强行配置zabbix官方repo安装server端,过程中遇到libpcre2版本过旧、libcurl被系统包锁定等问题,最后虽然能用yum参数强行降级解决,但这种操作在生产环境里无异于埋雷,下次yum update可能就搞崩了。
其次,Zabbix监控系统本身组件多、依赖重。server端需要PHP、前端需要Nginx和PHP-FPM、数据库需要PostgreSQL/MySQL,再加上agent,纯手工部署至少要调整六七个配置文件,任何一个环节版本不一致都会引入奇怪的问题。而容器化方案下,每个组件都是独立镜像,官方镜像里的版本组合是经过测试的,直接把复杂性封装在镜像内部。
第三也是最重要的:升级与备份。Zabbix 7.0是LTS版本,后面会有小版本迭代。容器化部署下升级只需拉取新镜像重建容器,数据卷保留,数据库升级脚本在server容器启动时自动执行。这在传统rpm部署下需要手动执行一堆数据库迁移脚本,效果差远了。如果你的目标是“在生产环境稳定运行三五年”,容器化是更省心的选择。
2. Zabbix 7.0镜像选型与架构理解
2.1 官方镜像拆分逻辑:server、web、agent各司其职
Zabbix 7.0时代的官方镜像已经非常成熟了,它们不是把整个栈打在一个镜像里,而是按照服务角色拆分成了多个镜像。理解了这套镜像的拆分逻辑,部署的时候就不会懵。
我使用的镜像主要是这几个:
zabbix/zabbix-server-pgsql:Zabbix Server核心进程,负责数据采集、触发器计算、告警发送。zabbix/zabbix-web-nginx-pgsql:Web前端 + Nginx + PHP-FPM,通过PG的connection信息连接同一个数据库。zabbix/zabbix-agent:被监控端采集代理,配置为被动模式,由server主动拉数据。postgres:16-alpine:Zabbix 7.0的后端数据库,使用官方PostgreSQL 16版本。
选择-pgsql后缀版本而不是-mysql,是因为Zabbix 7.0+PostgreSQL是官方优化最好的组合。这里多说一句:网上有帖子讨论Zabbix 7.0能否用OceanBase这类国产数据库作为后端,从技术上说Zabbix官方在流通版本里对PostgreSQL和MySQL的兼容性是最成熟的,而OceanBase虽然兼容MySQL协议,但Zabbix对它的支持目前还不是官方认证路径。所以生产环境里最稳妥的组合仍然是PostgreSQL,这也是为什么我坚持用zabbix-server-pgsql镜像的原因。
很多初次部署的同学喜欢直接搜zabbix/zabbix-appliance这种all-in-one镜像,觉得一条命令把所有事情都解决了。这个镜像确实方便,但是有两个问题:一是它把所有组件跑在同一个容器里,后续扩容、迁移、单组件升级都很痛苦;二是appliance镜像内部自带的数据库数据卷管理比较隐蔽,一旦容器被删除重建,历史监控数据很可能直接消失。我强烈建议在正规的监控体系里,把server、web、db拆成三个容器。
2.2 Zabbix 7.0相比旧版本的几个重要变化
Zabbix 7.0是LTS版本(长期支持版本),意味着它会得到至少5年的官方维护。相比6.0等旧版本,7.0有几个值得关注的改进,也直接影响部署方式。
第一个变化是Web界面的大规模重构,仪表盘和可视化配置响应速度快了很多,这也是Zabbix近些年被吐槽的痛点之一。7.0的前端UI不再那么“老气”,对于做数据展示和领导汇报的场景,体验提升明显。
第二个变化是内置的模板体系更丰富了,特别是对主流数据库、中间件、云原生环境的监控模板成熟度提高。例如Zabbix 7.0原生对MySQL的监控可以直接套用MySQL by Zabbix agent 2模板,对Redis、Nginx、Kafka等也都有相对完善的模板,减少了自定义监控项的编写成本。
第三个变化是对加密传输的支持更完善了。Zabbix Server和Agent之间支持PSK(预共享密钥)和证书加密方式,在容器化部署中可以通过环境变量配置,7.0在这方面配置比6.0清晰不少,后面我会讲具体配置方法。
这些变化带来的结果是:如果你之前用的是Zabbix 5.0或6.0,迁移到7.0的容器化方案后,监控能力上限提升了一个量级,特别是在大批量监控项和仪表盘展示上都更顺畅。
2.3 为什么选择PostgreSQL而不是MySQL作为数据库
这里我想专门展开说一下数据库选型,因为这是Zabbix 7.0部署里争议比较大的一个点。
Zabbix 7.0官方文档对数据库的要求中,PostgreSQL和MySQL都支持,但在高并发场景下PostgreSQL的查询优化能力和复杂SQL性能是优于MySQL的。Zabbix的监控数据写入和读取模式非常特殊:高频率的时序数据写入,加上频繁的聚合查询和报表查询,这种混合负载对数据库的优化器要求很高。PostgreSQL的查询计划器在处理这类复杂JOIN和聚合时,长期表现优于MySQL,尤其是监控节点和监控项数量上来以后,差距会越来越明显。
另一个考虑因素是分区表的自动管理。Zabbix的history和trends表会随数据量剧增,如果不做分区管理,数据库会在几个月内膨胀到失控。PostgreSQL 12以后的声明式分区和Zabbix官方提供的分区管理脚本配合得很好,而MySQL在分区管理和Zabbix的兼容性支持上相对弱一些。
最后是运维便利性:PostgreSQL的容器镜像在数据卷挂载、权限管理、初始化脚本执行方面做得非常规范和稳定。postgres:16-alpine镜像体积小、启动快、资源占用低,作为监控系统的后端非常合适。
3. Docker-Compose完整配置:直接复用的生产级方案
3.1 目录结构与数据卷规划
在动手写compose之前,先规划好目录结构和数据卷。我的方案是在宿主机上创建统一的目录:
sudo mkdir -p /srv/zabbix sudo mkdir -p /srv/zabbix/postgresql sudo mkdir -p /srv/zabbix/server sudo mkdir -p /srv/zabbix/web为什么单独创建目录而不是完全依赖Docker命名卷?因为命名卷用docker volume inspect虽然也能管理,但在需要备份、迁移、巡检时,绑定挂载目录的透明度和可操作性更高。尤其是postgresql的数据目录,直接挂载到宿主机目录,备份的时候用rsync或者tar一把梭就行,不用先进容器再执行pg_dump,排查问题时也方便很多。
另一个需要注意的点是目录权限。PostgreSQL容器在启动时会以postgres用户身份运行,如果宿主机目录权限配置不当,容器会因为无法写入数据目录而启动失败。最简单的办法是设置合适的属主:
sudo chown -R 999:999 /srv/zabbix/postgresql注意PostgreSQL官方镜像里postgres用户的UID是999,这个值在不同版本中基本固定。我把权限设置成999:999后,容器启动就不会再报权限问题了。
3.2 完整docker-compose.yml配置与关键参数说明
这是我实测通过的完整配置文件,每个服务的环境变量和参数都标注了实际作用:
version: "3.8" services: postgres: image: postgres:16-alpine container_name: zabbix-postgres restart: always environment: POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pass_2024 POSTGRES_DB: zabbix TZ: "Asia/Shanghai" volumes: - /srv/zabbix/postgresql:/var/lib/postgresql/data networks: zabbix-net: ipv4_address: 172.20.0.10 healthcheck: test: ["CMD-SHELL", "pg_isready -U zabbix -d zabbix"] interval: 10s timeout: 5s retries: 5 start_period: 20s zabbix-server: image: zabbix/zabbix-server-pgsql:7.0-ubuntu-5.0 container_name: zabbix-server restart: always environment: DB_SERVER_HOST: postgres POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pass_2024 POSTGRES_DB: zabbix ZBX_STARTPOLLERS: "10" ZBX_STARTPOLLERS_UNREACHABLE: "2" ZBX_STARTPREPROCESSORS: "5" ZBX_CACHESIZE: "128M" ZBX_HISTORYCACHESIZE: "64M" ZBX_TRENDCACHESIZE: "64M" ZBX_HISTORYINDEXCACHESIZE: "16M" ZBX_TIMEOUT: "4" ZBX_LOGLEVEL: "3" ZBX_TLSCONNECT: "psk" ZBX_TLSACCEPT: "psk" ZBX_TLSCPSKIDENTITY: "zabbix_psk_001" ZBX_TLSCPSKFILE: "/etc/zabbix/psk.key" TZ: "Asia/Shanghai" volumes: - /srv/zabbix/server/psk.key:/etc/zabbix/psk.key:ro - /etc/localtime:/etc/localtime:ro depends_on: postgres: condition: service_healthy networks: zabbix-net: ipv4_address: 172.20.0.20 ports: - "10051:10051" - "10051:10051/udp" zabbix-web: image: zabbix/zabbix-web-nginx-pgsql:7.0-ubuntu-5.0 container_name: zabbix-web restart: always environment: ZBX_SERVER_HOST: zabbix-server DB_SERVER_HOST: postgres POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pass_2024 POSTGRES_DB: zabbix PHP_TZ: "Asia/Shanghai" ZBX_SERVER_NAME: "OpenEuler-Zabbix-7.0" TZ: "Asia/Shanghai" depends_on: zabbix-server: condition: service_started networks: zabbix-net: ipv4_address: 172.20.0.30 ports: - "8080:8080" zabbix-agent: image: zabbix/zabbix-agent:7.0-ubuntu-5.0 container_name: zabbix-agent restart: always environment: ZBX_SERVER_HOST: zabbix-server ZBX_HOSTNAME: "OpenEuler Host" ZBX_SERVER_ACTIVE: zabbix-server ZBX_PASSIVE_ALLOW: "true" ZBX_ACTIVE_ALLOW: "true" ZBX_TLSCONNECT: psk ZBX_TLSACCEPT: psk ZBX_TLSPSKIDENTITY: "zabbix_psk_001" ZBX_TLSPSKFILE: "/etc/zabbix/psk.key" TZ: "Asia/Shanghai" volumes: - /srv/zabbix/server/psk.key:/etc/zabbix/psk.key:ro - /etc/localtime:/etc/localtime:ro depends_on: zabbix-server: condition: service_started networks: zabbix-net: ipv4_address: 172.20.0.40 ports: - "10050:10050" networks: zabbix-net: driver: bridge ipam: config: - subnet: "172.20.0.0/24"这个文件里每个配置项都是我实际跑过的,有几个地方是踩了坑之后才总结出来的,重点说下。
第一是健康检查。postgres服务的healthcheck非常关键,它决定了整个依赖链能不能正确启动。Zabbix Server容器在启动时要连接数据库执行初始化脚本,如果数据库还没就绪,server容器就会直接报连接失败然后退出。用depends_on配合condition: service_healthy可以很好地控制启动顺序,避免手动等待。如果你用的是旧版本docker-compose不支持condition语法,那就要在server容器里额外写一个wait-for-it脚本,麻烦很多。
第二是PSK加密配置。ZBX_TLSCONNECT: psk和ZBX_TLSACCEPT: psk表示server端主动连接agent时使用PSK加密,同时也接受agent用PSK加密连接回来。这里最关键的是PSK文件,需要在宿主机上提前生成,并且server和agent容器都要挂载同一个文件:
openssl rand -hex 64 > /srv/zabbix/server/psk.key生成后文件内容是一串64字节的十六进制字符串,也就是128个字符。两个容器挂载同一个文件,PSK身份标识保持一致,通信才能建立。如果不启用加密,Zabbix 7.0默认的明文通信在跨网段监控时会存在安全隐患,尤其监控数据经过核心交换机时,明文传输很容易被截获分析。虽然启用加密会带来一点点性能损耗,但相比安全收益完全可以忽略。
第三是web服务的端口。Zabbix Web默认服务端口是8080,我在compose里映射成了8080:8080。如果你宿主机上还有别的服务占用了8080,果断改成18080:8080之类的映射,这个根据实际情况调整即可。
3.3 启动命令与初始化验证
配置文件写好之后,启动命令很简单:
cd /srv/zabbix docker-compose up -d第一次启动会拉取大量镜像,postgres:16-alpine大约80MB,zabbix-server和zabbix-web镜像加起来大约1GB左右,根据网络情况可能需要几分钟到十几分钟不等。启动完成后看一下所有服务的状态:
docker-compose ps正常情况下四个服务都应该是Up状态。如果某个服务不断重启,用下面的命令查看日志:
docker-compose logs -f zabbix-server这里我要特别强调:Zabbix Server容器首次启动时会执行数据库schema初始化,这个过程可能持续2到5分钟。如果用docker-compose ps看到server容器一直显示“restarting”或者还在“starting”,不要急着删了重来,先看日志里是否在打印初始化SQL语句。一旦初始化和升级完成,server会产生突破性的“Zabbix server started”日志。如果日志里反复出现“FATAL: password authentication failed”,那就要检查数据库容器里的账号密码是否和compose文件里的配置一致。
整个启动完成后,在浏览器访问http://<服务器IP>:8080,看到Zabbix的登录页面,默认账号是Admin,密码是zabbix,这一步就算一半成功。登录进去以后第一件事是修改默认密码,这一点不用我多提醒,Zabbix默认密码在公网环境下基本等于裸奔。
4. Zabbix 7.0核心功能落地:邮件告警与MySQL监控
4.1 邮件告警配置:从媒介到动作的完整链路
Zabbix装好只是第一步,真正让它发挥价值的是告警能力。我项目上经常需要给客户配置邮件告警,Zabbix 7.0里邮件告警的配置链路比旧版本清晰了不少,但新手还是有容易卡住的地方。
首先要在“管理 → 报警媒介类型”里配置SMTP服务器。Zabbix 7.0内置的Email媒介类型已经支持SMTP认证和SSL/TLS,不需要额外安装脚本。配置时注意几个关键字段:
- SMTP服务器:填写你公司邮件网关的地址,比如
smtp.example.com。 - SMTP服务器端口:常用的有465(SSL)、587(STARTTLS)、25(明文),根据邮件服务器配置选择。实测很多企业邮箱使用465端口效果最稳定。
- SMTP HELO:填写本机或监控服务器的域名,格式比如
zabbix.example.com,这个值必须和SMTP服务器的反解记录匹配,否则部分网关会拒信。 - 加密方式:如果端口是465就选SSL/TLS,是587就选STARTTLS。
- 认证:开启后填写发件邮箱账号和授权码。这里特别强调:大多数企业邮箱不能用登录密码做SMTP认证,要用客户端授权码,很多人在这一步卡住。去邮箱后台开启SMTP服务并生成授权码后再填入。
媒介类型保存后,下一步是给用户配置告警媒介。路径是“管理 → 用户 → 选择Admin用户 → 报警媒介 → 添加”,在这里选择刚才配置好的Email媒介,填入收件人邮箱地址,告警时间范围默认全天即可。
最后也是最容易忽略的一步:创建告警动作。在“告警 → 动作 → 创建动作”里配置触发条件,比如触发器严重性≥警告,然后添加操作,操作类型选择“发送消息”,收件人选择“用户群组”,媒体类型选择刚才的Email。很多人配置完媒介就以为会收到告警,结果什么都没收到,问题就出在动作没创建。
测试方法很简单:可以手动停掉一个被监控服务,等触发器触发后看“告警 → 问题”里是否正常生成条目,以及“报告 → 动作日志”里邮件发送的日志状态。如果动作日志显示发送失败,去查一下SMTP配置的认证信息和端口,这是最常在的点。
4.2 监控MySQL数据库:模板应用与账号授权
Zabbix 7.0内置的MySQL监控模板叫“MySQL by Zabbix agent 2”,这个模板走的是agent 2的插件机制,比旧版本用外部脚本的方式稳定得多。要在被监控的MySQL实例上做两件事:创建监控账号、配置agent插件。
MySQL端创建账号的授权SQL如下:
CREATE USER 'zabbix'@'%' IDENTIFIED BY 'zabbix_monitor_pass'; GRANT SELECT, PROCESS, REPLICATION CLIENT ON *.* TO 'zabbix'@'%'; FLUSH PRIVILEGES;这里强调一下:PROCESS权限是必须的,否则模板里的很多监控项会返回“Access denied”。REPLICATION CLIENT权限用于获取主从复制状态,如果只监控单实例,不配置也不影响核心监控项,但为了模板完整建议都加上。
然后需要在被监控主机上安装Zabbix Agent 2,并配置MySQL插件参数。agent 2的配置文件默认在/etc/zabbix/zabbix_agent2.conf,需要新增以下配置:
Plugins.Mysql.Uri=tcp://127.0.0.1:3306 Plugins.Mysql.User=zabbix Plugins.Mysql.Password=zabbix_monitor_pass如果MySQL不在本机,把Uri改成对应主机的IP和端口。重启agent后,在Zabbix Web界面的“数据采集 → 主机”里为这台机器添加模板,选择“MySQL by Zabbix agent 2”,然后等一个采集周期(默认60秒),在“监测 → 最新数据”里筛选主机就能看到大量MySQL监控指标。
这里必须提醒一个实际遇到过的问题:很多生产数据库出于安全考虑,限制了本机回环之外的MySQL连接。如果你的agent和MySQL不在同一台机器上,光在SQL层面授权还不够,还要检查MySQL的bind-address配置和防火墙策略,确保agent所在主机可以TCP访问MySQL的3306端口。
5. 常见故障与避坑实录
5.1 故障速查表
这一节直接用一个表格把我在这套部署中遇到的故障现象、原因和解决办法列出来,方便后续排查时直接对照参考。
| 故障现象 | 根本原因 | 解决办法 |
|---|---|---|
zabbix-server容器反复重启,日志报database is down | 数据库初始化未完成或连接参数不一致 | 确认POSTGRES_USER/PASSWORD和数据库容器环境变量一致;首次启动等待3-5分钟;用docker-compose logs postgres看数据库日志 |
Web界面访问提示Unable to connect to database | web容器与数据库的网络连通性异常 | 检查compose网络配置,确认web容器可以ping通postgres;检查数据库账号密码是否匹配;用docker exec -it zabbix-web ping postgres排查 |
| 仪表盘所有图表显示时间为UTC,差8小时 | 容器默认时区未配置 | 在所有服务环境变量里设置TZ: "Asia/Shanghai",并挂载/etc/localtime到容器 |
| 重启宿主机后所有容器没有自动启动 | 缺少restart: always策略 | 在compose文件中为所有服务添加restart: always,或者用docker update --restart always <容器名>批量设置 |
agent被动监控项全部返回ZBX_NOTSUPPORTED | agent连接server失败或PSK配置不一致 | 检查10051端口监听和防火墙;确认server和agent挂载的PSK文件一致、身份标识相同 |
邮件告警发送失败,动作日志提示SMTP connection refused | SMTP端口被防火墙屏蔽或邮件网关拒绝转发 | 测试从宿主机telnet smtp.example.com 465看端口连通性;检查是否用过时的密码而非授权码 |
| 数据库目录占用空间快速增长 | 未清理历史数据 | 配置Zabbix历史数据保留策略,或使用分区表脚本定期清理history表 |
5.2 时区问题的全面排查思路
时区问题在这套部署里非常高频,值得专门展开说一下。Zabbix 7.0容器化部署涉及三种“时间”概念:宿主机时间、容器系统时间、数据库时间。如果三者不一致,就会看到监控数据采集正常但图表显示时间偏移8小时。
我的排查顺序是:
第一步看宿主机时间:
date如果宿主机时间正常,第二步进容器看:
docker exec -it zabbix-server date如果容器显示UTC时间,那就是环境变量TZ没有生效。注意老版本的镜像对TZ环境变量的支持不完全一致,稳妥起见同时挂载/etc/localtime:
/usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro第三步看数据库时间:
docker exec -it zabbix-postgres psql -U zabbix -d zabbix -c "SELECT NOW();"PostgreSQL的时间如果也是UTC,需要在postgres容器中也设置TZ环境变量。只要三个层面都统一为北京时间,图表上的时间就正常了。
5.3 容器网络与防火墙的典型坑
OpenEuler 22.03 LTS默认开启了firewalld服务,这会导致Docker映射端口外部无法访问。我遇到过用户反馈Web页面打不开,结果排查半天发现是firewalld拦住了8080端口。
解决办法有两种:一种是直接放行端口:
sudo firewall-cmd --permanent --add-port=8080/tcp sudo firewall-cmd --permanent --add-port=10051/tcp sudo firewall-cmd --permanent --add-port=10050/tcp sudo firewall-cmd --reload另一种是如果内网环境信任所有来源,可以临时关闭firewalld,但生产环境不建议。更优雅的做法是把Docker的bridge网段加入firewalld的信任区:
sudo firewall-cmd --permanent --zone=trusted --add-interface=docker0 sudo firewall-cmd --reload这种方法适用于所有Docker映射端口都需要对宿主机网络开放的情况,避免了逐个端口放行的繁琐操作。
另外还有一个隐藏问题:当agent与server在不同宿主机时,agent的ZBX_SERVER_HOST要填写server宿主机的IP,不能填容器IP。因为agent是被动模式下由server主动向agent的10050发起TCP连接,agent需要知道server从哪里来,但不需要真正主动连到server(主动模式除外)。如果填写容器IP,agent在被动模式下不影响,但ZBX_SERVER_ACTIVE配置的主动检查就无法连上server了。
5.4 容器内存限制与性能调优经验
Zabbix 7.0对内存的需求比旧版本略高,尤其是PHP-FPM进程和Zabbix Server的缓存。我在OpenEuler上遇到过一个问题:部署完毕后Web界面偶尔出现502 Bad Gateway,重启web容器能恢复,但过两天又出现。最终排查是容器内存不足,PHP-FPM进程被OOM Killer杀掉。
当时的宿主机器内存只有8GB,PostgreSQL加上Zabbix Server加上Web,三个容器加起来吃掉了将近5GB。解决办法是在compose配置里给每个服务设置内存上限:
deploy: resources: limits: memory: 2G同时调整PHP-FPM进程数,在web容器的环境变量中设置:
environment: PHP_MAX_CHILDREN: "20" PHP_START_SERVERS: "5" PHP_MIN_SPARE_SERVERS: "2" PHP_MAX_SPARE_SERVERS: "5"这套参数的含义是:最多启动20个PHP-FPM进程处理Web请求,初始启动5个,最少保留2个空闲进程,最多保留5个空闲进程。对于几十个节点的中小型监控环境,这个配置足够流畅。如果节点数上百,建议把宿主机内存加到16GB以上,PHP_MAX_CHILDREN可以调到30。
6. 最后再说几句大实话
整套Zabbix 7.0在OpenEuler 22.03 LTS上容器化部署,从我接触这个组合到彻底跑通,前前后后花了差不多两个完整工作日。大部分时间其实不是花在Zabbix上,而是花在环境差异的适配和不知道去哪查问题的过程里。官方文档写的是通用情况,但每个发行版都有自己的脾气,OpenEuler更不例外。
我个人操作下来的体会是:如果预算和团队精力允许,直接用这套容器化方案作为生产环境的标准部署方式,不要再走rpm手工安装的老路。容器化带来的可复现性、升级便利性和故障恢复速度,在长期运维中节省的时间绝对值得前期这几天的折腾。
最后再分享一个小技巧:这套compose配置尽量保存到Git仓库里,版本化管理。后面如果有机器需要批量部署,把配置拉下来改一下IP和密码就能直接用。我后面的项目里凡是新装监控,基本都是直接复用这套模板,从拉代码到监控页面能登录,半小时以内就能搞定。