Keepalived 高可用

Keepalived 高可用
[TOC]
HTTP Keep-Alive
| 名称 | 用途 | 层级 | 作用 |
|---|---|---|---|
| HTTP Keep-Alive | 保持 HTTP 长连接 | 应用层(HTTP) | 避免反复建立/断开 TCP 连接,提升网页加载速度 |
| Keepalived | 实现 服务器高可用(HA) | 网络层 | 通过 VIP 漂移实现故障自动切换,保障服务不中断 |
- ✅ 正确理解:Keep-Alive ≠ Keepalived
❗它们名字像,但 完全不是一回事
- 就像“苹果(水果)”和“Apple(公司)”——只是碰巧同名
✅什么是 HTTP Keep-Alive?在HTTP/1.1中,默认启用了长连接(会话保持),也就是常说的 Keep-Alive📌 传统短连接(HTTP/1.0 默认) 请求一次,断开一次 特别消耗资源,所以我们现在不用1.0📌 长连接(HTTP/1.1 默认): 握上手后,再也不断开了 请求一次响应一次=======================================💡 Nginx如何控制 Keep-Alive?[root@lb01 conf.d]# grep keepalive /etc/nginx/nginx.conf keepalive_timeout 65;# 长连接的超时时间# 我只等你65秒,如果65秒没有新的请求过来,我网站给你4次挥手,主动断开连接# 如果改为0,就是短连接,请求一次断开一次=======================================keepalive_requests 100;# Nginx默认值就是100、可以不用单独设置# 即使没超时,一个连接最多处理 100 个请求后也会关闭(防资源耗尽)🔸 绝大多数情况下,保持默认 100 是最安全、最平衡的选择Keepalived概述
🌟 一、什么是 Keepalived?
它是一个开源的高可用(HA)解决方案,主要用于:
- 实现 故障自动切换
- 提供 虚拟 IP 漂移 能力
- 常用于 负载均衡器 或 关键服务 的高可用部署
💡 举个生活例子: 就像你家有两台路由器,主路由器坏了,备用路由器 自动接管网络,你手机/电脑完全无感——这就是“高可用”
🧩 二、核心原理:VRRP 协议
Keepalived 基于 VRRP 协议工作:
💡 虚拟路由冗余协议 ,主要用于解决 ==单点故障== 问题
-
多台服务器组成一个 VRRP 组
-
其中一台是 MASTER(主),其余是 BACKUP(备)
-
所有成员共享一个 虚拟 IP(VIP)(如
192.168.1.100) -
和一个 虚拟 MAC 地址(格式通常为
00:00:5E:00:01:XX) -
正常时, 只有 MASTER 拥有 VIP 和虚拟 MAC
-
所有 BACKUP(备) 成员都处于 监听状态
持续接收并监控来自 MASTER(主) 的 VRRP 报文
默认间隔通常是 1 秒
-
只要 BACKUP 能正常收到 MASTER 的 VRRP 报文
就认为 MASTER 仍然存活,不会发起抢占
-
当 MASTER 宕机(如主机断电、网络中断等导致 VRRP 报文停止)
-
优先级最高的 BACKUP 会自动接管 VIP 和虚拟 MAC
成为新的 MASTER,继续提供服务
-
并 开始向外发送自己的 VRRP 报文,宣告自己是新主
-
用户始终访问同一个 VIP,无需感知后端哪台设备在工作
❗ 重要限制🔴: 仅判断主机是否存活,不判断服务是否正常
==比如:==
- LB01 的 Nginx 进程崩溃了,但操作系统还在运行
- VRRP 仍认为 LB01 是主,但 Nginx 返回 502 或无响应!
✅ ==Keepalived(带健康检查) + VRRP = 高可用负载均衡解决方案==
| 故障类型 | 原生 VRRP | Keepalived + 自定义健康检查 |
|---|---|---|
| 主服务器宕机(如关机、断电) | ✅ VIP 漂移 | ✅ VIP 漂移 |
| 主服务器网络中断(无法发 VRRP 报文) | ✅ VIP 漂移 | ✅ VIP 漂移 |
| Nginx/服务进程崩溃,但系统仍运行 | ❌ 不会漂移 | ✅ 会漂移(如果配置了健康检查) |
架构图

高可用安装配置
'环境准备'作用 IP 角色node1 10.0.0.5 Masternode2 10.0.0.6 BackupVIP 10.0.0.3 虚拟=====================================(1)备一台LB02 10.0.0.6
(2)配置nginx官网仓库[root@lb02 ~]# scp 10.0.0.5:/etc/yum.repos.d/nginx.repo /etc/yum.repos.d/Authorized users only. All activities may be monitored and reported.root@10.0.0.5's password: 'nginx.repo 100% 113 87.5KB/s 00:00
(3)安装nginx服务[root@lb02 ~]# yum -y install nginx.....Complete!
(4)将lb01的配置文件同步到lb02[root@lb02 ~]# rsync -avz 10.0.0.5:/etc/nginx/ /etc/nginx/# 增量拷贝[root@lb02 ~]# nginx -tnginx: [emerg] unknown directive "check_status" in /etc/nginx/conf.d/admin.conf:17nginx: configuration file /etc/nginx/nginx.conf test failed[root@lb02 ~]# cd /etc/nginx/conf.d/[root@lb02 conf.d]# rm -rf admin.conf# 将之前编译的check检查模块配置文件删除[root@lb02 conf.d]# nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful
(5)启动nginx[root@lb02 conf.d]# systemctl enable nginx.../usr/lib/systemd/system/nginx.service.[root@lb02 conf.d]# systemctl start nginx
(6)测试访问lb02windows的hosts解析到10.0.0.610.0.0.6 wp.kpyun.com
'主服务器 10.0.0.5 部署keepalived'[root@lb01 ~]# ip a sh eth02: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:87:ce:27 brd ff:ff:ff:ff:ff:ff inet 10.0.0.5/24 brd 10.0.0.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe87:ce27/64 scope link valid_lft forever preferred_lft forever[root@lb01 ~]# yum -y install keepalived[root@lb01 ~]# vim /etc/keepalived/keepalived.conf# 配置keepalivedglobal_defs { #全局配置 router_id lb01 #标识身份->名称}
vrrp_instance VI_1 { state MASTER #标识角色状态 interface eth0 #网卡绑定接口 virtual_router_id 50 #组的标识ID priority 150 #优先级 advert_int 1 #监测间隔时间(秒)
authentication { #组内成员之间的认证 auth_type PASS #认证方式 auth_pass 1111 #认证密码 }
virtual_ipaddress { 10.0.0.3 #虚拟的VIP地址 }}# IP 地址的格式应该是没有子网掩码(如 /24)的'因为这里指定的是虚拟 IP 地址,而不是一个网络段'[root@lb01 ~]# systemctl enable keepalived.../usr/lib/systemd/system/keepalived.service.[root@lb01 ~]# systemctl start keepalived# 启动keepalived[root@lb01 ~]# ip a sh eth02: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:87:ce:27 brd ff:ff:ff:ff:ff:ff 'eth0MAC地址:00:0c:29:87:ce:27' inet 10.0.0.5/24 brd 10.0.0.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever inet 10.0.0.3/32 scope global eth0 '多了一个IP地址!虚拟IP' valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe87:ce27/64 scope link valid_lft forever preferred_lft forever=================================================C:\Users\LENOVO>arp -a 'Windows主机'接口: 10.0.0.1 --- 0x19Internet 地址 物理地址 类型10.0.0.5 00-0c-29-87-ce-27 动态10.0.0.6 00-0c-29-00-9c-58 动态# 现在显示的是eth0的mac地址!C:\Users\LENOVO>ping 10.0.0.3# ping一下这个虚拟IP正在 Ping 10.0.0.3 具有 32 字节的数据:来自 10.0.0.3 的回复: 字节=32 时间=1ms TTL=64来自 10.0.0.3 的回复: 字节=32 时间=1ms TTL=64C:\Users\LENOVO>arp -a'再次查看arp地址映射'Internet 地址 物理地址 类型10.0.0.3 00-0c-29-87-ce-27 动态10.0.0.5 00-0c-29-87-ce-27 动态10.0.0.6 00-0c-29-00-9c-58 动态# 这个虚拟IP的Mac地址是eth0的Mac地址# 它绑定在eth0上,与10.0.0.5共用一个mac地址=================================================说明 Keepalived 没有正确使用 VRRP 虚拟 MAC,而是用本机物理 MAC 响应了 VIP 的 ARP 请求'这通常是因为配置问题或内核行为导致的“非标准模式”'🔍 为什么会这样?🧩 根本原因:Linux 内核的 ARP 响应策略这意味着:即使你通过 Keepalived 添加了 VIP 10.0.0.3/32Linux 内核看到 “我有这个 IP”,就会用 eth0 的物理 MAC(比如 00:0c:29:87:ce:27)去响应 ARP'VRRP 虚拟 MAC 根本没被用上!'❌ 这破坏了 VRRP 的标准行为,导致主备切换时可能因 MAC 变化引发短暂中断=================================================✅ 如何让 Keepalived 使用 真正的虚拟 MAC?需要修改 Linux 内核参数①让系统允许 VIP 绑定到虚拟 MAC②并且只用虚拟 MAC 响应 ARP
步骤 1:在 LB01 和 LB02 上修改内核参数(/etc/sysctl.conf)net.ipv4.conf.all.arp_ignore = 1# 忽略对非本机 IP 的 ARP 请求(更严格)net.ipv4.conf.all.arp_announce = 2# 优先使用目标 IP 所在接口的 MAC(避免用物理 MAC 回应 VIP)应用配置:sysctl -p# 打印输出内核参数配置!
步骤 2:在 Keepalived 配置中,显式启用虚拟 MAC# 虽然默认开启,但可强调use_vmac on # ← 这行很重要!# 启用虚拟 MAC🔔 use_vmac on 会让 Keepalived 创建一个虚拟网络接口=================================================[root@lb01 ~]# vim /etc/sysctl.conf[root@lb01 ~]# sysctl -p |tail -2net.ipv4.conf.all.arp_ignore = 1net.ipv4.conf.all.arp_announce = 2[root@lb01 ~]# grep use_vmac /etc/keepalived/keepalived.conf use_vmac on[root@lb01 ~]# systemctl restart keepalived[root@lb01 ~]# ip a...2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:87:ce:27 brd ff:ff:ff:ff:ff:ff inet 10.0.0.5/24 brd 10.0.0.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe87:ce27/64 scope link valid_lft forever preferred_lft forever'这个eth0没有什么变化!'5: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff inet 10.0.0.3/32 scope global on valid_lft forever preferred_lft forever'多出了这个虚拟IP,并且有它自己的Mac地址!'# 00:00:5e:00:01:32=================================================C:\Users\LENOVO>ping 10.0.0.3# 我们再来ping一下!正在 Ping 10.0.0.3 具有 32 字节的数据:来自 10.0.0.3 的回复: 字节=32 时间<1ms TTL=64来自 10.0.0.3 的回复: 字节=32 时间<1ms TTL=64C:\Users\LENOVO>arp -aInternet 地址 物理地址 类型10.0.0.3 00-00-5e-00-01-32 动态10.0.0.5 00-0c-29-87-ce-27 动态10.0.0.6 00-0c-29-00-9c-58 动态# 这次虚拟IP是它的虚拟的Mac地址!# 00:00:5e:00:01:32=================================================windows hosts解析到10.0.0.3测试10.0.0.3 wp.kpyun.com
'备用服务器 10.0.0.6 部署keepalived'# lb02部署keepalived服务[root@lb02 ~]# yum -y install keepalived[root@lb02 ~]# vim /etc/keepalived/keepalived.conf# 配置keepalivedglobal_defs { router_id lb02 #标识身份->名称}
vrrp_instance VI_1 { state BACKUP #标识角色状态 interface eth0 virtual_router_id 50 priority 100 #优先级 advert_int 1
authentication { auth_type PASS auth_pass 1111 }
use_vmac on # ← 这行很重要! # 启用虚拟 MAC virtual_ipaddress { 10.0.0.3 }}[root@lb02 ~]# vim /etc/sysctl.conf[root@lb02 ~]# sysctl -p |tail -2net.ipv4.conf.all.arp_ignore = 1net.ipv4.conf.all.arp_announce = 2[root@lb02 ~]# systemctl enable keepalived.../usr/lib/systemd/system/keepalived.service.[root@lb02 ~]# systemctl start keepalived# 启动keepalived[root@lb02 ~]# ip a2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:00:9c:58 brd ff:ff:ff:ff:ff:ff inet 10.0.0.6/24 brd 10.0.0.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe00:9c58/64 scope link valid_lft forever preferred_lft forever'eth0没雨什么变化!'4: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff# 多出来一张网卡!有虚拟的Mac地址!但是没有虚拟IP地址# 因为Master在用!================================================='测试'(1)模拟master宕机[root@lb01 ~]# poweroffConnection closing...Socket close.[root@lb02 ~]# ip a'lb02'4: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff inet 10.0.0.3/32 scope global on valid_lft forever preferred_lft forever'出现了IP地址!'# VIP自动漂移到backup服务器
(2)测试wp是否正常访问wp.kpyun.com

(3)查看windows的arp表是否更新C:\Users\LENOVO>ping 10.0.0.3正在 Ping 10.0.0.3 具有 32 字节的数据:来自 10.0.0.3 的回复: 字节=32 时间<1ms TTL=64来自 10.0.0.3 的回复: 字节=32 时间<1ms TTL=64C:\Users\LENOVO>arp -aInternet 地址 物理地址 类型10.0.0.3 00-00-5e-00-01-32 动态10.0.0.5 00-0c-29-87-ce-27 动态10.0.0.6 00-0c-29-00-9c-58 动态'依旧是这个虚拟IP和虚拟Mac地址'
(4)恢复lb01,是否抢占?[root@lb02 ~]# ip a sh on4: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff# lb02(Backup)再次失去ip地址![root@lb01 ~]# ip a sh on4: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff inet 10.0.0.3/32 scope global on valid_lft forever preferred_lft forever# 原来的Master抢占回虚拟IP地址!'默认抢占!且Master的优先级高'
当 MASTER 宕机(如主机断电、网络中断等导致 VRRP 报文停止)
优先级最高的 BACKUP 会自动接管 VIP 和虚拟 MAC
成为新的 MASTER,继续提供服务
并 开始向外发送自己的 VRRP 报文,宣告自己是新主
VIP抢占
✅ 正确的核心思想:
是否发生 VIP 抢占,取决于两个因素:
priority(优先级)
preempt(抢占模式)是否允许
高优先级节点“抢回”MASTER 角色
🔧 关键概念说明:
- 优先级(Priority)
- VRRP 中每台设备配置一个
priority(范围 1~254,默认 100) - 数值越大,优先级越高
- MASTER 是当前组内 优先级最高且存活 的节点
⚠️ 注意:如果两台设备
priority相同,IP 地址更大的那台会成为 MASTER
- 实验下来 —> 往往和==启动顺序==有关系
- 后启动的会被任务新加入的节点 <— 非抢占
- 抢占模式
- 默认开启抢占(preempt)
- 当原 MASTER 恢复后,若其优先级 ≥ 当前 MASTER,就会 立即抢回 VIP
- 可通过配置 关闭抢占,实现“谁先上谁就一直当主”,即使原主恢复也不抢
state 只是一个“建议初始状态”,并不是强制锁定角色📌 官方文档和社区最佳实践普遍建议:不要写 state,让 Keepalived 自动协商'如果是抢占式,最好写上state,Master给一个较高的优先级!'# 非抢占式,就不给state了!======================================✅ 场景 1:希望主恢复后自动抢回 VIP(常见)priority 150 # LB01(主)priority 100 # LB02(备)# 默认 preempt,无需写→ 主恢复 → 抢回 VIP======================================✅ 场景 2:希望避免频繁切换# (如主备性能相当,不希望主恢复时再切一次)priority 100# lb01和lb02的优先级相同!⚠️ MASTER 和启动顺序有关'谁先启动,一般来说他就是master' <-- 同时启动,IP地址大的为masternopreempt # 关闭抢占→ 后续即使对方恢复也不切换(真正非抢占)======================================📌 关键机制:nopreempt 只在已有 VRRP 状态上下文时才生效!🔍 如何复现出'非抢占模式'???✅ 只能是先stop、再start --》Keepalived# 关机重启,和restart都不行!不能复现!'以上两种情况!都会认为自己是“全新加入”的节点'======================================
(1)lb01[root@lb01 ~]# vim /etc/keepalived/keepalived.conf[root@lb01 ~]# egrep 'priority|nopreempt' /etc/keepalived/keepalived.conf priority 100 #优先级 nopreempt'这里把state也删掉了!'[root@lb01 ~]# systemctl restart keepalived
(2)lb02[root@lb02 ~]# vim /etc/keepalived/keepalived.conf[root@lb02 ~]# egrep 'priority|nopreempt' /etc/keepalived/keepalived.conf priority 100 #优先级 nopreempt'这里把state也删掉了!'[root@lb02 ~]# systemctl restart keepalived
(3)查看虚拟IP在哪台机器上!'这里两边可以多重启几次!!!'# 恢复初始状态![root@lb01 ~]# ip a sh on5: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff[root@lb02 ~]# ip a sh on4: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff inet 10.0.0.3/32 scope global on valid_lft forever preferred_lft forever'在lb02上面,优先级相同,IP地址大的为Master'
(4)测试非抢占![root@lb02 ~]# systemctl stop keepalived[root@lb01 ~]# ip a sh on4: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff inet 10.0.0.3/32 scope global on'VIP来到了lb01'=== 启动lb02的 keepalived ===[root@lb02 ~]# systemctl restart keepalived[root@lb02 ~]# ip a sh on5: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff# 没有VIP[root@lb01 ~]# ip a sh on4: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff inet 10.0.0.3/32 scope global on valid_lft forever preferred_lft forever'非抢占,在lb01上面!'======================================'第二种测试非抢占!'# 让他们的优先级不同![root@lb01 ~]# vim /etc/keepalived/keepalived.conf[root@lb01 ~]# egrep 'priority|nopreempt' /etc/keepalived/keepalived.conf priority 150 #优先级 nopreempt# 把lb01的优先级调高!# lb02不需要调整优先级!systemctl restart keepalived'两边都重启启动一下!'[root@lb01 ~]# ip a sh on6: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff inet 10.0.0.3/32 scope global on valid_lft forever preferred_lft forever# 肯定是lb01的主,它的优先级高![root@lb01 ~]# systemctl stop keepalived# 关闭keepalived[root@lb02 ~]# ip a sh on5: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff inet 10.0.0.3/32 scope global on valid_lft forever preferred_lft forever'此时VIP就会漂到lb02'🧪 启动lb01的keepalived'是start并非❗restart'[root@lb01 ~]# systemctl start keepalived[root@lb01 ~]# ip a sh on7: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff👉 VIP 并没有漂回来,即使它的优先级更高!✅ 非抢占![root@lb02 ~]# ip a sh on5: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff inet 10.0.0.3/32 scope global on valid_lft forever preferred_lft forever'依旧在lb02上面!'======================================现在肯定能够正常访问网页🐴我们试着关闭lb02的Nginx服务看看会怎么样??'直接挂掉了!VIP并没有漂移!'# 后续需要通过脚本进行检测Nginx服务的状态才行!
脑裂
脑裂 是高可用集群(如 Keepalived)中一个非常危险的问题
- 指主备节点之间因 通信中断 ,彼此无法感知对方状态
- 从而都以为自己是
“主”节点,同时对外提供服务
常见原因
- 双方开启了防火墙
- Keepalived 默认使用 **VRRP 协议 **不是 TCP/UDP,而是 IP 层协议
- 如果防火墙未放行 VRRP,会导致心跳包被丢弃
- 解决方法:
# iptables 示例iptables -A INPUT -p vrrp -j ACCEPTiptables -A OUTPUT -p vrrp -j ACCEPT
# firewalld 示例firewall-cmd --permanent --add-protocol=vrrpfirewall-cmd --reload- 网卡问题 / 网卡名写错
- 配置文件中指定的
interface eth0实际不存在
解决方法:
- 使用
ip a确认真实网卡名 - 在配置中使用正确的
interface
- 网络设备问题(交换机、路由器等)
- 中间网络设备可能丢弃组播/广播包(VRRP 默认使用 224.0.0.18 组播地址)
解决方法:
- 确保交换机允许 VRRP 组播流量
- 网线问题
- 物理链路故障(如网线松动、损坏)直接导致心跳中断
检测与处理
'大致流程'写一个脚本,放在备份服务器 1)如果lb01和lb02同时出现VIP(虚拟IP)时 # 说明发生脑裂 2)立即 kill 自己的keepalived 3)把脚本放在定时任务中!======================================(1)恢复抢占式[root@lb01 ~]# egrep 'priority' /etc/keepalived/keepalived.conf priority 150 #优先级[root@lb02 ~]# egrep 'priority' /etc/keepalived/keepalived.conf priority 100 #优先级# lb01的优先级高!lb02的优先级低!修改配置文件,重启服务# 可以多重启几次![root@lb01 ~]# ip a sh on5: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff inet 10.0.0.3/32 scope global on valid_lft forever preferred_lft forever[root@lb02 ~]# ip a sh on6: on@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff# VIP在lb01这里!
(2)复现脑裂[root@lb02 ~]# systemctl start firewalld# lb02开启防火墙后,收不到Master的包!# 认为自己是老大'这个时候,出现脑裂,两台机器都有VIP'[root@lb01 ~]# ip a | grep 10.0.0.3 inet 10.0.0.3/32 scope global on[root@lb02 ~]# ip a | grep 10.0.0.3 inet 10.0.0.3/32 scope global on
(3)脚本准备备用服务器得知道Master是否有VIP1)先做免密登录[root@lb02 ~]# ssh-keygen -t rsa -b 4096 -f /root/.ssh/id_rsa_test -N ''# 备用服务器生成密钥对Generating public/private rsa key pair.Your identification has been saved in /root/.ssh/id_rsa_testYour public key has been saved in /root/.ssh/id_rsa_test.pubThe key fingerprint is:SHA256:TtwMdRFqEslN5Q0ak8iccWV//QGPpRC9DqCe0wJeaX4 root@lb02The key's randomart image is:'+---[RSA 4096]----+| +oB**@+ . || B=oO.=* .|| = = .o+oo|| . * * . . .o|| . * S o o .|| . O E . || = || || |+----[SHA256]-----+[root@lb02 ~]# ssh-copy-id 10.0.0.5[root@lb02 ~]# ssh -i /root/.ssh/id_rsa_test 10.0.0.5# 但需要指定私钥才行![root@lb02 ~]# grep '^IdentityFile' /etc/ssh/ssh_configIdentityFile ~/.ssh/id_rsa_test# 改一下配置文件![root@lb02 ~]# ssh 10.0.0.5
Authorized users only. All activities may be monitored and reported. |\ /| ___| \,,/_/ ---__/ \/ \ __--/ (D) \# 成功免密登录,但还有需要优化的地方!![root@lb01 ~]# > /etc/issue[root@lb01 ~]# > /etc/issue.net'清空登录前的提示信息'[root@lb01 ~]# > /etc/motd# 优化掉小马...[root@lb02 ~]# ssh 10.0.0.5 "ip a | grep 10.0.0.3 | wc -l"1# 过滤出了这个VIP--------------- 判断上一条命令是否成功-----------方法1.使用$? 结果为0则成功 非0失败[root@web01 ~]# [ 1 -eq 1 ]# 用来判断是否相等![root@web01 ~]# echo $?0# 执行成功返回0[root@web01 ~]# [ 1 -eq 1 ] && echo okok# && 前面执行成功,则输出OK[root@web01 ~]# [ 1 -eq 10 ] && echo ok# 不成功则不输出!-----------------------------------[root@lb02 ~]# cd /server/scripts/[root@lb02 scripts]# vim check_vip.shlb01=`ssh 10.0.0.5 "ip a" |grep 10.0.0.3|wc -l`lb02=`ip a|grep 10.0.0.3|wc -l`[ $lb01 -eq $lb02 ] && systemctl stop keepalived# 双方肯定有一方有这个VIP# 不可能是0:01:0 # 不暂停!0:1 # 不暂停!1:1☝出现脑裂、杀死备份的keepalived"[ $lb01 -eq 1 ] "# 写成这样可以吗?❌️即使lb02为0(没有脑裂)正常冗余备份也会杀死lb02的keepalived相当于只有lb01运行了keepalived# 那就没有冗余了[root@lb01 ~]# ip a|grep 10.0.0.3 inet 10.0.0.3/32 scope global on[root@lb02 scripts]# ip a|grep 10.0.0.3 inet 10.0.0.3/32 scope global on'出现脑裂!'[root@lb02 scripts]# sh check_vip.sh[root@lb02 scripts]# ip a|grep 10.0.0.3# 执行脚本后,lb02没有了VIP'后续放在定时任务里面每分钟执行一次!'Nginx挂掉
# 写一个nginx检查脚本、如果nginx不存在则杀死keepalived# 我们可以使用if判断、配合尝试拉起Nginx![root@lb01 ~]# ps -C nginx# 可检查Nginx是否存活! PID TTY TIME CMD 991 ? 00:00:00 nginx 993 ? 00:00:00 nginx[root@lb01 ~]# ps -C nginx --no-header# 去掉第一行的信息! 991 ? 00:00:00 nginx 993 ? 00:00:00 nginx[root@lb01 ~]# ps -C nginx --no-header|wc -l2[root@lb01 ~]# systemctl stop nginx[root@lb01 ~]# ps -C nginx --no-header|wc -l0# 关闭Nginx后,就没有它的进程了!======================================[root@lb01 ~]# cat check_web.sh#!/bin/shNG=`ps -C nginx --no-header|wc -l`if [ $NG -eq 0 ]then systemctl restart nginx # 如果nginx不存在则尝试重启nginx sleep 1 # 等待1秒 NG=`ps -C nginx --no-header|wc -l` # 再重新检查nginx是否存在 if [ $NG -eq 0 ] then # 如果$NG变量为0说明nginx还是没有启动、只能杀死keepalived systemctl stop keepalived # 关闭lb01的keepalived后,lb02接管! fifi[root@lb01 scripts]# chmod +x check_web.sh# 给脚本执行权限[root@lb01 scripts]# ll check_web.sh-rwxr-xr-x 1 root root 419 Mar 22 20:58 check_web.sh[root@lb01 scripts]# ./check_web.sh[root@lb01 scripts]# ip a | grep 10.0.0.3 inet 10.0.0.3/32 scope global on# 因为现在Nginx能起来,所以VIP没有漂移[root@lb01 scripts]# systemctl stop nginx'停止Nginx后,VIP没有漂移,业务瘫痪'
[root@lb01 scripts]# ./check_web.sh# 执行脚本后刷新页面# Nginx被拉起来了!业务恢复!'让Nginx拉不起来!'[root@lb01 scripts]# grep user /etc/nginx/nginx.conf | head -1user nginx'少个;分号'# 错误的修改配置文件![root@lb01 scripts]# systemctl stop nginx# 先关闭它[root@lb01 scripts]# systemctl start nginxJob for nginx.service failed because ...# 尝试重启失败![root@lb01 scripts]# ip a|grep 10.0.0.3 inet 10.0.0.3/32 scope global on# 现在是启动这keepalived[root@lb01 scripts]# ./check_web.shJob for nginx.service failed ...[root@lb01 scripts]# ip a|grep 10.0.0.3# 已经没有VIP了![root@lb01 scripts]# systemctl is-active keepalivedinactive# lb01的keepalived已被关闭![root@lb02 scripts]# ip a|grep 10.0.0.3 inet 10.0.0.3/32 scope global on# 现在VIP已经漂到了lb02上!'即使lb01的Nginx挂了,他可以实现VIP漂移!'======================================[root@lb01 scripts]# pwd/server/scripts# 将脚本集成进keepalived[root@lb01 ~]# vim /etc/keepalived/keepalived.confglobal_defs { #全局配置 router_id lb01 #标识身份->名称}
✅vrrp_script check_web { script "/server/scripts/check_web.sh" # 脚本的位置 interval 5 # 检测执行脚本时间 # 时间间隔一定要大于我们脚本执行的时间⌚️}✅
vrrp_instance VI_1 { state MASTER interface eth0 #网卡绑定接口 virtual_router_id 50 #组的标识ID priority 150 #优先级 advert_int 1 #监测间隔时间(秒)
authentication { #组内成员之间的认证 auth_type PASS #认证方式 auth_pass 1111 #认证密码 } use_vmac on virtual_ipaddress { 10.0.0.3 #虚拟的VIP地址 } ✅track_script { check_web # 调用check_web }✅}[root@lb01 ~]# systemctl restart keepalived[root@lb01 ~]# ss -lntup | grep nginxtcp LISTEN 0 128 0.0.0.0:443 users:(("nginx"...[root@lb01 ~]# systemctl stop nginx# 手动关闭![root@lb01 ~]# ss -lntup | grep nginx[root@lb01 ~]# ss -lntup | grep nginx[root@lb01 ~]# ss -lntup | grep nginx...0.0.0.0:80 0.0.0.0:* users:(("nginx"...# 一会就起来了![root@lb01 scripts]# grep user /etc/nginx/nginx.conf | head -1user nginx'少个;分号'[root@lb01 scripts]# systemctl stop nginx# 先关闭它[root@lb01 ~]# systemctl is-active keepalivedinactive# 自动关闭keepalived[root@lb02 scripts]# systemctl is-active keepalivedactive[root@lb02 scripts]# ip a|grep 10.0.0.3 inet 10.0.0.3/32 scope global on# VIP漂到web02'把Nginx错误的配置改回来'[root@lb01 ~]# systemctl start keepalived# 手动启动keepalived[root@lb01 ~]# ss -lntup | grep nginx...0.0.0.0:80 0.0.0.0:* users:(("nginx"...# Nginx就自动起来了![root@lb01 ~]# ip a|grep 10.0.0.3 inet 10.0.0.3/32 scope global on# VIP又漂回来了!文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!



