ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

liteio离线部署实战:内网环境下的数据接入中间件安装与排错指南

liteio离线部署实战:内网环境下的数据接入中间件安装与排错指南 干过工业现场或者内网机房运维的同学应该都有同感最怕的不是功能不会用而是设备搬进去了、系统装好了结果依赖装不上项目直接卡在环境上。这次要说的 liteio 离线环境部署就是我在几台边缘网关和隔离区服务器上折腾完一整套流程后沉淀下来的实操笔记。liteio 是一款轻量级的数据接入中间件主要解决设备数据采集、协议解析、数据转发这类问题常见的应用场景是边缘计算网关、车间数采盒子、内网数据汇聚节点。你可以把它理解成一个“数据的二传手”从 PLC、传感器、控制器把数据拿过来解析处理后再转给上层平台或者数据库。很多工业现场的网络环境是物理隔离的或者只能访问内网源这就逼着你必须走完整的离线部署流程。这篇内容不是官方文档翻译而是我按“提前准备、打包搬运、现场安装、问题兜底”这个思路跑通的实际流程。中间的坑我都踩过比如依赖包版本不一致、GLIBC 版本不够、systemd 服务起不来、防火墙把端口吞了等等下面都会挨个说清楚。不管你是刚接触 liteio 的新手还是已经在内网摸爬滚打过的老手按这套思路走基本能少走一半弯路。1. 离线部署前的整体思路与方案选型离线部署听起来就是“把文件拷过去装一下”但真正做起来最核心的问题不是“拷文件”而是“怎么保证拷过去的全套东西是齐的、版本是对的、装上去能跑”。1.1 先搞清楚 liteio 的运行形态第一步要明确 liteio 本身是哪种形态的程序因为这直接决定离线包的制作方式。根据我实际接触到的版本liteio 主要有三种运行形态纯二进制单文件编译产物就一个可执行文件比如liteio-server外加一个配置目录。这种形态最幸福离线部署几乎等于“拷贝 授权 配服务”。带依赖的脚本/服务比如基于 Python 或者 Node.js 运行时需要一堆第三方库。这种形态需要把整个依赖树都收集齐打包带进去。容器镜像形态官方或者自己构建的 Docker 镜像离线部署时用docker load导入镜像然后跑容器。我在实际项目里用的主要是纯二进制形态但因为有几台机器需要扩展协议插件另外也走了依赖打包的方式所以下面两部分都会讲到。先别急着动手装先把目标机器的架构确认了因为 liteio 的二进制通常分amd64和arm64两个版本装错了直接跑不起来。提示在 x86 服务器上装 ARM 版本大概率会报exec format error这个错误第一反应不是文件坏了而是架构不匹配。1.2 联网环境与目标环境的软件差异核对很多人只在目标机器上装 liteio却忘了检查基础运行环境。liteio 一般依赖几个基础能力操作系统用户态库比如glibc版本过低会导致二进制无法启动报version GLIBC_2.28 not found。网络转发能力如果 liteio 需要监听端口要确认内核参数net.ipv4.ip_forward是否开启。时区与时间同步工业场景经常出现设备时间偏差导致数据时间戳混乱。所以在联网环境准备离线包之前先去目标机器上跑几条命令把系统版本和架构信息记下来形成一个基本清单cat /etc/os-release uname -m ldd --version | head -n1这个清单就是你后面选包、选版本、写配置的依据。我见过最典型的问题就是开发机上跑的是 Ubuntu 20.04现场却是 CentOS 7结果一堆 .so 依赖对不上还得重新找兼容版本。离线环境不像在线环境那样apt install一下就能升级所以目标机器的“底子”必须在一开始就盯死。1.3 离线部署三种方案的取舍根据实际场景我总结过三种离线部署方案按优先级排序方案适用情况优点缺点A. 二进制直接部署官方提供可执行文件简单、依赖少、排错容易受架构和 glibc 版本限制B. 源码/依赖包部署需要定制协议或二次开发可扩展性强能改代码依赖树复杂收集困难C. 容器镜像部署系统环境差异大、需要隔离镜像打包后环境一致性好需要目标机有容器运行时如果你只是跑标准功能优先选 A。需要加自定义协议解析的选 B。现场系统比较老旧、又不想动系统库的选 C。下面我以方案 A 为主线把 B 里面依赖收集的部分也展开讲。2. 制作完整的 liteio 离线部署包离线部署的成败一半在准备工作。准备工作不是把你需要的东西塞进一个文件夹就完了而是要保证“闭着眼睛拷过去也能装”。2.1 联网环境准备基础软件包先从下载源头说。假设你在联网环境拿到了 liteio 的 release 包通常是一个.tar.gz里面包含liteio-server可执行文件、config/配置目录、plugins/协议插件目录。这个压缩包本身是核心但还不够。如果 liteio 依赖 Python 运行环境插件系统常见用 Python 写协议脚本那还需要准备 Python 离线依赖。这里我用pip download在当前 Python 版本下把所有依赖收集到一个目录里pip download -r requirements.txt -d ./liteio_pydeps -i https://pypi.tuna.tsinghua.edu.cn/simple注意pip download收集的包不等于全能装最好多加几个约束条件pip download -r requirements.txt -d ./liteio_pydeps \ --platform linux_x86_64 \ --python-version 3.9 \ --implementation cp \ --only-binary:all:这几个参数的意思是只下载 Linux x86_64 架构、Python 3.9 对应的二进制 wheel 包。如果不加这些参数可能下载的是源码包到现场源码编译会缺编译器反而更麻烦。如果用 Docker 镜像离线部署还需要在联网环境把镜像先打出来docker save liteio:latest -o liteio_image.tar这个 tar 包通常几百 MB 到 1GB 不等建议传到现场前先gzip压缩一下减少 U 盘或者内网传输压力。有人问我为什么不用docker export这里提醒一下docker save保存的是完整镜像层可以docker load回来继续跑容器docker export只导出容器文件系统会丢镜像元数据不是一类用途。2.2 整理目录结构与依赖校验清单联网环境准备完要形成一个结构清晰的“离线安装包”目录。我自己习惯的目录如下liteio-offline/ ├── liteio-2.4.1-x86_64.tar.gz ├── liteio_pydeps/ │ ├── paho_mqtt-1.6.1-py3-none-any.whl │ ├── pyserial-3.5-py2.py3-none-any.whl │ └── ... ├── python3_offline_installer/ │ └── Python-3.9.18.tar.xz ├── scripts/ │ ├── install.sh │ ├── uninstall.sh │ └── verify.sh └── checksums.txt为什么要把install.sh也放进去因为现场不同的人执行习惯不一样有的人喜欢 root 直接跑有的人喜欢 sudo有的人路径带空格就懵了。把安装脚本固化下来能减少人工输入命令带来的差异。比如安装的时候脚本自动解压、自动移动到/opt/liteio、自动创建liteio用户、自动写 systemd 服务文件一气呵成。生成checksums.txt是很多老手容易漏掉的一步。在离线包里跑一下sha256sum liteio-2.4.1-x86_64.tar.gz liteio_pydeps/* checksums.txt现场传输介质是 U 盘还是内网 FTP都有可能丢字节。万一某个包损坏现场安装时会出现莫名其妙的报错而离线环境又不好重新下载只能干瞪眼。所以我强烈建议把校验文件带上到现场先跑一遍sha256sum -c checksums.txt确认文件完整之后再动手。2.3 目标机上的基础目录规划目标机器上最好用一个统一的目录来放 liteio 相关文件不要散落在/root、/home到处都有。我建议采用/opt/liteio作为程序目录/etc/liteio作为配置目录/var/log/liteio作为日志目录/var/lib/liteio作为数据存储目录。这样的目录规划有两个好处第一备份和卸载都很清晰数据在哪个目录、配置在哪个目录、日志在哪个目录一目了然第二符合 Linux 目录规范后续如果用 SELinux 或者 AppArmor 做安全策略也更容易配置。系统里最好新建一个专用的运行账号而不是直接拿 root 跑useradd -r -s /sbin/nologin -d /var/lib/liteio liteio这样做的好处是即使 liteio 某个接口被攻击或者配置出错影响面也限制在这个低权限用户下。工业内网虽然相对可控但安全习惯不能省。3. 离线安装 liteio 的完整实操流程准备工作做完就该动手安装了。这个环节的节奏应该是“每一步都确认结果再进下一步”离线环境没有回滚的捷径所以最好稳扎稳打。3.1 目标机器的前置条件安装先确保目标机器上有解压工具、文本编辑器、进程管理工具在最小化安装的系统上这些可能都没有。我在 CentOS 和 Ubuntu 上分别会这样检查# CentOS / RHEL yum install -y tar gzip wget vim net-tools # Ubuntu / Debian apt install -y tar gzip wget vim net-tools如果目标机器连内网软件源也不能访问那这些基础工具必须在联网环境提前下载 RPM 或 DEB 包带过去。很多人以为只带 liteio 包就够了结果现场连tar都没有特别尴尬。接着把离线安装包上传到目标机我在内网环境一般用scp或者内网 FTP。这里建议传到/tmp/liteio_install目录解压之后不要在/tmp里直接启动服务因为部分系统会定期清理/tmp下的文件。解压到正式目录mkdir -p /tmp/liteio_install tar -xzf liteio-2.4.1-x86_64.tar.gz -C /tmp/liteio_install mv /tmp/liteio_install/liteio /opt/liteio然后立刻做一次版本验证确认二进制和系统兼容/opt/liteio/bin/liteio-server --version如果这一步能正常输出版本号说明 glibc、架构这些基础条件都过了后面主要是配置问题。如果报cannot execute binary file或者no such file or directory那基本是架构或 glibc 问题。3.2 Python 运行时与依赖包的离线安装如果你的 liteio 启用了 Python 插件系统那还需要把 Python 环境也装上。有的目标机器系统自带 Python 3.6但 liteio 要求 3.8 以上这时候就不能将就最好安装独立的 Python 版本不要覆盖系统自带的。具体实施时我习惯编译安装到/usr/local/python3.9源码包就是之前离线包里准备的Python-3.9.18.tar.xz。编译之前先检查目标机器有没有gcc、make、zlib-devel这些编译工具如果没有又得回到第一步去准备离线 RPM/DEB。编译安装的经典命令是tar -xJf Python-3.9.18.tar.xz cd Python-3.9.18 ./configure --prefix/usr/local/python3.9 --enable-optimizations make -j4 make install这里多说一句--enable-optimizations会明显拉长编译时间但运行时会快一些。如果现场机器性能一般可以去掉这个参数优先保证能装上。Python 装好后再对之前下载的依赖包进行离线安装/usr/local/python3.9/bin/pip install --no-index --find-links/tmp/liteio_install/liteio_pydeps -r requirements.txt--no-index是让 pip 完全不要去找在线源--find-links指定本地搜包目录。如果依赖包里有某个.whl与当前 Python 版本不匹配pip 会直接报错并且不装任何东西这也是为什么前面强调pip download的时候要锁定 Python 版本和平台参数。3.3 编辑 liteio 核心配置文件liteio 的主配置一般是一个 YAML 文件路径在/opt/liteio/config/liteio.yaml。这个文件控制了三块核心内容数据采集入口、协议插件加载、数据转发目标。下面是一份我在场站里用过的配置示例server: host: 0.0.0.0 port: 8899 log_level: info caps: modbus_tcp: enabled: true poll_interval: 1000 plugins: - name: modbus path: /opt/liteio/plugins/libmodbus.so - name: opcua path: /opt/liteio/plugins/libopcua.so forward: target: mqtt://192.168.10.20:1883 topic_prefix: factory/line1这里有一个很容易忽视的问题forward.target如果配置的是域名而不是 IP离线环境下 DNS 可能不可用导致 liteio 启动后一直无法上报数据。所以离线部署环境里建议把所有目标地址都写成 IP或者提前把主机名写入/etc/hosts。我在现场被这个问题卡过半天一开始以为服务没启动后来才发现是域名解析超时改成 IP 后立马上线。另外如果 liteio 要采集的 PLC 或者仪表分布在多个网段别忘记在目标机器上添加路由。之前有一台采集服务器连着两个网段的设备只有默认网关另一网段的 Modbus TCP 请求全部超时。这个排查过程很痛苦因为ping不通让你以为是设备问题其实设备根本没坏是目标机上没写路由。到现场第一件事把目标机的网络拓扑画清楚静态路由该加的加好ip route add 192.168.20.0/24 via 192.168.10.1 dev eth03.4 注册 systemd 服务并设置开机自启配置好了程序接下来要做的是把 liteio 注册成系统服务。不要直接nohup跑在后台一是进程意外退出没人管二是服务器重启后你得手动去拉起。用 systemd 管理才靠谱。在/etc/systemd/system/liteio.service里写一个服务单元[Unit] DescriptionLiteIO Data Access Service Afternetwork-online.target Wantsnetwork-online.target [Service] Typesimple Userliteio Groupliteio WorkingDirectory/opt/liteio ExecStart/opt/liteio/bin/liteio-server --config /etc/liteio/liteio.yaml Restarton-failure RestartSec5 LimitNOFILE65535 [Install] WantedBymulti-user.target写完之后依次执行systemctl daemon-reload systemctl enable liteio systemctl start liteio systemctl status liteio这里有个关键细节Afternetwork-online.target配合Wantsnetwork-online.target是为了确保网络完全就绪后再启动 liteio避免启动时连接远程设备或者目标平台失败。LimitNOFILE65535针对大量采集连接的场景默认的 1024 文件描述符很容易被耗完导致“Too many open files”报错。我现在凡是部署采集类服务都会习惯性把这个参数加上。启动之后还要验证端口监听是否正常ss -lntp | grep 8899如果这里看不到监听多半是配置里的端口被占用或者参数写错了进入下一步排查。4. 离线环境下的常见问题与排查技巧离线环境最让人头疼的事情就是“没有百度可以用”只能靠日志和系统命令一步步查。下面我把实际过程中遇到的高频问题整理成一个速查表附上我自己的排查思路。4.1 进程起不来或秒退如果systemctl start liteio之后进程几秒钟就退出了最常见的几个原因我按出现频率排序现象可能原因排查方式failed to load config配置文件路径写错或 YAML 格式错误检查/etc/liteio/是否存在手动执行二进制看详细报错address already in use端口被其他进程占用ss -lntp看占用进程改端口或停掉冲突进程permission denied运行用户没有数据目录写权限chown -R liteio:liteio /var/lib/liteioGLIBC_2.28 not found系统库版本过低换用兼容 glibc 的 liteio 版本或升级系统库这个阶段我习惯直接手动执行一遍二进制sudo -u liteio /opt/liteio/bin/liteio-server --config /etc/liteio/liteio.yaml放弃 systemd 直接跑好处是错误信息会直接打到终端上比journalctl里面翻日志来得更直观。看到完整报错之后再对症下药。4.2 服务起来了但数据上报失败systemctl status是 running 状态日志里也没报错但目标平台迟迟收不到数据。这时候要分层排查先确认 liteio 到设备之间的链路通不通再确认 liteio 到目标平台之间的链路通不通。很多工业现场设备在独立网段采控服务器有多块网卡这时最容易出现“采集正常但转发失败”的情况。我排查时常常这样看路由ip route get 192.168.10.20如果返回的出口网卡不对说明路由有问题比ping更直接。另外如果目标平台是 MQTT Broker还需要确认 broker 是否开启了匿名连接或者是否配置了正确的 ACL。liteio 的日志里通常会有connection refused或者not authorized之类的关键字直接grep日志是最高效的排查方式grep -i error\|fail\|refused /var/log/liteio/liteio.log别小看这一步我曾经在一个项目里发现日志里一直刷topic not allowed最终定位到 broker 端 ACL 策略只允许特定前缀的 topic而 liteio 里配置的前缀和它差了半级改了配置后立刻就好。4.3 防火墙和系统安全策略拦截离线环境尤其是内网环境很多人会忽略防火墙因为平时感觉不到它的存在。但 liteio 如果监听的是非标准端口比如8899而系统默认开启的firewalld或ufw只放行了常见端口那从外部访问就会超时。在 CentOS 上我通常会这样处理firewall-cmd --permanent --add-port8899/tcp firewall-cmd --reload在 Ubuntu 上则可能是ufw allow 8899/tcp还有一种情况是系统里启用了 SELinux。如果 SELinux 是 enforcing 模式liteio 写在/opt下的运行文件可能没有对应的文件上下文导致进程无法读取配置文件。排查思路是看/var/log/audit/audit.log里有没有denied记录如果有通过ausearch配合semanage调整策略ausearch -m avc -ts recent说实话SELinux 策略配置是离线部署中比较冷门但又致命的问题。很多人在内网环境图省事直接把 SELinux 设为 permissive 甚至 disabled但如果公司安全基线要求开 enforcing那还是要老老实实放行。这个道理想清楚之后你才能理解为什么我不建议直接甩锅给“重启”。4.4 日志、备份与回滚方案离线环境一旦部署完成后续升级也是同样的离线流程。所以每次安装完成之后要立即备份一份“有效配置”和依赖清单。我习惯把/etc/liteio/liteio.yaml和pip freeze的输出一起放到备份目录并且打一个带日期的 tagcp /etc/liteio/liteio.yaml /backup/liteio_$(date %Y%m%d).yaml /usr/local/python3.9/bin/pip freeze /backup/liteio_pydeps_$(date %Y%m%d).txt为什么要备份因为 liteio 升级时配置结构可能会有变化。有了备份升级失败还能快速回滚到旧版本和旧配置。我见过太多人升级前不做备份出问题后再也回不到原来的状态只能凭记忆重新配浪费时间还容易引入新错误。回滚操作其实不复杂把旧版本二进制换回来、恢复旧配置、重启服务即可。但前提是你之前有备份所以这一步不要偷懒。5. 几个值得长期坚持的部署习惯最后说点我在多次离线部署之后总结出来的小习惯不一定写在哪本手册里但实战中很管用。第一个习惯是“安装脚本里带验证步骤”。每次部署完 liteio不要只跑到服务启动就结束了还要自动去探测端口、检查进程、抽样采集一次数据。哪怕只是简单的ss -lntp | grep 8899也比人工看一眼 systemd 状态要可靠得多。第二个习惯是“把离线包固化版本号”。离线包的文件名里写清版本和适用架构比如liteio-2.4.1-x86_64-centos7.tar.gz这样传到现场后不会拿错。版本号里加目标系统信息是因为 glibc 版本和系统库差异太重要了同是 x86_64 的包CentOS 7 和 Ubuntu 22.04 可能不通用。第三个习惯是“先小范围验证再全面铺开”。如果现场有多台机器不要一次性全部部署。先拿一台最典型、配置最复杂的机器跑通全流程确认没有问题之后再批量复制同样的离线包去部署其他机器。这个习惯帮我避免过至少三次批量翻车因为很多隐藏的系统差异只有真正跑起来才会暴露。第四个习惯是“写部署记录”。每台机器部署完成后把安装时间、使用用户、安装路径、日志路径、启动方式、修改过的配置项记在一份 NOTES 里。离线环境没法随时查文档这份 NOTES 就是下一次排查问题的起点。对团队协作来说这个记录的价值会随着时间增长越来越大。我在实际踩坑过程中最大的体会是离线部署本身是个“一次性工程”但只要把准备工作、依赖梳理、验证回滚这些环节做到位它比在线部署反而更稳定因为环境一旦确定就不会被外部因素干扰。希望这套 liteio 离线部署流程能帮你少走点弯路尤其是那些“到现场才发现少带一个包”的尴尬能避免一次是一次。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进