Contents
前言
在上一篇文章中,我用cloudflare tunnel实现了多节点wordpress的"负载均衡"、"多活"、"自动冗余"功能。不过,这种方式并不适合我,因为我的需求是平时我的家庭数据中心正常时所有访问流量都走家庭数据中心的主wordpress,只有家庭数据中心出现断电、断网时才自动走灾备中心(腾讯云服务器)的wordpress站点。
需求分析
目前我有2个不同的tunnle:
顾名思义,”tencentcloud”是连接腾讯云服务器的,有单独的几个域名(不同tunnel里不能有重复的域名),”wudihome”是连接我的家庭数据中心的,”blog.tangwudi.com“就在这个tunnel里。所以现在腾讯云服务器上本来就运行了一个tunnel,那么我们首先要解决的问题是用什么方式能够在腾讯云服务器上既运行”tencentcloud” tunnel,又运行”wudihome”这个tunnel。
在我另一篇文章(参见:家庭数据中心系列 cloudflare教程(九) Zero Trust常用功能介绍及多场景使用教程)里提过:同一个位置只能运行同一个tunnel下的1个connector,但是却可以运行不同tunnel的connector,也就是说腾讯云服务器上本来就可以同时运行2个tunnel的connector,唯一的注意点只是需要采用不同的部署方式,比如:”tencentcloud”我是采用的service的方式部署,那么”wudihome”就要采用不同于service的方式部署,这里我采用了docker的方式。
然后的难点在于,平时正常的时候访问博客的请求只从”wudihome” tunnel连接家庭数据中心的connector进行访问,只有当家庭数据中心出问题的时候才自动切换到连接腾讯云的connector,换句话说,正常的时候”wudihome” tunnel在腾讯云服务器上的connector是关闭的,否则访问请求平时也会从腾讯云服务器访问wordpress站点,这就和我的需求冲突了。
解决思路
以docker方式部署”wudihome” tunnel的connector
要完全实现我的需求,首先需要在腾讯云服务器上以docker的方式部署connector,命令类似如下:
docker run --name cloudflare -d --restart=always \
cloudflare/cloudflared:latest tunnel run --token xxxxxxxxxx #token替换成自己的
然后使用命令docker stop cloudflare
来断掉这个connector,在以后需要的时候,只需要运行docker start cloudflare
就可以启用connector。
定时探测家庭数据中心的可达性
然后我需要有一种快速探测家里的网是否正常的方式,这个时候又要依靠tailscale了:直接使用wordpress主站点(macmini)的tailscale地址为探测目标(假设是100.100.100.100)。
注:为什么不直接ping wan口的IPv4公网地址?其实也是可以的,但是因为电信的IPv4公网地址都是动态公网ip,几天就要变一次,在发生变化的时候,使用wan口的动态域名探测的时间要等多久不好说(dns缓存的影响),而tailscale的固定私有IP会根据公网IP的变化快速调整保持可达性,所以肯定比ping wan口公网IP恢复得快。
然后,我只需要写一个脚本,定时运行一次(比如3分钟),那么家庭数据中心断网最多3分钟我就能发现。
如何让腾讯云的wordpress能使用”wudihome” tunnel里配置的访问方式
这个问题也很重要,在文章(家庭数据中心系列 cloudflare教程(九) Zero Trust常用功能介绍及多场景使用教程)中我说过,单tunnel、多connector环境要配置多个站点的”多活”、”相互冗余”、”负载均衡”功能,需要正确配置域名和应用的对应关系,一般是需要connector是直接部署在wordpress站点所在的主机上,因为这样才能统一用http://localhost:80
的方式进行访问。
不过我现在的情况就是不一般了,因为我的家庭数据中心的拓扑比较特殊,public hostname里,我的”blog.tangwudi.com“指向的是我的waf的50080端口:
腾讯云上肯定是不可能有这个IP的,那怎么办呢?其实很好办,就是使用loopback地址。只要在腾讯云服务器上添加一个loopback接口,然后把IP地址配置成和我家庭数据中心waf一样的IP就行了(这样腾讯云服务器就会认为192.168.1.1也是自身的地址,也就会接受目标地址是这个地址的请求包了,否则就会直接丢弃),只需要运行如下命令:
ifconfig lo:1 192.168.1.1/32 up #假设192.168.1.1是我的waf地址
而不需要的时候,只需要运行如下命令:
ifconfig lo:1 down
这里我要吐槽一下阿里云debian 12,默认就是使用了nmcli,我最习惯的/etc/network/interfaces文件没有了,我本来想一劳永逸的添加一个loopback接口,结果研究了半天也没研究出来怎么弄。。要知道,我最讨厌的就是花大量时间研究怎么添加接口,怎么改IP地址这种没技术含量的操作。。。我记得以前Ubuntu哪个版本也是忽然把这个取消了,搞得我很不习惯,然后就换成debian了~~。
IP有了,50080端口怎么办呢?也简单,直接建立一个blog.tangwudi.com:50080的站点,然后使用反向代理指向http://localhost:80
即可,我这里偷个懒,直接用宝塔面板搞定:
添加反向代理:
![image.png](https://image.tangwudi.com/images/2024/05/31/202405310010945.png)
检测到家庭数据中心断网时自动启用connector
现在就剩最后一步了:如何在检测到家庭数据中心断网时,自动启动connector并添加loobpack地址,这就要靠shell脚本来实现了:
#!/bin/bash
# 定义目标 IP 地址
TARGET_IP="100.100.100.100"
# 定义 Cloudflare 进程名称
CLOUDFLARE_PROCESS_NAME="cloudflare"
# 定义日志文件路径
LOG_FILE="/root/log/runcloudflare.log"
# 进行 ping 测试
if ping -c 1 TARGET_IP &> /dev/null; then
# 如果 ping 通
# 统计包含 cloudflare 关键字的进程数量
PROCESS_COUNT=(pgrep -f CLOUDFLARE_PROCESS_NAME | wc -l)
if [PROCESS_COUNT -eq 1 ]; then
# 如果进程数量等于 1,停止 cloudflare 容器并关闭网络接口
docker stop CLOUDFLARE_PROCESS_NAME
ifconfig lo:1 down
echo "(date) - Stopped cloudflare container" >> LOG_FILE
fi
else
# 如果 ping 不通
# 统计包含 cloudflare 关键字的进程数量
PROCESS_COUNT=(pgrep -f CLOUDFLARE_PROCESS_NAME | wc -l)
if [PROCESS_COUNT -lt 1 ]; then
# 如果进程数量小于 1,启动 cloudflare 容器并启用网络接口
docker start CLOUDFLARE_PROCESS_NAME
ifconfig lo:1 192.168.1.1/32 up
echo "(date) - Started cloudflare container" >> $LOG_FILE
fi
fi
逻辑很简单:如果能ping通而进程中又有cloudflared,说明是之前家庭数据中心down而现在又通了,所以禁用”wudihome” tunnel的connector并禁用loopback接口;如果ping不通,则说明家庭数据中心现在down了,那么启用connector并启用loopback接口。
为了理清这个脚本的格式和思路,我还恶补了一天的bash shell基础。。
最后直接设置这个脚本3分钟运行一次即可,是使用cron还是其他方式就看大家习惯了,我因为有宝塔面板,又偷个懒:
![image.png](https://image.tangwudi.com/images/2024/06/01/202406010957312.png)
进阶需求(新增)
因为我做实验的时候是在阿里云新撸的服务器上做的,上面本来没有跑tunnel,所以上一节的脚本是可以直接用的,但是,后来我用到腾讯云服务器上就不合适了,因为腾讯云上本来就已经运行了一条tencentcloud的tunnel了,所以需要进一步判断进程中名为”cloudflared”的进程的数量,如果等于2(或者大于1),则说明进程中2个tunnel都是启用的(说明主站点已经down过导致了切换),其他的情况(等于1)就是正常的,所以脚本修改如下:
#!/bin/bash
# 定义目标 IP 地址
TARGET_IP="100.100.100.100"
# 定义 Cloudflare 进程名称
CLOUDFLARE_PROCESS_NAME="cloudflare"
# 定义日志文件路径
LOG_FILE="/root/log/runcloudflare.log"
# 进行 ping 测试
if ping -c 10 TARGET_IP &> /dev/null; then
# 如果 ping 通
# 统计包含 cloudflare 关键字的进程数量
PROCESS_COUNT=(pgrep -f CLOUDFLARE_PROCESS_NAME | wc -l)
if [PROCESS_COUNT -gt 1 ]; then
# 如果进程数量大于 1,停止 cloudflare 容器并关闭网络接口
docker stop CLOUDFLARE_PROCESS_NAME
ifconfig lo:1 down
echo "(date) - Stopped cloudflare container" >> LOG_FILE
fi
else
# 如果 ping 不通
# 统计包含 cloudflare 关键字的进程数量
PROCESS_COUNT=(pgrep -f CLOUDFLARE_PROCESS_NAME | wc -l)
if [PROCESS_COUNT -eq 1 ]; then
# 如果进程数量等于 1,启动 cloudflare 容器并启用网络接口
docker start CLOUDFLARE_PROCESS_NAME
ifconfig lo:1 192.168.1.1/32 up
echo "(date) - Started cloudflare container" >> $LOG_FILE
fi
fi
其实,如果同一台主机上运行了更多的tunnel,也可以直接以上面这段脚本为例修改,就是需要考虑下正常情况是几条,非正常情况是几条,不过,有个前提是tunnel进程运行正常,如果有的断掉了,那上面的判断逻辑就会出问题。
后话
这个因为比较简单,我就不提供验证的过程了,反正就是在macmini上把tailscale临时断掉,然后观察腾讯云上定时脚本能否开启cloueflare容器和正确启用lo:1接口并设置ip;然后恢复macmini上tailscale,又观察腾讯云上定时脚本能否禁用cloudflare容器和禁用lo:1即可。
另:这篇文章中的方案和”使用cloueflare tunnel为动态博客搭建流量负载均衡的多活冗余站点”的想法其实是2种不同的方案(参见文章:家庭数据中心系列 cloudflare教程(九) Zero Trust常用功能介绍及多场景使用教程中的多场景描述),分别对应于”本地数据中心+同城灾备数据中心”以及”本地+同城双活数据中心”,这2个方案的基础都是家庭数据中心系列 wordpress多节点”半自动”、”近乎”实时同步方案。
这个系列我一直想写,不过以前知识储备不足,现在终于完成了,也算了了一个心愿,不过我估计,这3篇文章感兴趣的人不多~~。