这段时间在调研 MySQL HA 方面的东西,看到大多数实现方法都是通过虚IP + IP 漂移实现,所以打算先将此过程实现一下。
虚IP ,就是一个未分配给真实主机的IP,也就是说对外提供数据库服务器的主机除了有一个真实IP外还有一个虚IP,使用这两个 IP 中的任意一个都可以连接到这台主机,所有项目中数据库链接一项配置的都是这个虚IP,当服务器发生故障无法对外提供服务时,动态将这个虚IP切换到备用主机。这个切换的过程我们称之为IP漂移
其实现原理主要是靠 TCP/IP 的 ARP 协议。因为 IP 地址只是一个逻辑 地址,在以太网中 MAC 地址才是真正用来进行数据传输的物理地址,每台主机中都有一个 ARP缓存,存储同一个网络内的IP地址与 MAC 地址的对应关系,以太网中的主机发送数据时会先从这个缓存中查询目标 IP 对应的MAC地址,会向这个 MAC 地址发送数据。操作系统会自动维护这个缓存。这就是整个实现的关键。
我们可以通过 Keepalived 来实现这个过程。 Keepalived 是一个基于 VRRP 协议(Virtual Router Redundancy Protocol,即虚拟路由冗余协议)来实现的LVS(负载均衡器)服务高可用方案,可以利用其来避免单点故障。
一个 LVS 服务会有2台服务器运行 Keepalived,一台为主服务器(MASTER),另一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候,备份服务器就会接管虚拟IP,这时就需要根据 VRRP 的优先级来选举一个 backup 当 master,保证路由器的高可用,继续提供服务,从而保证了高可用性。
先来准备两台机器,IP地址如下: 1 2 lc1: 172.24.8.101 lc7: 172.24.8.107
我们现在要实现添加一个虚IP:172.24.8.150
,当 lc1
机器正常时,172.24.8.150
指向 lc1
,当 lc1
出现故障时指向 lc7
。
此时通过 ping
可以看到 172.24.8.150
是无法 ping
通的。
在这两台机器上分别安装 Keepalived 1 $ sudo yum install -y keepalived
配置 Keepalived lc1
的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ cat keepalived.conf vrrp_instance VI_1 { state MASTER interface enp7s0f0 virtual_router_id 51 priority 101 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 172.24.8.150 } }
lc7
的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 vrrp_instance VI_1 { state MASTER interface enp7s0f0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 172.24.8.150 } }
启动 lc1 和 lc7 上的 Keepalived 服务 1 sudo systemctl restart keepalived.service
将 Keepalived 加入开机启动项 1 sudo systemctl enable keepalived.service
测试 通过 ping 172.24.8.150
发现已经可以通了。
查看 lc1 的 IP信息 1 2 3 4 5 6 7 8 9 $ ip addr show enp7s0f0 2: enp7s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000 link/ether 6c:92:bf:0d:09:47 brd ff:ff:ff:ff:ff:ff inet 172.24.8.101/24 brd 172.24.8.255 scope global enp7s0f0 valid_lft forever preferred_lft forever inet 172.24.8.150/32 scope global enp7s0f0 valid_lft forever preferred_lft forever inet6 fe80::6e92:bfff:fe0d:947/64 scope link valid_lft forever preferred_lft forever
其中可以看到 inet 172.24.8.150/32 scope global enp7s0f0,说明现在 lc1 是作为虚拟IP的 master 来运行的。
查看 lc7 的 IP信息 1 2 3 4 5 6 7 $ ip addr show enp7s0f0 2: enp7s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000 link/ether 6c:92:bf:0d:21:49 brd ff:ff:ff:ff:ff:ff inet 172.24.8.107/24 brd 172.24.8.255 scope global enp7s0f0 valid_lft forever preferred_lft forever inet6 fe80::6e92:bfff:fe0d:2149/64 scope link valid_lft forever preferred_lft forever
此时 lc7 中没有虚拟IP 的信息。
验证 Failover 我们手动停止 lc1 上的 Keepalived 服务: 1 sudo systemctl stop keepalived.service
此时 lc1 的 IP信息为: 1 2 3 4 5 6 7 $ ip addr show enp7s0f0 2: enp7s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000 link/ether 6c:92:bf:0d:09:47 brd ff:ff:ff:ff:ff:ff inet 172.24.8.101/24 brd 172.24.8.255 scope global enp7s0f0 valid_lft forever preferred_lft forever inet6 fe80::6e92:bfff:fe0d:947/64 scope link valid_lft forever preferred_lft forever
可以看到 lc1 已经不在有 虚拟IP 的信息了。
查看 lc7 的 IP信息: 1 2 3 4 5 6 7 8 9 ip addr show enp7s0f0 2: enp7s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000 link/ether 6c:92:bf:0d:21:49 brd ff:ff:ff:ff:ff:ff inet 172.24.8.107/24 brd 172.24.8.255 scope global enp7s0f0 valid_lft forever preferred_lft forever inet 172.24.8.150/32 scope global enp7s0f0 valid_lft forever preferred_lft forever inet6 fe80::6e92:bfff:fe0d:2149/64 scope link valid_lft forever preferred_lft forever
可以看到 lc7
的 IP信息中 已经有虚拟IP 172.24.8.150
的信息了。
此时如果再把 lc1
上的 Keepalived 启动,可以看到 虚拟IP 又重新绑定到了 lc1
上。