Keepalived简述
一、简介
Keepalived是一个开源的软件,用于在Linux系统上实现高可用性和负载均衡。它提供了一种简单而可靠的方式来确保关键服务的持续可用性,并将流量分发到多个服务器上以实现负载均衡。
Keepalived的主要功能如下:
-
高可用性:通过使用虚拟路由冗余协议(VRRP),Keepalived允许多台服务器组成一个虚拟路由器,并提供一个共享的虚拟IP地址。其中一台服务器被指定为主服务器(Master),负责处理所有的请求,而其他服务器则作为备份服务器(Backup)待命。如果主服务器发生故障或不可用,备份服务器会自动接管主服务器的角色,并继续提供服务,实现高可用性。
-
健康检查:Keepalived可以定期检查服务器的健康状态,包括检查服务是否正常运行、服务器的负载情况等。如果服务器不可用或负载过高,Keepalived可以自动将其排除在负载均衡的范围之外,确保只有健康的服务器接收请求。
-
负载均衡:Keepalived的负载均衡由lvs提供,只需在配置中指定 lb_algo 和 lb_kind 参数,就可以直接使用 LVS 的负载均衡算法和转发模式。LVS介绍
-
通知和日志:Keepalived可以配置通知机制,以便在发生故障或状态变化时发送通知。它还提供详细的日志记录,便于故障排查和监控。
Keepalived使用简单的配置文件进行配置,可以通过编辑配置文件来定义虚拟路由器、指定服务器的角色和权重、配置健康检查和负载均衡算法等。一旦配置完成,Keepalived会自动运行并监控服务器的状态,并根据配置执行故障转移和负载均衡。
Keepalived通常用于构建高可用性的网络服务,如负载均衡器、防火墙、虚拟专用网络(VPN)等。它在互联网服务提供商、企业网络和数据中心等环境中广泛应用,提供了一种可靠的方式来确保关键服务的持续可用性和性能优化。
VRRP(Virtual Router Redundancy Protocol)是一种网络协议,用于在局域网(LAN)环境中提供虚拟路由器的冗余和故障转移功能。它允许多台路由器共同提供一个虚拟IP地址,确保在主路由器故障时能够无缝地切换到备用路由器,从而实现网络的高可用性。
VRRP的工作原理如下:
-
虚拟路由器:VRRP允许多台路由器组成一个虚拟路由器组(VRG),并提供一个虚拟IP地址(Virtual IP,VIP)。这个虚拟IP地址是由VRG中的路由器共享的,作为默认网关提供给局域网上的其他设备。
-
主备选举:VRG中的路由器通过选举确定一个主路由器(Master)和一个或多个备用路由器(Backup)。主路由器负责处理所有的数据流量,而备用路由器处于待命状态。
-
心跳和状态通告:主路由器通过使用组播地址(224.0.0.18),周期性地发送心跳消息(vrrp包)来宣告自己的存在,并通知其他路由器自己的状态。备用路由器监听心跳消息,以检测主路由器的可用性。
-
故障转移:如果主节点失去连接或不可用,备节点中的某台(高优先级)会被选举为新的主节点,并接管主节点的功能,包括继续处理数据流量和提供虚拟IP地址(VIP飘移)。
选举机制:
- 选举过程:当一个 VRRP 组中的节点启动或检测到其他节点故障时,它们将进入选举过程。在选举过程中,每个节点根据其配置的优先级和其他参数竞争成为主节点。
- 优先级:每个节点都配置有一个优先级值。具有较高优先级的节点更有可能成为master节点。通常,优先级值越高,成为master节点的机会就越大。
优先级:
priority
参数:在 Keepalived 配置中,可以为每个节点设置priority
参数,指定其优先级值。较高的优先级值表示更高的优先级。默认情况下,优先级值为 100。advert_int
参数:advert_int
参数定义了 VRRP 路由器发送广告消息的时间间隔。较短的广告间隔可以提高 VRRP 节点被选举为主节点的机会。
非抢占模式:
keepalived默认为抢占模式,由参数 perrmpt 控制,抢占模式下,当优先级高的主机恢复在线后,会抢占优先级低的主机的master角色,在网络不稳定时,可能导致 VIP 频繁切换,不利于系统稳定性。
如:利用keepalived做热备,其中一台设置为master,一台设置为backup,master优先级高于backup。当master出现异常后,backup自动切换为master。当backup成为master后,原master恢复正常后由于优先级比当前master节点优先级高,所以原master节点会再次抢占成为master。
非抢占模式,由参数 nopreempt 控制,非抢占模式下,当master节点故障,vip飘移,后又恢复正常时,不会抢占成为master节点。当其他节点都异常时,vip会再次偏移到最初的master节点上。
配置:
服务器角色都设置为backup,在优先级高的服务器上设置nopreempt
vrrp_instance VI_1 { state BACKUP #角色为backup interface eth0 virtual_router_id 51 priority 100 #优先级要高于其他节点 nopreempt #设置成非抢占模式 }
二、安装及配置
安装:
yum -y install keepalived
配置文件默认位置:/etc/keepalived/keepalived.conf,配置文件都是以块(block)的形式组成,每一个块的内容都包含在{ }中
全局配置
global_defs { #全局配置标识 notification_email { #用于设置报警的邮件地址,可以设置多个,每行一个。如果要开启邮件报警,需要开启本机的sendmail服务 acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc #邮件的发送地址 smtp_server 192.168.200.1 #邮件的smtp server地址 smtp_connect_timeout 30 #连接smtp server的超时时间 router_id LVS_DEVEL #路由标识,唯一 vrrp_skip_check_adv_addr #yes:如果收到的通告报文和上一个报文是同一个路由器,则跳过检查,no:默认值为全检查 vrrp_strict #yes:开启严格模式,Keepalived 将对接收到的 VRRP 广告进行更严格的验证和处理,建议关闭 vrrp_garp_interval 0 #ARP接口之间发送报文的延迟时间,可以精确到毫秒,默认是0,0表示不延迟 vrrp_gna_interval 0 #非请求消息的发送延迟时间,默认为0 script_user root #指定在执行脚本时使用的用户身份,如果未指定,则用户默认为keepalived_script }
VRRPD配置
VRRP同步组(可选)
VRRP Sync Group(VRRP 同步组)是用于在 VRRP(Virtual Router Redundancy Protocol)环境中实现多个 VRRP 实例之间状态同步和协调的配置机制。它的作用是确保在一个组内的 VRRP 实例之间实现一致性,并在故障发生时实现快速主备切换。
VRRP Sync Group 在以下场景中非常有用:
- 多个 VRRP 实例:当存在多个 VRRP 实例时,可以使用 VRRP Sync Group 来确保它们之间的状态同步和一致性,以实现更高级别的冗余和可用性。
- 多个网段:当有多个网段(如内网和外网)需要进行冗余和故障转移时,VRRP Sync Group 可以确保这些网段的 VRRP 实例之间的状态同步,并在故障发生时进行快速切换。
比如:有两个网段,一个是内网(192.168.1.0/24),一个是外网(203.0.113.0/24),每个网段都有一个 VRRP 实例来提供冗余。为了确保内外网的一致性和故障转移,可以创建一个名为 "VG_1" 的 VRRP Sync Group,并将内网和外网的 VRRP 实例配置为该组的成员。
vrrp_sync_group VG_1 { #同步组名称
group {
vrrp_instance_internal #与后文的vrrp_instance实例名称一致。内网 VRRP 实例配置
vrrp_instance_external #外网 VRRP 实例配置
}
}
VRRP实例
vrrp_instance VI_1 { #虚拟路由器实例,VI_1为实例名称 state MASTER #指定keepalived的角色,MASTER表示此主机是主服务器,BACKUP表示此主机是备服务器 interface eth0 #指定检测网络的网卡接口 virtual_router_id 51 #虚拟路由标识,数字形式,取值范围为0-255,同一个VRRP实例使用唯一的标识,即在同一个vrrp_instance下,master和backup必须一致 priority 100 #节点优先级,取值范围为1-254,数字越大表示节点的优先级越高,在一个VRRP实例下,MASTER的优先级必须要比BACKUP高,不然就会切换角色 advert_int 1 #VRRP通告的时间间隔,单位为秒,默认1 nopreempt #设置ARRT的抢占模式,yes为禁用抢占模式,默认为no preempt_delay 300 #抢占延迟,默认5分钟,单位秒 authentication { #认证机制 auth_type PASS #认证类型,可选择AH和PASS两种,AH为IPSC互联网安全协议认证,PASS为简单密码认证,推荐PASS认证 auth_pass 1111 #预共享秘钥设置,仅前8位有效,同一虚拟路由器的多个keepalived节点auth_pass值必须保持一致 } virtual_ipaddress { #虚拟路由器的IP,并可设置IP对应的子网掩码、网卡和标签等,不指定网卡时默认添加在eth0上,不设置子网掩码时默认为32位 192.168.200.16 #不同的虚拟IP分行隔开 192.168.200.17 192.168.200.18 } }
负载均衡配置(可选)
默认情况下,Keepalived 主要关注的是 VIP 的高可用性,它将监控 VIP 所在的服务器状态,并在主服务器发生故障时将 VIP 转移到备份服务器上。
例:将keeplived部署在nginx上,设置脚本监控nginx进程状态,由keeplived提供vip对外提供服务,同时保障nginx的高可用性(故障飘移),由nginx提供转发和负载均衡功能。
不过Keepalived 也支持负载均衡功能,将请求分发到后端的多个服务器上,通过配置 virtual_server,Keepalived 将负责接收请求,并根据负载均衡算法将请求转发到后端服务器上,以实现负载均衡和高可用性。
例:机器上单独部署keeplived,并配置后端,如tomcat,keeplived提供vip对外服务,对内负责转发请求与负载均衡,tomcat则是实际的服务程序。
virtual_server 192.168.200.100 443 { #VIP地址,可以是IP+PORT;也可以是fwmark 数字,也就是防火墙规则,要和vrrp_instance模块中的virtual_ipaddress地址一致 delay_loop 6 #健康检查时间间隔,单位秒 lb_algo rr #指定lvs负载均衡算法:rr(轮询)|wrr(加权轮询)|lc(最少连接)|wlc|lblc|sh|dh lb_kind NAT #指定lvs负载均衡的类型,可以是 NAT、DR 或 TUN persistence_timeout 50 #持久会话的超时时间(以秒为单位) protocol TCP #虚拟服务器使用的协议,例如 TCP 或 UDP real_server 192.168.201.100 443 { #后端实际服务器的 IP 地址 weight 1 #权重,用于加权轮询负载均衡算法 TCP_CHECK { #TCP健康检查(常用) connect_port 443 #健康检查的端口,默认为real_server定义的端口 bindto 192.168.201.100 #健康检查的ip,默认为real_server定义的ip connect_timeout 3 #连接超时时间,单位秒 nb_get_retry 3 #重试次数 delay_before_retry 3 #重试延迟:在重试前等待 3 秒 } HTTP_GET { #健康检查方法(不常用) url { #检测url path /testurl/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d #检测内容的哈希值 } url { path /testurl2/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl3/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.200.3 1358 { ... } }
VRRP脚本(可选)
适用于自定义脚本来检测服务或资源状态的场景,可以根据脚本的执行结果来决定实例的状态切换。
注:如果脚本中涉及到weight的配置,同时又关闭了抢占模式时,脚本中应添加杀掉keepalived进程的方式。因为当检测到后端进程出现问题,priority变动时,因关闭了抢占模式,即使本机priority值比其他实例低,仍然不会发生主备切换。
vrrp_script check_web_server { #定义脚本模块名称 script "/usr/local/bin/check_web_server.sh" #脚本路径;也可以是具体的命令,命令用绝对路径 interval 2 #每隔2秒执行一次 weight 2 #权重,如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加,如果脚本执行结果非0,并且weight配置的值小于0,则优先级相应的减少,其他情况,维持原本配置的优先级 fall 2 #连续失败次数达到2时,将视为脚本执行结果为非 0 } vrrp_instance VI_1 { ... track_script { check_web_server #使用定义好的脚本模块 } ... notify_master "/path/to/script.sh <group_name> master" #在切换到 Master 角色时执行的脚本或命令,如启动nginx notify_backup "/path/to/script.sh <group_name> backup" #在切换到 Backup 角色时执行的脚本或命令 notify_fault "/path/to/script.sh <group_name> fault" #在发生故障时执行的脚本或命令 }
三、Keepalived 高可用集群脑裂问题
脑裂是指由于网络故障或其他原因导致 Keepalived 实例之间无法正常通信,从而导致多个实例同时认为自己是主节点,进而导致资源冲突和服务中断的情况。
脑裂可能发生的原因包括:
- 网络分区:网络分区是指由于网络故障或配置错误,导致 Keepalived 实例之间无法通信,从而使它们无法达成一致的状态。
- 通信延迟:在高延迟或拥塞的网络环境中,Keepalived 实例之间的通信可能存在延迟,这可能导致实例之间无法及时达成一致。
- 服务器上开启了 iptables 防火墙,阻挡了心跳消息传输。
注意:Keepalived 配置里同一 VRRP 实例如果 virtual_router_id 参数两端配置不一致,也会导致脑裂问题发生。
为了解决脑裂问题,可以采取以下措施:
- 心跳检测:使用可靠的心跳机制进行实例之间的健康状态检测。这可以包括基于网络连接或专用的心跳通道进行通信。如果一个实例无法与其他实例正常通信,它将认为其他实例已经失去联系,并采取适当的动作。
- 投票机制:通过引入投票机制,实例之间可以基于多数原则来决定主节点。这可以减少单点故障和脑裂问题的发生。例如,在 VRRP 中,多个实例之间通过优先级和预选主节点来决定主备角色的切换。
- 多个监控点:在不同的子网或物理位置设置多个监控点,以减少网络分区的风险。这样,即使一个监控点无法与其他实例通信,其他监控点仍然可以维持正常的通信和状态同步。
示例:检测节点间通信异常并关闭失去联系的节点的 Keepalived 进程
#!/bin/bash # 检测节点间通信异常并关闭失去联系的节点的 Keepalived 进程的函数 check_communication() { # 获取当前节点的主备状态 local state=$(keepalived --check-state) # 获取当前节点的通信接口 local interface="eth0" # 替换为实际的通信接口 # 获取当前节点的虚拟路由器ID local vrid=51 # 替换为实际的虚拟路由器ID # 获取其他节点的IP地址列表,替换为实际的IP地址 local other_nodes=("192.168.0.2" "192.168.0.3" "192.168.0.4") # 遍历其他节点,检测与每个节点的通信状态 for node in "${other_nodes[@]}"; do # 使用 ping 命令检测与其他节点的通信 if ! ping -c 3 -I $interface -W 1 $node > /dev/null 2>&1; then echo "Communication with node $node is lost. Taking corrective action..." # 关闭失去联系节点的 Keepalived 进程 killall keepalived # 删除失去联系节点的状态文件,以便后续重新启动 Keepalived rm -f /var/run/keepalived/vrrp_${vrid}_${node}.state fi done } # 主程序 main() { while true; do # 检测节点间通信异常并关闭失去联系的节点的 Keepalived 进程 check_communication # 等待一段时间后再次检测,可以根据实际情况调整等待时间 sleep 5 done } # 执行主程序 main
四、主备,双主,多主
4.1 主备
一般情况下,用的是主备结构,平常由master节点提供服务,backup节点做备份,当master节点故障时,vip飘移到backup节点上,将backup节点变成master节点提供服务。
主节点配置(抢占模式):
! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 192.168.1.100 } } virtual_server 192.168.1.100 443 { delay_loop 6 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.1.101 80 { weight 1 TCP_CHECK { connect_port 443 bindto 192.168.1.101 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } HTTP_GET { url { path /testurl/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl2/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl3/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.1.102 80 { weight 1
TCP_CHECK {
connect_port 443
bindto 192.168.1.102
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
备节点配置:
! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 192.168.1.100 } } virtual_server 192.168.1.100 443 { delay_loop 6 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.1.101 80 { weight 1 TCP_CHECK { connect_port 443 bindto 192.168.1.101 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } HTTP_GET { url { path /testurl/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl2/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl3/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.1.102 80 { weight 1 TCP_CHECK { connect_port 443 bindto 192.168.1.102 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }
4.2 双主
在大流量的场景下,所有流量通过一台机器去分发请求,很容易打满机器负载,造成请求延时,甚至机器宕机。所以,keepalived还支持双主,多主的形式,让多台机器负载流量,减少性能损耗的同时还保证其高可用性。
双主即集群有两个主节点,共同向外提供服务,每个主节点有一个vip,如果一个主节点故障,流量会全部切换到另一个主节点上。多主模式也是相同原理。
配置: vrrp_instance 模块配置两个vrrp实例,互为主备。
主节点1:
vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass mypassword } virtual_ipaddress { 192.168.0.100 } } vrrp_instance VI_2 { state BACLUP interface eth0 virtual_router_id 52 priority 90 advert_int 1 authentication { auth_type PASS auth_pass mypassword } virtual_ipaddress { 192.168.0.101 } }
主节点2:
vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 90 advert_int 1 authentication { auth_type PASS auth_pass mypassword } virtual_ipaddress { 192.168.0.100 } } vrrp_instance VI_2 { state MASTER interface eth0 virtual_router_id 52 priority 100 advert_int 1 authentication { auth_type PASS auth_pass mypassword } virtual_ipaddress { 192.168.0.101 } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?