keepalived 实现高可用负载均衡(与LVS和nginx联动)
一、keepalived 相关知识点概要
1. 单服务的风险
单服务风险即单点故障问题,一般在说,在企业应用中,只使用单台服务器承单应用,如果发生单点故障,企业服务就将会发生中断,会造成极大的损失和危害
所以,一般情况下,都会通过负载均衡策略避免单服务
2. 一个合格的集群应该具备的特性
- 负载均衡:通过使用软件类,LVS;Nginx;HAProxy 或硬件类 F5 等
- 健康检查:for 调度器/节点服务器;Keepalived;Heartbeat
- 故障转移:主备切换
3. VRRP 虚拟路由冗余协议
虚拟路由冗余协议(Virtual Router Redundancy Protocol,简称VRRP)是一种路由容错协议,也可以叫做备份路由协议
VRRP可以将两台或者多台物理路由器设备虚拟成一个虚拟路由,这个虚拟路由器通过虚拟IP对外提供服务,而在虚拟路由器内部有多个物理路由器协同工作,同一时间只有一台物理路由器对外提供服务,这台物理路由设备被设置成为:主路由器(Master角色),一般情况下Master是由选举算法产生,它拥有对外服务的虚拟IP,提供各种网络功能,而且其它的物理路由器不拥有对外的虚拟IP,也不提供对外网络功能,仅仅接收MASTER的VRRP状态通告信息,这些路由器被统称为"BACKUP的角色",当主路由器失败时,处于BACKUP角色的备份路由器将重新进行选举,产生一个新的主路由器进入MASTER角色,继续提供对外服务,这种选举角色切换非常之快,因而保证了服务的持续可用性。
简单概述:
- VRRP(虚拟路由冗余协议) 是针对路由器的一种备份解决方案
- 由多台路由器组成一个热备组,通过共用的虚拟IP地址对外提供服务
- 每个热备组内同时只有一台主路由器提供服务,其他路由器处于冗余状态
- 若当前在线的路由器失效,则其他路由器会根据设置的优先级自动接替虚拟IP地址,继续提供服务
4. 健康检查(探针)
健康检查,别名探针,用于监测和评估系统或应用程序的健康状态。它们会定期发送请求到目标系统,并根据返回的响应来确定系统是否正常运行。健康检查探针可以检测到网络连接问题、服务器故障、数据库故障等各种常见的故障情况,并及时通知管理员采取相应的措施。通过使用健康检查探针,可以提高系统的可用性和稳定性,确保用户正常的使用体验。
简单说就是:
-
发送心跳消息 ping/pang
-
TCP端口检查 向一个主机的IP:PORT 发起TCP连接
-
HTTP URL 检查 向一个主机的 http://IP:PORT/URL路径 发送HTTP GET请求方法,主机响应返回
2XX
3XX
状态码则认为健康检查正常,如响应返回4XX
5XX
状态码则认为健康检查异常 -
数据库连接检查:对于依赖数据库的应用程序,可以通过尝试连接数据库来检查健康状态。如果连接成功,表示数据库正常。
-
日志检查:通过分析系统日志或应用程序日志,检查是否存在异常日志,来判断系统的健康状态。
检查服务器 | 作用 |
---|---|
节点服务器 | 如果发现有故障的节点就会将其隔离或者剔除集群,待其恢复 |
负载均衡器 | 会定时检查主服务器的状态(包括主机和服务的状态),如果主服务器故障就自动切换到备服务器上,待主服务器恢复后再重新让主服务器去承载业务请求 |
5. "脑裂"现象
5.1 "脑裂"的定义
通常情况下,VIP是漂浮的,基于vrrp协议,只会漂浮在主服务器上,只有主服务器产生故障的时候,才会漂浮到备服务器上,即新的主服务器,一般VIP只有主服务拥有
所以主备服务器同时拥有VIP就是脑裂
脑裂现象通常会产生严重的后果,会对系统的稳定性,数据一致性和业务可靠性产生严重的影响
-
数据不一致性:
脑裂可能导致分布式系统或计算集群中的不同节点之间的数据不一致。当节点无法相互通信或同步时,数据可能会在节点之间发生冲突或不同步,导致数据的不一致性。这可能会造成系统行为的不确定性和错误的结果。
-
冲突和竞争条件:
在脑裂出现的情况下,不同节点可能会尝试独立执行相同或相互依赖的操作,这可能导致冲突和竞争条件的发生。例如,多个节点同时尝试写入同一份数据,可能会导致数据丢失或数据覆盖的问题。
-
服务中断和响应延迟:
当脑裂现象发生时,受影响的节点可能无法提供正常的服务或响应请求,这可能导致服务中断和延迟。这对于依赖这些节点提供关键服务的应用程序或系统来说,可能会对业务造成严重影响。
-
故障恢复困难:
在脑裂发生后,当节点再次恢复通信时,可能会面临故障恢复困难的问题。这是因为数据的不一致性和冲突可能会导致节点之间的状态差异,需要进行复杂的故障恢复和数据同步操作。
5.2 "脑裂"现象产生的原因和解决方法
一般来说,"脑裂"现象产生的原因是
主备服务器之间的通信链路中断,导致备服务器无法正常收到主服务器发送的VRRP心跳报文;
所以对应的解决方法其实比较简单
只需要关闭主服务器或者备服务器其中一个的keepalived服务既可解决"脑裂"现象
5.3 如何预防"脑裂"现象
- 主服务器与备服务器之间添加双通信链路;
- 在主服务器上定义运行脚本判断与备服务器通信链路是否中断,如果中断则自行关闭keepalived服务;
- 利用第三方监控软件检测是否发生脑裂故障,如果发生则通过监控软件关闭主或者备服务器上的keepalived服务。
二、keepalived
官方网站:www.keepalived.org/
1. keepalived 的概念
Keepalived是Linux下一个轻量级别的高可用解决方案,可以实现服务的高可用或热备,用来防止单点故障的问题
Keepalived起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态,它根据TCP/IP参考模型的第三、第四层、第五层交换机制检测每个服务节点的状态,如果某个服务器节点出现异常,或者工作出现故障,Keepalived将检测到,并将出现的故障的服务器节点从集群系统中剔除,这些工作全部是自动完成的,不需要人工干涉。
Keepalived的核心是VRRP协议,支持故障自动切换(Failover), 支持节点健康状态检查(Health Checking)
当master主机出现故障时,及时切换到backup节点保证业务正常,当master故障主机恢复后将其重新加入群集并且业务重新切换回master节点
所以 keepalived 的实现原理就是基于VRRP协议的
2. Keepalived体系主要模块及其作用
Keepalived的主要模块 | 作用 |
---|---|
core模块 | 为Keepalived的核心,负责主进程的启动、维护及全局配置文件的加载和解析 |
vrrp模块 | 是来实现VRRP协议的(调度器之间的健康检查和主备切换) |
check模块 | 负责健康检查,常见的方式有端口检查及URL检查(节点服务器的健康检查) |
3. Keepalived工作原理
两台主备机器通过keepalived,虚拟一个IP,也就是VIP(Virtual IP)。
VIP开始为主机器所有,备份机为空闲状态,同时在两台keepalived之间通信相当于有一条心跳线,通过心跳线互相通信,只要主机器监控(通过脚本)到ngin服务停止,则主机器自己停止keepalived,将VIP交给备份机器处理web请求,直至主机器再次恢复正常,将VIP返还给主机器。
4. keepalived如何实现故障切换?
在一个LVS服务集群中通常有主服务器(MASTER)和备份服务器(BACKUP)两种角色的服务器
但是对外表现为一个虚拟IP(VIP)。
主服务器会发送VRRP通告信息给备份服务器,当备份服务器收不到VRRP消息的时候,即主服务器异常的时候
备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性
5. 抢占模式和非抢占模式的区别
抢占模式即MASTER从故障中恢复后,会将VIP从BACKUP节点中抢占过来。
非抢占模式即MASTER恢复后不抢占BACKUP升级为MASTER后的VIP。
非抢占式俩节点state必须为bakcup,且必须配置nopreempt。
注意:这样配置后,我们要注意启动服务的顺序,优先启动的获取master权限,与优先级没有关系了。
6. Keepalived通过什么判断哪台主机为主服务器,通过什么方式配置浮动IP
Keepalived首先做初始化先检查state状态,master为主服务器,backup为备服务器。
然后再对比所有服务器的priority,谁的优先级高谁是最终的主服务器。
优先级高的服务器会通过ip命令为自己的电脑配置一个提前定义好的浮动IP地址。
二、keepalived + LVS 高可用集群
名称 | IP地址 |
---|---|
LVS-Master | 192.168.1.10 |
LVS-Backup | 192.168.1.20 |
Web-A | 192.168.1.30 |
Web-B | 192.168.1.40 |
VIP | 192.168.1.188 |
Client | 192.168.1.50 |
1. LVS-Master 服务器配置
192.168.1.10
bash
#关闭防火墙
systemctl disable firewalld.service --now
setenforce 0
#安装keepalived
yum -y install ipvsadm keepalived
#加载ip_vs内核模块
modprobe ip_vs
cat /proc/net/ip_vs
#修改主服务器配置文件
###先备份配置文件
cd /etc/keepalived/
cp keepalived.conf keepalived.conf.bak
#编辑配置文件
vim keepalived.conf
......
global_defs { #定义全局参数
--10行--修改,邮件服务指向本地
smtp_server 127.0.0.1
--12行--修改,指定服务器(路由器)的名称,主备服务器名称须不同,主为LVS_01,备为LVS_02
router_id LVS_01
--14行--注释掉,取消严格遵守VRRP协议功能,否则VIP无法被连接
#vrrp_strict
}
vrrp_instance VI_1 { #定义VRRP热备实例参数
--20行--修改,指定热备状态,主为MASTER,备为BACKUP
state MASTER
--21行--修改,指定承载vip地址的物理接口
interface ens33
--22行--修改,指定虚拟路由器的ID号,每个热备组保持一致
virtual_router_id 10
#nopreempt #如果设置非抢占模式,两个节点state必须为BACKUP,并加上配置 nopreempt
--23行--修改,指定优先级,数值越大优先级越高,这里设置主为100,备为90
priority 100
advert_int 1 #通告间隔秒数(心跳频率)
authentication { #定义认证信息,每个热备组保持一致
auth_type PASS #认证类型
--27行--修改,指定验证密码,主备服务器保持一致
auth_pass abc123
}
virtual_ipaddress { #指定群集vip地址
192.168.1.188
}
}
--36行--修改,指定虚拟服务器地址(VIP)、端口,定义虚拟服务器和Web服务器池参数
virtual_server 192.168.1.188 80 {
delay_loop 6 #健康检查的间隔时间(秒)
lb_algo rr #指定调度算法,轮询(rr)
--39行--修改,指定群集工作模式,直接路由(DR)
lb_kind DR
persistence_timeout 0 #连接保持时间(秒)
protocol TCP #应用服务采用的是 TCP协议
--43行--修改,指定第一个Web节点的地址、端口
real_server 192.168.1.30 80 {
weight 1 #节点的权重
--45行--删除,添加以下健康检查方式
TCP_CHECK {
connect_port 80 #添加检查的目标端口
connect_timeout 3 #添加连接超时(秒)
nb_get_retry 3 #添加重试次数
delay_before_retry 3 #添加重试间隔
}
}
real_server 192.168.1.40 80 { #添加第二个 Web节点的地址、端口
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
##删除后面多余的配置##
}
#保存退出后,启动服务、查看虚拟网卡vip
systemctl start keepalived
ip a
#调整proc响应参数,关闭Linux内核的重定向参数响应
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.ens33.send_redirects = 0
#刷新一下
sysctl -p
#配置负载分配策略,并启动服务
ipvsadm-save >/etc/sysconfig/ipvsadm
systemctl start ipvsadm.service
#清空ipvsadm,并做策略
ipvsadm -C
ipvsadm -A -t 192.168.1.188:80 -s rr
ipvsadm -a -t 192.168.1.188:80 -r 192.168.1.30:80 -g
ipvsadm -a -t 192.168.1.188:80 -r 192.168.1.40:80 -g
#保存设置
ipvsadm
ipvsadm -ln
ipvsadm-save >/etc/sysconfig/ipvsadm
##注意,如果ipvsadm -ln,没有查看到VIP的分布策略,需要重启keepalived 服务,systemctl restart keepalived
2. LVS-Backup 服务器配置
192.168.1.20
keepalived 备用服务器的配置与主服务器基本相同,只需要注意服务器名称,热备状态和优先级即可
bash
##与主服务器类似
#关闭防火墙
systemctl stop firewalld.service
setenforce 0
#安装服务
yum install ipvsadm -y
yum install keepalived -y
#修改配置文件keeplived.conf
cd /etc/keepalived/
cp keepalived.conf keepalived.conf.bak #备份配置文件
vim keepalived.conf
#编辑配置文件
......
global_defs { #定义全局参数
--10行--修改,邮件服务指向本地
smtp_server 127.0.0.1
--12行--修改,指定服务器(路由器)的名称,主备服务器名称须不同,主为LVS_01,备为LVS_02
router_id LVS_02
}
vrrp_instance VI_1 { #定义VRRP热备实例参数
--20行--修改,指定热备状态,主为MASTER,备为BACKUP
state BACKUP
--21行--修改,指定承载vip地址的物理接口
interface ens33
--22行--修改,指定虚拟路由器的ID号,每个热备组保持一致
virtual_router_id 10
--23行--修改,指定优先级,数值越大优先级越高,主为100,备为90
priority 90
advert_int 1 #通告间隔秒数(心跳频率)
authentication { #定义认证信息,每个热备组保持一致
auth_type PASS #认证类型
--27行--修改,指定验证密码,主备服务器保持一致
auth_pass 123123
}
virtual_ipaddress { #指定群集vip地址
192.168.1.188
}
}
--36行--修改,指定虚拟服务器地址(VIP)、端口,定义虚拟服务器和Web服务器池参数
virtual_server 192.168.1.188 80 {
delay_loop 6 #健康检查的间隔时间(秒)
lb_algo rr #指定调度算法,轮询(rr)
--39行--修改,指定群集工作模式,直接路由(DR)
lb_kind DR
persistence_timeout 50 #连接保持时间(秒)
protocol TCP #应用服务采用的是 TCP协议
--43行--修改,指定第一个Web节点的地址、端口
real_server 192.168.1.30 80 {
weight 1 #节点的权重
--45行--删除,添加以下健康检查方式
TCP_CHECK {
connect_port 80 #添加检查的目标端口
connect_timeout 3 #添加连接超时(秒)
nb_get_retry 3 #添加重试次数
delay_before_retry 3 #添加重试间隔
}
}
real_server 192.168.1.40 80 { #添加第二个 Web节点的地址、端口
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
##删除后面多余的配置##
#启动服务、查看虚拟网卡vip
systemctl start keepalived
ip addr show dev ens33
#调整proce响应参数,关闭Linux内核的重定向参数响应
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.ens33.send_redirects = 0
#刷新一下
sysctl -p
############################# 配置ipvsadm #################################
#配置负载分配策略,并启动服务
ipvsadm-save >/etc/sysconfig/ipvsadm
systemctl start ipvsadm.service
#清空ipvsadm,并做策略
ipvsadm -C
ipvsadm -A -t 192.168.1.188 -s rr
ipvsadm -a -t 192.168.1.188:80 -r 192.168.1.20:80 -g
ipvsadm -a -t 192.168.1.188:80 -r 192.168.1.30:80 -g
#保存设置
ipvsadm
ipvsadm -ln
ipvsadm-save >/etc/sysconfig/ipvsadm
##注意,如果ipvsadm -ln,没有查看到VIP的分布策略,需要重启keepalived 服务,systemctl restart keepalived
3. 配置 Web 节点服务器,准备测试页面
- Web-A:192.168.1.30
- Web-B:192.168.1.40
bash
# Web-A 和 Web-B 均需关闭防火墙,安装http服务并启动
systemctl stop firewalld
setenforce 0
yum -y install httpd
systemctl start httpd
#建立测试页
## Web-A
--192.168.1.30---
echo 'this is Web-A 30 web!' > /var/www/html/index.html
#配置虚拟vip
vim /etc/sysconfig/network-scripts/ifcfg-lo:0
DEVICE=lo:0
ONBOOT=yes
IPADDR=192.168.1.188
NETMASK=255.255.255.255
#重启网络服务,开启虚拟网卡
systemctl restart network
ifup lo:0
ifconfig lo:0
#设置路由
route add -host 192.168.1.188 dev lo:0
route -n
#调整 proc 响应参数
#添加系统只响应目的IP为本地IP的ARP请求
#系统不使用原地址来设置ARP请求的源地址,而是物理mac地址上的IP
vim /etc/sysctl.conf
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
//刷新proc参数
sysctl -p
## Web-B
--192.168.1.40---
echo 'this is Web-B 40 web!' > /var/www/html/index.html
#配置虚拟vip
vim /etc/sysconfig/network-scripts/ifcfg-lo:0
DEVICE=lo:0
ONBOOT=yes
IPADDR=192.168.1.188
NETMASK=255.255.255.255
#重启网络服务,开启虚拟网卡
systemctl restart network
ifup lo:0
ifconfig lo:0
#设置路由
route add -host 192.168.1.188 dev lo:0
route -n
#调整 proc 响应参数
#添加系统只响应目的IP为本地IP的ARP请求
#系统不使用原地址来设置ARP请求的源地址,而是物理mac地址上的IP
vim /etc/sysctl.conf
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
//刷新proc参数
sysctl -p
4. 测试结果和验证高可用
在浏览器访问:http://192.168.1.188,观察访问结果
将 LVS-Master 服务的 keepalived 服务关闭,测试高可用
systemctl stop keepalived
三、 nginx + keepalived 高可用集群
名称 | IP地址 |
---|---|
Nginx-Master | 192.168.1.10 |
Nginx-Backup | 192.168.1.20 |
Web-A | 192.168.1.30 |
Web-B | 192.168.1.40 |
VIP | 192.168.1.188 |
Client | 192.168.1.50 |
两台服务器 安装 keepalived 和 nginx 就不做示例了(可以看之前的博客)
1. 编写 nginx 服务监控脚本
bash
#!/bin/bash
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
/usr/local/bin/nginx
sleep 2
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
/etc/init.d/keepalived stop
fi
fi
#检查当前系统中是否有正在运行的nginx进程。
#如果没有正在运行的nginx进程,尝试启动nginx服务,并等待2秒后再次检查nginx进程。
#如果仍然没有nginx进程,则停止keepalived服务。
2. 主备服务器中配置 keepalived
1. 主服务器
192.168.1.10
bash
global_defs {
router_id Nginx_01
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -5
fall 3
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.188
}
track_script {
check_nginx
}
}
2. 备服务器
192.168.1.20
bash
global_defs {
router_id Nginx_02
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -5
fall 3
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.188
}
track_script {
check_nginx
}
}
3. 主备服务器上配置 nginx 负载配置
主备服务器均配置四层反向代理
bash
#主备nginx都要配置四层反向代理
#以主为例
vim /apps/nginx/conf/nginx.conf
stream{
upstream phpserver1 {
server 192.168.1.30:80;
server 192.168.1.40:80;
}
server {
listen 8080;
proxy_pass http://phpserver1;
}
}
# 准备测试用的网页
## 主 nginx
echo this is nginx1 > /var/share/nginx/html/index.html
## 备 nginx
echo this is nginx2 > /var/share/nginx/html/index.html
4. 负载均衡 及 高可用测试
bash
#客户端访问 VIP 地址
curl 192.168.1.188
#执行多次,观察结果,由于默认采用的负载均衡配置为 rr,所以结果执行结果应该为
curl 192.168.1.188
this is nginx1
curl 192.168.1.188
this is nginx2
curl 192.168.1.188
this is nginx1
.......
轮询
#测试高可用
#关闭主备任意一台的 keepalived 服务
#再次执行多次,执行结果无变化,及高可用测试成功