ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker Compose 部署 LibreNMS 网络监控系统实战

Docker Compose 部署 LibreNMS 网络监控系统实战 1. 先问自己网络设备多起来之后你靠什么活先说个我自己的经历。有一段时间我手里管着三四十台网络设备分布在不同机房和办公区。平时用命令行查接口状态、看CPU占用单台设备还好说设备一多整个人就不够用了。更难受的是某些设备半夜出现丢包、接口流量异常我往往是第二天早上被业务同事叫醒才知道出了幺蛾子。那时候我意识到手工巡检的路子走不长必须上一套能自动发现、自动画拓扑、带告警的网络监控系统。挑来挑去最后选了LibreNMS。它是一套开源的网络监控平台基于PHP和MySQL走的是SNMP协议来采集设备数据。它支持自动发现设备、自动识别厂商和型号、自动生成端口列表和流量图还内置了告警引擎、NFSen流量分析甚至能调用Oxidized做配置备份。协议层面支持SNMP、ICMP、ARP、BGP等一堆内容基本覆盖了主流网络设备和服务器。关键是它的社区活跃度一直不错更新频率很高插件机制也灵活比某些商业平台的“黑盒”逻辑要好懂得多。不过LibreNMS官方推荐的是裸机LNMP部署方式——下载安装脚本、配PHP扩展、建库、跑web installer一条龙下来虽然不算难但对环境的要求比较细。比如对PHP版本有明确要求系统包版本不对就很容易出现半路报错。于是我在实际部署时换了一条路用Docker Compose把它整个包起来跑。这样GitHub上拉一份官方compose仓库改一改环境变量一个命令就能把整套监控系统拉起来数据库、PHP、调度器、Web服务全都齐活。迁移和升级也方便备份整个数据卷就行。这篇博文就把我整个采坑和实操过程完整梳理一遍。不光是照着敲命令还会详细说清楚每一步为什么要这么做以及你在自己机器上大概率会遇到哪些坑、怎么排掉。适合两类人看一类是想把LibreNMS跑起来的新手另一类是已经跑起来了但想用Docker方式重新梳理一遍部署的老手。2. 为什么我会坚定选Docker Compose而不是裸机安装2.1 裸机安装LibreNMS的隐藏成本官方文档的安装流程其实写得挺清楚的准备一个干净的Linux系统装Apache或Nginx、PHP 8.1以上、MySQL或MariaDB然后跑脚本拉源码、建库、设权限、配置SNMP等等。看起来一步步走就行但实操里隐藏成本远比预期高。我自己踩得最深的一个坑是PHP扩展。LibreNMS依赖的扩展特别多包括curl、gd、json、mbstring、mysqlnd、openssl、xml、zip等有一堆还和图片处理相关。系统源里自带的PHP版本往往不是官方推荐的版本比如Ubuntu 20.04自带的PHP 7.4LibreNMS新版就明确不支持了。你要是用旧一点的教程大概率装的还是php-fpm那一套老配置方式。我试过在Ubuntu上手动加ondrej/php源来装新版PHP折腾一晚上结果跑到数据库迁移那一步又出现内存不足的问题。另外LibreNMS的调度机制里需要跑python3脚本来做轮询和发现还需要rrdtool来画图。这些依赖如果版本和系统lib不匹配极容易出现“轮询进程静默失败”这种诡异问题——表面上服务都在跑实际数据根本写不进RRD文件。排查起来非常痛苦。所以部署成本不只是“跑几条命令”的事真正花时间的是把PHP、数据库、调度器这三者的版本和环境变量对齐。Docker Compose方案之所以让我省心是因为它把所有依赖全部固定在了镜像里。你不需要关心宿主机是Debian还是CentOS也不需要关心系统自带的PHP是什么版本只需要把镜像跑起来环境就已经是LibreNMS官方验证过的组合了。2.2 对比单容器运行Compose的优势在哪里也有不少人图省事直接docker run一个LibreNMS镜像。但LibreNMS天生是多组件的系统至少有四个大件要协作数据库、Web服务NginxPHP-FPM、调度器定时轮询、RRD数据持久化。单容器方案要把这些进程全部压进一个容器里进程管理要么用supervisor要么靠自定义启动脚本复杂度并不低。而且你升级某个组件时整个容器都要重建很不灵活。Compose的玩法就是把这些拆成多个独立容器让它们各干各的活。我用到的服务大概是下面这些db跑MariaDB的数据库容器librenms主应用容器内含Nginx、PHP-FPM、RRD工具dispatcher定时任务容器跑librenms-service.py这类调度进程syslog/snmptrap可选接收设备主动发来的syslog和SNMP trap消息rrdcached负责缓存RRD写入降低IO压力每个容器各管一个进程日志分开看、状态分开查、资源占用分开监控。出问题定位起来也方便比如轮询数据不更新你直接看dispatcher容器日志就知道调度器是否还活着而不用在单体容器里慢慢翻一堆进程的输出。另外Compose的volume挂载机制让数据保护和迁移变得极其简单。数据库和RRD目录都挂在宿主机上备份这两个目录就相当于备份了整套监控数据。我后来换服务器时直接把整个compose目录拷过去docker compose up -d就完成了迁移整个过程不超过十分钟。3. 开始搭建前先把宿主机环境理顺3.1 版本选型和硬件规划先说硬件。LibreNMS本身不算吃资源但它的负载取决于你监控的设备数量和轮询频率。按官方说法单台普通VPS跑上千台设备的问题不大但那是在优化过RRD缓存和轮询粒度的前提下。我自己的经验是如果你只监控几十台设备2核4G内存就够用了如果设备过百建议4核8G起步。主要的消耗在MySQL的查询和RRD绘图上设备数量上去了存储占用也会明显增加。操作系统方面我自己用的是Debian系的系统但说实话用Docker Compose之后宿主机是哪个发行版根本不重要只要Docker能装上去就行。这是我选容器化路线最大的收益之一。3.2 安装Docker和Compose插件附常见坑很多人在第一步就卡住了。Docker有两种安装方式老式的docker-compose命令是Python写的独立二进制新式的docker compose是Docker官方插件。LibreNMS官方compose仓库里给的命令是docker compose up -d这种新写法所以你要确保装的是新版插件。装Docker最省事的方式是用官方脚本curl -fsSL https://get.docker.com | sh这个脚本会自动帮你配置源、装上docker-ce以及docker compose插件。装完后检查一下docker --version docker compose version如果docker compose version提示“unknown command”说明你的Docker是旧的二进制版本没有附带compose插件。最常见的场景是服务器上原来装了老版本Docker升级时没带插件过来。解决办法是去GitHub的docker/compose-release页面下对应架构的二进制文件放到/usr/libexec/docker/cli-plugins目录下或者干脆重装一遍Docker。还有一点要提醒如果你的机器是国内的服务器直接拉镜像非常慢甚至会超时。建议先配置镜像加速器编辑/etc/docker/daemon.json加上几个国内可用的镜像源然后重启Docker。这一步不做后面拉LibreNMS映像时你会等到怀疑人生。而且LibreNMS的镜像体积不小如果网络再不稳定大概率会拉一半就失败前功尽弃。3.3 提前规划目录结构Compose部署LibreNMS的核心是把数据落在宿主机上所以目录结构要提前规划好。我采用的结构比较简单直观/opt/librenms/ ├── docker-compose.yml ├── .env ├── data/ │ ├── librenms/ # 主应用代码与RRD数据挂载点 │ ├── mysql/ # 数据库数据目录 │ └── logs/ # 日志目录把数据目录集中在一个地方后续做快照、备份、迁移都很清晰。我个人不太建议直接把数据卷放到home目录下因为监控数据会越来越大home目录所在分区空间一旦不够扩容就会比较麻烦。4. 编写docker-compose.yml的核心思路4.1 官方compose仓库的获取方式LibreNMS官方给了现成的compose部署模板在GitHub上是librenms/docker仓库里面有个compose目录。建议直接把整个目录clone下来比你自己从零写要靠谱得多因为官方仓库里的配置已经包含了各种生产环境才需要的细节处理比如健康检查、环境变量默认值等。git clone https://github.com/librenms/docker.git cd docker/compose这个目录下会有完整的compose文件、.env样例、Nginx配置等。官方默认的docker-compose.yml里已经定义好了db、librenms、dispatcher等几个核心容器。你接下来要做的只是改一改.env文件里的参数而不是全网搜索一堆来路不明的写法。4.2 关键配置项逐条解读拿我当时用的compose文件举例重点说几个容易被忽略的字段。数据库部分db: image: mariadb:10.5 container_name: librenms_db command: --max-connections512 environment: - MYSQL_DATABASElibrenms - MYSQL_USERlibrenms - MYSQL_PASSWORDyour_password - MYSQL_ROOT_PASSWORDyour_root_password volumes: - ./data/mysql:/var/lib/mysql restart: unless-stoppedMariaDB镜像我建议固定到指定版本号不要用latest。官方模板在某个时间点默认用的是10.5版本如果你直接拉了最新的MariaDB镜像后续一旦跟应用容器的兼容性测试不同步数据库连接就会出现一些很不好查的“版本不匹配”问题。我当时就把镜像固定成了mariadb:10.5后面升级时再手动改版本号。主应用部分librenms: image: librenms/librenms:latest container_name: librenms_app hostname: librenms ports: - 8000:8000 environment: - TZAsia/Shanghai - PUID1000 - PGID1000 - DB_HOSTdb - DB_NAMElibrenms - DB_USERlibrenms - DB_PASSWORDyour_password volumes: - ./data/librenms:/data restart: unless-stopped depends_on: - db端口映射我特意选了8000而不是默认的80是因为宿主机上很可能已经有别的Web服务占着80端口。你完全可以根据自己的环境改成任意空闲端口。需要注意的是TZ时区字段一定要设对默认是UTC如果你不改成Asia/Shanghai监控图上所有时间线都会偏差8小时告警时段判断也会错位这个问题很多人一开始根本没注意。调度器部分dispatcher: image: librenms/librenms:latest container_name: librenms_dispatcher depends_on: - librenms volumes: - ./data/librenms:/data restart: unless-stoppeddispatcher容器没有端口映射它的唯一职责是跑定时任务。官方镜像里默认的调度间隔是5分钟轮询一次这个频率对绝大多数场景都够用了。如果你有更细粒度的需求可以通过环境变量或额外配置调整调度策略。4.3 .env文件里的陷阱官方模板还有一个.env文件里面有MYSQL_PASSWORD、BASE_URL、PUID、PGID等参数。最容易被坑的是BASE_URL这个值决定LibreNMS页面里所有链接和重定向的地址。如果你通过IP加端口访问比如http://192.168.1.100:8000就一定要把这个地址填进BASE_URL。不填或填错会导致登录之后页面跳转异常、链路功能链接全打不开。还有一个参数是PUID和PGID。LibreNMS容器默认以非root用户运行但数据目录如果权限不对RRD文件写入时就会报权限错误。我在首次部署时就没设好结果调度器一直在后台报错但页面上看不出任何异常只有打开RRD文件才发现全是空的。后来我把PUID设成宿主机上当前用户的UID用id -u查一下再填进.env里重启容器之后一切正常。5. 初始化流程从compose up到填Web安装向导5.1 拉镜像、起容器、看日志确认.env文件没问题之后就可以启动了docker compose up -d第一次启动时会花比较长时间拉镜像。三个主要镜像加起来体量不小建议观察拉取进度不要中途打断。如果某个镜像拉取失败用docker compose pull单独重试通常就能解决。启动完成后用docker compose ps看容器状态。看到State列都是running或healthy就说明基本正常了。接着看日志docker compose logs -f librenms这一步很有必要官方镜像首次启动时会自动完成数据库初始化还会把需要的表结构迁移好。日志里如果出现Initialization complete字样恭喜你数据库部分已经过了。5.2 Web安装向导的表单填写浏览器打开http://你的服务器IP:8000会看到LibreNMS的安装向导页面。第一个页面是检查环境依赖容器方案里这一步基本是全绿的你不需要像裸机那样一个个装PHP扩展。即使有一些黄色提示项大概率是邮件发送和SNMP相关的可选功能后续可以补配置。接着会让你填数据库连接信息这个直接在Web页面上填Database Hostdb不是localhost因为MySQL跑在独立的容器里Database NamelibrenmsDatabase UserlibrenmsDatabase Password你在.env里配置的那个有些用官方模板的人在这里会卡住为什么填了localhost连不上因为Web容器和数据库容器是隔离的localhost指的是Web容器自己它里面可没有MySQL。这里必须填compose里的服务名dbDocker内部DNS会自动解析到数据库容器IP。填完数据库信息后向导会生成一个config.php文件的内容下面有个输入框让你手动粘贴保存或者直接让你在服务器上写文件。容器方案里最方便的做法是直接在宿主机上创建data/librenms/config.php文件填入向导给出的内容然后重启librenms容器让配置生效。重启后回到页面继续下一步设置管理员账号、密码LibreNMS部署就算大体完成了。5.3 添加第一台设备并验证SNMP通信装完监控系统后的第一件事肯定是把设备加进来试试。在Web界面的Devices - Add Device里填入设备的IP地址LibreNMS默认会用SNMP v2c来探测设备所以你要提前在设备上开好SNMP。拿最常见的交换机为例配置大致长这样snmp-server community public RO snmp-server location Beijing-DC snmp-server contact netadminexample.com如果你手头有Linux服务器也可以装个snmpd来测试。apt install snmpd然后编辑/etc/snmp/snmpd.conf把rocommunity public那行取消注释重启服务即可。添加设备后在设备列表页面等几分钟LibreNMS会自动完成首次发现。你可以点进设备详情页看到系统信息、接口列表、CPU/内存占用、端口流量图都出现时就说明整条链路已经从“Web下发请求 - 后台轮询 - SNMP采集 - RRD写入 - 前端出图”全部跑通了。我强烈建议在设备列表里挑一台你觉得最不重要的设备来做这个首次添加测试而不是一上来就把核心业务设备全部加入。因为首次自动发现的压力比较大如果SNMP配置错了会产生不少报错日志和无效的发现任务污染监控系统的初始状态。6. 日常运维必做的几件事告警、备份、时区与自动发现6.1 告警规则怎么配才不会半夜被烦死LibreNMS自带告警引擎默认规则里已经内置了设备宕机、端口掉线等基础告警。但直接用它默认规则你很快会被告警风暴淹没——只要有一台设备短暂重启或者某条链路抖动一两分钟邮件和钉钉就会追着你轰炸。我自己后来调整了一套比较实用的规则。核心思路是加“持续次数”和“恢复通知”两个逻辑一条告警必须在连续N个轮询周期内都触发才真正发送通知这个“持续次数”我通常设在3以上也就是大约15分钟左右的持续时间恢复通知则一定要开启不然告警结束了你还在那边瞎担心。至于告警渠道LibreNMS支持的方案很多邮件、Slack、Telegram、飞书、钉钉都有插件。国内场景我用得多的是邮件和钉钉机器人。钉钉自定义机器人只需要一个webhook地址在告警模板里加上POST请求配置就能接入。注意webhook地址不要泄露到公网否则别人可以拿你的机器人疯狂发垃圾消息。6.2 自动发现规则的精细化LibreNMS的自动发现功能是很强但默认的网段扫描范围是空的你必须主动定义要监控的子网。在Settings - Auto-Discovery里可以配置自动发现类型我推荐的做法是先用SNMP (discover new devices via network)给定一个你想发现的IP段比如192.168.1.0/24。然后重点勾选“只给已知设备添加新接口”这个选项避免系统把网络里所有回声请求都当成新设备。自动发现跑起来之后你会发现它能自动识别设备厂商型号自动给接口命名甚至能在拓扑图里画出设备之间的物理连接。这个功能在机房设备变动频繁的场景下简直是救命稻草——新增设备开机加入网络后什么都不用配LibreNMS就能自己把它纳管进来。不过也要注意自动发现不是万能的。部分老设备的SNMP实现有兼容问题MIB库不标准LibreNMS识别出来的型号可能不准接口表也可能缺失。这种情况需要你手动去设备上补全SNMP配置或者安装LibreNMS的其他MIB库插件。6.3 备份策略监控数据丢了等于回到解放前监控系统本身也是需要被监控的。我最开始部署完就没想过备份这事直到有一次服务器系统盘故障整个/data目录全没了多年的流量趋势、故障历史全归零那一瞬间是真的肉疼。现在我的备份策略很简单核心就是两套方案并行数据库做每日逻辑备份RRD文件做每日快照。因为RRD文件是二进制时序数据库无法用文本导出只能整体复制。虽然RRD文件数量多、体积大但胜在变更频率有规律用rsync做增量备份效率很高。写个简单的crontab脚本#!/bin/bash docker compose exec -T db mysqldump -u root -p$MYSQL_ROOT_PASSWORD librenms /backup/librenms_$(date %F).sql rsync -av /opt/librenms/data/librenms /backup/数据量大了之后记得用find命令定期清理旧备份只保留最近30天即可。另外提醒一句备份文件不要放在和监控系统同一块物理磁盘上否则磁盘挂了你连备份一起没了。6.4 时区问题的隐藏影响时区这个问题做监控的人最容易忽略。LibreNMS前端页面默认显示的时区其实跟PHP时区设置有关如果你把compose里的TZ设成了Asia/Shanghai但系统底层的date.timezone没同步一些告警的历史时间戳就会偏。在LibreNMS的Settings - General - Date里有一个Time zone选项我建议设置成Asia/Shanghai。另外系统里所有RRD文件名的时间基准也跟时区有关如果你在部署时就固定好时区后续RRD文件名和历史数据不会有偏移如果你中途改时区老的数据文件不会迁移旧时间戳新老数据之间会出现一段时间的“断层”。所以时区务必在首次启动前配好这个真的很重要。7. 实测中遇到的坑和解决路径7.1 坑一docker compose无法识别老派命令习惯害人这个坑我在帮朋友远程排障时遇到过好几次。他明明装了Docker但输入docker compose up时报错docker: unknown command: docker compose。问题很简单——他的系统里只装了纯Docker引擎没有安装compose插件。处理方式前面已经提到但这里补充一个实测中更省事的办法直接用docker-compose带横杠的独立版本。如果你电脑上原来就有这个二进制不在乎新旧命令样式那继续用也行。LibreNMS官方compose文件在老版本docker-compose下也能正常解析。不过我还是建议只用官方新插件。原因很简单新插件对compose文件的版本支持更完整特别是官方模板里用的healthcheck等字段老版本有时候会解析出错。7.2 坑二cannot start docker compose application. reason: compose [start] exit status这类启动报错这类报错表面看是compose启动失败实际上80%的原因是容器启动后立刻退出。常见情况有两种。一种是数据库容器起不来密码配置不一致.env里写的数据库密码和compose文件里不一致导致数据库初始化脚本失败退出。这种情况排查很简单看docker compose logs db日志里会有mysqld的启动错误提示。另一种是宿主机端口被占librenms容器映射的8000端口已经被别的进程占用容器启动时端口绑定失败。用ss -lntp | grep 8000查一下进程换个端口重试即可。还有一种是相对难查的data/mysql目录里已经有残留数据但残留数据对应的密码跟现在的.env不一致。MariaDB容器在数据目录存在时不会重新初始化密码它会直接用老数据里的密码。解决办法是把data/mysql目录备份后清空再重新up一次让数据库以全新的方式初始化。7.3 坑三设备加进来了但页面一直不出图出图依赖RRD文件。设备成功添加后要过几个轮询周期才会生成RRD。但如果你发现等了半小时还没图大概率是轮询进程挂了。先看调度器日志docker compose logs dispatcher --tail 50如果日志里出现大量RRD相关的权限错误就是数据目录权限问题回到.env里修PUID和PGID。还有一种可能是容器内的python3版本不对导致poller.php执行失败这种情况把镜像更新到最新版基本能解决。7.4 坑四端口流量的历史数据异常大或为负数有时候接口流量图会突然出现峰值爆表明明设备端口是千兆图上却画出几千Mbps的数字。这个通常不是设备的真实流量而是SNMP计数器回绕counter wrap导致的。LibreNMS对标准的ifHCInOctets处理得较好但如果设备走的是老的ifInOctets遇到32位计数器溢出就会这样。解决办法是检查设备连接的接口速率设置确保SNMP返回正确速率类型。对于核心链路建议在LibreNMS设备设置里强制走64位计数器让SNMP v2c明确取值ifHCInOctets。如果设备本身不支持64位计数那只能在告警规则里忽略掉这类异常数据或者定期重启设备重置计数器。7.5 坑五升级LibreNMS版本后自定义修改全部丢失这是Docker部署一个很容易踩的坑。很多人用了官方模板后会跑去修改容器内的PHP源码或Nginx配置比如调整上传大小限制、修改网页标题、加自定义脚本。你要记住容器一旦重建容器内非volume挂载的文件全部重置回镜像默认值。所以正确的做法是所有自定义配置统统写到data/librenms/config.php里或者放在librenms数据目录下的自定义目录里。Nginx配置如果有特殊需求也应该在compose里加额外的volume映射。升级完镜像后数据目录里的配置是保持不变的。我亲眼见过有人升级后一脸懵——“我改过的主题咋不见了”——其实就是这个原因。8. 进阶玩法把监控系统本身也用起来LibreNMS跑起来之后很多人的使用方式停留在“打开页面看状态”这个层面但其实它能力远不止于此。我自己用得比较顺手的几个进阶功能也一并分享出来。一是Oxidized联动。Oxidized是一个网络设备配置备份工具把它和LibreNMS放同一个网络里LibreNMS每次发现设备时能自动通知Oxidized去备份设备配置文件。这样任何交换机配置被误改你都能随时回滚到历史版本。在事故处理场景里这个能力比流量图还救命。二是流量数据导出。LibreNMS通过API接口可以拉取历史流量数据、CPU信息、接口状态等我用它接了公司的内部报表系统每周自动生成设备健康报告再也不用人工去一台台excel里抄数据了。API接入方式不复杂在个人设置里生成API token然后调用/api/v0/devices、/api/v0/ports等接口就能拿到JSON数据。三是警报联动自动化。告警引擎除了发消息还能调webhook接口。我把部分告警接到了自动化平台上比如某台服务器连续三次ping不通自动平台会直接重启它的远程管理卡。这个玩法的前提是告警规则要足够精准否则自动操作会带来不可控风险。我自己的原则是重启类操作只绑定“设备完全离线”这一条告警其他一律先人工确认。四是接入NFSen做NetFlow分析。如果你的网络设备支持NetFlow或sFlowLibreNMS可以配合NFSen采集流量会话信息细到“哪个IP在跟哪个IP通信、跑了多少流量、持续多久”都能查出来。这个对排查网络瓶颈和判断异常外联特别有用。很多人以为LibreNMS只能画端口图其实流量会话分析才是它真正杀手级的功能。9. 我最终落地这套方案后的实际感受整套系统用下来最大的变化是“告警从催命符变成了真正的值班工具”。以前设备半夜重启我第二天才知道现在只要某一台交换机连续几轮轮询无响应告警通知立刻就到等到业务同事上班反馈时我和他掌握的信息已经完全对等了。故障响应时间从“小时级”压缩到了“分钟级”。不过我也要给你提个醒不要一上来就把所有监控对象全加进去。我见过一个同事刚部署完就一口气导入了两百台设备结果自动发现任务堆成山数据库负载瞬间飙升页面整个卡死。正确的做法是先加10台左右设备观察几天确认轮询稳定、数据正常再逐步扩量。监控系统是越用越顺的工具不是你从第一天起就要背上所有包袱的那个东西。另外我个人始终坚持一条管理原则Docker容器能随时重建但数据目录才是你真正需要认真伺候的资产。每次升级镜像前我都会先备份数据库和RRD数据再执行docker compose pull和docker compose up -d。这套流程下来我的LibreNMS经历了不下十次升级从来没有因为升级导致监控数据丢失。最后再分享一个我在实际使用中的小技巧给LibreNMS容器配置日志轮转。默认情况下Docker日志会无限增长时间久了能把磁盘塞满。在compose文件里加一段logging配置限制单文件大小和保留份数能帮你少处理很多“磁盘告警”的破事。生产环境里提前把这类小事做掉比事后再拍脑袋解决要舒服得多。
返回列表