我正在使用 keepalived 在两个虚拟机之间切换浮动 IP。
/etc/keepalived/keepalived.conf
在虚拟机 1 上:
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 101
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass secret
}
virtual_ipaddress {
1.2.3.4
}
}
/etc/keepalived/keepalived.conf
在虚拟机 2 上:
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 101
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass secret
}
virtual_ipaddress {
1.2.3.4
}
}
这基本上可以正常工作,但有一个例外:每次 systemd 更新(它运行的是 Ubuntu 18.04)时,它都会重新加载它的网络组件,导致浮动 IP 丢失,因为它没有在系统中配置。由于两个 keepalived 实例仍然可以相互 ping 通,因此它们都没有发现任何问题,也没有对此做出反应,导致浮动 IP 保持关闭。
我发现您可以使用如下简单脚本检查 IP:
vrrp_script chk_proxyip {
script "/sbin/ip addr |/bin/grep 1.2.3.4"
}
vrrp_instance VI_1 {
# [...]
track_script {
chk_proxyip
}
}
但我不确定这是否是一种可行的方法。
如果我理解正确,如果我在 VM1 上配置此脚本,则会发生以下情况:
- 由于 systemd 重新启动,VM1 丢失了 IP
- VM1 上的 keepalived 检测到 IP 丢失
- keepalived 切换到
FAULT
状态并停止广播 vrrp 包 - VM2 上的 keepalived 检测到 VM1 上的 keepalived 丢失并将浮动 IP
此时 IP 再次在 VM2 上工作,但 VM1 将保持此状态,因为 IP 再也不会在 VM1 上出现。如果 VM2 出现故障(无论出于何种原因),VM1 不会接管它,因为它仍处于FAULT
状态。
如何确保浮动 IP 始终在其中一个 VM 上运行?
进一步测试:
我尝试 ping 浮动 IP,而不是检查它是否在 check_script 中的特定主机上处于活动状态:
vrrp_script chk_proxyip {
script "/bin/ping -c 1 -w 1 1.2.3.4"
interval 2
}
在节点 2 上配置此脚本会导致以下结果:
- 删除节点 1 上的 IP 进行测试
- 节点 2 检测到 IP 丢失并从 更改
BACKUP
为FAULT
- 节点 1 忽略状态变化并停留
MASTER
结果:IP 保持不变。
在节点 1 上配置脚本会导致以下结果:
- 删除节点 1 上的 IP
- 节点 1 检测到 IP 丢失并从 更改
MASTER
为FAULT
- 节点 2 检测到节点 1 上的状态变化并从 更改
BACKUP
为MASTER
,在节点 2 上配置浮动 IP
嗯,然后……
Feb 13 10:11:26 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Transition to MASTER STATE
Feb 13 10:11:27 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Entering MASTER STATE
Feb 13 10:11:29 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Received advert with higher priority 150, ours 100
Feb 13 10:11:29 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Entering BACKUP STATE
Feb 13 10:11:32 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Transition to MASTER STATE
Feb 13 10:11:33 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Entering MASTER STATE
Feb 13 10:11:36 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Received advert with higher priority 150, ours 100
Feb 13 10:11:36 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Entering BACKUP STATE
Feb 13 10:11:38 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Transition to MASTER STATE
Feb 13 10:11:39 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Entering MASTER STATE
Feb 13 10:11:41 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Received advert with higher priority 150, ours 100
Feb 13 10:11:41 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Entering BACKUP STATE
Feb 13 10:11:44 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Transition to MASTER STATE
Feb 13 10:11:45 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Entering MASTER STATE
Feb 13 10:11:47 node2 Keepalived_vrrp[3486]: VRRP_Instance(VI_1) Received advert with higher priority 150, ours 100
...
我不得不在 node1 上重新启动 keepalived 以停止节点之间的乒乓球比赛。
我们遇到了这个问题,并认为这是现在使用 netplan 的 ubuntu 18.04 中的 systemd-networkd 的问题。更新版本的 keepalived 应该可以解决此问题,因为它可以检测导致故障转移的浮动 IP 的删除,请参阅https://github.com/acassen/keepalived/issues/836。
更新版本的 keepalived 在 18.04 中不可用,我们没有尝试向后移植,而是决定留在 ubuntu 16.04 并等到 ubuntu 20.04 用于我们使用 keepalived 的服务器。
此问题已在 2018-05-26 的 keepalived 2.0.0 中修复,请参阅keepalived 的更新日志
我认为您可以对浮动 ip 进行 ping 检查,然后当它失败时重新启动所有节点上的 keepalived 服务
你的 ip 会回来的
把它放在每分钟或 5 分钟运行一次的 cronjob 中
我认为您的一般方法很好,但是您需要重新考虑您的测试条件。您关心的条件是 systemd 是否正在重新启动网络基础设施(这种情况的间接后果,无论您的 VIP 是否已启动),因此您需要检查这一点。
我没有一个可以在键入时轻松测试的系统,因此 YMMV
systemctl is-active network.service
可能足以涵盖这一点。如果不检查systemctl show network.service | grep 'ActiveState'
“活动”以外的状态的状态,则应该这样做。顺便说一句,您的一个节点是否应该不配置为“BACKUP”状态,而不是同时配置为“MASTER”?
作为一种解决方法,我将浮动 IP 配置为主节点上的附加 IP(具有更高优先级)
/etc/netplan/01-netcfg.yaml:
这样,在引导或 systemd 重新配置时,浮动 IP 位于主节点上。如果它失败,它由辅助节点通过keepalived接管。如果主节点返回 IP 将由辅助节点上的 keepalived 释放。
这不是一个真正的解决方案,但目前我没有看到更好的东西。
更新
虽然这种解决方法有点奏效,但它有一些副作用。重新启动后,浮动 IP 地址在接口上存在两次:
这似乎没有影响任何事情,它有效,但它困扰着我。最后,我得到了 mp3foley 的答案,并用 Ubuntu 16.04 重新安装了虚拟机。