本文介绍,如何通过ipvsadm配置负载均衡,并且转发模式为DR直接路由模式
如下图:
LVS负载均衡的机器,配置了一个VIP:10.1.0.7
每台机器关闭防火墙
systemctl stop firewalld
RS装好nginx,我测试时用的docker来装的
为以验证结果,对应的nginx首页面,设置如下:
root@cd7e26aa7159:~# cat /usr/share/nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>10.1.0.9 </h1>
</body>
</html>
分别输出两台机器的IP10.1.0.9 和10.1.0.10
[root@localhost ~]# ifconfig enp0s8:0 10.1.0.7/16
配置后的检查结果
[root@localhost ~]# ifconfig enp0s8:0
enp0s8:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.1.0.7 netmask 255.255.0.0 broadcast 10.1.255.255
ether 08:00:27:b8:e6:5d txqueuelen 1000 (Ethernet)
在宿主机或者同局域网的机器上ping 10.1.0.7
C:\Users\Administrator>ping 10.1.0.7
正在 Ping 10.1.0.7 具有 32 字节的数据:
来自 10.1.0.7 的回复: 字节=32 时间<1ms TTL=64
来自 10.1.0.7 的回复: 字节=32 时间=1ms TTL=64
来自 10.1.0.7 的回复: 字节=32 时间<1ms TTL=64
[root@localhost ~]# ipvsadm -C #清空ipvs历史设置
[root@localhost ~]# ipvsadm --set 30 5 60 #设置超时时间(tcp tcpfin udp)
[root@localhost ~]# ipvsadm -A -t 10.1.0.7:80 -s rr -p 20
#说明:
#-A:添加一个虚拟路由主机(LB)
#-t:指定虚拟路由主机的VIP地址和监听端口
#-s:指定负载均衡算法
# -p:指定会话保持时间
[root@localhost ~]# ipvsadm -a -t 10.1.0.7:80 -r 10.1.0.10:80 -g -w 1
[root@localhost ~]# ipvsadm -a -t 10.1.0.7:80 -r 10.1.0.9:80 -g -w 1
#说明:
#-a:添加RS节点
#-t:指定虚拟路由主机的VIP地址和监听端口
#-r:指定RS节点的RIP地址和监听端口
#-g:指定DR模式
#-w:指定权值
[root@localhost ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.1.0.7:80 rr persistent 20
-> 10.1.0.9:80 Route 1 0 0
-> 10.1.0.10:80 Route 1 0 0
[root@lvs01 ~]# #ipvsadm -D -t 10.1.0.7:80 -s rr #删除虚拟路由主机
[root@lvs01 ~]# #ipvsadm -d -t 10.1.0.7:80 -r 10.1.0.9:80 #删除RS节点
此时,可以打开浏览器访问http://10.1.0.8体验结果,如果没意外,是无法访问的。(RS将包丢弃了)
[root@localhost ~]# curl -X GET http://10.1.0.7
#无法请求
在每台realServer上设置
[root@localhost ~]# ifconfig lo:0 10.1.0.7/32 up
[root@localhost ~]# ifconfig lo:0
lo:0: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 10.1.0.7 netmask 0.0.0.0
loop txqueuelen 1000 (Local Loopback)
上面的配置,重启后就掉了,工作中得写在配置文件里面
todo 上述配置,如何保存到配置文件?
vim /etc/sysconfig/network-scripts/ifcfg-lo:0
添加路由
[root@localhost ~]# route add -host 10.1.0.7 dev lo
[root@localhost ~]# route -n | grep 10.1.0.7
10.1.0.7 0.0.0.0 255.255.255.255 UH 0 0 0 lo
执行下面四句命令
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/all/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce
在10.1.0.11机器,即上图中的机器B上执行命令
[root@localhost ~]# curl -X GET http://10.1.0.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>10.1.0.9 </h1>
</body>
</html>
[root@localhost ~]# curl -X GET http://10.1.0.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>10.1.0.10 </h1>
</body>
</html>
在LVS机器上抓包
可以看到只有请求(10.1.0.11)进来(10.1.0.7),并没有返回报文
在RS机器上抓包
可以看到请求的ip是client ip(10.1.0.11),而不是LVS的IP,同时返回报文,是直接返回给client
由于现在没有健康检查功能,所以删除实例我们手工来操作一下
删除一台RS,再试着请求
[root@localhost ~]# ipvsadm -d -t 10.1.0.7:80 -r 10.1.0.10:80
[root@localhost ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.1.0.7:80 rr persistent 20
-> 10.1.0.9:80 Route 1 0 0
可以看到现在每次都只能请求到10.1.0.9的那台服务了
[root@localhost ~]# curl -X GET http://10.1.0.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>10.1.0.9 </h1>
</body>
</html>
最后再把RS加回去
ipvsadm -a -t 10.1.0.7:80 -r 10.1.0.10:80 -g -w 1
[root@localhost ~]# ipvsadm-save > /etc/sysconfig/ipvsadm
[root@localhost ~]# cat /etc/sysconfig/ipvsadm
-A -t localhost.localdomain:http -s rr -p 20
-a -t localhost.localdomain:http -r 10.1.0.9:http -g -w 1
-a -t localhost.localdomain:http -r 10.1.0.10:http -g -w 1
[root@localhost ~]# service ipvsadm restart ##重启ipvsadm看看
Redirecting to /bin/systemctl restart ipvsadm.service
[root@localhost ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 127.0.0.1:80 rr persistent 20
-> 10.1.0.9:80 Route 1 0 0
-> 10.1.0.10:80 Route 1 0 0
上面的操作有几个问题,就是配置并没有保存,重启之后,相关的配置会丢失。
cd /etc/sysconfig/network-scripts/
cp ifcfg-enp0s8 ifcfg-enp0s8:0
vim ifcfg-enp0s8:0
#删除UUID,dns与网关,注意子网
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
IPADDR=10.1.0.7
PREFIX=32
DEFROUTE=yes
NAME=lo:30
DEVICE=lo:30
ONBOOT=yes
#重启网络服务、启动网卡???centos8 重启网卡是什么命令?让网卡配置生效果是什么命令
重启网卡使配置文件生效
Centos7:
systemctl restart network
Centos8:
ifup lo:0 -->好像不行
nmcli c reload /etc/sysconfig/network-scripts/ifcfg-ens33 # 我验证不行
nmcli networking off && nmcli networking on # 验证可行,其它命令自行验证
ifdown ens33 && ifup ens33 # 验证可行,其它命令自行验证
nmcli con down ens33 && nmcli con up ens33
systemctl restart NetworkManager
#保存设置
ipvsadm
ipvsadm -ln
ipvsadm-save >/etc/sysconfig/ipvsadm
#添加回环网卡,修改回环网卡名,IP地址,子网掩码
cd /etc/sysconfig/network-scripts/
cp ifcfg-lo ifcfg-lo:0
vim ifcfg-lo:0
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
IPADDR=10.1.0.7
PREFIX=32
DEFROUTE=yes
NAME=lo:30
DEVICE=lo:30
ONBOOT=yes
重启网卡使配置文件生效
Centos7:
systemctl restart network
Centos8:
ifup lo:0 -->好像不行
nmcli c reload /etc/sysconfig/network-scripts/ifcfg-ens33 # 我验证不行
nmcli networking off && nmcli networking on # 验证可行,其它命令自行验证
ifdown ens33 && ifup ens33 # 验证可行,其它命令自行验证
nmcli con down ens33 && nmcli con up ens33
systemctl restart NetworkManager
4、RS 通过route add的路由规则,重启后丢失
#开机执行命令
vim /etc/rc.d/rc.local
/usr/sbin/route add -host 10.1.0.7 dev lo:0
chmod +x /etc/rc.d/rc.local
[root@lvs01 scripts]# cat ipvs_server.sh
#!/bin/bash
# author:Mr.chen
#LVS scripts
. /etc/init.d/functions
VIP=192.168.0.240
SUBNET="eth0:`echo $VIP | awk -F "." '{print $4}'`"
PORT=80
RIP=(
192.168.0.223
192.168.0.224
)
function start(){
if [ `ifconfig | grep $VIP | wc -l` -ne 0 ];then
stop
fi
ifconfig $SUBNET $VIP broadcast $VIP netmask 255.255.255.0 up
ipvsadm -C
ipvsadm --set 30 5 60
ipvsadm -A -t $VIP:$PORT -s rr -p 20
for ((i=0;i<${#RIP[*]};i++))
do
ipvsadm -a -t $VIP:$PORT -r ${RIP[$i]} -g -w 1
done
}
function stop(){
ipvsadm -C
if [ `ifconfig | grep $VIP | wc -l` -ne 0 ];then
ifconfig $SUBNET down
fi
route del -host $VIP dev eth0 &>/dev/null
}
case "$1" in
start)
start
echo "ipvs is started"
;;
stop)
stop
echo "ipvs is stopped"
;;
restart)
stop
echo "ipvs is stopped"
start
echo "ipvs is started"
;;
*)
echo "USAGE:$0 {start | stop | restart}"
esac
[root@web01 scripts]# cat rs_server.sh
#!/bin/bash
# author:Mr.chen
# RS_sever scripts
. /etc/rc.d/init.d/functions
VIP=192.168.0.240
case "$1" in
start)
echo "start LVS of REALServer IP"
interface="lo:`echo $VIP | awk -F "." '{print $4}'`"
/sbin/ifconfig $interface $VIP broadcast $VIP netmask 255.255.255.255 up
route add -host $VIP dev $interface
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/all/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce
;;
stop)
interface="lo:`echo $VIP | awk -F "." '{print $4}'`"
/sbin/ifconfig $interface down
echo "STOP LVS of REALServer IP"
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/all/arp_ignore
echo "0" > /proc/sys/net/ipv4/conf/all/arp_announce
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac