三连更有木有!(对不起我网文看多了,而且中间其实断过两天的,我不会告诉你其实是我把这事儿给忘了的)
另,这篇照例是工作需要。
使用 Keepalived 实现多机热备(无负载均衡)时,除了对网口状态的监控外,一般还要对系统关键进程(如 Web 服务器的话就是 nginx 或者 httpd 之类的)进行监控,这时就要用到 vrrp_script
配置。网上能找到的 vrrp_script
示例都使用了 weight
选项,以实现基于优先级机制的切换,我在使用中遇到了一点儿问题,总结一下。
一般在使用双机热备时,如果当前主机——假设为 A ——出了问题(关键进程挂掉,优先级降低,低于备机),这时会自动切换到备机——假设为 B ——继续完成工作,同时等待管理员对 A 的问题进行修复。当 A 的问题修复时,我们不希望 A 马上切换为主机,因为这样有可能断掉用户正在使用的连接,体验不好。在 keepalived 中,通过给 A 增加一条 nopreempt
配置,就可以防止 A 主动抢回主机状态。
这时问题就来了。当 A 的问题(关键进程恢复)修复之后,A 的优先级会恢复到原来的值,但由于 nopreempt
的存在,A 并不会立刻抢占。这时就相当于 A 作为备机,却有更高的优先级。如果 B 之后出了问题(关键进程挂掉,优先级降低),却不会导致切换,因为 B 在出问题之前,其优先级就已经比 A 低了。
网上有文章说,遇到这种情况,可以在 B 的进程监控脚本中把 B 的 keepalived 进程杀掉,来强制触发切换动作,这种作法显然并不优雅。有没有更好的方法呢?
注意到,当拔网线触发切换时,被拔网线的机器上,keepalived 并不是降低了自己的优先级,而是进入 FAULT 状态(除 MASTER 和 BACKUP 之外的另一种状态),这时是不会有上述由优先级引起的问题的。所以新的思路就是,当进程监控失败时,不要降低优先级,而是令 keepalived 进入 FAULT 状态,同时在主备两机都加上 nopreempt
选项。
至于怎么令 keepalived 进入 FAULT 状态,也很简单,直接去掉 vrrp_script
中的 weight
选项即可。虽然谁也没说 weight
是必选项,但因为网上能搜到的示例都是配了 weight
的,导致很多人(至少包括我)会主观认为这是必选项,从而无法意识到还有其他方法。当然这也跟 keepalived 的文档不太完善有关。
PS. 让我发现 weight
不是必选项的来源是……找不着了,囧。