目录

前言

1 、 LVS 环境组网

2 、 ipvsadm 安装前准备

3 、 httpd 与 ipvsadm 下载

4 、 LVS 负载均衡配置

5 、真实 WEB 服务器配置及 arp 抑制

6 、 LVS 负载均衡测试

7 、附: arp 抑制参数


前言

本文主要讲解 centos5.x LVS DR 模式,环境搭建,理论知识请参考 LVS 中文官网

http://www.linuxvirtualserver.org/zh/index.html

1  LVS 环境组网

由于是使用的 VM 环境,自己 PC 当作客户机(即公网地址),调度器与服务器都是 VM 中虚拟机,所以客户和所有服务器之间都是物理直接相连网络 , 逻辑拓扑图如下:


2  ipvsadm 安装前准备  (也可以使用 yum -y install ipvsadm 安装)

外部IP地址        内部IP地址         角色

10.0.0.30/24      192.168.1.1/24       LVS 调度器(虚拟机)

10.0.0.237/24     192.168.1.2/24       RS1 (虚拟机)

10.0.0.238/24    192.168.1.3/24       RS2 (虚拟机)

10.0.0.130/24    无            客户机(自己电脑)

注:实际应用中 RS1 RS2 没有外部地址,当前环境中,没有物理双网卡环境,都采用一个网卡配置多个 IP 地址。

3  httpd  ipvsadm 下载

)在各服务器上修改主机名:

[root@LVS1 ~]# hostname LVS1

[root@RS1 ~]# hostname RS1

[root@RS2 ~]# hostname RS2

)在 RS1 RS2 上安装 httpd 服务

[root@RS2 ~]# yum install httpd -y

[root@RS2 ~]# /etc/init.d/httpd start

[root@RS2 ~# ps -ef|grephttpd

[root@RS1 ~]# yum install httpd –y

[root@RS1 ~]# /etc/init.d/httpdstart

[root@RS1 ~# ps -ef|grephttpd <== 查看 httpd 服务是否起来

[root@RS1 ~]# cat/etc/httpd/conf/httpd.conf|grep DocumentRoot   <== 查找系统站点目录路径

# DocumentRoot: The directoryout of which you will serve your

DocumentRoot"/var/www/html"

# This should be changed towhatever you set DocumentRoot to.

#    DocumentRoot/www/docs/dummy-host.example.com

[root@RS1 ~]# echo"RS1" >/var/www/html/index.html

[root@RS2 src]# echo"RS2" >/var/www/html/index.html

Httpd 服务测试:

测试成功!

)下载 ipvsadm

wget http://www.linuxvirtualserver.org/software/kernel-2.6/ipvsadm-1.24.tar.gz

wget http://www.linuxvirtualserver.org/software/kernel-2.6/ipvsadm-1.26.tar.gz

我所使用的源包下载目录 /usr/local/src

我的 LVS 环境:

[root@RS1 src]# cat/etc/redhat-release

CentOS release 5.8 (Final)

[root@RS1 src]# uname -rm

2.6.18 -308.el5 x86_64

ipvsadm-1.26 对内核有要求,要求内核版本在 2.6.28 及以后的版本,如果符合了系统环境,还要安装依赖包 yum install -y wget make kernel-devel gcc gcc-c++ libnl* libpopt* popt-static

我的内核版本不满足,使用 ipvsadm-1.24 

[root@LVS1 src]# tar -zxfipvsadm-1.24.tar.gz

[root@LVS1 src]# ln -s /usr/src/kernels/2.6.18-348.12.1.el5-x86_64 /usr/src/linux <== 编译有使用的路径为 /usr/src/linux ,可在 Makefile 中查看,如果不做链接,会编译失败

[root@LVS1 src]# ll /usr/src/

total 16

drwxr-xr-x 2 root root 4096 May11  2011 debug

drwxr-xr-x 3 root root 4096Aug  5 03:53 kernels

lrwxrwxrwx1 root root   43 Aug  5 03:56 linux ->/usr/src/kernels/2.6.18-348.12.1.el5-x86_64 <== 要使用 ll /usr/src/ 查看,如果软链接一闪一闪的,代表链接失败

[root@LVS1 src]# cd ipvsadm-1.24

[root@LVS1 ipvsadm-1.24]# make && make install   <== 如果编译失败,请按上面步骤一步一步排错。

[root@LVS1 ipvsadm-1.24]# lsmod |grepip_vs     <== 查看内核模块是否有 ipvsadm

[root@LVS1 ipvsadm-1.24]# ipvsadm

IP Virtual Server version 1.2.1(size=4096)

Prot LocalAddress:PortScheduler Flags

 -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

# 还有一种加载 ipvsadm 方法,用 modprobe ip_vs

[root@LVS1 ipvsadm-1.24]# lsmod |grepip_vs   <== 查看内核模块,有代表 ipvsadm 加载进内核当中,此时 LVS 安装完毕

ip_vs                 122113  0

4  LVS 负载均衡配置

)配置 VIP  DIP

 IP 配置参考步骤 2 安装准备

[root@LVS1 ~]# ifconfig eth0 10.0.0.30 netmask 255.255.255.0 up   #VIP

[root@LVS1 ~]# ifconfig eth0:1 192.168.1.1 netmask 255.255.255.0 up #DIP

echo "1" >/proc/sys/net/ipv4/ip_forward        #设置转发

)添加真实服务器

[root@LVS1 ~]# ipvsadm –C       <== 手工清空原来表内容

[root@LVS1 ~]# ipvsadm --set 30 5 60   <== 设置连接超时值

[root@LVS1 ~]# ipvsadm -A -t 10.0.0.30:80 -s wrr -p 20   <== -A 添加地址, -t 指定VIP TCP 端口, -s 指定调度算法 –p 会话保持时间

[root@LVS1 ~]# ipvsadm -L –n     <== 查看表内容,添加了一组 VIP 地址和端口

IP Virtual Server version 1.2.1(size=4096)

Prot LocalAddress:PortScheduler Flags

 -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  10.0.0.30:80 wrr persistent 20

[root@LVS1 ~]# ipvsadm -a -t 10.0.0.30:80 -r 192.168.1.2:80 -g -w 1   <== -a 指定真实服务器, -t lvs  VIP  -r 真实服务器 ip 及端口, -w 权重值  -g 先择 DR 模式( -m  NAT 模式)

[root@LVS1 ~]# ipvsadm -a -t 10.0.0.30:80 -r 192.168.1.3:80 -g -w 1

[root@LVS1 ~]# ipvsadm -L –n       <== 查看表内容,添加了两台负载转发的真实服务器

IP Virtual Server version 1.2.1(size=4096)

Prot LocalAddress:PortScheduler Flags

 -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  10.0.0.30:80 wrr persistent 20

 -> 192.168.1.2:80               Route   1     0          0        

 -> 192.168.1.3:80               Route   1     0          0

如果添加服务器地址写错了,可用如下命令删除,即大 A 添加改为大 D 删除,小 a添加改为小 d 删除

ipvsadm –D –t10.0.0.30:80 –s wrr

ipvsadm –d –t10.0.0.30:80 –r 192.168.1.2:80

5 、真实 WEB 服务器配置及 arp 抑制

[root@RS1 ~]# ifconfig eth0|grep "inet addr"   <== 此地址用来自己电脑用 CRT 软件登陆设备,同时也用来发送 arp 请求客户机 MAC (因为是直接返回页面给客户机,而当前网络是同一物理网段,必须同网段才正常)。

         inet addr:10.0.0.237  Bcast:10.0.0.255  Mask:255.255.255.0

[root@RS1 ~]# ifconfig eth0:1192.168.1.2 netmask 255.255.255.0   <== 配置内部 IP 地址

[root@RS1 ~]# ifconfig lo10.0.0.30 netmask 255.255.255.255   <== 每台真实服务器都需要配置 VIP

为什么要绑定 VIP 呢? 因为 DR 模式原理是 LVS 调度器修改 mac 地址为真实服务器地址,报文的目的 IP 还是 VIP 没修改,,网卡只会把目的 MAC 和目的 IP 都是自己的报文上送 CPU ,所以真实服务器上必须配置 VIP!

为什么使用 lo 口呢? 因为 lo 口为本地环回口,防止本地局域网 IP 地址冲突 !

[root@RS2 src]# ifconfig eth0|grep "inet addr"   <== 此地址用来自己电脑用 CRT 软件登陆设备,同时也用来发送 arp 请求客户机 MAC (因为是直接返回页面给客户机,而当前网络是同一物理网段,必须同网段才正常)。

         inet addr:10.0.0.238  Bcast:10.0.0.255  Mask:255.255.255.0

[root@RS2 src]# ifconfig eth0:1192.168.1.3 netmask 255.255.255.0   <== 配置内部IP 地址

[root@RS2 src]# ifconfig lo10.0.0.30 netmask 255.255.255.255  

此时配置完成,只是测试时出现一个问题,再次登陆 CRT  10.0.0.30 地址时,登陆到 RS1 上去了,再刷新,登陆到 RS2 上去了。怎么解决呢?

通过分析,得出,访问 10.0.0.30 时,会发送 arp 请求 10.0.0.30  mac, 而这个网络中有 3  10.0.0.30 地址,此时,那谁给的 arp 回应到客户机,访问的就是谁了。如果 RS1  arp 回应先到,就访问的 RS1 

解决方法:

抑制 ARP 响应

该抑制只在真实服务器上配置

[root@RS1 ~]# echo"1" >/proc/sys/net/ipv4/conf/lo/arp_ignore

[root@RS1 ~]# echo"2" >/proc/sys/net/ipv4/conf/lo/arp_announce

[root@RS1 ~]# echo"1" >/proc/sys/net/ipv4/conf/all/arp_ignore

[root@RS1 ~]# echo"2" >/proc/sys/net/ipv4/conf/all/arp_announce

[root@RS2 src]# echo"1" >/proc/sys/net/ipv4/conf/lo/arp_ignore

[root@RS2 src]# echo"2" >/proc/sys/net/ipv4/conf/lo/arp_announce

[root@RS2 src]# echo"1" >/proc/sys/net/ipv4/conf/all/arp_ignore

[root@RS2 src]# echo"2" >/proc/sys/net/ipv4/conf/all/arp_announce

1 2 都代表什么内容,可在最后附录中查看,也可自己网上搜索

6  LVS 负载均衡测试

显示的值是 RS1, 则此时该链接是分配到 192.168.1.2 

我们使用的是 wrr 调度算法,该算法中,谁的权重值高,会优先分配给谁

查看配置,发现权重值一样

[root@LVS1 ~]# ipvsadm -L -n

IP Virtual Server version 1.2.1(size=4096)

Prot LocalAddress:PortScheduler Flags

 -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  10.0.0.30:80 wrr persistent 20

 -> 192.168.1.2:80               Route   1     0         0        

 -> 192.168.1.3:80               Route   1     0         0  

由于有会话保持功能,接下来修改权重值

[root@LVS1 ~]# ipvsadm -d -t10.0.0.30:80 -r 192.168.1.3:80  <== 删除原来配置

[root@LVS1 ~]# ipvsadm -a -t10.0.0.30:80 -r 192.168.1.3:80 -g -w 2 <== 重新配置权重值为 2

[root@LVS1 ~]# ipvsadm -L -n

IP Virtual Server version 1.2.1(size=4096)

Prot LocalAddress:PortScheduler Flags

 -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  10.0.0.30:80 wrr persistent 20

 -> 192.168.1.3:80               Route   2     0         0        

 -> 192.168.1.2:80               Route   1     0         0    

再次进行测试:

7 、附: arp 抑制参数

arp 响应限制

 arp_ignore:

定义对目标地址为本地 IP  ARP 询问不同的应答模式 0

0 - ( 默认值 ): 回应任何网络接口上对任何本地 IP 地址的 arp 查询请求

1 - 只回答目标 IP 地址是来访网络接口本地地址的 ARP 查询请求

2 - 只回答目标 IP 地址是来访网络接口本地地址的 ARP 查询请求 , 且来访 IP 必须在该网络接口的子网段内

3 - 不回应该网络界面的 arp 请求,而只对设置的唯一和连接地址做出回应

4-7 - 保留未使用

8 - 不回应所有(本地地址)的 arp 查询

 arp_announce:

对网络接口上,本地 IP 地址的发出的, ARP 回应,作出相应级别的限制 : 确定不同程度的限制 , 宣布对来自本地源 IP 地址发出 Arp 请求的接口

0 - ( 默认 ) 在任意网络接口( eth0,eth1  lo )上的任何本地地址

1 - 尽量避免不在该网络接口子网段的本地地址做出 arp 回应 . 当发起 ARP 请求的源 IP 地址是被设置应该经由路由达到此网络接口的时候很有用 . 此时会检查来访 IP是否为所有接口上的子网段内 ip 之一 . 如果改来访 IP 不属于各个网络接口上的子网段内 , 那么将采用级别 2 的方式来进行处理 .

2 - 对查询目标使用最适当的本地地址 . 在此模式下将忽略这个 IP 数据包的源地址并尝试选择与能与该地址通信的本地地址 . 首要是选择所有的网络接口的子网中外出访问子网中包含该目标 IP 地址的本地地址 . 如果没有合适的地址被发现 , 将选择当前的发送网络接口或其他的有可能接受到该 ARP 回应的网络接口来进行发送 .


LVS脚本:

vi lvs

#!/bin/sh

#

# Startup script for the Keepalived daemon

#

# processname: keepalived

# pidfile: /var/run/keepalived.pid

# config: /etc/keepalived/keepalived.conf

# chkconfig: - 21 79

# description: Start and stop Keepalived


# Source function library

. /etc/rc.d/init.d/functions


# Source configuration file (we set KEEPALIVED_OPTIONS there)

. /etc/sysconfig/keepalived


RETVAL=0


prog="keepalived"


start() {

    echo -n $"Starting $prog: "

    daemon keepalived ${KEEPALIVED_OPTIONS}

    RETVAL=$?

    echo

    [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog

}


stop() {

    echo -n $"Stopping $prog: "

    killproc keepalived

    RETVAL=$?

    echo

    [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog

}


reload() {

    echo -n $"Reloading $prog: "

    killproc keepalived -1

    RETVAL=$?

    echo

}


# See how we were called.

case "$1" in

    start)

        start

        ;;

    stop)

        stop

        ;;

    reload)

        reload

        ;;

    restart)

        stop

        start

        ;;

    condrestart)

        if [ -f /var/lock/subsys/$prog ]; then

            stop

            start

        fi

        ;;

    status)

        status keepalived

        ;;

    *)

        echo "Usage: $0 {start|stop|reload|restart|condrestart|status}"

        exit 1

esac


exit $RETVAL

#########


centos 7

/usr/lib/systemd/system/keepalived.service

#####

[Unit]

Description=LVS and VRRP High Availability Monitor

After=syslog.target network.target


[Service]

Type=forking

KillMode=process

EnvironmentFile=-/etc/sysconfig/keepalived

ExecStart=/usr/sbin/keepalived $KEEPALIVED_OPTIONS

ExecReload=/bin/kill -HUP $MAINPID


[Install]

WantedBy=multi-user.target

#####


##########################################

realServer脚本:

vi realserver

#!/bin/bash

#

# Add for chkconfig

# chkconfig: 2345 70 30  

# description: RealServer's script

# processname: realserver.sh


VIP=192.168.1.1


# Source function library.

. /etc/init.d/functions



case "$1" in

start)

       ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $VIP

       /sbin/route add -host $VIP dev lo:0

       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

       echo "RealServer Start OK"

       ;;

stop)

       ifconfig lo:0 down

       route del $VIP >/dev/null 2>&1

       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 "RealServer Stoped"

       ;;

       *)

       echo "Usage: $0 {start|stop}"

       exit 1

esac

exit 0