LVS服务之高级进阶


纸上得来终觉浅,绝知此事要躬行。

LVS服务之高级进阶


1. DR 模式的扩展

DR 模式VIPRIP在和不在同一网段的实验

LVS服务之高级进阶

主要纪要

  • 在虚拟一个路由器,将RIPs的网关都指向这个虚拟出来的路由器
  • 虚拟路由器的另一个端口连接至DS所在的交换机
  • 或者直接通过另外的路由器响应客户端

物理网络搭建

  • 本机当做客户端,创建四个虚拟机
  • DS和两个RIP只有一块物理网卡且都是桥接模式
  • 第四台虚拟机,一个网卡两个地址或者两块网卡各一个地址,打开网卡转发功能,分别将RIPs的网关都指向其中一个地址,另外一个接口还要连接交换机

1.1 配置都在同一网络

LVS服务之高级进阶

  • 物理网卡地址
# DS和RSs都是桥接模式
DS的DIP物理网卡:172.16.100.9
RS1的RIP物理网卡:172.16.100.21
RS2的RIP物理网卡:172.16.100.22
  • DS 配置网络地址
# 配置都在同一网络
# DS主机,可以使用ifconfig、ip、setup命令配置
ifconfig eno16777724:0 172.16.100.10 netmask 255.255.255.255 broadcast 172.16.100.10 up

# 别名配置路由
route add -host 172.16.100.10 dev eno16777724:0

# 在本机查看规则是否好了
arp -a
# 使用ip添加规则
ip addr add 172.16.100.10/32 dev eno16777724
ip addr list
ip addr del 172.16.100.10/32 dev eno16777724

# 添加路由规则,可以不加,没有使用别名
ip route add 172.16.100.10 dev eno16777724
ip route list
ip route del 172.16.100.10

# 在本机查看规则是否好了
arp -a
  • RSs 配置网络地址
# 分别配置RSs主机,启动web服务
[root@localhost ~]# vim set_lvs_dr.sh
#!/bin/bash
VIP=172.16.100.10
VIP_MASK=255.255.255.255

case $1 in
    start_dr)
        echo 1 > /proc/sys/net/ipv4/conf/all/arp-ignore
        echo 1 > /proc/sys/net/ipv4/conf/eth0/arp-ignore
        echo 2 > /proc/sys/net/ipv4/conf/all/arp-announce
        echo 2 > /proc/sys/net/ipv4/conf/eth0/arp-announce
        ;;
    stop_dr)
        echo 0 > /proc/sys/net/ipv4/conf/all/arp-ignore
        echo 0 > /proc/sys/net/ipv4/conf/eth0/arp-ignore
        echo 0 > /proc/sys/net/ipv4/conf/all/arp-announce
        echo 0 > /proc/sys/net/ipv4/conf/eth0/arp-announce
        ;;
    start_ip)
        ifconfig lo:0 $VIP netmask $(VIP_MASK) broadbcast $VIP up
        ;;
    stop_ip)
        ifconfig lo:0 down
        ;;
esac

[root@localhost ~]# chmod +x set_lvs_dr.sh
[root@localhost ~]# ./set_lvs_dr.sh start_dr
[root@localhost ~]# ./set_lvs_dr.sh start_ip
  • DS 配置调度算法
# DS上设置调度规则
ipvsadm -A -t 172.16.100.10:80 -s rr
ipvsadm -L -n

ipvsadm -a -t 172.16.100.10:80 -r 172.16.100.21 -g
ipvsadm -a -t 172.16.100.10:80 -r 172.16.100.22 -g

1.2 配置都不在同一网络

LVS服务之高级进阶

  • DS 配置网络地址
# DS上设置网络
# 删除之前配置的网络100.9的物理地址还在
ip addr del 172.16.100.10/32 dev eno16777724

# 添加非本网段地址,VIP地址
# 网关都要指向,172.16.0.1,包括物理地址和本机地址
ip addr add 192.168.0.10/32 dev eno16777724

# 在本机查看规则是否好了
arp -a
  • RSs 配置网络地址
# 分别配置RSs主机,启动web服务
[root@localhost ~]# vim set_lvs_dr.sh
#!/bin/bash
VIP=192.168.0.10
VIP_MASK=255.255.255.255

case $1 in
    start_dr)
        echo 1 > /proc/sys/net/ipv4/conf/all/arp-ignore
        echo 1 > /proc/sys/net/ipv4/conf/eth0/arp-ignore
        echo 2 > /proc/sys/net/ipv4/conf/all/arp-announce
        echo 2 > /proc/sys/net/ipv4/conf/eth0/arp-announce
        ;;
    stop_dr)
        echo 0 > /proc/sys/net/ipv4/conf/all/arp-ignore
        echo 0 > /proc/sys/net/ipv4/conf/eth0/arp-ignore
        echo 0 > /proc/sys/net/ipv4/conf/all/arp-announce
        echo 0 > /proc/sys/net/ipv4/conf/eth0/arp-announce
        ;;
    start_ip)
        ifconfig lo:0 $VIP netmask $(VIP_MASK) broadbcast $VIP up
        ;;
    stop_ip)
        ifconfig lo:0 down
        ;;
esac

[root@localhost ~]# chmod +x set_lvs_dr.sh
[root@localhost ~]# ./set_lvs_dr.sh start_dr
[root@localhost ~]# ./set_lvs_dr.sh start_ip
  • DS 配置调度算法
# 清除之前配置的规则
ipvsadm -C

# DS上设置调度规则
ipvsadm -A -t 192.168.0.10:80 -s rr
ipvsadm -L -n

ipvsadm -a -t 192.168.0.10:80 -r 172.16.100.21 -g
ipvsadm -a -t 192.168.0.10:80 -r 172.16.100.22 -g

1.3 示例脚本

  • DR 类型 director 脚本示例
#!/bin/bash

vip=172.16.100.33
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.33
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

2. LVS 的防火墙标记

我们都已经知道ipvs是定义在INPUT链上的,所有要进行防火墙标记就需要在PREROUTING链上进行,不然ipvs不可能对标记进行处理的。

防火墙标记的要点

  • 格式:-j MARK --set-mark 10
  • mark的取值范围为0-2^32,一般都会在设置100以内
  • 可以过滤某一类特定请求,如tcp/80进行标记处理
  • 可以将多个服务进行标记,如tcp/80tcp/22进行合并处理

定义集群的方式

# (1) 在DS上netfilter的mangle表的PREROUTING定义用于打标的规则
# $vip: VIP地址
# $protocol: 协议
# $port: 协议端口
iptables -t mangle -A PREROUTING -d $vip -p $protocol --dports $port -j MARK --set-mark xxx

# (2) 基于FWM定义集群服务
ipvsadm -A -f xxx -s scheduler

# 功用:将共享一组RS的集群服务统一进行定义

2.1 标记配置方式

  • 通过防火墙标记定义集群的方式
# -j MARK:来定义使用防火墙标记
# --set-mark:来设置防火墙标记的数字
iptables -t mangle -A PREROUTING -d 192.168.0.10 -p tcp --dport 80 -j MARK --set-mark 10

ipvsadm -C
ipvsadm -A -f 10 -s rr
ipvsadm -a -f 10 -r 172.16.100.21 -g
ipvsadm -a -f 10 -r 172.16.100.22 -g
  • 通过防火墙标记将多个服务进行标记
# http访问VIP可以在21和22上跳转
iptables -t mangle -A PREROUTING -d 192.168.0.10 -p tcp --dport 80 -j MARK --set-mark 10
# ssh访问VIP可以在21和22上跳转
iptables -t mangle -A PREROUTING -d 192.168.0.10 -p tcp --dport 22 -j MARK --set-mark 10
# https访问VIP可以在21和22上跳转
iptables -t mangle -A PREROUTING -d 192.168.0.10 -p tcp --dport 443 -j MARK --set-mark 10

ipvsadm -C
ipvsadm -A -f 10 -s rr
ipvsadm -a -f 10 -r 172.16.100.21 -g
ipvsadm -a -f 10 -r 172.16.100.22 -g

2.2 配置 HTTPS 服务

# DS作为CA颁发签名证书
cd /etc/pki/CA
(umask 077; openssl genrsa -out private/cakey.pem 2048)
touch index.txt
echo 01 > serial

openssl -req -new -x509 -key private/cakey.pem -out cacert.pem -days 465
填写信息等
# RS申请证书
mkdir -pv /etc/httpd/ssl
cd /etc/httpd/ssl
(umask 077; openssl genrsa -out httpd.key 1024)

openssl req -new -key httpd.key -out httpd.csr
填写信息等

scp httpd.csr [email protected]:/tmp
# CA颁发签名
openssl ca -in /tmp/httpd.csr -out /tmp/httpd.crt
scp /tmp/httpd.crt [email protected]:/etc/httpd/ssl
# 把21的证书复制给22服务器
cd /etc/httpd/ssl
scp -rp ssl/ [email protected]:/etc/httpd/
# 分别配置RS主机中安装ssl服务
yum install mod_ssl

vim /etc/httpd/conf.d/ssl.conf
启用ssl服务
DocumentRoot "/var/www/html"
SSLCertificateFile /etc/httpd/ssl/httpd.crt
SSLCertificateKeyFile /etc/httpd/ssl/httpd.key

httpd -t
service httpd restart
# 配置DS的ipvs规则的HTTPS服务,80
ipvsadm -C
ipvsadm -A -t 192.168.0.10:443 -s rr
ipvsadm -a -t 192.168.0.10:443 -r 172.16.100.21 -g
ipvsadm -a -t 192.168.0.10:443 -r 172.16.100.22 -g
# 配置DS的ipvs规则的HTTPS服务,80和443
# 也可以通过iptables的配置文件进行修改,查看一下呗
iptables -t mangle -A PREROUTING -d 192.168.0.10 -p tcp --dport 80 -j MARK --set-mark 10
iptables -t mangle -A PREROUTING -d 192.168.0.10 -p tcp --dport 443 -j MARK --set-mark 10

ipvsadm -C
ipvsadm -A -f 10 -s rr
ipvsadm -a -f 10 -r 172.16.100.21 -g
ipvsadm -a -f 10 -r 172.16.100.22 -g

2.3 session 保持

持久连接的引入

  • 对于HTTPHTTPS的会话保持就很难区分了,即使是sh算法也不可用了,即session绑定不可用了。
  • 用户一开始使用HTTP协议进行网页浏览,而结账的时候使用HTTPS协议,这就导致可能用户的请求被调度道不同的服务上了。session绑定就解决不了问题了,session复制和session服务器就可以保证,同一IP地址访问网站始终调用到同一服务器,但是会引入额外的组件。其实LVS自己也只有实现的机制,就是LVS的持久连接lvs persistence

持久连接的实现方式

  • **每端口持久(PPC)**:单服务持久调度
    • 可以实现sh的功能且可以设置超时时长,而sh不能设置超时时长
    • 用户如果超时之后没有断开连接,会自动续2min时长,之后连接为新请求
  • **每 FWM 持久(PFWMC)**:单防火墙标记持久调度
    • PORT AFFINITY
    • 只对标记进行调度,不管服务类型,需要将多种服务进行同一打标时使用
  • **每客户端持久(PCC)**:单客户端持久调度
    • DS会将用户的任何请求都识别为集群服务,并向RS进行调度
    • 请求TCP服务的端口范围:1-65535
    • 请求UDP服务的端口范围:1-65535

持久连接的注意事项

  • 持久连接的实现方式,会占据内存空间,而且空间存储的条目有限制
# PPC: DS上设置
# 定义: 将来自于同一个客户端对同一个集群服务的请求,始终定向至此前选定的RS ==> 持久端口连接
# 特点: client --> LVS(80) --> RS1 或 client --> LVS(80) --> RS2
# 缺陷: 期望访问不同的端口到同一台RS上,无法实现

# 单服务持久调度
# 可以实现类似于sh功能的调度算法,并可以设置超时时长
ipvsadm -C
ipvsadm -A -t 192.168.0.10:80 -s rr -p 3600
ipvsadm -a -t 192.168.0.10:80 -r 172.16.100.21 -g -w 1
ipvsadm -a -t 192.168.0.10:80 -r 172.16.100.22 -g -w 2

ipvsadm -L -n

# 加深理解: 原本的调度模式
# 没有-p参数,所有不是持久连接的方式
ipvsadm -A -t 192.168.0.10:22 -s rr
ipvsadm -a -t 192.168.0.10:22 -r 172.16.100.21 -g
ipvsadm -a -t 192.168.0.10:22 -r 172.16.100.22 -g
# PFWMC:DS上设置
# 定义: 根据iptables的规则,将对于某类服务几个不同端口的访问定义为一类 ==> 持久防火墙标记连接

# 配置DS的ipvs规则的HTTP/HTTPS服务,80和443端口
# 也可以通过iptables的配置文件进行修改,查看一下呗
iptables -t mangle -A PREROUTING -d 192.168.0.10 -p tcp --dport 80 -j MARK --set-mark 10
iptables -t mangle -A PREROUTING -d 192.168.0.10 -p tcp --dport 443 -j MARK --set-mark 10

# 单防火墙标记持久调度
ipvsadm -C
ipvsadm -A -f 10 -s rr -p 3600
ipvsadm -a -f 10 -r 172.16.100.21 -g
ipvsadm -a -f 10 -r 172.16.100.22 -g

ipvsadm -L -n

# 加深理解:原本的调度模式
ipvsadm -A -t 192.168.0.10:22 -s rr
ipvsadm -a -t 192.168.0.10:22 -r 172.16.100.21 -g
ipvsadm -a -t 192.168.0.10:22 -r 172.16.100.22 -g
# PCC: DS上设置
# 定义: 将来自于同一个客户端对所有端口的请求,始终定向至此前选定的RS ==> 持久客户端连接
# 特点: PCC是一个虚拟服务没有端口号或者端口号为0,使用-p来标识服务超市时长
# 缺陷: 定向所有服务,期望访问不同的RS无法实现

# 单客户端持久调度
ipvsadm -C
ipvsadm -A -t 192.168.0.10:0 -s rr -p
ipvsadm -a -t 192.168.0.10:0 -r 172.16.100.21 -g -w 1
ipvsadm -a -t 192.168.0.10:0 -r 172.16.100.22 -g -w 2

ipvsadm -L -n

# 加深理解: 原本的调度模式
ipvsadm -A -t 192.168.0.10:22 -s rr
ipvsadm -a -t 192.168.0.10:22 -r 172.16.100.21 -g
ipvsadm -a -t 192.168.0.10:22 -r 172.16.100.22 -g

3. LVS 的高可用解决方案

SPOF:Single Point of Failure

故障点

  • DS 服务器单点故障 -> HA高可用集群
    • DS如果挂了,会导致整个服务都不可用,所有需要做高可用
    • KeepAlived可以进行高可用,而且还可以实现对RS的健康监测
  • 后端真实主机挂了 -> DSRS做健康监测
    • 如果后端主机RS挂了,DS能够监测到并将其上的连接交给其他主机处理
    • RS恢复的时候,DS能够检测到恢复的主机,并让主机自动上线,继续提供对应的服务

健康监测设计方案

  • 1、基于协议层次检查:效率
    • IP 层: icmp
    • 传输层:检测端口的开放状态
    • 应用层:请求获取关键性的资源
  • 2、检查频度
    • 不能过于频繁也不能过于不频繁,折中处理
    • 日志中需要对其监测进行过滤,保存或者保存到其他地方
  • 3、状态判断
    • 下线:ok --> failure --> failure --> failure
    • 上线:failure --> ok --> ok
  • 4、back server
    • DS可以在RS都挂了的情况下,DS启动服务响应用户请求
#!/bin/bash

fwm=6
sorry_server=127.0.0.1
rs=('172.16.100.21' '172.16.100.22')
rw=('1' '2')
type='-g'
chkloop=3
rsstatus=(0 0)
logfile=/var/log/ipvs_health_check.log

addrs() {
    ipvsadm -a -f $fwm -r $1 $type -w $2
    [ $? -eq 0 ] && return 0 || return 1
}

delrs() {
    ipvsadm -d -f $fwm -r $1
    [ $? -eq 0 ] && return 0 || return 1
}

chkrs() {
    local i=1
    while [ $i -le $chkloop ]
    do
        if curl --connect-timeout 1 -s http://$1/.health.html | grep "OK" &> /dev/null; then
            return 0
        fi
        let i++
        sleep 1
    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 [ ${rsstatus[$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]} ${rw[$host]}
                [ $? -eq 0 ] && rsstatus[$host]=0
            fi
        fi
    done
    sleep 5
done

文章作者: Escape
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Escape !
  目录