目录
- keepalived
- HA简介
- 常用的高可用软件
- keepalived简介
- keepalived常用模块
- keepalived功能简介
- keepalived常用文件
- keepalived配置文件详解
- keepalived实验1-上手
- 环境准备
- 安装服务
- 主配置文件修改
- 启动服务
- 效果查看
- keepalived脑裂
- 1. 脑裂现象简介
- 2. 脑裂的原因
- 3. 脑裂的预防和解决方案
- 4. 脑裂的处理流程
- keepalived实验2-nginx+keepalived联动
- 编写脚本,检测到nginx down,关闭keepalived服务使主备切换
- 测试脚本
- 修改keepalived配置脚本,使其调用
- 验证
- keepalived 非抢占&延迟抢占
- 不抢占
- 延迟抢占
- keepalived 双主模式
- keeplived 通知脚本
- 语法
- 脚本
- 脚本解释
- 脚本增加x权限并修改keepalived配置文件
- 测试
keepalived
官网:http://keepalived.org/
官方文档:https://keepalived.org/doc/
官方文档:http://keepalived.org/documentation.html
HA简介
高可用,即HA,是指系统或服务能够在大部分时间内保持可用状态的能力。高可用性的设计目标是确保系统在面对硬件故障、软件错误、网络问题或其他意外情况时,能够持续提供服务而不中断或降低性能。
常用的高可用软件
- heartbeat
- keepalived(本文核心)
- HAproxy
keepalived简介
keepalived是基于vrrp协议改进出的一种用于Linux主机上的高可用软件,用于进行L4的负载均衡(ipvs)。
keepalived的检查原理即vrrp协议是数通的一个常用协议,用于热备路由器,若主路由器宕机,备份路由器自动接管业务,无需修改配置
,本文不过多赘述,可期待我后续文章或自行查阅别的文档。
keepalived为vip地址所在的节点生成ipvs规则(在配置文件中预先定义),为ipvs集群的各RS做健康状态检测
keeplived支持基于脚本调用接口完成脚本中定义的功能,进而影响集群事务,以此支持nginx、haproxy等服务
分为主,备一般是2个节点.主备之间通过vrrp协议发送数据包沟通.
主给备定期发送数据包,备收到数据包表示主还活着,备无法收到数据包,表示主挂了,备胎转正了,接管用户请求流量.
vrrp协议使用组播的ip. 224.xx.xx.xx(可修改)
keepalived常用模块
官方文档:https://keepalived.org/doc/software_design.html
- 核心模块包含:
- LVS Framework: Uses the getsockopt and setsockopt calls to get and set options on sockets.
- Netfilter Framework: IPVS code that supports NAT and Masquerading
- Netlink Interface: Sets and removes VRRP virtual IPs on network interfaces.
- Multicast: VRRP advertisements are sent to the reserved VRRP MULTICAST group (224.0.0.18).
- Core:是keepalived的核心,负责主进程的启动和维护,全局配置文件的加载解析等 。
- Check:负责healthchecker(健康检查),包括了各种健康检查方式,以及对应的配置的解析包括LVS的配置解析;
- Vrrp:VRRPD子进程,VRRPD子进程就是来实现VRRP协议;
- Libipfwc:iptables(ipchains)库,配置LVS会用到;
- Libipvs:虚拟服务集群,配置LVS会使用。
keepalived功能简介
- 提供负载均衡:以vip(虚拟ip)进行工作,提供L4的负载均衡(但实际是主备架构)
- 检测服务器状态:定时检查服务器状态,不正常时自动启用备份服务器
keepalived常用文件
- 主配置文件:/etc/keepalived/keepalived.conf
- 主程序文件:/etc/sysconfig/keepalived
/usr/sbin/keepalived - 日志文件(keeplived没有自己的日志文件):/var/log/messages
keepalived配置文件详解
配置文件keepalived.conf可以包含三个文本块:
全局定义块
、VRRP实例定义块
及虚拟服务器定义块
。全局定义块
和虚拟服务器
定义块是必须
的,如果在只有一个
负载均衡器的场合,就不须VRRP实例定义块
。
- Global definitions(全局配置):定义邮件配置,route_id,vrrp配置,组播地址 等
- VRRP instance(s):定义vrrp协议中的每个vrrp虚拟路由器的规则,基本信息,vrrp协议配置,vip,主备,网卡…
经常改动
部分. - Virtual server(s):LVS集群的VS和RS
[全局定义块]
global_defs {
notification_email { # 指定keepalived在发生切换时需要发送email到的对象,一行一个;
xxx@yyy.com
}
notification_email_from root@localhost # 指定发件人
smtp_server 127.0.0.1 # 指定smtp服务器地址
smtp_connect_timeout 3 # 指定smtp连接超时时间
router_id LVS_DEVEL # 运行keepalived机器的标识
}
[监控Nginx进程]
vrrp_script chk_nginx {
script "/server/script/nginx.sh" # 监控服务脚本,脚本需要有x执行权限;
interval 2 # 检测时间间隔(执行脚本间隔)
weight 1 # 权重
user root # 执行脚本的用户
}
[VRRP实例定义块]
vrrp_sync_group VG_1{ # 监控多个网段的实例
group {
VI_1 # 实例名1
VI_2
}
notify_master /data/sh/nginx.sh # 指定当切换到master时,执行的脚本
notify_backup /data/sh/nginx.sh # 指定当切换到backup时,执行的脚本
notify /data/sh/nginx.sh # 发生任何切换,均执行的脚本
smtp_alert # 使用global_defs中提供的邮件地址和smtp服务器发送邮件通知;
}
vrrp_instance VI_1 {
state BACKUP # 设置主机状态,MASTER|BACKUP
nopreempt # 设置为不抢占
interface ens33 # 对外提供服务的网络接口
lvs_sync_daemon_inteface ens33 # 负载均衡器之间监控接口;
track_interface { # 设置额外的监控,网卡出现问题都会切换;
ens33
ens37
}
mcast_src_ip # 发送组播包的地址,如果不设置默认使用绑定网卡的primary ip
garp_master_delay # 在切换到master状态后,延迟进行gratuitous ARP请求
virtual_router_id 50 # VRID标记 ,路由ID,可通过#tcpdump vrrp查看
priority 90 # 优先级,优先级高者竞选为master
advert_int 5 # 检查间隔,默认5秒
preempt_delay # 抢占延时,默认5分钟
debug # debug日志级别
authentication { # 设置认证
auth_type PASS # 认证方式
auth_pass 1111 # 认证密码
}
track_script { # 以脚本为监控chk_nginx;
chk_nginx
}
virtual_ipaddress { # 设置vip地址
192.168.111.188
}
}
注意:使用了脚本监控Nginx或者MYSQL,不需要下面虚拟服务器设置块。
[虚拟服务器定义块]
virtual_server 192.168.111.188 3306 {
delay_loop 6 # 健康检查时间间隔
lb_algo rr # 调度算法rr|wrr|lc|wlc|lblc|sh|dh
lb_kind DR # 负载均衡转发规则NAT|DR|TUN
persistence_timeout 5 # 会话保持时间
protocol TCP # 使用的协议
real_server 192.168.1.12 3306 {
weight 1 # 默认为1,0为失效
notify_up <string> | <quoted-string> # 在检测到server up后执行脚本;
notify_down <string> | <quoted-string> # 在检测到server down后执行脚本;
TCP_CHECK {
connect_timeout 3 # 连接超时时间;
nb_get_retry 1 # 重连次数;
delay_before_retry 1 # 重连间隔时间;
connect_port 3306 # 健康检查的端口;
}
HTTP_GET {
url {
path /index.html # 检测url,可写多个
digest 24326582a86bee478bac72d5af25089e # 检测效验码
# digest效验码获取方法:genhash -s IP -p 80 -u http://IP/index.html
status_code 200 # 检测返回http状态码
}
}
}
不过上述完整脚本非常复杂,实际上简单实用仅需以下内容即可:
[root@lb01 scripts]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id lb01 # 所有keepalived集群中router_id唯一
}
vrrp_instance VRRP_55 { # 实例名相同的在一个vrrp实例组中
state MASTER # 只有一个master,可以有多个BACKUP
interface ens33 # 使用的网口
virtual_router_id 55 # vrrp id
priority 100 # 优先级,越高越优先
advert_int 1 # vrrp通告报文间隔1s
authentication { # 认证模块
auth_type PASS # 是否认证
auth_pass 5555 # 认证密码
}
virtual_ipaddress { # 该vrrp实例的vip
192.168.100.55 dev ens33 label ens33:0
}
}
keepalived实验1-上手
环境准备
lb01 nginx+keeplived
lb02 (克隆lb01)
安装服务
rpm -qa | grep keepalived
yum install -y keepalived
主配置文件修改
具体的主配置文件参数,见上文
配置详解
启动服务
# 关闭防火墙和selinux,不然会导致脑裂
systemctl stop firewalld
setenforce 0
systemctl start keeplived
效果查看
-
vip
-
抓包
keepalived脑裂
1. 脑裂现象简介
脑裂是指在多节点系统中,由于网络问题、节点故障或其他原因导致系统中的多个节点同时认为自己是活动的,从而产生数据不一致或服务中断的现象。在分布式系统中,脑裂是一个严重的问题,可能导致数据丢失或损坏,服务不可用,甚至系统崩溃。
在keeplived中,即主备均有vip
2. 脑裂的原因
脑裂通常由以下原因引起:
- 时钟同步问题:节点间的时间不一致可能导致节点对系统状态的理解产生分歧。
- 配置错误:不当的配置可能导致节点无法正确判断其他节点的状态。
- 节点故障:节点的硬件故障或软件异常可能导致节点行为异常。
- 防火墙:selinux和防火墙默认不放行vrrp流量,需要进行放行流量或关闭。
3. 脑裂的预防和解决方案
为了预防和解决脑裂问题,可以采取以下措施:
- 心跳检测:节点之间通过定期发送心跳消息来监控彼此的状态,一旦发现某个节点失联,可以及时采取措施。
- 时钟同步:使用NTP(网络时间协议)或其他同步机制来确保节点间的时间一致性。
- 监控和报警:实时监控系统的状态,一旦发现异常立即报警并采取措施。
可以考虑只要BACKUP上出现vip,就让MASTER下线(非常粗暴的解决方式)
4. 脑裂的处理流程
当系统发生脑裂时,可以按照以下步骤进行处理:
- 检测脑裂:通过监控系统或日志分析,发现节点间通信异常。
- 隔离问题节点:将问题节点从服务中隔离,避免其继续影响系统状态。
- 故障排查:分析脑裂的原因,修复网络或配置问题。
keepalived实验2-nginx+keepalived联动
需求:在nginx服务down时,自动触发keepalived主备切换
keepalived是主机down才会切换,默认不会监控某个服务
可以修改主配置文件,增加脚本监控
编写脚本,检测到nginx down,关闭keepalived服务使主备切换
[root@lb01 scripts]# cat check_ngx.sh
#!/bin/bash
# 脚本用于检测nginx的进程是否等于0,nginx没有进程时就关闭keepalived服务
# 注意: 脚本名.sh不要写全服务名,不然在过滤进程时会将脚本过滤出来,导致出现错误
count=`ss -tunlp | grep nginx | wc -l`
echo "ngx 端口数量 $count"
# -eq用于数值的比较,==用于字符串的比较;-ne不等于
if [ ${count} -eq 0 ]; then
systemctl stop keepalived
fi
测试脚本
- nginx存在
[root@lb01 scripts]# sh check_ngx.sh
ngx 端口数量 1
[root@lb01 scripts]# systemctl status keepalived.service
Active: active (running) since Tue 2024-06-18 11:18:08 CST; 17min ago
- nginx不存在
[root@lb01 scripts]# pkill nginx
[root@lb01 scripts]# sh check_ngx.sh
ngx 端口数量 0
[root@lb01 scripts]# systemctl status keepalived.service
Active: inactive (dead)
# 查看日志
[root@lb01 scripts]# tail -10 /var/log/messages
Jun 18 11:35:41 lb01 systemd[1]: nginx.service: Failed with result 'exit-code'.
Jun 18 11:35:44 lb01 systemd[1]: Stopping LVS and VRRP High Availability Monitor...
Jun 18 11:35:44 lb01 Keepalived[19322]: Stopping
Jun 18 11:35:45 lb01 Keepalived_vrrp[19323]: (VRRP_55) sent 0 priority
Jun 18 11:35:45 lb01 Keepalived_vrrp[19323]: (VRRP_55) removing VIPs.
Jun 18 11:35:46 lb01 Keepalived_vrrp[19323]: Stopped - used 0.001242 user time, 0.161294 system time
Jun 18 11:35:46 lb01 Keepalived[19322]: CPU usage (self/children) user: 0.001348/0.001242 system: 0.000000/0.162545
Jun 18 11:35:46 lb01 Keepalived[19322]: Stopped Keepalived v2.1.5 (07/13,2020)
Jun 18 11:35:46 lb01 systemd[1]: keepalived.service: Succeeded.
Jun 18 11:35:46 lb01 systemd[1]: Stopped LVS and VRRP High Availability Monitor.
修改keepalived配置脚本,使其调用
# 脚本增加x权限
[root@lb01 scripts]# chmod +x check_ngx.sh
[root@lb01 scripts]# ll
total 4
-rwxr-xr-x 1 root root 144 Jun 16 09:52 check_ngx.sh
# 修改keepalived配置文件
[root@lb01 scripts]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id lb01
}
# 添加以下内容,定义vrrp脚本
vrrp_script check_ngx { # 脚本名,用于在vrrp_instance中调用
script /server/scripts/check_ngx.sh # 指定的运行脚本,需要x权限
interval 2 # 检测间隔2s
weight 1 # 权重1
user root # 执行脚本的用户为root
}
vrrp_instance VRRP_55 {
state MASTER
interface ens33
virtual_router_id 55
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 5555
}
virtual_ipaddress {
192.168.100.55 dev ens33 label ens33:0
}
track_script { # 调用上述vrrp脚本
check_ngx # 即上面定义的名字
}
}
# 重启服务
[root@lb01 scripts]# systemctl restart keepalived.service
验证
# 直接kill nginx,不用执行脚本,keepalived自动检测,并关闭自身
[root@lb01 scripts]# pkill nginx
[root@lb01 scripts]# tail -5 /var/log/messages
Jun 18 11:50:21 lb01 Keepalived_vrrp[21044]: Stopped - used 0.000000 user time, 0.026432 system time
Jun 18 11:50:21 lb01 Keepalived[21043]: CPU usage (self/children) user: 0.001334/0.090439 system: 0.000000/0.265936
Jun 18 11:50:21 lb01 Keepalived[21043]: Stopped Keepalived v2.1.5 (07/13,2020)
Jun 18 11:50:21 lb01 systemd[1]: keepalived.service: Succeeded.
Jun 18 11:50:21 lb01 systemd[1]: Stopped LVS and VRRP High Availability Monitor.
[root@lb01 scripts]# systemctl status keepalived.service
Active: inactive (dead)
# 现在vip出现在lb02即BACKUP上
[root@lb02 ~]# ip a | grep 100.55
inet 192.168.100.55/32 scope global ens33:0
# 即使手动拉起lb01的keepalived,若没有在lb01上启动nginx,keepalived仍然会自动关闭
keepalived 非抢占&延迟抢占
keepalived默认是抢占模式,即MASTER活了之后会抢夺vip的控制权
如果在动荡网络中,一直抢占与被抢占,会导致业务不稳定
所以可以考虑修改为不抢占
,延迟抢占
不抢占
- 修改流程:
- 两个节点均为BACKUP
- 两个节点都增加一行
nopreempt
延迟抢占
- 修改流程:
- 两个节点均为BACKUP
- 仅其中一台增加一行
preempt_delay 30
keepalived 双主模式
即两个vrrp实例,类似于数通中mstp+vrrp
实验。
keeplived 通知脚本
具体的配置邮件分发,请参考我之前的博客如何使用openEuler 22.03 配置mail.rc给邮箱发送邮件
语法
事件 | 脚本参数 |
---|---|
当前节点成为主节点时触发的脚本 | `notify_master |
当前节点转为备节点时触发的脚本 | `notify_backup |
当前节点转为“失败”状态时触发的脚本 | `notify_fault |
通用格式的通知触发机制 | `notify |
当停止VRRP时触发的脚本 | `notify_stop |
脚本
#!/bin/bash
#
contact='xxx@qq.com'
notify() {
mailsubject="$(hostname) to be $1, vip floating"
mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
echo "$mailbody" | mail -s "$mailsubject" $contact
}
case $1 in
master)
notify master
;;
backup)
notify backup
;;
fault)
notify fault
;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"
exit 1
;;
esac
脚本解释
联系邮箱
:contact=‘xxx@qq.com’,这行代码设置了接收通知的电子邮件地址。在实际使用中,应该替换为真实的邮箱地址。notify 函数
:这个函数用于发送电子邮件。它接受一个参数,表示Keepalived的新状态(master、backup 或 fault)。函数内部,它构建了邮件的主题和正-文,并使用 mail 命令将通知发送到指定的邮箱。mailsubject
:邮件主题,包含了主机名和新状态的信息。mailbody
:邮件正文,包含了变化发生的时间和主机名以及状态变化的信息。case 语句
:这是一个选择语句,根据脚本接收的第一个参数($1)来执行不同的操作。master
:如果参数是 master,则调用 notify 函数并传入 master 参数,表示主机成为主节点。backup
:如果参数是 backup,则调用 notify 函数并传入 backup 参数,表示主机成为备节点。fault
:如果参数是 fault,则调用 notify 函数并传入 fault 参数,表示主机状态变为故障。*
:如果参数不是以上任何一个,脚本会输出一条使用帮助信息,并退出脚本,返回码为1。
脚本增加x权限并修改keepalived配置文件
chmod +x malikl.sh
# vrrp_instance中添加
[root@lb01 scripts]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id lb01
}
vrrp_script check_ngx {
script /server/scripts/check_ngx.sh
interval 2
weight 1
user root
}
vrrp_instance VRRP_55 {
state MASTER
interface ens33
virtual_router_id 55
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 5555
}
virtual_ipaddress {
192.168.100.55 dev ens33 label ens33:0
}
# 添加以下3行
notify_master "/server/scripts/mailkl.sh master"
notify_backup "/server/scripts/malikl.sh backup"
notify_fault "/server/scripts/malikl.sh fault"
track_script {
check_ngx
}
}
测试
[root@lb01 scripts]# systemctl restart keepalived.service
检测到keepalived服务变化时,自动发送邮件