一、LVS介绍
LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统,本项目在1998年5月由阿里巴巴的著名工程师章文嵩博士开发的一款开源软件,是中国国内最早出现的自由软件项目之一。
LVS工作在一台server上提供Director(负载均衡器)的功能,本身并不提供服务,只是把特定的请求转发给对应的real server(真正提供服务的主机),从而实现集群环境中的负载均衡。
LVS工作在ISO模型中的第四层,由于其工作在第四层,因此与iptables类似,必须工作在内核空间上。因此lvs与iptables一样,是直接工作在内核中的,叫ipvs,主流的linux发行版默认都已经集成了ipvs,因此用户只需安装一个管理工具ipvsadm即可。
官网:http://www.linuxvirtualserver.org/
中文站点: http://zh.linuxvirtualserver.org/
1、Lvs组成
LVS 由2部分程序组成,包括 ipvs 和 ipvsadm。
LVS的核心组件ipvs工作在kernel中,是真正的用于实现根据定义的集群转发规则把客户端的请求转发到特定的real server。而另一个组件ipvsadm是工作在用户空间的一个让用户定义ipvs规则的工具。故我们只要在server上装了ipvsadm软件包就可以定义ipvs规则,
而在linux kernel的2.6版本之后kernel是直接支持ipvs的。
2、Lvs的专用名词
DS:Director Server。指的是前端负载均衡器节点。
RS:Real Server。后端真实的工作服务器。
VIP:向外部直接面向用户请求,作为用户请求的目标的IP地址。
DIP:Director Server IP,主要用于和内部主机通讯的IP地址。
RIP:Real Server IP,后端服务器的IP地址。
CIP:Client IP,访问客户端的IP地址。
3、LVS的负载均衡算法
针对不同的网络服务和配置需要,LVS调度器提供多种不同的负载调度算法,其中最常用的算法包括轮询、加权轮询、最少连接、权最少连接和source hashing源地址hash。
1、轮询(rr, RoundRobin):
将收到的访问请求按照顺序轮流分配给集群中的各节点(真实服务器)。
2、加权轮询(wrr, Weighted RoundRobin):
根据真实服务器的处理能力轮流分配收到的访问请求,它将依据不同RS的权重分配任务。权重较高的RS将优先获得任务,并且分配到的连接数将比权重较低的RS更多。这样可以保证处理能力强的服务器承担更多的访问流量。相同权重的RS得到相同数目的连接数。
3、最少连接(lc, Least Connections):
IPVS表存储了所有的活动的连接。把新的连接请求发送到当前连接数最小的RS。
4、加权最少连接(wlc,WeightedLeastConnections):
在服务器节点的性能差异较大的情况下,可以为真实服务器设置权重,权重较高的节点将承担更大比例的活动连接负载。假设各台RS的权重依次为Wi(i = 1..n),当前的TCP连接数依次为Ti(i=1..n),依次选取Ti/Wi为最小的RS作为下一个分配的RS。
5、source hashing源地址hash(sh)
将来自同一个ip的请求始终调度至同一RS
4、Lvs的工作模式
NAT模式(Network Address Translation)
NAT模式通过修改数据包的目标IP地址和端口,将请求转发到后端真实服务器。响应数据包经过负载均衡器再次修改源IP地址返回客户端。
优点:隐藏后端服务器真实IP,配置简单。
缺点:负载均衡器需处理双向流量,易成为性能瓶颈。
TUN模式(IP Tunneling)
TUN模式通过IP隧道封装数据包,直接发送给后端服务器。后端服务器解封装后直接响应客户端,无需经过负载均衡器。
优点:减轻负载均衡器压力,适合跨机房部署。
缺点:需后端服务器支持隧道协议,配置复杂。
DR模式(Direct Routing)
DR模式下,负载均衡器仅修改数据包的MAC地址,将请求直接转发到后端服务器。后端服务器通过配置VIP(Virtual IP)直接响应客户端。
优点:性能最优,负载均衡器仅处理请求流量。
缺点:需后端服务器与负载均衡器在同一局域网,且需配置ARP抑制。
区别:
- 流量路径:NAT模式需双向流量经过负载均衡器;TUN和DR模式仅请求流量经过负载均衡器。
- 网络要求:DR模式要求同一局域网;TUN模式可跨网络。
- 性能:DR模式性能最高,NAT模式最低。
- 配置复杂度:NAT最简单,TUN和DR需额外网络配置。
二、配置LVS-DR
DR模式是通过改写请求报文的目标MAC地址,将请求发给真实服务器的,而真实服务器响应后的处理结果直接返回给客户端用户。DR模式可以极大的提高集群系统的伸缩性。但是要求调度器LB与真实服务器RS都有一块网卡连接到同一物理网段上,必须在同一个局域网环境。DR模式是互联网使用比较多的一种模式。
1、准备环境
|----|---------------|-----|
| 主机 | IP | |
| DR | 192.168.1.100 | VIP |
| RS | 192.168.1.101 | rr |
| RS | 192.168.1.102 | rr |
2、DR服务配置
从lvs-dr模式的工作原理我们可以看出负载调度器ens33有2个IP地址,所以我们需要配置ens33和ens33:0两个IP
生成ens33:0配置文件
[root@ds ~]# cd /etc/sysconfig/network-scripts/
[root@ds network-scripts]# cp ifcfg-ens33 ifcfg-ens33:0
[root@ds network-scripts]# vim ifcfg-ens33:0

重启网卡配置文件
[root@ds network-scripts]# systemctl restart network
配置lvs-dr规则
LVS现在已成为Linux内核的一部分,默认编译为ip_vs模块,必要时能够自动调用。以下操作可以手动加载ip_vs模块,并查看当前系统中ip_vs模块的版本信息。
[root@ds ~]# modprobe ip_vs
[root@ds ~]# lsmod | grep ip_vs
安装ipvsadm软件包
[root@ds ~]# yum -y install ipvsadm
清除策略:清除内核虚拟服务器表中的所有记录
[root@ds ~]# ipvsadm -C
添加规则:
创建虚拟服务器,集群的VIP地址为192.168.1.250,针对TCP的80端口提供负载分流服务,使用的调度算法为轮询(rr代表轮循)。
[root@ds ~]# ipvsadm -A -t 192.168.1.250:80 -s rr
选项:
-A 添加虚拟服务器
-t 用来指定VIP地址及TCP端口
-s 指定调度算法,rr(轮询)、wrr(加权轮询)、lc(最少连接)、wlc(加权最少连接)。
添加服务器节点:
[root@ds ~]# ipvsadm -a -t 192.168.1.250:80 -r 192.168.1.112:80 -g -w 1
[root@ds ~]# ipvsadm -a -t 192.168.1.250:80 -r 192.168.1.113:80 -g -w 1
选项:
-a 表示添加real server的地址
-r 指定real server的IP地址和端口
-g 表示route 也就是DR方式的LVS,(-m: NAT模式、-i:TUN模式)
-w用来设置权重(权重为0时表示暂停节点)。
保存策略
[root@ds ~]# touch /etc/sysconfig/ipvsadm
[root@ds ~]# ipvsadm-save /etc/sysconfig/ipvsadm
-A -t ds:http -s rr
-a -t ds:http -r 192.168.1.101:http -g -w 1
-a -t ds:http -r 192.168.1.102:http -g -w 1
设置ipvsadm服务为自动启动:
[root@ds ~]# systemctl start ipvsadm.service
[root@ds ~]# systemctl enable ipvsadm.service
查看负载均衡策略
[root@ds ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 rr
-> 192.168.1.101:80 Route 1 0 0
-> 192.168.1.102:80 Route 1 0 0
3、RS配置(2台)
关闭APR转发
同一个广播域: 配置了多个相同的VIP 是不允许的, 要想实现,就必须让外面的网络, 无法发现这个VIP的存在。因此在Linux里面, 可以修改内核参数, 实现接口IP的广播不响应、不广播。
临时生效:
[root@rs1 ~]# echo 1 > /proc/sys/net/ipv4/conf/ens33/arp_ignore
[root@rs1 ~]# echo 2 > /proc/sys/net/ipv4/conf/ens33/arp_announce
永久生效:(注意网卡名称)
[root@rs1 ~]# vim /etc/sysctl.conf 最后添加
net.ipv4.conf.ens33.arp_ignore = 1
net.ipv4.conf.ens33.arp_announce = 2
或:
net.ipv4.conf.ens33.arp_ignore = 1
net.ipv4.conf.ens33.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
生效
[root@rs1 ~]# sysctl -p
net.ipv4.conf.ens33.arp_ignore = 1
net.ipv4.conf.ens33.arp_announce = 2
配置虚拟ip地址(vip)
生成回环口配置文件
[root@rs1 ~]# cd /etc/sysconfig/network-scripts/
[root@rs1 network-scripts]# cp ifcfg-lo ifcfg-lo:0
[root@rs1 network-scripts]# vim ifcfg-lo:0
DEVICE=lo:0
IPADDR=192.168.1.250
NETMASK=255.255.255.255
ONBOOT=yes
NAME=loopback

重启网卡服务
[root@rs1 network-scripts]# systemctl restart network
配置httpd服务
[root@rs1 ~]# yum -y install httpd
把/etc/httpd/conf/httpd.conf的ServerName配置修改为自己的IP地址
启动
[root@rs1 ~]# systemctl start httpd
写入测试文件
[root@rs1 ~]# echo "web 1" > /var/www/html/index.html
[root@rs2 ~]# echo "web 2" > /var/www/html/index.html
4、测试
不要在LVS上测试 因为请求源IP和目标IP都在LVS本身 不符合"客户端-LVS-RS"的三层流量模型,因此无法触发转发
[root@localhost ~]# curl 192.168.1.250
web 2
[root@localhost ~]# curl 192.168.1.250
web 1
[root@localhost ~]# curl 192.168.1.250
web 2
[root@localhost ~]# curl 192.168.1.250
web 1
[root@localhost ~]# curl 192.168.1.250
web 2
[root@localhost ~]# curl 192.168.1.250
web 1
[root@localhost ~]# curl 192.168.1.250
web 2
[root@ds ~]# ipvsadm -Lnc
IPVS connection entries
pro expire state source virtual destination
TCP 01:56 FIN_WAIT 192.168.1.103:55590 192.168.1.250:80 192.168.1.102:80
TCP 01:57 FIN_WAIT 192.168.1.103:55596 192.168.1.250:80 192.168.1.101:80
TCP 01:56 FIN_WAIT 192.168.1.103:55588 192.168.1.250:80 192.168.1.101:80
TCP 01:57 FIN_WAIT 192.168.1.103:55592 192.168.1.250:80 192.168.1.101:80
TCP 01:57 FIN_WAIT 192.168.1.103:55594 192.168.1.250:80 192.168.1.102:80
5、webbench压力测试
Webench是一款轻量级的网站测压工具,最多可以对网站模拟3w左右的并发请求,可以控制时间、是否使用缓存、是否等待服务器回复等等,且对中小型网站有明显的效果,基本上可以测出中小型网站的承受能力,对于大型的网站,如百度、淘宝这些巨型网站没有意义,因为其承受能力非常大。同时测试结果也受自身网速、以及自身主机的性能与内存的限制,性能好、内存大的主机可以模拟的并发就明显要多。
Webbench是由 Lionbridge公司(http://www.lionbridge.com)开发的网站压力测试工具,webbench不但能具有便准静态页面的测试能力,还能对动态页面(ASP,PHP,JAVA,CGI)进行测试的能力。
Webbench用C语言编写,运行于linux平台,下载源码后直接编译即可使用,非常迅速快捷,对于中小型网站的制作者,在上线前用webbench进行系列并发测试不失为一个好的测试方法。
官网:http://home.tiscali.cz/~cz210552/webbench.html
[root@cong15 ~]# yum -y install ctags wget make apr* autoconf automake gcc gcc-c++
下载
[root@cong15 ~]# wget http://home.tiscali.cz/~cz210552/distfiles/webbench-1.5.tar.gz
解压
[root@cong15 ~]# tar -zxvf webbench-1.5.tar.gz
编译
[root@cong15 ~]# cd webbench-1.5
[root@cong15 webbench-1.5]# make
[root@cong15 webbench-1.5]# mkdir -p /usr/local/man/man1
#不创建这个执行make install报错:
install: cannot create regular file `/usr/local/man/man1': No such file or directory
make: *** [install] Error 1
[root@cong15 webbench-1.5]# make install
模拟100个并发,持续访问60s
[root@localhost ~]# webbench -t 60 -c 100 http://192.168.1.250/
Webbench - Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
Benchmarking: GET http://192.168.1.250/
100 clients, running 60 sec.
在dr服务器查看
[root@dr ~]# ipvsadm -Lnc
IPVS connection entries
pro expire state source virtual destination
TCP 01:56 FIN_WAIT 192.168.1.103:55590 192.168.1.250:80 192.168.1.102:80
TCP 01:57 FIN_WAIT 192.168.1.103:55596 192.168.1.250:80 192.168.1.101:80
TCP 01:56 FIN_WAIT 192.168.1.103:55588 192.168.1.250:80 192.168.1.101:80
TCP 01:57 FIN_WAIT 192.168.1.103:55592 192.168.1.250:80 192.168.1.101:80
TCP 01:57 FIN_WAIT 192.168.1.103:55594 192.168.1.250:80 192.168.1.102:80
三、Keepalived
1、Keepalived介绍
Keepalived软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,主要用来提供故障切换和健检查功能,如判断LVS负载调度器、节点服务器的可用性,及时隔离并替换为新的服务器,当故障主机恢复后将其重新加入集群。后来又加入了可以实现高可用的VRRP功能。因此,keepalived除了能够管理LVS软件外,还可以作为其他服务的高可用解决方案软件(如nginx、Mysql等应用服务)。
keepalived软件主要是通过VRRP协议实现高可用功能的。VRRP是Virtual Router Redundancy Protocol(虚拟路由冗余协议)的缩写,VRRP出现的目的就是为了解决路由器的单点故障问题的,它能保证当个别节点宕机时,整个网络可以不间断地运行。所以,keepalived一方面具有配置管理LVS的功能,同时还具有对LVS下面节点进行健康检查的功能,另一方面也可以实现系统网络服务的高可用功能。
2、Keepalived工作原理
OSI七层模型

Layer3、4、5工作在IP/TCP协议栈的IP层,TCP层,及应用层。
keepalived具有3、4、5层交换及健康检测功能。
Layer3层检测:进行ICMP ping包检测,确认主机是否存活,如果异常,则会该主机从服务器集群中剔除。Keepalived 使用 Layer3 的方式工作式时, Keepalived 会定期向集群中的服务器发送一个 ICMP 的数据包(既我们平时用的 Ping 程序),如果发现某台服务的IP地址没有激活,Keepalived 便报告这台服务器失效,并将它从集群中剔除,这种情况的典型例子是某台服务器被非法关机。Layer3 的方式是以服务器的IP地址是否有效作为服务器工作正常与否的标准。
Layer4层检测: 进行端口检测,例如80、3306等,端口不通时,将服务器从集群中剔除;主要以TCP端口的状态来决定服务器工作正常与否。如 web server 的服务端口一般是80,如果 Keepalived 检测到 80 端口没有启动,则 Keepalived 将把这台服务器从服务器群中删除。
Layer5层检测:这个就是基于应用的了,如http返回码是否为200,确认主机是否正常。Layer5 就是工作在具体的应用层了,比 Layer3,Layer4 要复杂一点,在网络上占用的带宽也要大一些。 Keepalived 将根据用户的设定检查服务器程序的运行是否正常,如果与用户的设定不相符,则 Keepalived 将把服务器从服务器群中剔除(例如:http返回码是否为200,确认主机是否正常)。
3、Keepalived的功能和核心组件
1.管理LVS
2.对LVS集群节点检查
3.作为其他网络服务的高可用功能

keepalived也是模块化设计,不同模块负责不同的功能,它主要有三个模块,分别是core、check和VRRP,其中:
core模块:为keepalived的核心组件,负责主进程的启动、维护以及全局配置文件的加载和解析;
check:负责健康检查,包括常见的各种检查方式;
VRRP模块:是来实现VRRP协议的。
其他组件:
system call:系统调用
watch dog:监控check和vrrp进程的看管者,check负责检测健康状态,当其检测到master上的服务不可用时则通告vrrp将其转移至backup服务器上。
大致如下:
1.利用VRRP协议进行主备通信。组播224.0.0.18
2.利用VRRP协议进行主备竞选,产生VIP
3.利用VRRP协议主向备发送组播包。当备服务器接收不到主服务器的组播包,就会认为主出现故障,主动接管资源
4.当主恢复时,根据配置决定是否抢占备服务器资源
ipvs wrapper:为集群内的所有节点生成IPVS规则
注意,keepalived和LVS完全是两码事,只不过他们各负其责,相互配合而已。
Keepalived启动后会有三个进程:
父进程:内存管理,子进程管理等等
子进程:vrrpd子进程
子进程:healthchecker子进程
由上图可知,两个子进程都被系统WatchDog看管,两个子进程各自实现自己的事,healthchecker子进程实现检查各自服务器的健康程度,例如HTTP,LVS等等,如果healthchecker子进程检查到MASTER上服务不可用,就会通知本机上的VRRP子进程,让他删除通告,并且去掉虚拟IP,转换为BACKUP状态。
4、Keepalived如何实现故障转移的
Keepalived高可用服务对(主备)之间的故障切换转移,是通过VRRP来实现的。在keepalived服务工作时,主Master节点会不断地向备节点发送(多播的方式)心跳消息,用来告诉备Backup节点自己还活着。当主节点发生故障时,就无法发送心跳的消息了,备节点也因此无法继续检测到来自主节点的心跳了。于是就会调用自身的接管程序,接管主节点的IP资源和服务。当主节点恢复时,备节点又会释放主节点故障时自身接管的IP资源和服务,恢复到原来的备用角色。
四、keepalived+lvs-dr模式
四层负载均衡(TCP转发)
LVS在内核里转发,性能极强
流量走DR模式,请求进LVS,回包直接从后端服务器回给客户端,不经过lvs
|---------------|-------------------|
| ip | 角色 |
| 192.168.1.100 | keepalived master |
| 192.168.1.101 | keepalived slvae |
| 192.168.1.102 | httd |
| 192.168.1.103 | httd |
1、安装Keepalived(主备都需要)
2台服务做相同的安装操作
# 安装依赖
[root@m_director ~]# yum -y install gcc openssl-devel pcre-devel libnl-devel
# 下载源码包
[root@m_director ~]# wget https://www.keepalived.org/software/keepalived-2.0.18.tar.gz
[root@m_director ~]# tar zxf keepalived-2.0.18.tar.gz
[root@m_director ~]# cd keepalived-2.0.18/
[root@m_director keepalived-2.0.18]# ./configure --prefix=/usr/local/keepalived
[root@m_director keepalived-2.0.18]# make && make install
2、修改配置文件(M_director)
[root@m_director ~]# ln -s /usr/local/keepalived/sbin/keepalived /usr/sbin/
[root@m_director ~]# mkdir /etc/keepalived
[root@m_director ~]# cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
keepalived.conf配置文件完整内容如下所示:
[root@m_director ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id m_director
}
vrrp_instance lvs-dr {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.250
}
}
virtual_server 192.168.1.250 80 {
delay_loop 6
lb_algo rr
lb_kind DR
#persistence_timeout 50
protocol TCP
real_server 192.168.1.102 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
connect_port 80
}
}
real_server 192.168.1.103 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
connect_port 80
}
}
}
说明
! 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 server地址,即发邮件服务器
smtp_connect_timeout 30 #设置smtp超时连接时间,以上参数可以不配置
router_id m_director #表示运行keepalived服务器的一个标识,这个标识(router_id)是唯一的
}
vrrp_instance lvs-dr { #定义一个实例,一个集群就是一个实例。 默认VI_1 可以随意改
state MASTER #MASTER表示指定本节点为主节点,备用节点上设置为 BACKUP。注意节点状态均大写。
interface ens33 #绑定虚拟 IP 的网络接口
virtual_router_id 51 #虚拟路由ID标识,这个标识最好是一个数字,在一个keepalived.conf配置中是唯一的, MASTER和BACKUP配置中相同实例的virtual_router_id必须是一致的。
priority 100 #节点的优先级(1-255之间),越大越优先。备用节点必须比主节点优先级低。
advert_int 1 #为同步通知间隔。MASTER与BACKUP之间心跳检查的时间间隔,单位为秒,默认为1。
authentication { #设置验证信息,两个节点必须一致,同一vrrp实例的MASTER与BACKUP使用相同的密码才能正常通信。
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { #指定虚拟 IP, 两个节点设置必须一样
192.168.1.250
}
}
#至此为止以上为实现高可用配置,如只需使用高可用功能下边配置可删除
#以下为虚拟服务器定义部分
#类似添加虚拟服务器 ipvsadm -A -t 172.16.16.172:80 -s rr
virtual_server 192.168.1.250 80 { #设置虚拟服务器,指定虚拟IP和端口
delay_loop 6 #健康检查时间为6秒,即Keepalived多长时间监测一次RS。
lb_algo rr #设置负载调度算法为rr算法
lb_kind DR #设置负载均衡模式,有NAT,TUN和DR三种模式可选
nat_mask 255.255.255.0 #非NAT模式注释掉此行 注释用!号
persistence_timeout 50 #连接保持时间,单位是秒。有了这个会话保持功能,用户的请求会被一直分发到某个服务节点,直到超过这个会话的保持时间。同一IP地址的客户端50秒内的请求都发到同个real server ,这个会影响LVS的 rr 调度算法,同一IP的客户端超过50 秒后,再次访问,才会被转发到另一台real server上。Persistence是持久性的意思
protocol TCP #指定转发协议类型,有TCP和UDP两种
real_server 192.168.1.100 80 { #配置RS节点1,需要指定 realserver 的真实 IP 地址和端口,IP和端口之间用空格隔开
weight 1 ##权重,权重大小用数字表示,数字越大,权重越高
TCP_CHECK { #节点健康检查。这段内容要手动添加,把原来的内容删除
connect_timeout 3 #超时时间,表示3秒无响应超时。
retry 3 #表示重试次数
delay_before_retry 3 #表示重试间隔
connect_port 80 #检测端口,利用80端口检查
}
}
real_server 192.168.1.101 80 { #RS节点2
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
connect_port 80
}
}
}
3、修改配置文件(S_director)
创建存放配置文件的目录
[root@s_director ~]# mkdir /etc/keepalived
把主配置文件拷贝过来
[root@s_director ~]# scp root@192.168.1.100:/etc/keepalived/keepalived.conf /etc/keepalived/
修改配置文件
[root@m_director ~]# vim /etc/keepalived/keepalived.conf
global_defs {
router_id s_director #修改名称 不能重复
}
vrrp_instance lvs-dr {
state BACKUP #修改为BACKUP
interface ens33
virtual_router_id 51
priority 99· #修改权重
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.250
}
}
4、安装Ipvs(m_s都操作)
[root@m_director ~]# yum -y install ipvsadm
[root@m_director ~]# modprobe ip_vs
[root@m_director ~]# lsmod | grep ip_vs
ip_vs_rr 12600 1
ip_vs 145497 3 ip_vs_rr
nf_conntrack 133095 1 ip_vs
libcrc32c 12644 3 xfs,ip_vs,nf_conntrack
# 清空规则
[root@m_director ~]# ipvsadm -C
5、安装Http服务(m_s都操作)
配置httpd服务
[root@ds1 ~]# yum -y install httpd
把/etc/httpd/conf/httpd.conf的ServerName配置修改为自己的IP地址
启动
[root@ds1 ~]# systemctl start httpd
写入测试文件
[root@ds1 ~]# echo "web 1" > /var/www/html/index.html
[root@ds2 ~]# echo "web 2" > /var/www/html/index.html
6、开启Keepalived服务
[root@m_director ~]# systemctl start keepalived
[root@m_director ~]# systemctl enable keepalived
# 查看规则
[root@m_director ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 rr
-> 192.168.1.102:80 Route 1 0 0
-> 192.168.1.103:80 Route 1 0 0
# 关掉ds2的httpd服务
[root@ds2 ~]# systemctl stop httpd
# 查看规则
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 rr
-> 192.168.1.102:80 Route 1 0 0
7、关闭ARP装发和配置虚拟ip地址(ds01 02都操作)
[root@ds1 ~]# vim /etc/sysctl.conf ##最后添加
net.ipv4.conf.ens33.arp_ignore = 1
net.ipv4.conf.ens33.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
使内核参数修改生效:
[root@ds1 ~]# sysctl -p
配置虚拟ip地址(VIP)
生成回环口配置文件:
[root@ds1 ~]# cd /etc/sysconfig/network-scripts/
[root@ds1 network-scripts ~]# cp ifcfg-lo ifcfg-lo:0
[root@ds1 network-scripts ~]# vim ifcfg-lo:0
DEVICE=lo:0
IPADDR=192.168.1.250
NETMASK=255.255.255.255
ONBOOT=yes
NAME=loopback
重启network服务:
[root@ds1 network-scripts ~]# systemctl restart network
8、测试VIP漂移
首先在主上m_director上查看VIP
[root@m_director ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.1.250/32 brd 192.168.1.250 scope global lo:0
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:29:f9:9e brd ff:ff:ff:ff:ff:ff
inet 192.168.1.100/24 brd 192.168.1.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet 192.168.1.250/32 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::de6c:e47b:b978:456f/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::cb3:ba25:61d3:ac20/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::f49c:7df8:7b18:3984/64 scope link noprefixroute
valid_lft forever preferred_lft forever
在s_director上查看状态
[root@s_director ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.1.250/32 brd 192.168.1.250 scope global lo:0
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:85:c8:29 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.101/24 brd 192.168.1.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::de6c:e47b:b978:456f/64 scope link noprefixroute
valid_lft forever preferred_lft forever
在m_director上停掉keepalived服务, 模拟故障,再查看s_director
[root@m_director ~]# systemctl stop keepalived
[root@s_director ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.1.250/32 brd 192.168.1.250 scope global lo:0
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:85:c8:29 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.101/24 brd 192.168.1.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::de6c:e47b:b978:456f/64 scope link noprefixroute
valid_lft forever preferred_lft forever
# 客户段访问测试
[root@localhost ~]# curl 192.168.1.250
2
[root@localhost ~]# curl 192.168.1.250
1
[root@localhost ~]# curl 192.168.1.250
2
[root@localhost ~]# curl 192.168.1.250
1
[root@localhost ~]# curl 192.168.1.250
2
[root@localhost ~]# curl 192.168.1.250
1
[root@localhost ~]# curl 192.168.1.250
2
[root@localhost ~]# curl 192.168.1.250
1
[root@localhost ~]# curl 192.168.1.250
2
[root@localhost ~]# curl 192.168.1.250
1
[root@localhost ~]# curl 192.168.1.250
2
[root@localhost ~]# curl 192.168.1.250
9、VIP不抢占模式
和抢占模式的配置相比,只改了两个地方:
- 在vrrp_instance块下,两个节点各增加了nopreempt指令,表示不争抢vip。
- 两个节点的state都为BACKUP。
在非抢占模式下,两个keepalived节点都启动后,默认都是BACKUP状态,双方在发送组播信息后,会根据优先级来选举一个MASTER出来。由于两者都配置了nopreempt,所以MASTER从故障中恢复后,不会抢占vip。这样会避免VIP切换可能造成的服务延迟。
global_defs {
router_id s_director
}
vrrp_instance lvs-dr {
state BACKUP #非抢占模式无论主备都是BACKUP
interface ens33
virtual_router_id 51
nopreempt #配置非抢占模式
priority 99·
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.250
}
}
五、Keepalived脑裂及解决办法
1、什么是脑裂
"脑裂" 是高可用集群的噩梦:主备调度器之间网络不通(比如交换机故障、防火墙拦截),但两者都活着→都认为自己是主,都绑定 VIP,导致两个 VIP 在网络里冲突,流量混乱。
2、脑裂的原因
主备之间的网络链路故障(比如网线断了、路由器挂了);
防火墙拦截了 VRRP 报文(默认 VRRP 用组播地址 224.0.0.18,UDP 112 端口);
主备的 VRRP 配置不一致(比如组 ID 不同、认证密码不同)。
3、脑裂的解决办法
方法 1:加强网络冗余
- 主备调度器之间用双网卡、双交换机连接(一条链路断了,另一条能用);
- 配置 bonding(网卡绑定),提升链路可靠性。
方法 2:添加 "仲裁机制"
- 引入第三方服务器(比如 ZooKeeper、Etcd),主备都向仲裁服务器 "报备",仲裁服务器判定谁是真主;
- 用脚本监控:如果本机检测到 VIP,但 ping 不通备机,就自动释放 VIP(避免双主)。
方法 3:严格配置防火墙
-
确保主备之间允许 VRRP 组播报文(224.0.0.18)和 UDP 112 端口通信;
-
配置 iptables 规则:
iptables -A INPUT -d 224.0.0.18 -p vrrp -j ACCEPT
iptables -A OUTPUT -d 224.0.0.18 -p vrrp -j ACCEPT
方法 4:配置 "脑裂检测脚本"
在主备调度器上部署脚本,定期检测是否双主:
# 示例脚本:检测到双主就释放本机VIP
#!/bin/bash
VIP=192.168.1.200
# ping备机IP(比如备机是192.168.1.101)
ping -c 3 192.168.1.101 > /dev/null
if [ $? -ne 0 ]; then
# 备机不通,检查本机是否有VIP
ip addr | grep $VIP > /dev/null
if [ $? -eq 0 ]; then
# 释放VIP
ip addr del $VIP/24 dev ens33
echo "脑裂发生,释放本机VIP" >> /var/log/keepalived-brain.log
fi
fi
把脚本加入 crontab(每分钟执行一次):
*/1 * * * * /root/check-brain.sh
六、keepalived的常用检查方式
1、TCP_CHECK
real_server 192.168.1.112 80 {
weight 100
TCP_CHECK {
connect_port 80 #检测端口,利用80端口检查
connect_timeout 3 #连接超时时间
nb_get_retry 3 #重连次数
delay_before_retry 3 #重连间隔
}
}
real_server 192.168.1.113 80 {
weight 100
TCP_CHECK {
connect_port 80 #检测端口,利用80端口检查
connect_timeout 3 #连接超时时间
nb_get_retry 3 #重连次数
delay_before_retry 3 #重连间隔
}
}
默认用的都是tcp检查
2、HTTP_GET
基于状态码的检查
real_server 192.168.1.112 80 {
weight 1
HTTP_GET {
url {
path /index.html
status_code 200 #http://172.16.16.177/index.html的返回状态码
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.1.112 80 {
weight 1
HTTP_GET {
url {
path /index.html
status_code 200 #http://172.16.16.177/index.html的返回状态码
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}

3、MISC_CHECK
自定义脚本监控
real_server 192.168.1.112 80 {
weight 100
MISC_CHECK {
misc_path "/opt/mytools/check_web.sh 172.16.16.177" #脚本名,需全路径
misc_timeout 30 #脚本执行的超时时间
misc_dynamic #如果设置了misc_dynamic,healthchecker程序的退出状态码会用来动态调整服务器的权重(weight)。
}
}
real_server 192.168.1.113 80 {
weight 100
MISC_CHECK {
misc_path "/opt/mytools/check_web.sh 172.16.16.177" #脚本名,需全路径
misc_timeout 30 #脚本执行的超时时间
misc_dynamic #如果设置了misc_dynamic,healthchecker程序的退出状态码会用来动态调整服务器的权重(weight)。
}
}
用脚本来检测,脚本如果带有参数,需将脚本和参数放入双引号内。脚本的返回值需为:
#返回0:健康检查OK,权重不被修改
#返回1:健康检查失败,权重设为0
#返回2-255:健康检查OK,权重设置为:退出状态码-2,比如返回255,那么weight=255-2=253

keepalived检测脚本内容/opt/mytools/check_web.sh,返回0代表检查正常,返回1代表检查异常
创建脚本存放的位置
主从都要创建
[root@m_director ~]# mkdir /opt/mytools
[root@s_director ~]# mkdir /opt/mytools
编辑脚本
[root@m_director ~]# vim /opt/mytools/check_web.sh
#!/bin/sh
serverip=$1
curl -s -m 2 http://$serverip
if [ $? -eq 0 ];then
exit 0
else
exit 1
fi
注:curl命令中的-s选项表示静音模式,不输出任何东西。-m选项表示设置数据传输的最大时间。传输的最大允许时间
赋予执行权限
[root@m_director ~]# chmod +x /opt/mytools/check_web.sh
七、Keepalived只实现高可用
vim /etc/keepalived/keepalived.conf
keepalived.conf配置文件完整内容如下所示:
! Configuration File for keepalived
global_defs {
router_id nginx-01
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
interval 2 #每2秒检测一次nginx的运行状态
weight -20 #失败一次,将自己的优先级-20
}
vrrp_instance VI-1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
!nopreempt #不抢占模式,如果使用抢占模式,只需将其注释即可
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.200
}
}
不做LVS转发的情况下,不需要关闭ARP转发,也不需要配置回环地址!