高可用入门:keepalived 双机热备与 VIP 漂移
「高可用」听起来很高级,最基础的实现其实就是一个虚拟 IP 在两台机器之间漂移。理解这个,就理解了大部分 HA 方案的原理。
一、VIP 是什么
两台服务器各有自己的真实 IP(比如 .10 和 .11),再共同持有一个虚拟 IP(VIP).100。
node1 192.168.1.10 (MASTER)
node2 192.168.1.11 (BACKUP)
VIP 192.168.1.100 ← 对外服务的地址,飘在其中一台上用户只访问 .100。谁持有 VIP,流量就到谁那里。MASTER 挂了,BACKUP 自动接管。
二、VRRP 协议
keepalived 用的是 VRRP:
- 节点间互相发心跳(组播,协议号 112);
- 每个节点有优先级,高的成为 MASTER;
- MASTER 定期广播,BACKUP 收不到就认为它挂了,自己顶上。
# 抓 VRRP 包看心跳
sudo tcpdump -i eth0 vrrp三、最小配置
sudo apt install -y keepalivedMASTER 节点 /etc/keepalived/keepalived.conf:
global_defs {
router_id LVS_01
script_user root
enable_script_security
}
# 健康检查脚本:检测本机 Nginx 是否活着
vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -20
fall 2
rise 1
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51 # 同一组必须一致,0-255
priority 100 # MASTER 高一些
advert_int 1 # 心跳间隔秒
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.100/24 dev eth0
}
track_script {
chk_nginx
}
}BACKUP 节点:只有三处不同
router_id LVS_02
state BACKUP
priority 90 # 比 MASTER 低健康检查脚本:
# /etc/keepalived/check_nginx.sh
#!/usr/bin/env bash
if ! pgrep -x nginx > /dev/null; then
systemctl start nginx
sleep 2
if ! pgrep -x nginx > /dev/null; then
exit 1 # 起不来,让 VIP 漂走
fi
fi
exit 0chmod +x /etc/keepalived/check_nginx.sh
sudo systemctl enable --now keepalived
# 看 VIP 在谁身上
ip a | grep 192.168.1.100四、测试故障切换
# 在 BACKUP 上盯日志
sudo journalctl -u keepalived -f
# 停掉 MASTER 的 nginx
sudo systemctl stop nginx
# 2 秒后应该看到 VIP 漂到 BACKUP
# 或者直接停 keepalived / 关机
sudo systemctl stop keepalived五、抢占与非抢占
| 模式 | 配置 | 行为 |
|---|---|---|
| 抢占(默认) | state MASTER | MASTER 恢复后抢回 VIP |
| 非抢占 | nopreempt + 双 BACKUP | 当前持有者继续持有,不来回切 |
vrrp_instance VI_1 {
state BACKUP # 两边都设 BACKUP
nopreempt # 不抢占
priority 100
}生产环境推荐非抢占。抢占会造成一次额外的抖动,如果 MASTER 反复出问题,VIP 会来回漂,服务反而更不稳定。
六、脑裂(Split Brain)
心跳线断了但两台都活着 → 两台都认为自己是 MASTER → 都持有 VIP → 网络冲突。
防范措施:
- 双心跳链路(网络 + 串口/第二条网线);
- 监控告警:检测到两台都持有 VIP 立刻报警;
- 用
unicast_src_ip/unicast_peer替代组播(云环境组播常被禁):
unicast_src_ip 192.168.1.10
unicast_peer {
192.168.1.11
}- 脚本里加「能否访问网关」的判断,防止自己网络断了还抢 VIP。
七、云环境要注意
| 平台 | 说明 |
|---|---|
| 阿里云 | 不支持普通 VRRP,需用「高可用虚拟 IP」产品 |
| 腾讯云 | 类似,要用「HAVIP」 |
| AWS | 用 Elastic IP + 脚本切换,或直接用 ELB |
| 自建/机房/VMware | VRRP 正常可用 |
大多数云平台禁用了组播和 ARP 欺骗,keepalived 直接跑不生效。云上更简单的做法是用云厂商的负载均衡器,把两台机器挂到后面。
八、还有别的方案吗
| 方案 | 层级 | 特点 |
|---|---|---|
| keepalived + VIP | 网络层 | 简单,切换快 |
| 云负载均衡 | 平台层 | 最省事,但要花钱 |
| Nginx/HAProxy 多节点 + DNS 轮询 | 应用层 | 简单但切换慢(受 TTL 影响) |
| Pacemaker + Corosync | 集群层 | 功能强,复杂 |
九、个人项目要不要做
我的真实看法:基本不需要。
理由:
- 单点故障的概率远低于「配置错误导致故障」的概率;
- 两台机器的成本翻倍,运维复杂度也翻倍;
- 静态站挂 CDN 后,源站短暂不可用影响很小;
- 真要高可用,用云负载均衡 + 两台后端,比自己搞 keepalived 省心。
值得做的场景:
- 有明确的可用性要求(比如对外的 API 服务);
- 已经有两台机器在跑;
- 想练手(那就练,反正也不贵)。
# 如果只是为了「机器挂了能自动恢复」,更简单的办法是:
# systemd Restart=always + 云厂商的自动重启/告警高可用的本质是消除单点。先想清楚单点在哪——很多时候瓶颈不在服务器,而在你只有一份没备份的数据。
