起因

事情起因是这样的:作为一名垃圾佬,手里有好几家云厂商的(低价)服务器,之前在阿里云广州已经部署了一个 MongoDB 副本集,现在想在腾讯云广州新增一个节点,于是按照 MongoDB 的官方文档执行

rs.add("xxx.xxx.xxx.xxx:27017")

一开始以为只需要在阿里云的防火墙安全组放通腾讯云访问、腾讯云安全组放通阿里云访问,结果折腾半天发现新节点一直处在 STARTUP 状态不会进入 SECONDARY,很纳闷。

后来用 telnet 发现不管是在阿里云还是腾讯云的机器上访问自身公网 IP:27017 也不通的,遂在各自防火墙上放通自己访问自己 27017 端口,新节点一下子就成功加入副本集了。

反思

查了一下文档,原来 MongoDB 副本集节点在加入和运行时还会尝试访问自己。而 rs.add 的时候我使用的是公网 IP,在没有设置云安全组规则之前,本机是无法通过公网 IP 连接上自己的,自然也就无法顺利加入副本集。

我一开始的误解是,自己访问自己的 IP,有点类似于访问 127.0.0.1 这个环回地址。因为以前在家庭宽带内网测试过访问公网 IP:80 能连上(但在其他网络访问则被运营商屏蔽了 80 端口),后来研究发现这通常是由于路由器支持 NAT 回环(NAT Loopback / Hairpin NAT) 功能,内网的流量在路由器直接转发而没有离开 WAN 口。所以,我带着这种「访问自身公网 IP 约等于环回」的刻板印象,忽略了安全组的放通规则。

只是这样?

但问题来了,如果说安全组放通自己就能访问,是不是意味着自己访问自己的流量也会被计入公网流量?那这样岂不是浪费了(毕竟腾讯云这台机器是大带宽但限流量),不妥!不妥!

那有解决方案吗?

有!常见的思路是组个 VLAN,让它们通过内网地址访问就行,这样就只有跨云的流量是计费的,访问自身的流量就不会计费了。

但是跨云的 VLAN 价格还是挺高的。那换 Tailscale 或者 n2n 这类 SD-WANP2P VPN 就行了!

更巧的方案

考虑到搭 HeadscaleTailscale 的开源替代)还是略麻烦的,然后在翻 n2n 文档的时候突然灵光一闪!

如果我把节点由 IP 换成域名(MongoDB 副本集支持域名访问),然后把指向自己的域名解析到 127.0.0.1 不就规避了访问公网吗!而且还不需要引入别的工具,更简单更稳定。

于是我定了两个域名:mongo.aliyun-gz.internalmongo.qcloud-gz.internal 分别指向阿里云和腾讯云,然后改 /etc/hosts

修改阿里云机器上的 /etc/hosts

127.0.0.1 mongo.aliyun-gz.internal        # 本机访问自己时走环回
QCLOUD_PUBLIC_IP mongo.qcloud-gz.internal # 访问腾讯云节点时走公网

修改腾讯云机器上的 /etc/hosts

127.0.0.1 mongo.qcloud-gz.internal          # 本机访问自己时走环回
ALIYUN_PUBLIC_IP mongo.aliyun-gz.internal   # 访问阿里云节点时走公网

然后修改 MongoDB 的节点 host 为域名并应用,问题解决!

当然,这个解决方案也有个缺点,就是需要手动改 hosts,如果有内网自建的 DNS 会好一些,但我的服务器架构目前还是非常简单的,先这样用着就行。

这个方案也适用于其他组集群的应用/中间件 :-P

标签: MongoDB, 云计算, 混合云, 网络

添加新评论