MongoDB 企业实操:TLS 复制集、事务与恢复

验证:未记录
适用版本
未记录
验证范围
尚未登记验证记录。

选择三台不同故障域 VM(虚拟机),运行已批准的 MongoDB 8.0 补丁,三投票数据节点,不用 arbiter(仲裁节点)替代第三份数据。域名为 mongo1/2/3.internal.example.com,均私网;以下只对全新实验复制集操作。

1. 安装与网络#

按 Setup 配置官方 Ubuntu 24.04 软件源,查询并固定包版本,三机一致:

apt-cache madison mongodb-org
# 在变更记录填入相同精确版本;安装组件也固定同一版本。
sudo apt-get install mongodb-org=REPLACE_APPROVED_PACKAGE_VERSION
mongod --version

防火墙只允许三节点相互及应用/运维网段的 27017;禁止公网。企业 CA(证书颁发机构)为每节点签发独立证书,包含其 DNS 名及 127.0.0.1 IP SAN(证书备用名称),供本机初始管理;证书含 serverAuth/clientAuth 用途。节点证书与私钥合并为 /etc/mongodb/tls/node.pem,CA 放 ca.pem,所有私钥只由 mongodb 用户读取。

在受控机器生成一次复制集共享 keyFile,经秘密通道投递到三节点,不能复制进 Git:

umask 077
openssl rand -base64 756 > replica.key
# 每台节点安装后:
sudo chown mongodb:mongodb /etc/mongodb/replica.key /etc/mongodb/tls/node.pem
sudo chmod 0400 /etc/mongodb/replica.key /etc/mongodb/tls/node.pem

2. 三机配置与初始化#

分别保存 /etc/mongod.conf,替换各自私网 IP:

storage:
  dbPath: /var/lib/mongodb
systemLog:
  destination: file
  path: /var/log/mongodb/mongod.log
  logAppend: true
net:
  bindIp: 127.0.0.1,REPLACE_NODE_PRIVATE_IP
  port: 27017
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/mongodb/tls/node.pem
    CAFile: /etc/mongodb/tls/ca.pem
    allowConnectionsWithoutCertificates: true
security:
  authorization: enabled
  keyFile: /etc/mongodb/replica.key
replication:
  replSetName: orders-rs

allowConnectionsWithoutCertificates 允许客户端用用户名/密码认证;不会关闭 TLS 或授权。内部复制仍校验证书和共享密钥。三机 sudo systemctl restart mongod,mongo1 本机利用首次初始化 localhost exception(仅尚无用户时)连接:

mongosh --host 127.0.0.1 --tls --tlsCAFile /etc/mongodb/tls/ca.pem
rs.initiate({_id:'orders-rs',members:[
  {_id:0,host:'mongo1.internal.example.com:27017'},
  {_id:1,host:'mongo2.internal.example.com:27017'},
  {_id:2,host:'mongo3.internal.example.com:27017'}]})
// 等本节点成为 PRIMARY,再建立管理员;passwordPrompt 不把密码写入历史。
use admin
db.createUser({user:'platform-admin',pwd:passwordPrompt(),roles:['root']})

退出后用 --username platform-admin --authenticationDatabase admin --password 重新连接,通过提示输入密码。创建应用仅 readWrite:orders、监控 clusterMonitor、备份 backup 独立角色;root 收入应急保险库,不给应用。

3. 可重放的业务事务#

应用使用包含三个 seed 的连接串、replicaSet=orders-rs、TLS、retryWrites=true、w=majority;密码来自文件/秘密系统,URI 不进日志。以下在已认证应用会话执行:

const s = db.getMongo().startSession();
const d = s.getDatabase('orders');
s.withTransaction(() => {
  const old = d.requests.findOne({_id:'exercise-001'});
  if (old) {
    if (old.amount_cents !== 1200) throw new Error('idempotency conflict');
    return;
  }
  d.requests.insertOne({_id:'exercise-001',amount_cents:1200,status:'completed'});
  d.ledger.insertOne({_id:'exercise-001',amount_cents:1200});
}, {readConcern:{level:'snapshot'},writeConcern:{w:'majority',j:true}});
s.endSession();
db.getSiblingDB('orders').requests.findOne({_id:'exercise-001'});
db.getSiblingDB('orders').ledger.findOne({_id:'exercise-001'});

重复执行只有一笔请求和账本;同键不同金额必须拒绝。真实并发产生 duplicate key 时应在外层重新读取已提交结果并比对,不能忽略错误继续另一半写入。业务请求完成依据多数提交,不把节点本地接受当成功。

4. 主节点切换与权限#

  1. rs.status() 确认一主两从,延迟正常;使用授权监控账号观测复制、oplog 窗口、磁盘与连接。
  2. 主节点以受控管理员执行 rs.stepDown(60),连接中断可能是预期;驱动重新发现主节点后继续同键事务。
  3. 核对请求/账本数量和金额,记录错误与恢复窗口。失去两个投票节点应不能接受多数写入;禁止 rs.reconfig(...,{force:true}) 作为常规恢复。
  4. 未认证查询、应用读 admin 数据、明文连接必须失败。

5. 全量加 oplog 备份与独立恢复#

使用同一兼容版本的 MongoDB Database Tools。备份机器能访问三节点,账号为 backup 角色;配置文件权限 600,包含受控 uri 和 password,不把密码放命令参数。

set -euo pipefail
umask 077
mongodump --config=/secure/mongo-backup.yaml --tls --tlsCAFile=/secure/ca.pem --oplog --archive=orders-full.archive.gz --gzip
sha256sum orders-full.archive.gz > orders-full.sha256

必须完整复制集备份,--oplog 不能当作任意分库导出的附加选项;备份期间不做不兼容 DDL/FCV(功能兼容版本)变更,并确保 oplog 窗口覆盖全过程。将归档与校验和存入加密、跨故障域备份库。

在隔离的恢复复制集(相同引擎/FCV,独立证书、无生产出口)执行。目标业务库必须为空,不能对失败的半成品恢复直接重跑;保留日志后重建恢复目标。源/目标 Database Tools 版本一致:

set -euo pipefail
sha256sum -c orders-full.sha256
mongorestore --config=/secure/mongo-restore.yaml --tls --tlsCAFile=/secure/restore-ca.pem --archive=orders-full.archive.gz --gzip --oplogReplay --stopOnError

恢复角色按官方 oplogReplay 权限设置,仅在恢复环境临时授权;普通 restore 角色未必足够。全量备份可能包含用户/角色与敏感数据,恢复环境不能复用生产入口。不要加过滤 namespace 参数,也不要对既有生产库运行此命令。恢复后以恢复数据对应的身份查询请求和账本,核对 ID、金额、总数及业务登录,记录实际 RPO/RTO(恢复点/恢复时间目标)。

在恢复集已认证的 mongosh 会话执行以下断言;任何异常都不开放业务流量:

const restored = db.getSiblingDB("orders");
const request = restored.requests.findOne({_id:"exercise-001"});
const ledger = restored.ledger.findOne({_id:"exercise-001"});
if (!request || !ledger || request.status !== "completed" || request.amount_cents !== 1200 || ledger.amount_cents !== request.amount_cents) throw new Error("restore reconciliation failed");
print("restore probe verified");

这是本篇事务探针;真实验收还需与备份时独立保存的批次水位、全量请求数及金额对账。--oplog 只包含本次 dump 期间的记录,不提供备份结束后任意时间点恢复;持续 PITR 需要另外部署连续备份。新增业务写入后不能直接切回旧集群。

6. 升级与清理#

补丁升级先在恢复集演练,从 secondary 逐个升级、追平后再受控 stepDown 升主;每次只有一个节点维护。跨主版本逐一遵守官方支持路径,二进制升级后先验证再提升 FCV;FCV 变更可能限制回退,不能把降镜像当通用回滚。

删除本次恢复集前保留脱敏验收和加密备份;临时 root/restore 权限及时撤销。不要删除原集数据卷和仍在恢复窗口内的归档。

MongoDB TLS、mongodump、mongorestore 限制。

搜索文档

输入关键词,搜索所有文档。

↑ ↓ 选择 · Enter 打开 · Esc 关闭