1.概念
集群类型
- LB负载均衡:LVS、haproxy、nginx
- HA高可用集群:mysql、redis
- SPoF解决单点故障
- HPC高性能集群
系统高可用性
SLA:Service-Level Agreement 服务等级协议(提供服务的企业与客户之间就服务的品质、水准、性能等方面所达成的双方共同认可的协议或契约)
A = MTBF / (MTBF+MTTR)
系统故障
硬件故障:设计缺陷、wear out(损耗)、非人为不可抗拒因素
软件故障:设计缺陷 bug
高可用类型
提升系统高用性的解决方案:降低MTTR- Mean Time To Repair(平均故障时间)
解决方案:建立冗余机制
- active/passive 主/备
- active/active 双主
- active --> HEARTBEAT --> passive
- active <–> HEARTBEAT <–> active
VRRP
虚拟路由冗余协议,解决静态网关单点风险
运用:
- 物理层:路由器、三层交换机
- 软件层:keepalived
VRRP 相关术语
- 虚拟路由器:Virtual Router
- 虚拟路由器标识:VRID(0-255),唯一标识虚拟路由器
- VIP:Virtual IP
- VMAC:Virutal MAC (00-00-5e-00-01-VRID)
- master:主设备
- backup:备用设备
- priority:优先级
VRRP 相关技术
- 通告:心跳,优先级等;周期性
- 工作方式:抢占式,非抢占式
安全认证:无认证、简单字符认证:预共享密钥、MD5
工作模式:主/备、主/主
2.keepalived部署
功能
- 基于vrrp协议完成地址流动
- 为vip地址所在的节点生成ipvs规则(在配置文件中预先定义)
- 为ipvs集群的各RS做健康状态检测
- 基于脚本调用接口完成脚本中定义的功能,进而影响集群事务,以此支持nginx、haproxy等服务
2.1keepalived架构
2.2keepalived环境准备
- 各节点时间必须同步:ntp, chrony
- 关闭防火墙及SELinux
- 各节点之间可通过主机名互相通信:非必须
- 建议使用/etc/hosts文件实现:非必须
- 各节点之间的root用户可以基于密钥认证的ssh服务完成互相通信:非必须
2.4 keepalived安装
相关文件
- 软件包名:keepalived
- 主程序文件:/usr/sbin/keepalived
- 主配置文件:/etc/keepalived/keepalived.conf
- 配置文件示例:/usr/share/doc/keepalived/
- Unit File:/lib/systemd/system/keepalived.service
- Unit File的环境配置文件:/etc/sysconfig/keepalived
dnf install keepalived -y
systemctl start keeplived
systemctl enable --now keepalived
2.5 keepalived配置
/etc/keepalived/keepalived.conf配置文件组成部分
Global definitions :定义邮件配置,route_id,vrrp配置,多播地址等
VRRP instance(s):定义每个vrrp虚拟路由器
Virtual server group(s)
Virtual server(s) :LVS集群的VS和RS
#Global Definitions 全局定义段
global_defs {
notification_email {
admin@example.com #告警接收邮箱(需配置SMTP)
backup@example.com
}
notification_email_from keepalived@hostname #发件人标识
smtp_server 192.168.1.1 #SMTP服务器地址
smtp_connect_timeout 30 #SMTP连接超时(秒)
router_id LVS_DEVEL #节点唯一标识(重要!)
script_user root #检查脚本执行用户
enable_script_security #禁止脚本中变量传递
vrrp_skip_check_adv_addr #对所有通告报文都检查,会比较消耗性能;
#用此配置后,如果收到的通告报文和上一个报文是同个路由器,则跳过检查,默认值为全检查
vrrp_strict #严格遵循vrrp协议
#启用此项后以下状况将无法启动服务:1.无VIP地址;2.配置了单播邻居;3.在VRRP版本2中有IPv6地址
#建议不加此项配置
vrrp_garp_interval 1 #免费 ARP(Gratuitous ARP)报文时间间隔
#免费 ARP用于通知网络中其他设备,某 IP 地址对应的 MAC 地址发生了变化
#帮助网络设备更新 ARP 缓存,确保数据能正确转发到新的主节点
vrrp_gna_interval 1 #用于配置发送 Gratuitous NA(免费邻居通告)报文的时间间隔
#通知网络中其他设备,某 IPv6 地址对应的链路层地址(MAC 地址)发生了变化
#帮助网络设备更新邻居缓存(Neighbor Cache)
#确保 IPv6 数据包能正确转发到新的主节点
vrrp_mcast_group4 224.0.0.44 #指定组播IP地址范围
}
#VRRP Instance VRRP实例段
vrrp_instance VI_1 {
state MASTER # 初始状态(MASTER/BACKUP)
interface eth0 # 绑定VRRP的物理网卡
virtual_router_id 51 # 虚拟路由ID(0-255,集群内一致)
# 同属一个虚拟路由器的多个keepalived节点必须相同
priority 100 # 选举优先级(MASTER需>BACKUP)
advert_int 1 # 通告间隔(秒)
unicast_src_ip 192.168.1.2 # 单播模式下的源IP(可选)
unicast_peer {
192.168.1.3 # 对端IP(替代组播)
}
authentication #认证机制{
auth_type PASS # 认证类型(PASS/AH)
auth_pass 1111 # 密码(明文,建议8字符)
}
virtual_ipaddress #虚拟IP,生产环境可能指定上百个IP地址{
#<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
192.168.1.100/24 dev eth0 label eth0:0 # 虚拟IP配置
2001:db8::1/64 # 支持IPv6
}
track_script {
chk_nginx # 关联的健康检查脚本(见下文)
}
notify_master "/path/to/script.sh master" # 状态切换触发脚本
notify_backup "/path/to/script.sh backup"
}
#检查配置文件语法
keepalived -t -f /etc/keepalived/keepalived.conf
例:
#master
global_defs {
router_id KA1.timinglee.org # 唯一标识
vrrp_garp_interval 1 # 免费ARP广播间隔
vrrp_mcast_group4 224.0.0.18 # VRRP组播地址
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 20 # 集群ID需一致
priority 100 # 高优先级
virtual_ipaddress {
172.25.254.100/24 dev eth0 label eth0:0 # VIP配置
}
}
#backup
global_defs {
router_id KA2.timinglee.org # 唯一标识
vrrp_mcast_group4 224.0.0.18 # 与Master相同组播地址
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 20 # 与Master相同的集群ID
priority 80 # 低优先级
virtual_ipaddress {
172.25.254.100/24 dev eth0 label eth0:0 # 相同的VIP
}
}
22:48:23.294894 IP 172.25.254.50 > 224.0.0.18: VRRPv2, Advertisement, vrid 20, prio 100 # Master通告
22:48:24.084793 IP 172.25.254.60 > 224.0.0.18: VRRPv2, Advertisement, vrid 20, prio 80 # Backup监听
2.5.1 keepalived日志功能
vim /etc/sysconfig/keepalived
KEEPALIVED_OPTIONS="-D -S 6" #日志级别为0-7
vim /etc/rsyslog.conf
local6.* /var/log/keepalived.log
systemctl restart keepalived.service rsyslog.service
#测试
tail -f /var/log/keepalived.log
2.5.2实现独立子配置文件
mkdir /etc/keepalived/conf.d
vim /etc/keepalived/keepalived.conf
#在global下面添加
include /etc/keepalived/conf.d/*.conf #相关子配置文件
vim /etc/keepalived/conf.d/router.conf
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 20
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.100/24 dev eth0 label eth0:0
}
}
3.keepalived示例
3.1master/slave的单主架构
master配置
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
lllll@lllll.com
}
notification_email_from keepalived@KA1.li.org
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id KA1.li.org
vrrp_skip_check_adv_addr
#vrrp_strict #添加此选项无法访问vip,可以用nft list ruleset查看
vrrp_garp_interval 1
vrrp_gna_interval 1
vrrp_mcast_group4 224.0.0.18
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 20
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.100/24 dev eth0 label eth0:0
}
}
backup配置
#只修改
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 20 #相同id管理同一个虚拟路由
priority 80 #低优先级
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.100/24 dev eth0 label eth0:0
}
}
#测试
tcpdump -i eth0 -nn host 224.0.0.18
3.2抢占模式和非抢占模式
抢占模式工作流程
3.2.1非抢占模式
特点:
- 原 Master 节点恢复后不会自动抢回 VIP,保持 Backup 状态
- 需显式配置 nopreempt 参数
- 适合避免频繁切换导致服务波动的场景
- 所有节点都要设置backup
工作流程
配置
vrrp_instance VI_1 {
state BACKUP # 所有节点均设为BACKUP
priority 100 # 优先级仍可不同
advert_int 1
nopreempt # 显式声明非抢占模式
}
3.2.2 延迟抢占模式
作用
- 立即检测到恢复,但不立即抢回 VIP
- 等待延迟时间(preempt_delay) 确认节点稳定性
- 延迟结束后,若节点仍健康,则执行 VIP 抢占
工作流程
配置
vrrp_instance VI_1 {
state MASTER
priority 100
preempt # 显式启用抢占模式(默认已启用)
preempt_delay 300 # 抢占延迟时间(秒,建议5-300秒)
advert_int 1 # 心跳间隔需小于preempt_delay
}
3.3VIP单播配置
启用 vrrp_strict 时,不能启用单播
unicast_src_ip <IPADDR> #指定发送单播的源IP
unicast_peer {
<IPADDR> #指定接收单播的对方目标主机IP
}
3.4Keepalived 通知脚本配置
默认以用户keepalived_script身份执行脚本,如果此用户不存在,以root执行脚本可以用 script_user <USER> 指定脚本执行用户的身份
global_defs {
......
script_user <USER>
......
}
通知脚本类型
notify_master <STRING>|<QUOTED-STRING> #当前节点成为主节点时触发的脚本
notify_backup <STRING>|<QUOTED-STRING> #当前节点转为备节点时触发的脚本
notify_fault <STRING>|<QUOTED-STRING> #当前节点转为“失败”状态时触发的脚本
脚本的调用
#在vrrp_instance VI_1 语句块下面加
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
#创建通知脚本
vim /etc/keepalived/mail.sh
#!/bin/bash
mail_dest='llll@llll.com'
mail_send()
{
mail_subj="$HOSTNAME to be $1 vip 转移"
mail_mess="`date +%F\ %T`: vrrp 转移,$HOSTNAME 变为 $1"
echo "$mail_mess" | mail -s "$mail_subj" $mail_dest
}
case $1 in
master)
mail_send master
;;
backup)
mail_send backup
;;
fault)
mail_send fault
;;
*)
exit 1
;;
esac
#邮件配置
dnf install s-nail sendmail -y
vim /etc/mail.rc
#######mail set##########
set smtp=smtp.163.com
set smtp-auth=login
set smtp-auth-user=lllll@163.com
set smtp-auth-password=
set from=lllll@163.com
set ssl-verify=ignore
systemctl enable --now sendmail.service
3.4.1Keepalived 状态切换的通知脚本
vim /etc/keepalived/mail.sh
#!/bin/bash
mail_dest='llll@llll.com'
mail_send()
{
mail_subj="$HOSTNAME to be $1 vip 转移"
mail_mess="`date +%F\ %T`: vrrp 转移,$HOSTNAME 变为 $1"
echo "$mail_mess" | mail -s "$mail_subj" $mail_dest
}
case $1 in
master)
mail_send master
;;
backup)
mail_send backup
;;
fault)
mail_send fault
;;
*)
exit 1
;;
esac
chmod +x /etc/keepalived/mail.sh
vim /etc/keepalived/keepalived.conf
global_defs {
enable_script_security #开启keepalived执行脚本功能
script_user root #指定脚本执行用户身份
}
vrrp_instance VI_1 {
……
notify_master "/etc/keepalived/mail.sh master"
notify_backup "/etc/keepalived/mail.sh backup"
notify_fault "/etc/keepalived/mail.sh fault"
}
3.5master/master的双主架构
双master分别走不同的业务,互为主备
vim /etc/keepalived/keepalived.conf
#KA1
vrrp_instance VI_1 {
state MASTER #主
interface ens33
virtual_router_id 50
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.50 dev ens33 label ens33:0
}
}
vrrp_instance VI_60 {
state BACKUP #备
interface ens33
virtual_router_id 60
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.60 dev ens33 label ens33:1
}
}
#KA2
vrrp_instance VI_1 {
state BACKUP #备
interface ens33
virtual_router_id 50
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.50 dev ens33 label ens33:0
}
}
vrrp_instance VI_60 {
state MASTER #主
interface ens33
virtual_router_id 60
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.60 dev eth0 label eth0:1
}
}
3.6实现IPVS的高可用性
实现 IPVS (IP Virtual Server) 的高可用性需要结合 Keepalived 和 LVS 技术,通过 VIP 漂移和健康检查确保服务持续可用。
virtual_server IP port {
...
real_server {
...
}
real_server {
...
}
…
}
virtual_server IP port #定义虚拟主机IP地址及其端口
virtual_server fwmark int #ipvs的防火墙打标,实现基于防火墙的负载均衡集群
virtual_server group string #使用虚拟服务器组
配置
virtual_server IP port { #VIP和PORT
delay_loop <INT> #检查后端服务器的时间间隔
lb_algo rr|wrr|lc|wlc|lblc|sh|dh #定义调度方法
lb_kind NAT|DR|TUN #集群的类型,注意要大写
persistence_timeout <INT> #持久连接时长
protocol TCP|UDP|SCTP #指定服务协议,一般为TCP
sorry_server <IPADDR> <PORT> #所有RS故障时,备用服务器地址
real_server <IPADDR> <PORT> { #RS的IP和PORT
weight <INT> #RS权重
notify_up <STRING>|<QUOTED-STRING> #RS上线通知脚本
notify_down <STRING>|<QUOTED-STRING> #RS下线通知脚本
HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK { ... } #定义当前主机健康状
态检测方法
}
}
#应用层检测:HTTP_GET|SSL_GET
HTTP_GET|SSL_GET {
url {
path <URL_PATH> #定义要监控的URL
status_code <INT> #判断上述检测机制为健康状态的响应码,一般为 200
}
connect_timeout <INTEGER> #客户端请求的超时时长, 相当于haproxy的timeout server
nb_get_retry <INT> #重试次数
delay_before_retry <INT> #重试之前的延迟时长
connect_ip <IP ADDRESS> #向当前RS哪个IP地址发起健康状态检测请求
connect_port <PORT> #向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS> #向当前RS发出健康状态检测请求时使用的源地址
bind_port <PORT> #向当前RS发出健康状态检测请求时使用的源端口
}
#传输层检测:TCP_CHECK
TCP_CHECK {
connect_ip <IP ADDRESS> #向当前RS的哪个IP地址发起健康状态检测请求
connect_port <PORT> #向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS> #发出健康状态检测请求时使用的源地址
bind_port <PORT> #发出健康状态检测请求时使用的源端口
connect_timeout <INTEGER> #客户端请求的超时时长
#等于haproxy的timeout server
}
3.7实现其它应用的高可用性 VRRP Script
keepalived利用 VRRP Script 技术,可以调用外部的辅助脚本进行资源监控,并根据监控的结果实现优先动态调整,从而实现其它应用的高可用性功能
建议配置文件路径:/usr/share/doc/keepalived/keepalived.conf.vrrp.localcheck
#配置模板
#定义脚本
vrrp_script <SCRIPT_NAME> {
script <STRING>|<QUOTED-STRING> #此脚本返回值为非0时,会触发下面OPTIONS执行
OPTIONS
}
#调用脚本
track_script {
SCRIPT_NAME_1
SCRIPT_NAME_2
}
#定义脚本
vrrp_script <SCRIPT_NAME> { #定义一个检测脚本,在global_defs 之外配置
script <STRING>|<QUOTED-STRING> #shell命令或脚本路径
interval <INTEGER> #间隔时间,单位为秒,默认1秒
timeout <INTEGER> #超时时间
weight <INTEGER:-254..254> #默认为0,如果设置此值为负数,
#当上面脚本返回值为非0时
#会将此值与本节点权重相加可以降低本节点权重, #即表示fall.
#如果是正数,当脚本返回值为0,
#会将此值与本节点权重相加可以提高本节点权重
#即表示 rise.通常使用负值
fall <INTEGER> #执行脚本连续几次都失败,则转换为失败,建议设为2以上
rise <INTEGER> #执行脚本连续几次都成功,把服务器从失败标记为成功
user USERNAME [GROUPNAME] #执行监测脚本的用户或组
init_fail #设置默认标记为失败状态,监测成功之后再转换为成功状态
}
#调用脚本
vrrp_instance test {
... ...
track_script {
check_down
}
}