MongoDB——centos7 docker容器访问宿主机的 ip-无法初始mongo副本集
问题描述:
在三台centos7上配置mongo副本集,
三节点启动
docker run -d --name mongoconfig \ -p 26001:27019 \ -v /root/data/soft/mongo/configdb:/data/configdb \ \mongo:4.0.24 \ --configsvr \ --replSet "replconfig" \ --bind_ip_all
初始化config副本集 rs.status() config = { _id : "replconfig", members : [ {_id : 0, host : "192.168.1.20:26001" }, {_id : 1, host : "192.168.1.21:26001" }, {_id : 2, host : "192.168.1.22:26001" } ] } rs.initiate(config)
在初始化副本集时,用的是宿主ip,报错不识别本节点,即无法从容器内访问宿主ip。
报错如下:
[root@bogon mongo]# docker exec -it mongoconfig mongo 192.168.1.20:26001 -eval "rs.status()" MongoDB shell version v4.0.24 connecting to: mongodb://192.168.1.20:26001/test?gssapiServiceName=mongodb 2021-05-17T10:02:06.601+0000 E QUERY [js] Error: couldn't connect to server 192.168.1.20:26001, connection attempt failed: SocketException: Error connecting to 192.168.1.20:26001 :: caused by :: No route to host : connect@src/mongo/shell/mongo.js:356:17 @(connect):2:6 exception: connect failed [root@bogon mongo]#
> config
{
"_id" : "replconfig",
"members" : [
{
"_id" : 0,
"host" : "192.168.1.20:26001"
},
{
"_id" : 1,
"host" : "192.168.1.21:26001"
},
{
"_id" : 2,
"host" : "192.168.1.22:26001"
}
]
}
>
>
> rs.initiate(config)
{
"ok" : 0,
"errmsg" : "No host described in new configuration 1 for replica set replconfig maps to this node",
"code" : 93,
"codeName" : "InvalidReplicaSetConfig",
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("000000000000000000000000")
},
"lastCommittedOpTime" : Timestamp(0, 0)
}
>
问题分析
在 centos7 上部署 docker 容器,其网络模式采用的是 bridge 模式。
启动 docker 时,docker 进程会创建一个名为 docker0 的虚拟网桥,用于宿主机与容器之间的通信。当启动一个 docker 容器时,docker 容器将会附加到虚拟网桥上,容器内的报文通过 docker0 向外转发。
如果 docker 容器访问宿主机,那么 docker0 网桥将报文直接转发到本机,报文的源地址是 docker0 网段的地址。而如果 docker 容器访问宿主机以外的机器,docker 的 SNAT 网桥会将报文的源地址转换为宿主机的地址,通过宿主机的网卡向外发送。
因此,当 docker 容器访问宿主机时,如果宿主机服务端口会被防火墙拦截,那么就无法连通宿主机,出现 No route to host 的错误。
而访问宿主机所在局域网内的其他机器,由于报文的源地址是宿主机 ip,因此,不会被目的机器防火墙拦截,所以可以访问。
解决问题 方法一
粗暴关闭
systemctl stop firewalld
解决问题 方法二
容器访问宿主机的地址使用 eth0 的地址,即宿主机内网 ip 地址。
运行 ipconfig 命令,查看网络的虚拟网桥相关信息。
注意:宿主机会把容器 ip 地址段当成外网 ip。(当前说明是 centos7 环境)
编辑防火墙文件 /etc/firewalld/zones/public.xml,添加下面 docker0 地址段到配置:
<rule family="ipv4">
<source address="172.17.0.0/16"/>
<accept/>
</rule>
如下
vim /etc/firewalld/zones/public.xml:
<?xml version="1.0" encoding="utf-8"?> <zone> <short>Public</short> <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description> <service name="ssh"/> <service name="dhcpv6-client"/> <rule family="ipv4"> <source address="172.17.0.0/16"/> <accept/> </rule> </zone>
重启防火墙,docker 容器即可正常访问宿主机端口
firewall-cmd --reload
或者重启防火墙服务
service firewalld restart
之后再从容中访问宿主ip映射的26001,通过
[root@bogon mongo]# docker exec -it mongoconfig mongo 192.168.1.20:26001 -eval "rs.status()" MongoDB shell version v4.0.24 connecting to: mongodb://192.168.1.20:26001/test?gssapiServiceName=mongodb Implicit session: session { "id" : UUID("78e18609-4abb-453e-9de8-0b0f0617864e") } MongoDB server version: 4.0.24 { "ok" : 0, "errmsg" : "no replset config has been received", "code" : 94, "codeName" : "NotYetInitialized", "$gleStats" : { "lastOpTime" : Timestamp(0, 0), "electionId" : ObjectId("000000000000000000000000") }, "lastCommittedOpTime" : Timestamp(0, 0) } [root@bogon mongo]#