审计日志爆炸因分片内部通信被全量记录,需以client.host为锚点过滤终端ip,并排除replsetheartbeat等内部命令及config.*命名空间操作,同时隔离审计日志路径与格式。

审计日志默认会记录mongos与shard之间的内部通信
开审计后发现日志爆炸式增长,mongos 向 shardsvr 发的心跳、配置同步、chunk迁移命令全在里头,根本没法盯真实用户行为。这不是功能没开对,是 MongoDB 审计机制本身就把分片组件间所有 mongod ↔ mongod 流量当“操作”记了——哪怕只是 replSetHeartbeat 或 shardCollection 的内部协调调用。
实操建议:
- 别指望靠
auditFilter里写{"users": {"$exists": true}}过滤——内部通信压根不带users字段 - 必须用
client字段做源头识别:mongos发出的请求,client.host是它自己的 IP;而真正客户端连mongos时,client.host才是终端 IP - 启用审计前,在每个
mongod(包括 config server 和 shard)的启动参数里加--auditDestination file --auditFormat JSON --auditPath /var/log/mongodb/audit-$(hostname).log,避免 syslog 混淆来源
用 auditFilter 排除特定命令和命名空间
光靠 client.host 区分还不够,有些内部命令(比如 listDatabases 被 config server 频繁调用)或系统库操作(config.*、local.*)必须显式屏蔽,否则日志里全是噪音。
实操建议:
- 在
mongod.conf的auditLog块里配filter,不是全局开关,是 per 实例生效 - 排除心跳和复制协议命令:
{"atype": {"$in": ["authenticate", "replSetHeartbeat", "isMaster", "saslStart", "saslContinue"]}} - 排除 config server 内部读写:
{"users": {"$exists": false}, "param.ns": {"$regex": "^config\."}} - 注意:MongoDB 6.0+ 才支持
param.ns字段过滤;5.0 只能靠param.commandName+client.host组合筛
mongos 本身不产生审计日志,但可间接控制日志粒度
mongos 进程不支持 --auditDestination,它不存数据也不执行写操作,所有审计日志都来自后端 mongod。但你能在 mongos 层做前置收敛——比如禁止应用直连 shard,强制所有流量过 mongos,再配合 client.host 过滤,就能确保只有终端 IP 出现在审计日志里。
实操建议:
- 关掉 shard 的 directConnection:在每个 shard 的
mongod.conf里设net.bindIpAll: false,只 bind 内网 IP,并防火墙限制仅mongos和 config server 可连 - 在应用侧禁用
readPreference=primaryPreferred等可能触发直连的选项,统一走mongos的路由逻辑 - 检查现有连接:用
db.currentOp({"secs_running": {"$gt": 0}})在mongos上看是否有client.host直连 shard 的残留会话
审计日志路径和轮转必须独立于 mongod 日志
把审计日志和 mongod.log 写一起,或者共用 logrotate 配置,会导致解析失败——审计日志是 strict JSON 格式,每行一个事件;而 mongod 日志是文本混合时间戳,混在一起就废了。
实操建议:
- 每个实例用唯一路径:
/data/audit/shard1-audit.json、/data/audit/config-audit.json,别用通配符 - 用
logrotate单独管审计日志,copytruncate必须开,否则 MongoDB 不会自动切新文件 - 避免用
auditDestination: syslog:syslog 会重写时间戳和 host 字段,丢失原始client.host和local.time精度
client.host 是最稳的锚点,但得确保网络拓扑真把它传对了——比如 NAT 环境下,mongos 到 shard 的连接显示的是 mongos 的出口 IP,不是原始客户端 IP,这时候就得在 mongos 所在机器上配 net.ipv4.ip_forward=0 并确认没透明代理。










