负载均衡集群——LVS-DR配置
一、简介
1.1 什么是集群?
两台及以上的计算机完成一个任务的模式称为集群。
常见的集群类型包括:
LB(负载均衡)集群:按照不同的算法将前端的访问转发给后端计算点,使节点负载相对平衡。提高并发能力
缺点:负载节点只有一个,容易访问瓶颈,可能存在单点故障
解决方法:增加多个节点,选举主节点(master),访问的IP称为VIP,正常情况下绑定在master上。节点之间有一条心跳检测的线路,若master心跳检测不到了,重新选举master,VIP漂移到新的节点上。
HA(高可用性)集群:保障应用持久、不间断的提供服务,出现故障时应用可以自动快速的切换节点
重切换节点方式称为漂移
HPC(高性能计算)集群:软硬件协同工作的系统,通过集群架构、并行算法等实现单台计算机无法达到的运行速度。(科研居多)
1.2 基于Linux的负载均衡集群软件
LVS——开源的四层(传输层)负载均衡软件
Nginx——支持四层和七层(应用层)负载均衡
HAProxy——支持四层和七层负载均衡
1.3 基于Linux的高可用集群软件
Keepalived:轻量级高可用集群部署软件,为LVS设计,可实现集群的心跳检测、虚拟IP漂移等功能
Hearbeat:与keepalived类似,但不控制虚拟IP的漂移,配置也比较复杂。更擅长资源服务的控制(NFS)
Pacemaker:开源集群资源管理器,不具备心跳检测,需依赖Corosync或Hearbeat,应用广泛,可同时适用于任何规模的集群
集群常见概念
VIP:虚拟IP,一般使用VIP向外提供服务,避免切换master后引起的业务访问IP变化
地址漂移:VIP从一台主机切换到另一台主机
心跳:机制、在高可用集群中,主机之间相互监控彼此状态,以决定哪台主机提供服务
脑裂:现象、如果节点之间心跳中断或不正常,会导致彼此之间争夺资源
代理:正向代理和反向代理。相对与被代理者来说的,正向代理被代理的是客户端(客户需要什么),反向代理被代理的是服务端(商店提供什么)
1.4 LVS相关术语
为了方便大家探讨LVS技术,LVS社区提供了一个命名的约定,内容如下表
1.5 LVS调度算法
调度方法决定了如何在这些集群节点之间分布工作负荷。
当Director收到来自客户端计算机访问她的VIP上的集群服务的入站请求时,Director必须决定那个集
群节点应该获得请求。Director可用于做出该决定的调度方法分成两个基本类别:
固定调度算法:rr,wrr,dh,sh
动态调度算法:wlc,lblc,lblcr,SED,NQ(后两种官方站点没提到)
算法 | 说明 |
rr | 轮循调度(Round-Robin), 它将请求依次分配不同的RS,也就是在RS中均摊请求。这种算法简单,但是只适合于处理性能相差不大的情况 |
wrr | 加权轮循调度(Weighted Round-Robin) 它将依据不同RS的权值分配任务。权值较高的RS将优先获得任务,并且分配到的连接数将比权值较低的RS更多。相同权值的RS得到相同数目的连接数。 |
dh | 目的哈希调度(Destination Hashing) 以目的地址为关键字查找一个静态hash表来获得需要的RS。 |
sh | 源地址哈希调度(source hashing) 以源地址为关键字查找一个静态hash表来获得需要的RS。 |
wlc | 加权最小连接数调度(weighted leastconnection) 假设各台RS的权值依次为wi(i=1..n),当前的TCP连接数依次为Ti(i=1..n),依次选取Ti/Wi为最小的RS作为下一个分配的RS。 |
lc | 最小连接数调度(Least-Connection), IPVS表存储了所有的活动的连接。把心的连接请求发送到当前连接数最小的RS。 |
lblc | 基于地址的最小连接数调度(locality-Based Least-Connection) 将来自同一目的地址的请求分配给同一台RS如果这台服务器尚未满负荷,否则分配给连接数最小的RS,并以它为下一次分配的首先考虑。 |
lblcr | 基于地址带重复最小连接数调度(Locality-Based Least-Connection with Replication) 对于某一目的地址,对应有一个RS子集。 对此地址请求,为它分配子集中连接数最小RS;如果服务器中所有子集均已满负荷,则从集群中选择一个连接数较小服务器,将它加入到此子集并分配连接;若一定时间内,未被做任何修改,则将子集中负载最大的节点从子集删除。 |
SED | 最短期望的延迟(shortest expected delay scheduling SED)(SED) 基于wlc算法。 举例: ABC三台机器分别权重123,连接数也分别是123.那么如果使用wlc算法的话一个新请求进入时它可能会分给ABC中的任意一个。使用sed算法后会进这样一个运算 A(1+1)/1 B(1+2)/2 C(1+3)/3 根据运算结果,把连接交给C。 |
NQ | 最少队列调度(Never Queue Scheduling NQ)(NQ) 无需队列。如果有台realserver的连接数=0就直接分配过去,不需要在进行sed运算 |
二、负载均衡集群
2.1 LVS工作模式——DR配置
在DR模式中,所有的RS(真实的服务器)都需要配置两个地址:RIP和VIP
环境:四台虚拟机 一台配置为LVS服务器 两台用于Nginx服务器的搭建 剩余一台为Client.
LVS仅需要一个网卡可用,两台Nginx服务器和LVS服务器处于同一子网中,客户端位于另一个子网 ,思路如下
实际配置自己方便区分即可,但是VIP必须是该网段里没用过的
LB : 192.168.1.111
(RS)nginx1 : 192.168.1.112
(RS)nginx2 : 192.168.1.113
Client : 192.168.1.11
VIP: 192.168.1.10(后续单独配置)
2.1.1 nginx服务器配置
1.RS下载nginx服务
(两个nginx服务器都尝试相同的操作)
yum install nginx -y
会提供一个默认主页
尝试访问主页
向主页输入内容:
[root@openeuler-1 ~]# echo "web test page,ip is `hostname -I`." > /usr/share/nginx/html/index.html
设置开机自启动,将输入的内容覆盖原有页面:
[root@openeuler-1 ~]# systemctl enable --now nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
访问页面,覆盖成功:
[root@openeuler-1 ~]# curl localhost
web test page,ip is 192.168.1.113 .
注意: `hostname -I` 表示输入当前主机IP, 两台机器ip不一样,所以访问出来的页面IP也不一样
纠错提醒:如果输入时内容输错,重新输入重启服务即可覆盖
如果输错了文件夹,将其移动到正确的文件即可,不用重启: mv /错误的文件 /正确的文件
2.绑定VIP
[root@openeuler-1 ~]# nmcli con add type dummy ifname dummy1 ipv4.method manual ipv4.addresses 192.168.1.10/32
Connection 'dummy-dummy1' (231b9ead-7b44-4daf-b8b1-2a9a6d864dfb) successfully added.
[root@openeuler-1 ~]# ip a
3.arp抑制
在文件最后加入如下配置
[root@openeuler-1 ~]# vim /etc/sysctl.conf
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.dummy1.arp_ignore = 1
net.ipv4.conf.dummy1.arp_announce = 2
使文件生效:
[root@openeuler-1 ~]# sysctl -p
查看是否生效:
[root@openeuler-1 ~]# ip a
...
3: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
...
到此,nginx服务器就配置完成了。
2.1.2 LB服务器配置
1)绑定VIP
nmcli con add type dummy ifname dummy1 ipv4.method manual ipv4.addresses 192.168.1.10/32
2)安装工具ipvsadm
yum install ipvsadm -y
3)LVS配置
手工执行配置添加LVS服务并增加两台RS
[root@Directory ~]# ipvsadm -C 清除当前配置
[root@Directory ~]# ipvsadm --set 30 5 60
因为此前没有配置过,所以这两步可省略,直接添加LVS服务
添加LVS服务:
[root@Directory ~]# ipvsadm -At 192.168.1.10:80 -s rr
增加真实的服务器RS:
[root@Directory ~]# ipvsadm -at 192.168.1.10:80 -r 192.168.1.112:80 -g
[root@Directory ~]# ipvsadm -at 192.168.1.10:80 -r 192.168.1.113:80 -g
查看配置
[root@Directory ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.10:80 rr
-> 192.168.1.112:80 Route 1 0 0
-> 192.168.1.113:80 Route 1 0 0
rr:轮询算法 轮流提供服务
-g:DR模式
-At = -A -t 两种写法,可分开也可合并
[相关参数说明]
[root@Directory ~]# ipvsadm –help
-A 添加虚拟服务器
-t 设置群集地址(VIP,Virtual IP)
-s 指定负载调度算法
-a 添加真实服务器
-d 删除真实服务器
-r 指定真实服务器(Real Server)的地址
-m 使用NAT模式;-g、-i分别对应DR、TUN模式
-w 为节点服务器设置权重,默认为1
[删除方法]
# ipvsadm -D -t 192.168.79.110:80 -s wrr
# ipvsadm -d -t 192.168.79.110:80 -r 192.168.79.118:80
2.1.3 client客户机测试
1)测试连通性
访问nginx服务器,113服务器无法访问可能是该服务器防火墙有限制, 阻止了对目标端口(如 80 端口)的访问
[root@openeuler-1 ~]# curl 192.168.1.112
web test page,ip is 192.168.1.112 .
[root@openeuler-1 ~]# curl 192.168.1.113
curl: (7) Failed to connect to 192.168.1.113 port 80 after 0 ms: No route to host
开放nginx113服务器80端口
[root@openeuler-1 ~]# firewall-cmd --zone=public --add-port=80/tcp --permanent
success
[root@openeuler-1 ~]# firewall-cmd --reload
success
再次访问
[root@openeuler-1 ~]# curl 192.168.1.113
web test page,ip is 192.168.1.113 .
2)关闭服务器和客户机的防火墙和SElinux
ps:每台都要关
[root@openeuler-1 ~]# systemctl stop firewalld
[root@openeuler-1 ~]# setenforce 0
setenforce: SELinux is disabled
[root@openeuler-1 ~]# for ((i=1;i<=6;i++)); do curl 192.168.1.10; done
web test page,ip is 192.168.1.113 .
web test page,ip is 192.168.1.112 .
web test page,ip is 192.168.1.113 .
web test page,ip is 192.168.1.112 .
web test page,ip is 192.168.1.113 .
web test page,ip is 192.168.1.112 .
2.1.4自动配置脚本
每次都要手动配置较为麻烦,为了方便可以做一个启动脚本
1)清除之前的配置
ipvsadm -C #清除配置
ipvsadm -Ln #查看
nmcli connection delete dummy-dummy1 #删除网络
ip a
2)LB代理服务器 上的脚本:
注意:脚本内容需要根据自身ip、网段、端口不同更改相应配置
vim /etc/init.d/lvs_dr
#!/bin/sh
#
# Startup script handle the initialisation of LVS
# chkconfig: - 28 72
# description: Initialise the Linux Virtual Server for DR
#
### BEGIN INIT INFO
# Provides: ipvsadm
# Required-Start: $local_fs $network $named
# Required-Stop: $local_fs $remote_fs $network
# Short-Description: Initialise the Linux Virtual Server
# Description: The Linux Virtual Server is a highly scalable and highly
# available server built on a cluster of real servers, with the load
# balancer running on Linux.
# description: start LVS of DR
LOCK=/var/lock/ipvsadm.lock
VIP=192.168.95.10
RIP1=192.168.95.11
RIP2=192.168.95.12
DipName=ens33
. /etc/rc.d/init.d/functions
start() {
PID=`ipvsadm -Ln | grep ${VIP} | wc -l`
if [ $PID -gt 0 ];
then
echo "The LVS-DR Server is already running !"
else
#Set the Virtual IP Address
/sbin/ifconfig ${DipName}:10 $VIP broadcast $VIP netmask
255.255.255.255 up
/sbin/route add -host $VIP dev ${DipName}:10
#Clear IPVS Table
/sbin/ipvsadm -C
#Set Lvs
/sbin/ipvsadm -At $VIP:80 -s rr
/sbin/ipvsadm -at $VIP:80 -r $RIP1:80 -g
/sbin/ipvsadm -at $VIP:80 -r $RIP2:80 -g
/bin/touch $LOCK
#Run Lvs
echo "starting LVS-DR Server is ok !"
fi
}
stop() {
#clear Lvs and vip
/sbin/ipvsadm -C
/sbin/route del -host $VIP dev ${DipName}:10
/sbin/ifconfig ${DipName}:10 down >/dev/null
rm -rf $LOCK
echo "stopping LVS-DR server is ok !"
}
status() {
if [ -e $LOCK ];
then
echo "The LVS-DR Server is already running !"
else
echo "The LVS-DR Server is not running !"
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
echo "Usage: $1 {start|stop|restart|status}"
exit 1
esac
exit 0
3)RS上的脚本
vim /etc/init.d/rs_dr
#!/bin/sh
#
# Startup script handle the initialisation of LVS
# chkconfig: - 28 72
# description: Initialise the Linux Virtual Server for DR
#
### BEGIN INIT INFO
# Provides: ipvsadm
# Required-Start: $local_fs $network $named
# Required-Stop: $local_fs $remote_fs $network
# Short-Description: Initialise the Linux Virtual Server
# Description: The Linux Virtual Server is a highly scalable and highly
# available server built on a cluster of real servers, with the load
# balancer running on Linux.
# description: start LVS of DR-RIP
LOCK=/var/lock/ipvsadm.lock
VIP=192.168.95.10
. /etc/rc.d/init.d/functions
start() {
PID=`ifconfig | grep lo:10 | wc -l`
if [ $PID -ne 0 ];
then
echo "The LVS-DR-RIP Server is already running !"
else
/sbin/ifconfig lo:10 $VIP netmask 255.255.255.255 broadcast $VIP up
/sbin/route add -host $VIP dev lo:10
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" >/proc/sys/net/ipv4/conf/eth0/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/eth0/arp_announce
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
/bin/touch $LOCK
echo "starting LVS-DR-RIP server is ok !"
fi
}
stop() {
/sbin/route del -host $VIP dev lo:10
/sbin/ifconfig lo:10 down >/dev/null
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "0" >/proc/sys/net/ipv4/conf/eth0/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/eth0/arp_announce
echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
rm -rf $LOCK
echo "stopping LVS-DR-RIP server is ok !"
}
status() {
if [ -e $LOCK ];
then
echo "The LVS-DR-RIP Server is already running !"
else
echo "The LVS-DR-RIP Server is not running !"
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
echo "Usage: $1 {start|stop|restart|status}"
exit 1
esac
exit 0
两个脚本都设置开机自启,这里以LB服务器的为例
chkonfig --add lvs_dr
chkconfig lvs_dr on
systemctl start lvs_dr
然后在客户机上测试即可