将MongoDB 5.0.10的复制设置完成

环境

操作系统:Debian Bullseye、CentOS 7
软件版本:mongoDB Community Edition 5.0.10
使用了mongoDB的应用程序是Misskey。
https://github.com/atsu1125/misskey
我个人非常推荐这个优秀的开源SNS软件。
它基本上适用于所有使用mongoDB的软件。

首先

Misskey v10的运营人员们,
MongoDB的复制集已经设置好了吗?
如果是使用PostgreSQL,可以通过写入WAL并进行点恢复等操作。
https://qiita.com/atsu1125/items/676d24c0473ad94b3f2b
说实话觉得不需要复制集,但还是在使用复制集,但是MongoDB不可以像WAL那样写出用于点恢复的日志。
可以保存Oplog,但与WAL不同,它不能保证时间顺序,所以不能用于点恢复。
如果不是SNS,使用托管服务可以轻松进行点恢复和备份,但在SNS的情况下,由于大量的SQL查询,如果不是在本地部署,速度会很慢而且困难。
现在可以使用WAL-G将Oplog存档并类似地用于点恢复。
备份设置方法请参考这里。
https://qiita.com/atsu1125/items/aa160cefdb15c3a8cc28
这次我想在另一台服务器上进行复制集的设置。

MongoDB的复制机制如何工作?

在整个复制集中,至少需要三台能够运行相同版本MongoDB的服务器。
一台为主服务器,两台为从服务器的架构是常见的。
虽然也可以进行其他配置,但本次选择这种架构。
顺便说一下,如果只使用两台服务器组成,那么一旦主服务器宕机后再次启动,就无法变为任何一台主服务器。
PostgreSQL不会自动进行故障切换,但MongoDB会根据多数投票从复制集的服务器中自动选出主服务器。它首先作为从服务器启动,然后根据优先级和状态自动升级为唯一的主服务器。
此时,如果复制集的服务器只有两台,由于无法形成多数投票,两台服务器将继续等待作为从服务器。

另外,由于复制操作包括错误操作在内全部同步,所以它不能用作备份以应对操作错误和网络攻击。它仅用于应对计算机的物理故障。

设置主机名

在这里看到主机名出现真是令人惊讶,但这是非常重要的设置。
基本上,建立一个专用的内部DNS服务器并建立服务器间的复制,以便能够使用主机名解析它们。
如果使用了Zero Trust安全之类的外部DNS服务器,无法使用内部DNS时,请在每台服务器的/etc/hosts文件中写入主机名和IP地址的对应关系。
从mongodb 5.0开始,将不能再使用基于IP地址的复制。看起来似乎可以,但当使用mongodb获取状态时,它将保持在STARTUP状态并结束。
STARTUP2是接收数据并开始初始同步的正常状态。这真是令人困惑。

防火墙的设置

请在服务器的防火墙上允许复制服务器之间的连接。
请根据以下步骤根据环境进行设置。
嗯,既然是局域网,路由器会阻止连接,那就不需要设置防火墙了?
出于安全考虑,强烈建议进行设置。
特别是这次我们要在0.0.0.0上监听mongoDB,因此只有防火墙能够提供保护。

对于ufw

ufw allow from xxx.xxx.xxx.xxx to any port 27017 proto tcp`

对于firewalld,提供以下的中文表述:

对于火墙服务firewalld

firewall-cmd --add-rich-rule='rule family=ipv4 source address=xxx.xxx.xxx.xxx/32 port port=27017 protocol=tcp accept' --permanent
firewall-cmd --reload

MongoDB的认证设置

请开始时为了安全起见,请激活数据库的用户认证。
这个用户认证只能在首先成为副本集中的主服务器上设置。
以下文章提供更详细的信息。

确保设置了MongoDB用户认证配置 by @h6591
https://qiita.com/h6591/items/68a1ec445391be451d0d

在设置了用户认证之后,在使用mongoDB的应用程序中,最好在应用设置生效之后重新启动mongoDB。

設定完成後,將生成用於複製認證的金鑰文件。

openssl rand -base64 1024 > mongodbkeyfile

请将其移至/etc/mongodbkeyfile中。
对于CentOS,请使用mongod作为所有者。
对于Debian,请使用mongodb作为所有者。
确保只有所有者能够阅读。

请在mongod.conf文件中添加并修改以下设置。

net:
  port: 27017
  bindIp: 0.0.0.0

security:
  authorization: enabled
  keyFile: /etc/mongodbkeyfile

replication:
  replSetName: "replicaset0"

请将这些密钥文件和配置文件分别放置在每个复制服务器上。
完成配置后,请使用systemctl restart mongod命令重新启动所有服务器。

mongoDB的复制设置

首先,您需要连接到作为复制集的主服务器。由于用户认证已生效,您必须使用以下命令登录才能进行连接。请根据需要适配用户名和认证数据库。

mongo --authenticationDatabase admin -u mongo

当连接成功后,请输入以下内容。
虽然不是单行输入,但可以正确输入。
请将mongodbserver1.local等部分替换为各自服务器的主机名。
此次我们有意禁用故障转移功能进行设置。
请将当前正在操作的服务器主机名注册为作为id:0的初始主服务器。
我们将其他服务器注册为隐藏成员,不会晋升为主服务器,以确保id为0的服务器始终被选择为主服务器。
可能在没有特殊设置的情况下,当主服务器发生变化时,无法在应用程序中进行切换,这是无可奈何的。

rsconf = {
  _id: "replicaset0",
  members: [
    {
     _id: 0,
     host: "mongodbserver1.local:27017",
     "priority" : 10
    },
    {
     _id: 1,
     host: "mongodbserver2.local:27017",
     "hidden" : true,
     "priority" : 0
    },
    {
     _id: 2,
     host: "mongodbserver3.local:27017"
     "hidden" : true,
     "priority" : 0
    }
   ]
}

确认返回的内容,如果没有问题

rs.initiate( rsconf )

请将复制集设置应用。
虽然设置方式有些不同,但请尽快适应。

rs.conf()

您可以查看当前的复制设置。

rs.status()

您可以通过以下方法查看当前复制状态:
如果stateStr的值为PRIMARY,则应该有一个服务器,并且还应该有两个服务器的状态为SECONDARY或STARTUP2才算成功。
如果存在STARTUP服务器,则表示连接失败,请确认进程是否存活、防火墙是否允许访问以及配置文件是否正确。

监控 MongoDB 复制的操作

只是建立副本是不够的,我们需要确保它们正常运行。
在登录MongoDB时显示的免费监控URL非常方便,可以从任何地方查看。
同时,希望在副本失败时收到通知。
本次将使用shell脚本和systemd定时器进行构建。
可以通过rs.status()获取到副本的状态,其中一个是PRIMARY,两个是SECONDARY,表示正常状态。
虽然有点零乱,但我认为可以通过计算该字符串的数量来确认是否正常。
然后,总是将正常状态发送到心跳监视用的URL(如BetterUptime),即使监视脚本崩溃也能及时发现。
如果发生失败,希望立即通过WebHook将通知发送到Discord。
首先,先安装一个方便的discord.sh。

wget https://github.com/ChaoticWeg/discord.sh/raw/master/discord.sh
chmod +x discord.sh
mv discord.sh /usr/local/bin/

将jq和curl进行安装,并且适用于Debian系统。

apt install jq curl

对于CentOS来说

yum install jq curl

只要点击discord.sh并执行就可以了。

接下来会创建以下的Shell脚本。

#!/bin/bash
PRIMARY=`mongo --authenticationDatabase admin -u mongo -p パスワード --eval "printjson(rs.status())" | grep -c PRIMARY`
SECONDARY=`mongo --authenticationDatabase admin -u mongo -p パスワード --eval "printjson(rs.status())" | grep -c SECONDARY`
if [ $PRIMARY = 1 ] && [ $SECONDARY -ge 2 ] ; then
echo "streaming replication is healthy"
curl ハートビート監視のURL #正常性報告
if [ -e error-replication.txt ]; then
WEBHOOK_URL="DISCORDのWEBHOOKURL"
discord.sh \
    --webhook-url "$WEBHOOK_URL" \
    --username "Streaming Replication Notice" \
    --title "Streaming Replication Notice" \
    --description "ストリーミングレプリケーションは正常に復帰しました。"

rm -f error-replication.txt
exit 0
fi
else
echo "streaming replication is unhealhy"
if [ ! -e error-replication.txt ]; then
WEBHOOK_URL="DISCORDのWEBHOOKURL"
discord.sh \
    --webhook-url "$WEBHOOK_URL" \
    --username "Streaming Replication Notice" \
    --title "Streaming Replication Notice" \
    --description "ストリーミングレプリケーションに異常発生しました。"

touch error-replication.txt
fi
fi

如果您以这种方式写下来,您可以使用以下命令将以下服务文件注册到systemctl中:
systemctl edit –full –force mongodb-monitor.service

[Unit]
Description = Check replication state

[Service]
Type = oneshot
User = root
WorkingDirectory = /usr/local/bin/
ExecStart = bash /usr/local/bin/mongo-replica-monitor.sh

使用以下的命令以全面强制编辑形式进行注册计时器文件:systemctl edit –full –force mongodb-monitor.timer;然后使用命令systemctl enable –now mongodb-monitor.timer开始计时器。

[Unit]
Description = Check Replication State

[Timer]
OnBootSec=3min
OnUnitActiveSec=1m
Persistent=false

[Install]
WantedBy=timers.target

只需要一个翻译选项:
通过systemctl status mongodb-monitor.service来检查状态。
如果正常运行,则一切正常。
如果出现错误,则使用journalctl -u mongodb-monitor.service来进行确认。

最后

MongoDB的复制设置针对4版本的很多,我遇到了一些困难。
并且有个朋友因为复制突然崩溃导致丢失了数据。所以,为了方便大家,我写了一篇关于复制监控的文章。
希望对你们有所帮助。

广告
将在 10 秒后关闭
bannerAds