PG-ZA-GRA极度轻量化调优笔记
香橙派 2核2G 环境 Zabbix + PG + Grafana 轻量化部署笔记
一、 环境与架构说明
- 硬件限制:CPU 2核,内存 2GB(ARMv8 / Allwinner H618)。磁盘介质通常为 MicroSD 卡或 eMMC,I/O 性能极弱。
- 部署工具:Podman / Podman-compose
- 优化核心:
- 数据驱动优先:Grafana 尽量采用原生插件(如 Sun and Moon)或数据源驱动,避免使用高内存消耗的组件。
- 抹平磁盘 I/O:彻底关闭容器标准输出日志,关闭数据库 fsync 强行刷盘,降低 Zabbix 与 Grafana 日志级别。
- 内存严控:大幅缩减 Zabbix 和 PHP-FPM 的并发进程数,控制 PostgreSQL 缓存。
二、 容器服务调优配置
1. PostgreSQL 16 数据库配置
- 优化策略:通过命令行参数强制覆盖默认配置。关闭
fsync和synchronous_commit,牺牲断电时的极端数据安全性,换取闪存卡寿命;严控work_mem防止高并发查询导致 OOM。 - 数据持久化:必须进行宿主机卷挂载(
:Z用于 Podman/SELinux 权限适配)。
postgres:
image: docker.io/library/postgres:16-alpine
container_name: postgres
# 通过 -c 参数直接在启动命令中注入核心调优,覆盖默认配置文件
command: >
postgres
-c fsync=off # 强制关闭同步刷盘,极大延长 SD 卡寿命
-c synchronous_commit=off # 事务异步提交,降低磁盘写入高频等待
-c shared_buffers=256MB # 共享缓冲区大小,限制为系统总内存的 1/8
-c work_mem=4MB # 单个内部排序操作和哈希表使用的内存,防止并发高时内存溢出
-c maintenance_work_mem=32MB # 维护性操作(如创建索引、VACUUM)的最大内存
-c effective_cache_size=512MB # 估算可用于评估计划的磁盘高速缓存大小
-c wal_level=minimal # 将预写日志(WAL)降到最低,只保留崩溃恢复所需信息
-c max_wal_senders=0 # 关闭主从流复制线程,释放 CPU 与内存
-c checkpoint_completion_target=0.9 # 三级检查点刷新目标,平摊 I/O 写入压力
-c max_wal_size=512MB # 限制最大 WAL 日志体积,防止撑爆磁盘
-c min_wal_size=80MB # 最小 WAL 日志体积
-c logging_collector=off # 关闭 PG 内部的日志收集器
-c log_min_messages=panic # 仅记录导致服务器崩溃的灾难性错误,保持完全安静
environment:
- POSTGRES_DB=zabbix # 初始化自动创建的数据库名称
- POSTGRES_USER=zabbix # 数据库超级用户名
- POSTGRES_PASSWORD=your_secure_password # 数据库密码
volumes:
- /home/orangepi/pg_data:/var/lib/postgresql/data:Z # 宿主机持久化目录挂载
deploy:
resources:
limits:
memory: 600M # 严格限制该容器最大可用内存
logging:
driver: none # 丢弃容器标准输出日志,避免产生 JSON 日志文件
2. Zabbix Server 7.0 配置
- 优化策略:将日志级别压到最低。大幅裁撤不必要的常驻轮询进程(如关闭自动发现、Web 监测),控制历史数据写入线程数量(
ZBX_STARTDBSYNCERS=2),减少数据库锁争抢。 - 持久化说明:Server 容器为无状态,所有主机配置、触发器、监控项数据均由核心调优后的 PostgreSQL 承载,容器自身无需做持久化。
zabbix-server:
image: docker.io/zabbix/zabbix-server-pgsql:alpine-7.0-latest
container_name: zabbix-server
environment:
- ZBX_DEBUGLEVEL=0 # 关闭 Zabbix Server 内部的常规 Debug 日志
- ZBX_LOGLEVEL=2 # 调整日志输出级别,只打印错误和警告信息
- ZBX_STARTPOLLERS=3 # 常规主动/被动检测的轮询器线程数(从默认值大幅调低)
- ZBX_STARTPINGERS=2 # ICMP Ping 检查的线程数
- ZBX_STARTPOLLERSUNREACHABLE=1 # 不可达设备检查的线程数
- ZBX_STARTTRAPPERS=1 # 接收 Agent 主动上报数据的线程数
- ZBX_STARTDISCOVERERS=0 # 网络自动发现线程数(若固定设备监控,直接关闭设为0)
- ZBX_STARTHTTPPOLLERS=0 # Web 场景监测线程数(不使用自带网页探测则关闭设为0)
- ZBX_STARTDBSYNCERS=2 # 数据同步器线程数(控制从内存缓存同步到 PG 的并发,缓解I/O)
- ZBX_HISTORYCACHESIZE=16M # 存储历史数据的内存缓存大小
- ZBX_HISTORYINDEXCACHESIZE=4M # 存储历史数据索引的内存缓存大小
- ZBX_TRENDCACHESIZE=8M # 存储趋势(聚合)数据的内存缓存大小
- ZBX_VALUECACHESIZE=16M # 存储触发器计算历史值的内存缓存大小
- DB_SERVER_HOST=postgres # PostgreSQL 数据库的容器连接地址
- POSTGRES_USER=zabbix # 数据库连接用户名
- POSTGRES_PASSWORD=your_secure_password # 数据库连接密码
- POSTGRES_DB=zabbix # 目标数据库名
deploy:
resources:
limits:
memory: 400M # 严格限制该容器最大可用内存
logging:
driver: none # 丢弃容器标准输出日志,保护闪存卡
3. Zabbix Web (Nginx + PHP-FPM) 配置
- 优化策略:严格限制
PHP_MAX_CHILDREN数量,从默认值调低至 3,防止多图表同时请求时内存激增。 - 持久化说明:Web 前端为无状态。配置的自定义仪表盘(Dashboards)、用户界面布局均保存在 PostgreSQL 数据库中。重建容器仅会导致当前浏览器 Session 失效(需重新登录)以及容器内临时追加的特殊字体丢失。
3.1 Nginx 配置覆盖 (access_log off)
- 变量作用:彻底关闭 Nginx 引擎对每次页面刷新、API 请求的访问日志记录。
- 技术背景:Zabbix 7.0 官方 Alpine 镜像移除了传统的
/etc/nginx/conf.d/目录,改用主配置文件nginx.conf中的include /etc/nginx/includes/access-log.conf;来引入访问日志。 - 实现策略:无需重写复杂的 Nginx 虚拟主机配置,直接在宿主机生成一个空文件,强制挂载并覆盖容器内的
access-log.conf。此方案最安全,100% 保持官方网页服务的核心转发逻辑,且不影响后续版本升级。
3.2 在香橙派宿主机上创建空配置文件
执行以下命令,在宿主机指定工作目录下生成一个用于覆盖的完全空白的文件:
mkdir -p /home/orangepi/zabbix_nginx
touch /home/orangepi/zabbix_nginx/empty_access_log.conf
# 赋予该空文件全员可读写权限,否则容器报错起不来
chmod 666 /home/orangepi/zabbix_nginx/empty_access_log.conf
3.3 更新 podman-compose.yml 编排文件
zabbix-web:
image: docker.io/zabbix/zabbix-web-nginx-pgsql:alpine-7.0-latest
container_name: zabbix-web
volumes:
- /home/orangepi/zabbix_nginx/empty_access_log.conf:/etc/nginx/includes/access-log.conf:Z
environment:
- ZBX_MAXEXECUTIONTIME=150 # PHP 脚本最大执行超时时间
- PHP_MAX_CHILDREN=3 # PHP-FPM 最大子进程数(从5降到3,极限压榨内存开销)
- ZBX_DEBUGLEVEL=0 # 关闭前端页面的调试日志
- ZBX_LOGLEVEL=2 # 减小CPU 计算资源和内存,调整日志输出级别,只保留严重错误,阻断容器标准输出
- DB_SERVER_HOST=postgres # PostgreSQL 数据库的容器连接地址
- POSTGRES_USER=zabbix # 数据库连接用户名
- POSTGRES_PASSWORD=your_secure_password # 数据库连接密码
- POSTGRES_DB=zabbix # 目标数据库名
deploy:
resources:
limits:
memory: 300M # 严格限制该容器最大可用内存
logging:
driver: none # 丢弃容器标准输出日志,防止 Nginx 的 access.log 刷盘
4. Grafana 配置
- 优化策略:彻底关闭内部日志落盘、官方动态新闻及匿名数据上报。强制锁定全局中文(zh-Hans),允许加载未签名的 Zabbix 官方插件。同步配置上海时区,防止时序数据及天气组件出现 8 小时时差。
4.1 权限冲突原因说明
- 容器内部:Grafana 官方镜像默认以
grafana用户(UID472)和root组(GID0)运行。 - 宿主机内部:以 root 用户提取文件后,文件的所有者通常为宿主机的
root:root(0:0)。 - 后果:若不调整权限,容器启动后写数据库时会触发
Permission denied错误。
4.2 调整宿主机权限命令
在 Podman Root 模式下,容器内外 UID 映射是一致的。需要在香橙派宿主机上将数据目录的所有者修改为 472:0:
chown -R 472:0 /data/gra/gdata
修改后,宿主机中该目录下的文件所有者将显示为数字 472 或 grafana(若宿主机存在同名用户),容器即可获得完整的读写权限。
4.3 Grafana 编排配置
grafana:
image: docker.io/grafana/grafana:main-slim
container_name: grafana
logging:
driver: none # 告诉 Podman 这个容器不需要 any 标准输出日志,直接抛弃
tmpfs:
- /var/lib/grafana/png:size=30M # 限制 30M 供图表快照图片缓存使用
- /var/lib/grafana/csv:size=10M # 限制 10M 供临时数据导出使用
volumes:
- /data/gra/gdata/plugins:/var/lib/grafana/plugins:Z # 插件目录
- /data/gra/gdata/grafana.db:/var/lib/grafana/grafana.db:Z # 数据库文件
environment:
- TZ=Asia/Shanghai # 强制设定容器内部时区为北京时间
- GF_SECURITY_ALLOW_EMBEDDING=true # 允许 Grafana 仪表盘被 iframe 嵌入外部网页
- GF_USERS_ALLOW_SIGN_UP=false # 关闭前端注册功能,防止非授权人员注册
- GF_AUTH_ANONYMOUS_ENABLED=true # 开启匿名(免密)访问功能
- GF_AUTH_ANONYMOUS_ORG_NAME=Main Org. # 匿名访问关联的默认组织
- GF_AUTH_ANONYMOUS_ORG_ROLE=Viewer # 匿名用户的权限限制(只读查看者)
- GF_LOG_MODE=console # 强制日志仅输出到标准控制台,不写入本地文件
- GF_LOG_LEVEL=critical # 仅在发生灾难性系统崩溃时才记录日志
- GF_ANALYTICS_REPORTING_ENABLED=false # 关闭官方的匿名使用数据及崩溃信息上报
- GF_DASHBOARDS_NEWS_FEED_ENABLED=false # 彻底关闭首页右侧的 Grafana 最新动态新闻
- GF_DASHBOARDS_BLOG_FEED_URL= # 清空官方博客更新地址,阻断后台轮询请求
- GF_SECURITY_ADMIN_USER=aaaa # 默认管理员初始账号
- GF_SECURITY_ADMIN_PASSWORD=aaaaa # 默认管理员初始密码
- GF_USERS_DEFAULT_THEME=dark # 锁定全局默认主题为暗黑模式(降低屏幕开销与功耗)
- GF_FEATURE_TOGGLES_ENABLE=internationalization,languageChooser # 启用多语言支持特性开关
- GF_INTERNATIONALIZATION_DEFAULT_LANGUAGE=zh-Hans # 设置国际化组件默认语言为简体中文
- GF_ANALYTICS_DEFAULT_LANGUAGE=zh-Hans # 设置分析组件默认语言为简体中文
- GF_USERS_DEFAULT_LANGUAGE=zh-Hans # 设置默认新用户语言为简体中文
- GF_SERVER_OVERRIDE_LANGUAGE=true # 强制覆盖用户浏览器本地语言,统一锁定中文显示
- GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=alexanderzobnin-zabbix,alexanderzobnin-zabbix-app,alexanderzobnin-zabbix-datasource # 强制允许加载未经过官方安全签名的 Zabbix 核心插件
deploy:
resources:
limits:
memory: 250M # 严格限制该容器最大可用内存
logging:
driver: none # 丢弃容器标准输出日志,降低 I/O 开销
三、 生活信息大屏组件(天气/日出日落/日历)实现方案
在数据驱动的插件方案下,Grafana 可通过安装轻量化插件实现监控以外的信息看板功能。
1. 基础插件安装命令
在香橙派宿主机终端执行以下命令安装核心组件(安装后需重启 Grafana 容器):
# 安装本地经纬度算力数据源(计算日出日落)
podman exec -it grafana grafana-cli plugins install fetzerch-sunandmoon-datasource
# 安装 JSON API 解析插件(用于抓取天气数据)
podman exec -it grafana grafana-cli plugins install marcusolsson-json-datasource
# 注:新版 Grafana 已内置 Calendar(日历)面板,无需额外安装
2. 各组件具体配置方法
A. 日出日落时间(Sun and Moon 插件)
- 原理:纯本地算法,依靠经纬度计算,零网络 I/O。
- 数据源配置:添加
Sun and Moon数据源,输入当地经纬度(如北京:Latitude 39.9, Longitude 116.4)。 - 面板配置:添加 Stat(大数字)面板,Metric 选择
Sun,Field 选择Sunrise或Sunset。在Standard options -> Unit中将其格式化为Date & time -> Time (HH:mm:ss)。
B. 实时天气看板(JSON API 数据源)
- 原理:调用第三方网络 API(如和风天气、OpenWeatherMap),通过 JSON 驱动原生面板,避免加载复杂的外部 HTML iframe 网页。
- 数据源配置:添加
JSON API数据源,填入天气 API 基础 URL(如和风天气https://devapi.qweather.com/v7/weather/now)。 - 面板配置:在 Query Params 中传入城市 ID 和 API Key。在 Fields 属性中通过 JsonPath 提取当前温度(
$.now.temp)和天气文本($.now.text),并配合 Stat 面板 进行呈现。 - 优化频率:在
Query options -> Min interval中强制限制最小刷新间隔为30m(30分钟),降低高频网络请求和内存损耗。
C. 交互日历面板(内置 Calendar 组件)
- 原理:Grafana 内置 Calendar 面板可通过标准时间序列或 SQL 行数据自动绘制日程。
- 数据接入:可直接连接现有的 PostgreSQL 数据库。
- SQL 映射规范:编写 SQL 检索日程表时,必须通过
AS关键字将字段重命名为规范的别名,以便 Calendar 组件识别:
SELECT
task_start_time AS time, -- 时间戳绑定
task_name AS text, -- 日历单元格显示的文本内容
priority AS tags -- 可选:分类标签,用于多色彩日程标记
FROM my_todo_list
WHERE $__timeFilter(task_start_time)
四、 运维避坑与注意事项
- 容器重建与配置生效:使用
podman-compose up -d刷新配置时,无持久化的zabbix-server和zabbix-web容器会被删除并重建,属于正常行为。只要 PostgreSQL 映射了本地目录,核心资产(仪表盘、监控主机等)就不会丢失。 - 安全性审计:由于启用了匿名免密只读访问(
GF_AUTH_ANONYMOUS_ENABLED=true),必须进入 Zabbix Web 控制台,为 Grafana 创建一个专用的、仅具有 Read-Only(只读)权限的用户。绝对禁止直接将 Zabbix 的 Super Admin 账号暴露在公共大屏的 Grafana 数据源中。 - 刷新率红线:为了防止香橙派 CPU 被高频查询卡死,Grafana 所有的仪表盘默认自动刷新频率(Refresh interval)严禁设置为
5s或10s,建议统一放宽至1m(1分钟)或5m。