尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Ubuntu 22.04 安装 MongoDB:apt 仓库、启动排查与配置实战

Ubuntu 22.04 安装 MongoDB:apt 仓库、启动排查与配置实战 在 Ubuntu 22.04 上装 MongoDB很多人第一次都会卡在同一个地方照着三年前的教程敲sudo apt install mongodb回车之后终端甩回来一句Package mongodb has no installation candidate。不是网络问题也不是源没更新是 22.04 的软件仓库里压根就没有这个包了。我前阵子给一台内网机器重做环境就因为这句报错在文档里停留了半个多小时后来才发现整个安装路径跟旧版本完全不是一回事。这篇就把 Ubuntu 22.04 上装 MongoDB 这件事从头到尾捋一遍为什么旧办法失效、官方 apt 仓库怎么配、启动失败怎么查、配置文件改哪几行、认证和备份怎么落地。写给两类人看——刚接触 Linux 服务部署的新手能照着走通已经在用 MongoDB 但被版本升级坑过的老手可以重点看排查那一节。1. 22.04 的仓库里为什么找不到 mongodb 这个包1.1 从能装到装不上许可协议变更带来的连锁反应这件事得往回倒几年。Ubuntu 20.04 时代apt install mongodb是能用的装上来的是一个 3.6.x 的版本虽然旧但跑个测试环境够用。到了 22.04这个包从 universe 仓库里消失了。根本原因是 MongoDB 在 2018 年把开源协议从 AGPLv3 换成了 SSPLSSPL 不被 OSI 认定为开源协议主流发行版的打包者认为它不符合发行版对自由软件的定义于是陆续把 MongoDB 从官方仓库里移除了。这个变化对使用者的直接影响是22.04 上没有随手一装就能跑的 MongoDB 了你必须显式指定一个第三方来源。而这件事的连带影响比想象中大——很多自动化脚本、Dockerfile、运维手册里还留着apt install mongodb这一行在新机器上跑就会直接断掉。我见过不止一个 CI 流水线是因为基础镜像从 20.04 升到 22.04 之后构建阶段在这一步挂掉的。更麻烦的是信息污染。搜Ubuntu 22.04 安装 MongoDB前排结果里混着大量 20.04 的教程标题改了内容没改你照着敲前面几步公钥、源都加成功了apt update也没报错最后apt install mongodb扑空很容易误判成源配错了。判断方法很简单执行apt-cache policy mongodb如果输出里Candidate: (none)或者压根没有这个包的记录那就不是你的源的问题是这个包本来就不在。1.2 四条可走的路各自适合什么场景在没有官方仓库包的前提下摆在面前的选择其实有四条。我按自己实际用过的顺序说不谈理论优劣只谈什么情况下该选哪个。方式版本可控性上手成本适合场景主要短板官方 apt 仓库高可锁版本低单机、内网服务器、长期运行依赖外网、需处理公钥二进制 tarball最高中无外网、需要多版本共存需手写 systemd unit容器运行高低前提是已有容器环境开发测试、快速验证数据卷、内存参数易踩坑发行版自带包——22.04 上基本不可用包已移除官方 apt 仓库是绝大多数人的正解。它由 MongoDB 自己维护针对 jammy 有专门的构建安装完自动注册 systemd 服务、创建mongodb用户、生成/etc/mongod.conf后续升级也走 apt运维习惯不用改。缺点是必须能访问外网仓库纯离线环境就得换路。二进制 tarball是我在内网环境最常用的方案。下载一个压缩包传进去解压、建目录、写一个 systemd unit二十分钟能搞定而且不污染系统的包管理状态同一台机器上跑两个不同大版本互不干扰。代价是所有东西都得自己管日志轮转、用户权限、开机自启。容器这一条我个人建议只在开发机上用。生产环境跑容器版 MongoDB最容易出问题的是内存参数——WiredTiger 的缓存默认按宿主机物理内存的 50% 左右估算容器里读到的还是宿主机内存结果就是几个容器互相抢内存最后被内核 OOM 干掉。这个坑不在安装环节但装完不处理迟早会遇到。至于发行版自带包在 22.04 上就不用想了。如果你确实需要老版本比如某些遗留系统依赖 3.6 的驱动那正确做法是用 tarball 装一个独立实例而不是硬找仓库包。2. 走官方 apt 仓库这条路从公钥到第一个进程2.1 导入签名公钥apt-key 已经退场别再用老写法老教程里这一步普遍长这样wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -。这条命令在 22.04 上依然能跑但会打一行黄色警告说apt-key is deprecated而且 22.04 自带的 apt 2.4 已经开始对这种方式做限制。正确做法是把公钥落到/usr/share/keyrings/下然后在源条目里用signed-by明确指定。具体操作先把可能缺的工具补上精简版系统镜像里gnupg和curl经常没预装sudo apt-get install -y gnupg curl ca-certificates然后导入公钥。这里以 7.0 为例注意文件名要和后面源条目里的路径严格对应curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \ sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor--dearmor这一步不能省。.asc是 ASCII armored 格式apt 需要的是二进制格式的 keyring 文件不做转换虽然有时候也能过但在某些 apt 版本上会报NO_PUBKEY排查起来非常费劲。转换完可以顺手验证一下ls -l /usr/share/keyrings/mongodb-server-7.0.gpg file /usr/share/keyrings/mongodb-server-7.0.gpg输出应该是data类型而不是PGP public key block Public-Key这种文本描述。如果file命令显示的还是文本说明--dearmor没生效公钥文件其实是坏的后面apt update一定会报签名错误。提示 curl 加-f参数是为了让 HTTP 4xx/5xx 直接返回非零退出码。不加的话请求打到错误页也会把 HTML 内容写进 keyring 文件得到一个几 KB 的垃圾文件而后续报错信息完全不会指向这里。2.2 写源条目架构字段和仓库代号必须对上源文件写在/etc/apt/sources.list.d/下文件名随意但建议带版本号方便以后并排升级echo deb [ archamd64,arm64 signed-by/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse | \ sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list这一行里有四个地方容易填错逐个说archamd64,arm64这个字段是可选的但强烈建议写上。不写的话 apt 会尝试为所有已启用的架构拉取索引混装了 i386 多架构支持的系统上会产生一堆 404。另外如果你是 ARM 机器比如某些云厂商的 ARM 实例这里必须包含arm64否则apt update会报Skipping acquire of configured file ... doesnt support architecture。jammy这是 Ubuntu 22.04 的代号。填focal20.04有时也能装上但构建目标和系统库版本不匹配跑起来可能缺libssl符号。填错代号是apt update报404 Not Found最常见的原因。mongodb-org/7.0版本通道。这里改数字就能换大版本7.0、6.0、5.0 都是这个格式。multiverse组件名固定这么写就行。改完源必须sudo apt-get update。如果这一步报NO_PUBKEY回去检查 2.1 里的 keyring 路径和signed-by是否完全一致——路径错一个字符就是这个报错。报Hash Sum mismatch一般是缓存问题清一下/var/lib/apt/lists/再更新。2.3 安装、锁版本与第一次启动索引更新完之后sudo apt-get install -y mongodb-org这条命令会拉下来五个包mongodb-org元包、mongodb-org-server主程序、mongodb-org-mongos分片路由、mongodb-org-tools备份恢复等工具、mongodb-org-shell老版 shell。7.0 开始mongosh是单独分发的apt 装完不一定带上这点后面会讲。装完先别急着启动做一件事锁版本。sudo apt-mark hold mongodb-org mongodb-org-server mongodb-org-mongos mongodb-org-tools为什么因为apt upgrade会顺手把小版本升上去而 MongoDB 的大版本升级需要走专门的流程先升到最新小版本再换源再setFeatureCompatibilityVersion。如果不锁某次例行更新可能直接把你从 6.0 拽到 7.0数据文件格式跟着变回滚就麻烦了。锁上之后要升级时手动unhold心里有数。启动并设为开机自启sudo systemctl daemon-reload sudo systemctl enable --now mongod sudo systemctl status mongod --no-pagerstatus输出里看到Active: active (running)才算成了。如果显示failed别猜直接看日志sudo tail -n 50 /var/log/mongodb/mongod.log sudo journalctl -u mongod -n 50 --no-pager这两处信息互补mongod.log是服务自己的日志能看到 WiredTiger 初始化、端口绑定这些细节journalctl是 systemd 层面的能看到进程退出码、权限拒绝这类信息。启动失败的原因九成在这两个地方能找到线索。3. 启动失败的几类典型症状与对应排查3.1 Illegal instructionAVX 指令集这道硬门槛这是我在虚拟化环境里撞见最多、也最容易被误判的一个。症状是systemctl start mongod之后立刻失败journalctl里只有一行极其含糊的Main process exited, codedumped, status4/ILL日志文件甚至没来得及写内容。本质原因是 MongoDB 从 5.0 开始官方构建要求 CPU 支持 AVX 指令集。WiredTiger 的某些压缩和哈希计算路径用了 AVX 做加速编译时没留非 AVX 的回退分支。所以在一台老至强、或者某些没把 AVX 透传给虚拟机的宿主机上二进制一加载就触发 SIGILL。确认方法grep -o -m1 -w avx\|avx2 /proc/cpuinfo | sort -u有输出说明支持没输出就是不支持。也可以直接看lscpu输出里的 Flags 行。不支持的话有三条出路一是降到大版本 4.4那是最后一代不要求 AVX 的版本功能上够用但已经停止维护只适合内网隔离环境二是换机器或让虚拟化平台把 AVX 透传出来有些平台默认关闭三是干脆用容器跑 4.4 镜像省去在宿主机上折腾依赖。我个人在必须保留老硬件的场景下会选第三条隔离性好将来换机器直接迁数据目录。3.2 数据目录属主与 AppArmor 的两道门第二类失败是权限。手动改过dbPath或者从别处拷过数据目录的人容易遇到日志里会明明白白写Permission denied或者Unable to create/open lock file。MongoDB 的 apt 包会创建一个mongodb系统用户服务以这个身份运行。所以dbPath指向的目录必须让mongodb用户可读写sudo chown -R mongodb:mongodb /var/lib/mongodb sudo chmod 755 /var/lib/mongodb注意别图省事chmod 777。MongoDB 启动时会检查目录权限权限过宽反而会拒绝启动日志里会说目录权限不安全。755 或者 750 都可以。比权限更隐蔽的是 AppArmor。Ubuntu 默认开启 AppArmorapt 包会附带一个/etc/apparmor.d/usr.bin.mongod的配置把 mongod 能访问的路径白名单化了。如果你把dbPath改到/data/mongodb这种非默认路径即使chown做对了AppArmor 还是会拦日志里的表现是Permission denied但ls -l看权限完全正常——这种权限没问题却没权限的现象基本可以断定是 AppArmor。两个处理办法改 AppArmor 配置把新路径加进白名单或者干脆把 mongod 的 profile 设为 complain 模式观察。生产环境建议改配置别直接 disablesudo vim /etc/apparmor.d/local/usr.bin.mongod # 加入/data/mongodb/** rwk, sudo apparmor_parser -r /etc/apparmor.d/usr.bin.mongod3.3 端口、内存、文件句柄三个默认值还有一类能启动但不对劲的情况。比如systemctl status显示 running但客户端连不上。先查端口sudo ss -lntp | grep 27017如果只监听在127.0.0.1:27017那是正常的默认行为改mongod.conf的bindIp才能对外。如果压根没监听看日志里有没有Address already in use——多半是之前有个 mongod 进程没退干净ps -ef | grep mongod确认后 kill 掉。内存方面WiredTiger 的缓存默认取(物理内存 - 1GB) * 0.5。一台 8G 的机器上会占 3.5G 左右看着吓人但其实是虚拟预留不是立刻吃满。不过在容器里或者和别的服务混部时这个默认值必须手动压下来否则很容易触发 OOM。改法在下一节的配置里。文件句柄数也值得看一眼。MongoDB 官方建议nofile不低于 64000apt 包自带的 systemd unit 里设了LimitNOFILE64000一般不用动。但如果你是自己写的 unit 文件忘了这一行连接数一上来就会报Too many open files。查当前值cat /proc/$(pgrep -x mongod)/limits | grep open files4. mongod.conf 逐段拆解一台单机到底该改哪几行4.1 net 段bindIp 的边界在哪配置文件在/etc/mongod.confYAML 格式老版本是 YAML 兼容的类 YAML 写法新版是标准 YAML缩进必须用空格不能用 Tab这一点坑过不少人。net段控制监听行为net: port: 27017 bindIp: 127.0.0.1默认只监听本地回环这是安全默认值不是缺陷。要允许内网其他机器连接有两种写法net: port: 27017 bindIp: 127.0.0.1,10.0.3.15列出具体网卡地址这是推荐做法。另一种是0.0.0.0监听所有网卡我不建议在有多网卡尤其是带公网地址的机器上这么写——MongoDB 默认没有认证一旦监听公网且防火墙没配等于把数据库裸奔在互联网上。这类事故每年都有。如果确实需要0.0.0.0至少做两件事一是在security段开启认证见 4.3二是用防火墙限制来源sudo ufw allow from 10.0.3.0/24 to any port 27017 sudo ufw status verbose另外提一句改完mongod.conf必须重启服务才生效sudo systemctl restart mongod。MongoDB 不支持运行时 reload 这个配置文件。4.2 storage 段dbPath、缓存与压缩storage段是我改动最多的地方storage: dbPath: /var/lib/mongodb wiredTiger: engineConfig: cacheSizeGB: 1 collectionConfig: blockCompressor: snappycacheSizeGB是我建议所有单机部署都显式写死的参数。不写的话按物理内存动态算换台机器、加个内存条缓存大小就跟着变容量规划全乱。写死之后心里有数也方便和其他服务做资源分配。经验值是如果这台机器只跑 MongoDB给物理内存的 50% 到 60%如果混部先算清其他服务要多少剩下的再分。blockCompressor默认是snappy压缩比一般但 CPU 开销小。如果是日志类、文本类数据为主zstd压缩比能高不少代价是 CPU 占用上升如果是已压缩的二进制数据图片、视频分片压缩收益很低可以考虑none省 CPU。这个选择没有标准答案取决于数据特征建议先用默认跑一段时间看db.serverStatus().wiredTiger里的压缩率再决定。dbPath改到新盘的话记得把 3.2 节讲的属主和 AppArmor 一起处理。改路径之前先停服务用rsync -a把数据拷过去保留权限再改配置启动比cp稳妥。4.3 security 段先建用户还是先开认证这是新手最容易搞反顺序的地方。security.authorization: enabled开了之后所有操作都要认证。如果你在一台还没有任何用户的空库上直接开认证然后重启结果就是——你连自己都进不去了。因为本地豁免localhost exception只在没有用户时才生效一旦你建了第一个用户豁免就没了。正确顺序是配置文件里先不开authorization或者显式设为disabled重启服务用mongosh连进去在admin库创建管理员用户再改配置为enabled重启用刚建的用户认证登录验证。创建管理员use admin db.createUser({ user: siteAdmin, pwd: 换成你自己的强口令, roles: [ { role: userAdminAnyDatabase, db: admin }, { role: readWriteAnyDatabase, db: admin }, { role: clusterAdmin, db: admin } ] })这三个角色覆盖了日常运维管用户、读写任意库、管副本集和分片。如果你想更细粒度可以只给具体库的readWrite但对单机小规模部署来说没必要折腾。验证认证是否生效mongosh mongodb://siteAdmin:口令127.0.0.1:27017/?authSourceadmin --eval db.runCommand({connectionStatus:1})注意authSourceadmin这个参数不能省。用户是建在admin库的不指定认证库的话驱动会拿业务库去认证永远失败。这个参数漏写在应用侧报的错是Authentication failed但用户名密码明明是对的排查起来很浪费时间。5. 从能跑到能扛副本集、备份与常见运维动作5.1 单节点副本集不是为了高可用是为了事务很多人觉得单机没必要配副本集这是误解。MongoDB 4.0 之后的多文档事务只在副本集或分片集群上支持单机模式standalone下开事务会直接报错。所以哪怕只有一台机器只要业务里可能用到事务就得配一个单节点副本集。配置很简单在mongod.conf里加一段replication: replSetName: rs0重启服务后初始化mongosh --eval rs.initiate({_id:rs0, members:[{_id:0, host:127.0.0.1:27017}]})等几秒看状态mongosh --eval rs.status().myState返回1表示当前节点是 PRIMARY成功了。返回2是 SECONDARY单节点不该出现返回其他值说明还没选举完再等等。这里有个细节host字段建议写127.0.0.1还是内网 IP如果应用和数据库在同一台机器写127.0.0.1没问题。如果应用在别的机器必须写内网 IP——因为副本集成员地址会被写进 oplog客户端在连接时可能会被重定向到这个地址写127.0.0.1的话远端客户端会连不上。改这个字段需要重新rs.initiate所以一开始就想清楚。还有个高频坑配了副本集之后用mongosh直连127.0.0.1执行写操作可能报not master and slaveOkfalse。这是老版本驱动的行为新版驱动一般会自动发现主节点。真遇到的话连接串里加directConnectiontrue强制直连或者用replicaSetrs0让驱动走发现流程。5.2 mongodump 备份命令简单恢复才是考验mongodb-org-tools包里带了mongodump和mongorestore这是最基础的逻辑备份手段。开启认证之后的备份命令mongodump \ --urimongodb://siteAdmin:口令127.0.0.1:27017/?authSourceadmin \ --out/data/backup/$(date %F_%H%M) \ --gzip--gzip是我强烈建议加的文本类数据能压到原来的三分之一左右对磁盘和传输都友好。备份本身很少出问题恢复才是真正的考验。我建议每次做完备份策略之后都找一台空闲机器做一次完整恢复演练不然真出事的时候你会发现备份文件是坏的或者恢复命令少了参数。恢复到一个新库避免覆盖现有数据mongorestore \ --urimongodb://siteAdmin:口令127.0.0.1:27017/?authSourceadmin \ --gzip \ --nsFrombizdb.* \ --nsTobizdb_restore.* \ /data/backup/2024-06-01_0300--nsFrom和--nsTo是重命名命名空间的参数恢复演练时非常有用——不覆盖生产库的前提下验证备份完整性。恢复完连上去show collections和db.stats()对一下集合数量、文档数量、索引数量三个指标对得上基本可以放心。注意mongodump是逻辑备份对超大库几百 GB 以上耗时长且会对源库产生压力。数据量大的话应该用文件系统快照或者副本集从节点做物理备份mongodump只作为补充手段。另外它备份的是某一时刻的数据快照如果备份期间有大量写入一致性需要靠--oplog参数保证仅副本集可用。5.3 版本升级与彻底卸载升级小版本unhold之后apt upgrade就行小版本之间格式兼容。升级大版本要走固定流程先升到当前大版本的最新小版本 → 备份 → 换源到新大版本 →apt install→ 启动 → 执行db.adminCommand({setFeatureCompatibilityVersion: 7.0})。最后这一步不能漏不执行的话新版本特性用不了而且回滚会很麻烦。彻底卸载注意 apt 的purge不会删数据目录和日志目录sudo systemctl stop mongod sudo apt-get purge -y mongodb-org mongodb-org-server mongodb-org-mongos mongodb-org-tools mongodb-org-shell sudo rm -f /etc/apt/sources.list.d/mongodb-org-*.list sudo rm -f /usr/share/keyrings/mongodb-server-*.gpg sudo apt-get autoremove -y数据和日志要不要删自己判断# 确认不再需要数据后再执行 sudo rm -rf /var/lib/mongodb /var/log/mongodb sudo userdel mongodb我习惯在删之前先把/var/lib/mongodb打个包传到备份盘上多占几十 G 空间换一个万一还想找回来的余地比事后后悔强。6. 几个我踩过之后才记住的细节mongosh的安装容易被忽略。7.0 的 apt 包里mongodb-org-shell提供的是旧版mongoshell新版mongosh是独立 deb 包需要单独从官方仓库装。如果执行mongosh报 command not found不是装错了是少了这个包。老教程里满篇的mongo命令在新版本上会提示已废弃建议直接从mongosh开始用。时区问题在日志排查时很烦。mongod.conf里有个processManagement.timeZoneInfo: /usr/share/zoneinfoapt 包默认带上了。如果是自己写的配置漏了这行日志时间戳可能全是 UTC对着业务日志排查时间线会很痛苦。另外mongosh里new Date()输出的是 UTC 字符串ISODate存储也是 UTC展示层做时区转换这个别混。/var/log/mongodb/mongod.log会一直长。apt 包没配 logrotate默认是追加写。跑几个月可能几百 MB。可以自己加一个 logrotate 配置或者用 MongoDB 内置的日志轮转db.adminCommand({logRotate: 1})配合 cron 定期跑。最后说一个心态上的事。这类基础环境搭建的文章网上存量极大但时效性极差一个版本迭代就能让整篇教程失效。我现在的习惯是遇到装不上的包第一反应不是搜教程而是去看发行版仓库里到底有没有这个包、官方文档给的安装方式是什么。花五分钟确认源头比花半小时试错划算得多。
返回列表