
1. 离线部署的整体思路与前置准备先说结论离线部署MongoDB卡住你的从来不是MongoDB本身而是一堆你看不见的环境依赖。很多人第一次干这个事拿着一个安装包高高兴兴上传到内网服务器结果一执行就报error while loading shared libraries然后就开始漫漫排查路。这篇文章我把我自己踩过的坑、整理好的思路完整写一遍照着做基本能一次过。为什么会有离线部署的需求我遇到的大概有三类场景生产内网与公网物理隔离安全要求高外网根本不通机房有外网但出于变更管理和版本管控要求不允许直接在线装项目交付给客户客户现场环境不可控必须把所有东西都带进去。说白了离线部署是一件准备工作比安装本身更费时间的事情只要能在外网环境把安装包、依赖、配置一次性准备好内网的操作反而很快。1.1 为什么要选择离线部署mongodb在线部署一条yum install就完事舒服是舒服但在真实生产环境里根本不是这么玩的。你能在线装不代表客户的机器也能在线装。而且在线安装最大的问题是不可控你根本不知道今天镜像源里面MongoDB变成了什么版本依赖解析器会不会顺手帮你把某个底层库也升了级。变更不可控是运维的大忌。离线部署的核心优势就两个可复现和可审计。同一个安装包、同一套配置文件在这台机器上用什么样换一台机器还是什么样。以后出问题排查版本是确定的依赖是确定的配置是确定的少一大半扯皮的功夫。另外安全审计的时候你也能很清楚地说出来环境里放的是哪个版本、校验值是多少。1.2 部署前必须确认的三个关键信息收到离线部署MongoDB这个任务先别急着去找安装包。先确认三件事这三件事没确认你后面一定会返工第一操作系统发行版和版本。CentOS 7、CentOS 8 Stream、Rocky Linux、Ubuntu 20.04/22.04安装方式和依赖要求都有差异。比如说你用惯了yum到了 Ubuntu 就得切apt或者干脆都用通用二进制包来规避差异。我个人的习惯是只要平台不是特别冷门统一用 MongoDB 官方提供的通用二进制包下面会细说。第二CPU 架构。绝大多数服务器是 x86_64但ARM架构aarch64也越来越多了。下载安装包的时候一眼扫错下了个aarch64版本到x86机器上用一执行直接 core dump还查不出原因。当时真能折腾你半天。第三一个很多人都忽视的东西glibc 版本。MongoDB 的二进制包对操作系统的 glibc 有最低版本要求。如果你在老旧的 CentOS 7.x 上跑最新版的 MongoDB 7.0很有可能会因为 glibc 版本过低直接起不来。查一下当前环境的 glibc 版本ldd --version心里先有个数。这三条确认完接着就是把安装包和依赖准备齐全了。这个工作务必在能上网的跳板机上完成U盘也好内网传输工具也好反正都搬进内网去。2. 安装包选择与下载这一步决定后面的成败MongoDB 官方其实提供了好几种安装方式apt/yum在线源、RPM包、DEB包、通用二进制包TGZ。离线环境下我强烈建议直接用通用二进制包理由后面说。2.1 到底该选TGZ还是RPM包先对比一下两条路线的差别方式优点缺点RPM/DEB下载后rpm -ivh自带systemd服务文件、目录规范、能写进rpm数据库方便管理依赖关系比较麻烦经常缺libcrypto、libssl等底层库不同操作系统版本要选不同的包TGZ官方通用二进制版无需安装、解压即用、所有依赖集中在mongod这一个二进制上可以放任意目录多实例部署方便需要自己手工创建目录、用户、systemd服务文件我第一次离线部署用的是RPM包结果就是被依赖搞崩了rpm -ivh mongodb-org-server-xxx.rpm报缺少libcrypto.so.10()版本明明看起来是对的但需要的老库系统里就是没有。后来我换了TGZ包世界瞬间清净了。提示除非你的内网有完整的本地yum仓库并且已经同步好了所有依赖否则统一选TGZ包是最省心的。RPM是给有网络且源可用的场景准备的离线环境硬上RPM就是给自己找不自在。2.2 版本选型与下载注意事项版本选择上我的建议是选当前生产环境中已经验证过的主流稳定版本不要追最新也不要太老。举个例子如果你们公司在线的机器还在用 4.4 或者 5.0那离线包最好用同系列大版本这样配置文件、常用命令、行为习惯都一致不会给自己挖坑。下载的时候有几个细节值得注意地址要用官方下载中心不要随便找个第三方镜像站打包下载校验和都核对不上风险太高下载文件名要看仔细mongodb-linux-x86_64-xxx.tgz和mongodb-linux-aarch64-xxx.tgz别搞混下载完一定要校验。官方页面会给 SHA-256 值用sha256sum比对一下这个习惯能帮你挡掉很多文件损坏、被篡改的问题。我在准备离线包的时候一般会额外下载配套的mongosh新版Shell工具因为老版mongoshell 在新版本里已经移除了。如果你是 5.0 以上版本记得把 mongosh 的离线包也一起准备好不然装完连数据库都连不进去。另外如果生产环境要用监控或者备份工具比如 Compass、PITR 增量备份相关工具也一并下载好。到内网再想下载可就叫天天不应了。3. 离线安装实操从解压到systemd托管下面进入正题。我以一台 x86_64 架构的 Rocky Linux 8.x / CentOS 8.x 服务器为例装的是 MongoDB 6.0 系列具体小版本号自行替换把完整流程走一遍。3.1 目录规划与创建专用用户先把安装包传到一个固定目录比如/opt/src然后解压到/opt下mkdir -p /opt/src tar -zxvf mongodb-linux-x86_64-6.0.19.tgz -C /opt mv /opt/mongodb-linux-x86_64-6.0.19 /opt/mongodb然后规划数据目录、日志目录和配置文件目录。我的习惯是mkdir -p /var/lib/mongo mkdir -p /var/log/mongodb mkdir -p /etc/mongodb touch /var/log/mongodb/mongod.log为什么要单独建/var/lib/mongo而不是直接放在/opt/mongodb下面因为数据目录、日志目录都属于运行时动态数据和程序目录分开以后升级就是替换/opt/mongodb整个目录数据不受影响。这个习惯在线上很有用。接着创建专用用户禁止用 root 跑数据库useradd --system --no-create-home --shell /sbin/nologin mongod chown -R mongod:mongod /var/lib/mongo chown -R mongod:mongod /var/log/mongodb chown -R mongod:mongod /opt/mongodb这里有个细节/var/lib/mongo和/var/log/mongodb的属主必须是mongod否则启动的时候 mongod 会因为没有写权限直接退出。好多新手第一次装完启动报错说什么 permission denied十有八九就是这个原因。3.2 编写配置文件关键参数逐个说MongoDB 从 5.0 开始默认的配置文件格式是 YAML路径任意但建议统一放/etc/mongodb/mongod.conf。我分享一个生产环境常用的最小可用配置# mongod.conf systemLog: destination: file path: /var/log/mongodb/mongod.log logAppend: true storage: dbPath: /var/lib/mongo wiredTiger: engineConfig: cacheSizeGB: 4 processManagement: fork: true pidFilePath: /var/run/mongod.pid net: bindIp: 127.0.0.1,内网IP port: 27017 security: authorization: enabled几个关键点拆开说logAppend: true这个必须开。不然日志文件超过大小之后mongod 会尝试 rename 日志文件权限不够直接写着写着就崩了。fork: true表示以后台守护进程方式启动。如果用了 systemd 管理这个参数反而不需要因为 systemd 自己会管理进程生命周期。所以如果你打算用 systemdfork不要设 true。bindIp记得写实际要监听的内网 IP不要图省事只写127.0.0.1。否则部署完发现远程连不上还得回头看配置。cacheSizeGB这个参数很多人不调。WiredTiger 默认缓存是物理内存的一半减1GB在内存大的机器上很容易吃满内存。如果这台机器还跑别的服务建议手动限制到 4GB 或者按需分配。提示第 5 条很重要。MongoDB 不是吃得越多越好它本身是个吃内存大户如果你不给它上限它会逐渐把 page cache 顶到很高导致同机其它服务被挤兑。3.3 用systemd托管MongoDB服务TGZ 包不会帮你生成 systemd 服务文件这一步需要手工做。新建/etc/systemd/system/mongod.service内容如下[Unit] DescriptionMongoDB Database Server Documentationhttps://docs.mongodb.com/manual Afternetwork-online.target Wantsnetwork-online.target [Service] Typesimple Usermongod Groupmongod ExecStart/opt/mongodb/bin/mongod --config /etc/mongodb/mongod.conf PIDFile/var/run/mongod.pid LimitNOFILE64000 LimitNPROC64000 Restartalways RestartSec5 [Install] WantedBymulti-user.target注意两个细节Typesimple配合配置文件里fork: false就是前台运行systemd 来守护。如果配置文件里写了fork: true这里就要用TypeforkingPIDFile两种方式不要搞混。LimitNOFILE64000一定要设置。1067的时候默认文件描述符限制是1024高并发写入下mongod很容易触达这个限制然后报 too many open files。这个我踩过排查到最后一查 ulimit心都凉了。写好服务文件之后systemctl daemon-reload systemctl enable mongod --now到这里 MongoDB 已经能用 systemd 管理了systemctl start mongod、systemctl restart mongod、systemctl status mongod—— 这套组合拳下来后面运维就舒服了。4. 初始化数据库与开启认证服务起来了只是第一步MongoDB 默认是没有任何账号认证的也就是说只要能连上端口谁都能把数据库拖走。所以部署完成之后第一件事就是创建管理员账号并开启访问控制。4.1 首次启动与快速自检先用systemctl status mongod确认状态是 active (running)然后看日志确认没有异常tail -n 20 /var/log/mongodb/mongod.log正常会看到类似Waiting for connections的字样。如果报错翻日志最直接别瞎猜。然后连进去验证一下/opt/mongodb/bin/mongosh --port 27017 --eval db.runCommand({ping: 1})能返回{ ok: 1 }就说明服务没问题。这里如果用的是 5.0 以上版本命令是mongosh不是mongo。注意我前面说的离线包里要带 mongosh不然这一步就卡住了。4.2 创建管理员账号并开启访问控制MongoDB 的账号体系是分库的admin库是超级权限库业务账号要单独建在业务库里。我习惯先创建一个超级管理员用于后续管理再按业务创建最小权限账号。先连上 shelluse admin db.createUser({ user: admin, pwd: 这里换成强密码, roles: [ { role: root, db: admin } ] })这个root角色可以理解成管理员权限的总代称拥有整个数据库实例的所有权限包含用户管理、授权、集群运维等。但日常业务绝对不要用这个账号去读写数据权限太大万一连接串泄露就是灾难。创建完用户后重启才生效访问控制其实改配置文件也行但重启最稳妥systemctl restart mongod4.3 验证认证是否生效重启后重新连接/opt/mongodb/bin/mongosh localhost:27017/admin -u admin -p 密码 --authenticationDatabase admin能正常返回就说明认证生效了。也可以反向验证一下不带账号密码连接执行show dbs应该会报错command requires authentication。这里我再提一个生产环境的常见坑开了认证之后你的应用连接串也要跟着改。有些项目代码里连接串是写死没有用户名密码的重启数据库服务之后应用立刻报Unauthorized。所以初始化数据库的同时要同步检查所有应用配置里的连接参数。5. 离线环境下的常见问题与排查实录离线部署最麻烦的不是安装本身而是出了问题之后排查手段受限——没有外网、没有官方源、装不了额外的调试工具一切都要靠日志和手工判断。下面这些坑我基本都踩过逐个记录给大家参考。5.1 启动直接报错缺少依赖库最经典的就是/opt/mongodb/bin/mongod: error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file这个问题的根源是 MongoDB 二进制包在自己编译时依赖了特定版本的 OpenSSL而你机器上的 OpenSSL 版本偏老或者压根是另一个名字。排查方法ldd /opt/mongodb/bin/mongod | grep not found能直接列出缺少哪些库。解决思路有两个如果缺的库名字看起来差一点点比如libcrypto.so.1.1而系统里是libcrypto.so.1.0那基本可以判断是操作系统版本太老建议换低版本 MongoDB 或者升级系统如果库文件其实存在但路径不对可以通过设置LD_LIBRARY_PATH指向库文件所在目录但这是临时方案生产环境不建议这么干。我在本地测试环境准备离线包的时候会在最接近生产环境的虚拟机里先跑一遍确认该装的 NSS、OpenSSL 兼容性都没问题再真正拷进内网。这一步能省掉至少一个下午的排查时间。5.2 服务启动后又自动退出systemctl start mongod之后几秒钟状态变成 inactive (dead)。不要慌第一反应翻日志journalctl -u mongod -n 50一般来说几种常见原因数据目录权限不对。/var/lib/mongo不是 mongod 用户所属导致写入失败配置文件里dbPath写错了指向了一个不存在的目录/var/run/mongod.pid目录不可写磁盘空间满了mongod 初始化时发现空间不足直接退出。这些错误在日志里都有明确提示一条条对照着查就能解决。5.3 客户端远程连接不上服务明明起来了用别的机器 telnet 一下端口就是不通。按顺序排查net.bindIp是否配置本机实际 IP只写了 127.0.0.1 必然连不上防火墙有没有放行 27017 端口如果是云主机安全组规则是否允许内网访问这个端口SELinux 是否拦截这个在三方系统上很常见。SELinux 判断方法很简单先临时setenforce 0如果能连上了就是 SELinux 的锅别图省事关掉 SELinux正确的做法是给 mongod 放行semanage port -a -t mongod_port_t -p tcp 270175.4 老CPU上启动报 illegal instruction这个坑我印象太深了。MongoDB 5.0 开始官方在编译时默认启用了 AVX 指令集如果你的服务器 CPU 比较老比如某款多年前的至强处理器启动时直接报Illegal instruction (core dumped)。排查方法先确认 CPU 是否支持 AVXgrep -o avx[^ ]* /proc/cpuinfo | head -n1如果输出为空说明 CPU 不支持 AVX那你只能用 MongoDB 4.4 及以下版本或者换新的服务器。这个约束在采购选型的时候就应该考虑到别等部署到一半才发现硬件不支持。5.5 离线环境下如何解决 yum 依赖如果确实用了 RPM 方式离线环境缺依赖怎么办一个可行的方法是在一台有公网的、系统版本和内核尽量一致的机器上先试着yum install把依赖包全部下载好yum install --downloadonly --downloaddir/tmp/mongo-org mongodb-org-server mongodb-org-shell然后把/tmp/mongo-org整个拷进内网用yum localinstall *.rpm来装或者搭一个简单的本地 yum 仓库。不过说实话如果你已经能用 TGZ 方案绕开这个麻烦就没必要在这个方向上死磕。离线安装的核心目标是快速、可靠地跑起来不是把某一种安装方式坚持到底。6. 离线部署的几点个人体会最后分享几个我自己的习惯不一定标准但都是实战验证过的。第一个习惯是先做一次完整的离线演练。在能上网的虚拟机里把从下载、解压、建用户、写配置、启动、创账号到验证的全流程走一遍然后把整个/opt/mongodb目录连同配置、systemd 服务文件一起打包带走。到了内网现场解压、改 IP、启动、初始化半小时搞定。这个打包整个目录迁移的思路在离线场景特别好用因为所有依赖已经在包里面了。第二个习惯是把版本号写在显眼的地方。在/opt/mongodb/VERSION里写一行当前版本号以后看目录就知道装的什么版本不用翻命令历史。第三个习惯是初始化脚本要可重入。就是说同样一段初始化脚本跑两遍不会出问题。比如创建用户之前先查一下用户是否存在文件配置先备份再覆盖。这个习惯在多个节点重复部署的时候特别省事不用每次部署都战战兢兢。离线部署 MongoDB 说起来不复杂做起来也就是解压、配置、启动、初始化四步。但每一次踩坑基本都卡在那些看起来不是 MongoDB 的问题上操作系统兼容性、权限、依赖库、防火墙。把这篇文章里提到的准备工作做扎实你的离线部署就不会再变成一场盲人摸象式的排查战。