lvs类型、lvs调度方法


lvs类型:

lvs-nat: 通过修改请求报文的目标IP地址进行调度;类似多目标的DNAT;

lvs-dr:通过重新封闭请求报文的帧首部(目标为RS的RIP对应MAC地址)进行调度;

    (1) 在前端路由器上静态指定;

    (2) arptables;

    (3) 通过修改内核参数来限制arp通告和响应级别;

lvs-tun:通过为请求报文的原有IP首部之外再次封装外层IP首部完成调度;ipip;

lvs-fullnat:通过修改请求的报文的源IP以及目标IP地址进行调度;


lvs调度方法:

静态方法:rr, wrr, sh, dh

动态方法:lc(least connection), wlc, sed, nq, lblc, lblcr

lc: Overhead=Active*256+Inactive

sed: OVerhead=(Active+1)*256/weight


lvs: ipvs/ipvsadm

    ipvs: netfilter, input


ipvsadm:

    管理集群服务:

    定义集群服务的方法:

        -t service-address (IP:PORT)

        -u service-address (IP:PORT)

        -f service-address (FWM: firewall mark)

        

        -A|-E|-D

    

        -s scheduler


        管理集群服务的RS:

            为集群服务指定RS:

                -r server-address (IP[:PORT])

    

        lvs类型:-g|-i|-m

        指定权重:-w #

    

        -a|-e|-d

    

        查看:

            -L

            -n, --stats, --rate, --exact

        清空、保存及重载

        清空:-C

        保存:-S

        重载:-R

        

    session 保持:

    session sticky:基于源ip绑定,基于cookie绑定;

    session replication cluster:在各server之间以多播方式“复制”各session,从而每个server会持有所的session;(tomcat)

    session server:引入第三方存储,专用于共享存储session信息;(redis, memcached)

    

lvs-dr:

    (1) 各RS要直接响应Client,因此,各RS均得配置VIP;但仅能够让Director上的VIP能够与本地路由直接通信;

    (2) Director不会拆除或修改请求报文的IP首部,而是通过封装新的帧首部(源MAC为Director的MAC,目标MAC为挑选出的RS的MAC)完成调度;


2.4.26, 2.6.4 kernel引入了两个内核参数:

    arp_announce:定义arp通告限制级别;2----只能通告同一网络

    arp_ignore:定义arp忽略arp请求或arp通告的级别;1---只能请求目标就是目标地址


接口位置:/proc/sys/net/ipv4/conf/INTERFACE


配置过程总结:

    Director:

    (1) VIP配置在物理接口的别名上

    ifconfig INTERFACE:ALIAS $vip broadcast $vip netmask 255.255.255.255

    

    (2) 配置路由信息

    route add -host $vip dev INTEFACE:ALIAS

    

    RS:

    (1) 先修改内核参数

    echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore

    echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore

    echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

    echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce

    

    (2) VIP配置在lo的别名上

    ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up

    

    (3) 配置路径信息

    route add -host $vip dev lo:0


示例

集群及系统扩展基础(2)_dr

集群及系统扩展基础(2)_dr_02

集群及系统扩展基础(2)_dr_03

集群及系统扩展基础(2)_dr_04

集群及系统扩展基础(2)_dr_05

集群及系统扩展基础(2)_dr_06

集群及系统扩展基础(2)_dr_07

集群及系统扩展基础(2)_dr_08

集群及系统扩展基础(2)_dr_09

集群及系统扩展基础(2)_dr_10

集群及系统扩展基础(2)_dr_11

集群及系统扩展基础(2)_dr_12

集群及系统扩展基础(2)_dr_13

集群及系统扩展基础(2)_dr_14

集群及系统扩展基础(2)_dr_15

集群及系统扩展基础(2)_dr_16

集群及系统扩展基础(2)_dr_17

集群及系统扩展基础(2)_dr_18

集群及系统扩展基础(2)_dr_19

集群及系统扩展基础(2)_dr_20

集群及系统扩展基础(2)_dr_21

集群及系统扩展基础(2)_dr_22

集群及系统扩展基础(2)_dr_23


注意:vip和dip不是同一网段

    1.保证在路由器上要拥有各个网关地址,并开启路由转发

    2.rip配置ip和默认网关

    3.其他内核配置不变

    4.ipvsadm设置rip与VIP为不同网段

        


示例脚本:

DR类型director脚本示例:

    #!/bin/bash

    #

    vip=172.16.100.7

    rip=('172.16.100.8' '172.16.100.9')

    weight=('1' '2')

    port=80

    scheduler=rr

    ipvstype='-g'

    

    case $1 in

    start)

    iptables -F -t filter

    ipvsadm -C

    

    ifconfig eth0:0 $vip broadcast $vip netmask 255.255.255.255 up

    route add -host $vip dev eth0:0

    echo 1 > /proc/sys/net/ipv4/ip_forward

    

    ipvsadm -A -t $vip:$port -s $scheduler

    [ $? -eq 0 ] && echo "ipvs service $vip:$port added."  || exit 2

    for i in `seq 0 $[${#rip[@]}-1]`; do

    ipvsadm -a -t $vip:$port -r ${rip[$i]} $ipvstype -w ${weight[$i]}

    [ $? -eq 0 ] && echo "RS ${rip[$i]} added."

    done

    touch /var/lock/subsys/ipvs

    ;;

    stop)

    echo 0 > /proc/sys/net/ipv4/ip_forward

    ipvsadm -C

    ifconfig eth0:0 down

    rm -f /var/lock/subsys/ipvs

    echo "ipvs stopped."

    ;;

    status)

    if [ -f /var/lock/subsys/ipvs ]; then

    echo "ipvs is running."

    ipvsadm -L -n

    else

    echo "ipvs is stopped."

    fi

    ;;

    *)

    echo "Usage: `basename $0` {start|stop|status}"

    exit 3

    ;;

    esac



DR类型RS脚本示例:

    #!/bin/bash

    #

    vip=172.16.100.7

    interface="lo:0"

    

    case $1 in

    start)

    echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore

    echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore

    echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

    echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce

    

    ifconfig $interface $vip broadcast $vip netmask 255.255.255.255 up

    route add -host $vip dev $interface

    ;;

    stop)

    echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore

    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore

    echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce

    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce

    

    ifconfig $interface down

    ;;

    status)

    if ifconfig lo:0 |grep $vip &> /dev/null; then

    echo "ipvs is running."

    else

    echo "ipvs is stopped."

    fi

    ;;

    *)

    echo "Usage: `basename $0` {start|stop|status}"

    exit 1

    esac



lvs定义集群服务,有三种方式:

    -t service-address

    -u service-address

    -f service-address 

    FWM

    

    FWM: firewall mark

    iptables/netfilter, 

    filter, nat, mangle, raw

    

    mangle: 防火墙标记,目的为了使用不同端口访问同一个集群服务。

    

    前提:在ipvs生效之前的netfilter的某hook function上定义iptables规则,实现给报文打上防火墙标记;

    

    定义方法:

    (1) 打标:在Director上mangle表的PREROUTING链上实现

    # iptables -t mangle -A PREROUTING -d $vip -p $protocol --dport $port -j MARK --set-mark [1-99]

    

    (2) 基于FWM定义集群服务

    # ipvsadm -A -f FWM -s SCHEDULER

    # ipvsadm -a -f FWM -r server-address -g|-i|-m -w #

    

示例:

IP配置和路由配置和内核配置事先配置完毕

集群及系统扩展基础(2)_dr_24

集群及系统扩展基础(2)_dr_25



lvs的persistence: lvs持久连接


    无论使用哪一种调度方法,持久连接功能都能保证在指定时间范围之内,来自于同一个IP的请求将始终被定向至同一个RS;

    

    persistence template:持久连接模板

    

    PPC:每端口持久;持久连接生效范围仅为单个集群服务;如果有多个集群服务,每服务被单独持久调度;

    PCC:每客户端持久;持久连接生效范围为所有服务;定义集群服务时,其TCP或UDP协议的目标端口要使用0;

    PFWM:每FWM持久:持久连接生效范围为定义为同一个FWM下的所有服务;


示例

集群及系统扩展基础(2)_dr_26

集群及系统扩展基础(2)_dr_27

集群及系统扩展基础(2)_dr_28

集群及系统扩展基础(2)_dr_29

集群及系统扩展基础(2)_dr_30

集群及系统扩展基础(2)_dr_31

集群及系统扩展基础(2)_dr_32

集群及系统扩展基础(2)_dr_33

集群及系统扩展基础(2)_dr_34


    ipvsadm -A -t|-u|-f service-address -s SCHEDULER [-p [#]]

        无-p选项:不启用持久连接

        -p #:指定持久时长,省略时长,默认为300seconds

示例:(接上)ppc

集群及系统扩展基础(2)_dr_35

集群及系统扩展基础(2)_dr_36

集群及系统扩展基础(2)_dr_37

集群及系统扩展基础(2)_dr_38

集群及系统扩展基础(2)_dr_39

集群及系统扩展基础(2)_dr_40

集群及系统扩展基础(2)_dr_41

集群及系统扩展基础(2)_dr_42

集群及系统扩展基础(2)_dr_43

集群及系统扩展基础(2)_dr_44

集群及系统扩展基础(2)_dr_45


pcc

集群及系统扩展基础(2)_dr_46

集群及系统扩展基础(2)_dr_47

集群及系统扩展基础(2)_dr_48


pfwm

集群及系统扩展基础(2)_dr_49

集群及系统扩展基础(2)_dr_50

集群及系统扩展基础(2)_dr_51

集群及系统扩展基础(2)_dr_52

集群及系统扩展基础(2)_dr_53

集群及系统扩展基础(2)_dr_54

集群及系统扩展基础(2)_dr_55

集群及系统扩展基础(2)_dr_56

集群及系统扩展基础(2)_dr_57

集群及系统扩展基础(2)_dr_58

集群及系统扩展基础(2)_dr_59

集群及系统扩展基础(2)_dr_60

集群及系统扩展基础(2)_dr_61

集群及系统扩展基础(2)_dr_62


重做:

集群及系统扩展基础(2)_dr_63

集群及系统扩展基础(2)_dr_64

集群及系统扩展基础(2)_dr_65

集群及系统扩展基础(2)_dr_66

集群及系统扩展基础(2)_dr_67


dr的不同网段:

dr:vip,dip不同网段,同时指向各自网关

    vip:ifconfig eth0:0 192.168.0.2/24

    打开转发

    设置路由

    ipvs设置

rs:vip,dip不同网段,指向网关,设置路由,打开服务,配置防火墙





lvs集群:

    lvs本身不支持对RS的健康状态作检测;

    

    健康:周期性检查机制

    状态发生转变时,要作出相应处理

        up --> down: 建议要至少确认三次;

        down --> up: 建议一次以上(含一次);

    

    下线处理机制:

        (1) 设置权重为0;

        (2) 将相应的RS从ipvs的可用RS列表中移除;

    

    上线处理机制:

        (1) 设置为正常权重;

        (2) 将相应的RS添加至ipvs的可用RS列表;

    

    解决方案:

    (1) 写程序完成相应功能;


        如何做健康状态检查:

            三种方案:

                IP层:ping等主机在线状态探查工具;

                传输层:端口扫描工具探查服务在线状态;

                应用层:请求专用于健康状态检查的资源或者某正常资源;

        

        备用服务器:

            sorry server, backup server

            可以在Director上直接实现:即配置director成为web服务,仅提供有限资源,在所有RS都故障时,方才启用此server;

        

初始脚本,完成RS健康状态检查;


    #!/bin/bash

    #

    fwm=10

    sorry_server='127.0.0.1'

    lvstype='-m'

    checkloop=3

    logfile=/var/log/ipvs_health_check.log

    rs=('192.168.10.11' '192.168.10.12')

    rw=('1' '1')

    rsstatus=(0 0)

    

    addrs() {

       # $1: rs, $2: rs weight

       ipvsadm -a -f $fwm -r $1 $lvstype -w $2

       [ $? -eq 0 ] && return 0 || return 1

    }

    

    delrs() {

       # $1: rs

       ipvsadm -d -f $fwm -r $1

       [ $? -eq 0 ] && return 0 || return 1

    }

    

    chkrs() {

       # $1: rs

       local i=1

       while [ $i -le $checkloop ]; do

    if curl --connect-timeout 1 -s http://$1/index.html | grep -i "real[[:space:]]* server" &> /dev/null; then

        return 0

           fi

           let i++

    sleep 2

       done

       return 1

    }

      

    initstatus() {

       for host in `seq 0 $[${#rs[@]}-1]`; do

    if chkrs ${rs[$host]}; then

       if [ ${rsstatus[$host]} -eq 0 ]; then

    rsstatus[$host]=1

               fi

           else

       if [ ${rstatus[$host]} -eq 1 ]; then

    rsstatus[$host]=0

       fi

    fi

       done

    }

    

    initstatus

    

    while :; do

       for host in `seq 0 $[${#rs[@]}-1]`; do

    if chkrs ${rs[$host]}; then 

       if [ ${rsstatus[$host]} -eq 0 ]; then

    addrs ${rs[$host]} ${rw[$host]}

    [ $? -eq 0 ] && rsstatus[$host]=1

       fi

    else

       if [ ${rsstatus[$host]} -eq 1 ]; then

    delrs ${rs[$host]}

    [ $? -eq 0 ] && rsstatus[$host]=0

       fi

    fi

       done

       sleep 10

    done


    改进此脚本

(1) 启用在rs上下线时记录日志;

(2) 在所有rs下线时启用sorry_server;