停止 mongo 上的副本集,主节点进入恢复状态

Posted

技术标签:

【中文标题】停止 mongo 上的副本集,主节点进入恢复状态【英文标题】:Stop replica set on mongo and primary goes into recovery status 【发布时间】:2017-01-07 17:24:03 【问题描述】:

当我停止我的副本集的节点并再次启动它们时,主节点进入“正在恢复”状态。

我创建了一个副本集,未经授权运行。为了使用授权,我添加了用户“db.createUser(...)”,并在配置文件中启用了授权:

security:
   authorization: "enabled"

在停止副本集之前(甚至在不添加安全参数的情况下重新启动集群),rs.status() 显示:


        "set" : "REPLICASET",
        "date" : ISODate("2016-09-08T09:57:50.335Z"),
        "myState" : 1,
        "term" : NumberLong(7),
        "heartbeatIntervalMillis" : NumberLong(2000),
        "members" : [
                
                        "_id" : 0,
                        "name" : "192.168.1.167:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 301,
                        "optime" : 
                                "ts" : Timestamp(1473328390, 2),
                                "t" : NumberLong(7)
                        ,
                        "optimeDate" : ISODate("2016-09-08T09:53:10Z"),
                        "electionTime" : Timestamp(1473328390, 1),
                        "electionDate" : ISODate("2016-09-08T09:53:10Z"),
                        "configVersion" : 1,
                        "self" : true
                ,
                
                        "_id" : 1,
                        "name" : "192.168.1.168:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 295,
                        "optime" : 
                                "ts" : Timestamp(1473328390, 2),
                                "t" : NumberLong(7)
                        ,
                        "optimeDate" : ISODate("2016-09-08T09:53:10Z"),
                        "lastHeartbeat" : ISODate("2016-09-08T09:57:48.679Z"),
                        "lastHeartbeatRecv" : ISODate("2016-09-08T09:57:49.676Z"),
                        "pingMs" : NumberLong(0),
                        "syncingTo" : "192.168.1.167:27017",
                        "configVersion" : 1
                ,
                
                        "_id" : 2,
                        "name" : "192.168.1.169:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 295,
                        "optime" : 
                                "ts" : Timestamp(1473328390, 2),
                                "t" : NumberLong(7)
                        ,
                        "optimeDate" : ISODate("2016-09-08T09:53:10Z"),
                        "lastHeartbeat" : ISODate("2016-09-08T09:57:48.680Z"),
                        "lastHeartbeatRecv" : ISODate("2016-09-08T09:57:49.054Z"),
                        "pingMs" : NumberLong(0),
                        "syncingTo" : "192.168.1.168:27017",
                        "configVersion" : 1
                
        ],
        "ok" : 1

为了开始使用这个配置,我已经停止了每个节点如下:

[root@n--- etc]# mongo --port 27017 --eval 'db.adminCommand("shutdown")'
MongoDB shell version: 3.2.9
connecting to: 127.0.0.1:27017/test
2016-09-02T14:26:15.784+0200 W NETWORK  [thread1] Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused
2016-09-02T14:26:15.785+0200 E QUERY    [thread1] Error: couldn't connect to server 127.0.0.1:27017, connection attempt failed :
connect@src/mongo/shell/mongo.js:231:14

这次关闭后,我通过检查ps -ax | grep mongo的输出确认了该进程不存在。

但是当我再次启动节点并使用我的凭据登录时,rs.status() 现在显示:


        "set" : "REPLICASET",
        "date" : ISODate("2016-09-08T13:19:12.963Z"),
        "myState" : 3,
        "term" : NumberLong(7),
        "heartbeatIntervalMillis" : NumberLong(2000),
        "members" : [
                
                        "_id" : 0,
                        "name" : "192.168.1.167:27017",
                        "health" : 1,
                        "state" : 3,
                        "stateStr" : "RECOVERING",
                        "uptime" : 42,
                        "optime" : 
                                "ts" : Timestamp(1473340490, 6),
                                "t" : NumberLong(7)
                        ,
                        "optimeDate" : ISODate("2016-09-08T13:14:50Z"),
                        "infoMessage" : "could not find member to sync from",
                        "configVersion" : 1,
                        "self" : true
                ,
                
                        "_id" : 1,
                        "name" : "192.168.1.168:27017",
                        "health" : 0,
                        "state" : 6,
                        "stateStr" : "(not reachable/healthy)",
                        "uptime" : 0,
                        "optime" : 
                                "ts" : Timestamp(0, 0),
                                "t" : NumberLong(-1)
                        ,
                        "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
                        "lastHeartbeat" : ISODate("2016-09-08T13:19:10.553Z"),
                        "lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
                        "pingMs" : NumberLong(0),
                        "authenticated" : false,
                        "configVersion" : -1
                ,
                
                        "_id" : 2,
                        "name" : "192.168.1.169:27017",
                        "health" : 0,
                        "state" : 6,
                        "stateStr" : "(not reachable/healthy)",
                        "uptime" : 0,
                        "optime" : 
                                "ts" : Timestamp(0, 0),
                                "t" : NumberLong(-1)
                        ,
                        "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
                        "lastHeartbeat" : ISODate("2016-09-08T13:19:10.552Z"),
                        "lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
                        "pingMs" : NumberLong(0),
                        "authenticated" : false,
                        "configVersion" : -1
                
        ],
        "ok" : 1

为什么?也许关闭不是停止 mongod 的好方法;但是我也使用'kill pid'进行了测试,但重启最终处于相同的状态。

在这种状态下,我不知道如何修复集群;我又开始了(删除 dbpath 文件并重新配置副本集);我尝试了“--repair”但没有奏效。

关于我的系统的信息:

Mongo 版本:3.2 我以 root 身份启动进程,也许它应该以 'mongod' 用户身份启动? 这是我的启动命令:mongod --conf /etc/mongod.conf keyFile 配置不起作用;如果我添加“--keyFile /path/to/file”显示: “即将 fork 子进程,等待服务器准备好连接。”此文件拥有所有权限,但无法使用 keyFile。

“net.bindIp”配置示例,来自一台机器上的 mongod.conf:

net:
  port: 27017
  bindIp: 127.0.0.1,192.168.1.167

【问题讨论】:

启用认证后你做了什么?您的副本集成员如何尝试向各自的副本集验证他们的成员身份?启用身份验证后,您无法在没有适当凭据的情况下连接到实例,除非您从 localhost 进行连接 你试过这个docs.mongodb.com/manual/core/security-internal-authentication 在所有配置文件中启用身份验证后,我启动副本集(使用 mongod --config /etc/mongod.conf),然后使用我的凭据访问,然后关闭我插入的集群。密钥文件身份验证是可选的,不是我的问题。只有我想要用户/通行证的访问权限 您应该添加一些额外的配置,因为不仅客户端需要能够与副本集进行身份验证,而且副本集节点也需要能够相互进行身份验证。因此,每个副本集节点都以具有足够权限的特殊内部用户身份与其他节点进行身份验证 例如可以为每个副本集成员添加一个密钥文件,并在其中输入管理员用户的密码。然后使用--keyFile /path/to/keyfile arg 启动 mongod 实例。 【参考方案1】:

最后我解决了这个问题,对于集群副本集来说,必须使用 keyFile 来与所有节点通信,当我指出 keyFile 时它返回错误,因为在 mongod.log 中指出:

I ACCESS   [main] permissions on /etc/keyfile are too open

keyfile 的权限必须为 400。谢谢@Saleem

当人们说“您可以添加密钥文件”时,我认为这是一个可选参数,但它是强制性的。

【讨论】:

【参考方案2】:

注意:此解决方案是特定于 Windows 的,但可以轻松移植到基于 *nix 的系统。

您需要按顺序执行步骤。首先,启动你的 mongod 实例。

start "29001" mongod --dbpath "C:\data\db\r1" --port 29001
start "29002" mongod --dbpath "C:\data\db\r2" --port 29002
start "29003" mongod --dbpath "C:\data\db\r3" --port 29003 

用 mongo 连接到每个节点并创建一个管理员用户。我更喜欢创建超级用户。

> use admin
> db.createUser(user: "root", pwd: "123456", roles:["root"])

您可以根据需要创建其他用户。

创建密钥文件。有关有效的密钥文件内容,请参阅文档。

注意:在基于 *nix 的系统上,将密钥文件的 chmod 设置为 400

就我而言,我将密钥文件创建为

echo mysecret==key > C:\data\key\key.txt

现在重新启动您的 MongoDB 服务器并启用 --keyFile--replSet 标志。

start "29001" mongod --dbpath "C:\data\db\r1" --port 29001 --replSet "rs1" --keyFile C:\data\key\key.txt
start "29002" mongod --dbpath "C:\data\db\r2" --port 29002 --replSet "rs1" --keyFile C:\data\key\key.txt
start "29003" mongod --dbpath "C:\data\db\r3" --port 29003 --replSet "rs1" --keyFile C:\data\key\key.txt

一旦所有mongod 实例启动并运行,就可以通过身份验证连接任何一个。

mongo --port 29001 -u "root" -p "123456" --authenticationDatabase "admin"

启动复制集,

> use admin
> rs.initiate()
> rs1:PRIMARY> rs.add("localhost:29002")
 "ok" : 1 
> rs1:PRIMARY> rs.add("localhost:29003")
 "ok" : 1 

注意:您可能需要将 localhost 替换为机器名称或 IP 地址。

【讨论】:

【参考方案3】:

节点应该一次关闭一个,以便其他次要成员将选择主要成员。并且它将在恢复节点中同步到其他成员。这个一一关闭不需要重新添加节点。

【讨论】:

以上是关于停止 mongo 上的副本集,主节点进入恢复状态的主要内容,如果未能解决你的问题,请参考以下文章

[Mo]MongoDB分片副本集搭建

初识mongodb一二三

docker-compose搭建mongoDB副本集(1主+1副+1仲裁)

MongoDB 错误:连接到 mongo 副本集时无法到达集合 [set_name] 的主节点

docker-compose 配置 mongodb 副本集/复制集

18.副本集