問題描述:
在三台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]#