1. 软件说明

从2.4版本开始 , linux内核默认支持LVS。要使用LVS的能力 , 只需安装一个LVS的管理工具: ipvsadm。

  • LVS的结构主要分为两部分:

    • 工作在内核空间的IPVS模块。LVS的能力实际上都是由IVPS模块实现。

    • 工作在用户空间的ipvsadm管理工具。其作用是向用户提供一个命令接口 , 用于将配置的虚拟服务、真实服务等传给IPVS模块。

2. 命令使用

其实LVS的本身跟iptables很相似,而且连命令的使用格式都很相似,其实LVS是根据iptables的框架开发的,那么LVS的本身分成了两个部分:

第一部分是工作在内核空间的一个IPVS的模块,其实LVS的功能都是IPVS模块实现的。

第二部分是工作在用户空间的一个用来定义集群服务的一个工具ipvsadm , 这个工具的主要作用是将管理员定义的集群服务列表传送给工作在内核空间中的IPVS模块 , 下面来简单的介绍下ipvsadm命令的用法。

集群服务管理 : 增、删、改

  1. 增加、修改

    • 语法 : ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p timeout] [-M netmask] [-b sched-flags]

      • -A, --add-service : 添加一个虚拟服务 , 使用ip地址、端口号、协议来唯一定义一个虚拟服务, 添加内容保存在内核虚拟服务器列表中

      • -E ,--edit-service : 编辑内核虚拟服务器表中的一个虚拟服务器记录

      • -t , --tcp-service : tcp协议的某个服务添加为集群服务

      • -u , --udp-service : udp协议的某个服务添加为集群服务

      • -f , --fwmark-service: firewall mark 防火墙标记

        • service-address

          -t : TCP协议时, 此地址对应为: VIP:PORT

          -u : UDP协议时, 此地址对应为: VIP:PORT

          -f : 防火墙标记时,此地址对应为: MARK(防火墙的标记)

      • -s scheduler , --scheduler scheduling-method: 指明调度算法。省略此项时,默认为wlc

      • -p timeout , --persistent timeout : 当定义LVS的持久连接时,指明持久连接时长

      • -M,--network netmask : 指定客户地址的子网掩码。用于将同属一个子网的客户的请求转发到相同的服务器。使用网络掩码来屏蔽持久化来源IP的地址范围 , 默认值为255.255.255.255 , 即所有来源IP请求都会享受持久化服务

      • --sched-flags sched-flags , -b flags , scheduler flags (comma-separated) : 设置调度算法的范围标识 , 用于SH算法。

        有两个标识:sh-fallback , 如果真实服务器不可用 , 则将其转发到其他真实服务器上。

        sh-port,将源地址的端口号也添加到散列键=值中

      示例

      #表示添加一个tcp类型的集群服务, 服务监听的地址是:10.1.32.68的80端口, 采取的调度算法为rr算法
      ipvsadm -A -t 10.1.32.68:80 -s rr
      ​
      #添加一个tcp类型的集群服务,服务监听的地址是10.1.32.68的3306端口采用的调度算法是wlc
      ipvsadm -A -t 10.1.32.68:3306 -s wlc
      ​
      #修改集群服务
      ipvsadm -E -t 10.1.32.68:80 -s wlc 

  2. 删除指定的集群服务

    • 语法 : ipvsadm -D -t|u|f service-address

      • -D : 删除内核虚拟服务器表中的一条虚拟服务器记录, 并删除所有与该虚拟服务器相关联的真实服务器

    • 示例

      ipvsadm -D -t 10.1.32.68:80

集群上Real Server的管理

  1. 增加、修改

    ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight] [-x upper] [-y lower]
    • -a,--add-server : 在内核虚拟服务器表的一条记录里添加一条新的真实服务器记录。也就是在一个虚拟服务器中增加一台新的真实服务器

    • -e,--edit-server : 编辑一条虚拟服务器记录中的某条真实服务器记录

    • -t|u|f service-address

      • -t/--tcp-service service-address : 说明虚拟服务器提供的是tcp的服务。服务器的地址形式为: 主机[:端口]。

        主机可以是IP地址也可以是主机名。

        端口可以是普通的端口号 , 也可以是端口的服务名称。端口可以被省略 , 在这种情况下 , 默认端口号为0。当端口号为0时, 需要指定服务器提供持久稳固的服务(也即是使用了-p / --persistent选项)才有效 。在这种情况下, 它是一个通配符端口 , 即访问任何端口的连接都将被接受。

      • -u/--udp-service service-address : 虚拟服务器提供的是udp 的服务。服务器地址的形式为 主机[:端口]。

      • -f/--fwmark-service fwmark : 使用fwamrk(fwmark是一个大于0的整数值)来防火墙标识集群服务 , 而不是地址、 端口和协议使用它 , fwmark可以通过结合IPtables将多个以调度器为目标的端口定义成一个防火墙标识 , 由ipvsdam通过此项关联标识 , 则可以实现对一个IP多端口调度 , 即实现后端服务器可以开放多个服务

    • -r server-address : 指定真实服务器的主机ip和端口

    • -g|i|m : 指明集群类型。不指定时, 默认为lvs-dr

      • -g , --gatewaying : 指定ipvs的工作模式为DR模式

      • -i , --ipip : 指定IPVS 的工作模式为IP隧道模式

      • -m ,--masquerading : 指定ipvs的工作模式为NAT模式

    • -w weight ,--weight : 指定真实服务器的权重值

    • -x --u-threshold uthreshold : 设置一个服务器可以维持的连接上限 , 当服务器的连接数超过其连接上限阈值时, 将不会向服务器发送新连接。。0~65535。设置为0表示没有上限。

    • -y --l-threshold lthreshold : 设置一个服务器的连接下限, 当连接数低于其下限连接阈值时,服务器将接收新连接。如果此值未设置 , 则当服务器的连接数连续三次低于uthreshold时服务器才可以接收到新的连接。

    • 示例:

      ipvsadm -a -t 10.1.32.68:80 -r 10.1.32.72 -m -w 2
      #表示向10.1.32.68:80 这个tcp类型的集群服务添加一个real server, 其地址为10.1.32.72,采用的集群工作模型为lvs-nat模型, 该real server 的权重为2

  2. 删除

    ipvsadm -d -t|u|f service-address -r server-address
    • -d ,--delete-server: 删除

    • -t|u|f service-address : 指明从哪个集群服务中

    • -r server-address ,--real-server : 表示删除哪个real server

  • 查看集群的相关信息

    ipvsadm -L|l [options]
    • options

      • -n : 表示数组格式显示为IP和PORT, 而不进行反解到主机名和服务

      • -exact : 表示显示大小单位时 , 不以M、G,而是以精确值来显示大小

      • -c : 表示显示当前ipvs的连接情况

      • --stats : 表示显示ipvs的统计数据, 如发送报文速量, 接受报文数量

      • --rate: 速率, 显示集群服务及real server上的平均每秒接受的报文速率、每秒发送的报文数量

      • --timeout : 显示tcp、tcpfin和udp的会话超时时长

      • --sort : 把列表排序

      • --nosort : 不排序

      • --thresholds : 列出阈值

      • --presistent-conn : 坚持连接

      [root@Director ~]# ipvsadm -Ln --stats 
      IP Virtual Server version 1.2.1 (size=4096)
      Prot LocalAddress:Port               Conns   InPkts  OutPkts  InBytes OutBytes
        -> RemoteAddress:Port
      TCP  10.10.88.128:80                    11       63       41     4120     4876
        -> 192.168.194.131:80                  5       27       17     1744     1972
        -> 192.168.194.141:80                  6       36       24     2376     2904
      [root@Director ~]# ipvsadm -Ln --rate 
      IP Virtual Server version 1.2.1 (size=4096)
      Prot LocalAddress:Port                 CPS    InPPS   OutPPS    InBPS   OutBPS
        -> RemoteAddress:Port
      TCP  10.10.88.128:80                     0        0        0        0        0
        -> 192.168.194.131:80                  0        0        0        0        0
        -> 192.168.194.141:80                  0        0        0        0        0
      ​
      [root@Director ~]# ipvsadm -Ln --timeout
      Timeout (tcp tcpfin udp): 900 120 300
      ​
      [root@Director ~]# ipvsadm -Ln --thresholds
      IP Virtual Server version 1.2.1 (size=4096)
      Prot LocalAddress:Port            Uthreshold Lthreshold ActiveConn InActConn 
        -> RemoteAddress:Port
      TCP  10.10.88.128:80 rr
        -> 192.168.194.131:80           0          0          0          0         
        -> 192.168.194.141:80           0          0          0          0         
      ​

清空所有ipvs规则

  • 语法 : ipvsadm -C。表示清空当前ipvs上的所有的集群定义的规则。

清空ipvs的计数器(接受报文数、发送报文数...)

  • 语法 : ipvsadm -Z [-t|u|f service-address]

保存和重载ipvs规则

  • 保存语法 :

    ipvsadm-save > /PATH/TO/FILE

    ipvsadm -S > /PATH/TO/FILE

  • 重载语法 :

    ipvsadm-restore < /PATH/FROM/FILE

    ipvsadm -R < /PATH/FROM/FILE

  • 示例

    #保存ipvs规则
    [root@Director ~]# ipvsadm -S
    -A -t Director:http -s rr
    -a -t Director:http -r 192.168.194.131:http -m -w 1
    -a -t Director:http -r 192.168.194.141:http -m -w 1
    [root@Director ~]# ipvsadm -Sn
    -A -t 10.10.88.128:80 -s rr
    -a -t 10.10.88.128:80 -r 192.168.194.131:80 -m -w 1
    -a -t 10.10.88.128:80 -r 192.168.194.141:80 -m -w 1
    [root@Director ~]# ipvsadm -Sn > /etc/sysconfig/ipvsadm
    ​
    #清理ipvs规则
    [root@Director ~]# ipvsadm -C
    [root@Director ~]# ipvsadm -Sn
    [root@Director ~]# 
    ​
    #恢复ipvs规则
    [root@Director ~]# ipvsadm -R < /etc/sysconfig/ipvsadm
    ​
    #设置开机加载ipvs规则
    [root@Director ~]# systemctl enable ipvsadm  --now
    [root@Director ~]# cat /usr/lib/systemd/system/ipvsadm.service 
    [Unit]
    Description=Initialise the Linux Virtual Server
    After=syslog.target network.target
    ​
    [Service]
    Type=oneshot
    ExecStart=/bin/bash -c "exec /sbin/ipvsadm-restore < /etc/sysconfig/ipvsadm"
    ExecStop=/bin/bash -c "exec /sbin/ipvsadm-save -n > /etc/sysconfig/ipvsadm"
    ExecStop=/sbin/ipvsadm -C
    RemainAfterExit=yes
    ​
    [Install]
    WantedBy=multi-user.target
    ​
    ​

设置IPVS连接的超时值

  • 语法 : ipvsadm --set tcp tcpfin udp

启动连接同步守护进程

  • 语法 : ipvsadm --start-daemon state [--mcast-interface interface] [--syncid syncid]

    • state : 该值可以设置为master/backup

    • --macast-interface interface : 设置用于连接同步守护进程的组播接口

    • --syncid sid : 设置连接同步守护进程的SID , 用于标识。范围·0~255·,默认为255。

停止连接同步守护进程

  • 语法 : ipvsadm --stop-daemon state

3. 防火墙标记

将来自于同一个客户端的所有请求都定义到同一个realserver上 ; 如使用防火墙标记将443和80定义为同一个集群服务, 这样就可以实现统一调度到后端的real server。

当用户请求报文进行防火墙(PREROUTING) , 防火墙就将特定报文(如 : 443和80) , 打上标记 ,假设标记为10 ; LVS设置的时候 , 就可以根据标记进行设置 , 只要请求带有标记10 , 就会将请求调度到同一个RS服务器。

  • 在director的mangle表上打标记

    iptables -t mangle -A PREROUTING -d $vip -p $proto –m multiport --dports $port1,$port2,… -j MARK --set-mark NUMBER
  • 在Director主机基于标记定义集群服务:

    ipvsadm -A -f NUMBER [options] 

  • 配置示例

    [root@Director ~]# iptables -t mangle -A PREROUTING -d 192.168.194.200 -p tcp -m multiport --dports 80,8080,8081 -j MARK --set-mark 10
    [root@Director ~]# iptables -t mangle -vnL
    Chain PREROUTING (policy ACCEPT 10 packets, 612 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 MARK       tcp  --  *      *       0.0.0.0/0            192.168.194.200      multiport dports 80,8080,8081 MARK set 0xa
    ​
    Chain INPUT (policy ACCEPT 10 packets, 612 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    ​
    Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    ​
    Chain OUTPUT (policy ACCEPT 6 packets, 800 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    ​
    Chain POSTROUTING (policy ACCEPT 6 packets, 800 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    ​
    [root@Director ~]# ipvsadm -A -f 10 -s rr
    [root@Director ~]# ipvsadm -a -f 10 -r 192.168.194.131 -g
    [root@Director ~]# ipvsadm -a -f 10 -r 192.168.194.141 -g
    [root@Director ~]# ipvsadm -Ln
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    FWM  10 rr
      -> 192.168.194.131:0            Route   1      0          0         
      -> 192.168.194.141:0            Route   1      0          0   
    ​
    #需要注意的是,如果FWM中指定的端口,后端所有的RS都要有这个端口  , 不然调度的时候会失败。后端的RS配置需要一致
    ​
    [root@Director ~]# cat /proc/net/ip_vs
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port Forward Weight ActiveConn InActConn
    FWM  0000000A rr 
      -> C0A8C28D:0000      Route   1      0          1         
      -> C0A8C283:0000      Route   1      0          0         
    ​
    ​

4. 持久连接

4.1 使用持久连接原因

在LVS中 , 持久连接是为了用来保证当来自同一个client的请求时 , director能够将这些请求调度定位到同一台Real Server。

一般来说 , Real Server需要靠session来标记用户的会话 , 如果集群内没有共享存储session信息 , 而用户前后两次操作分别被调度到两台Real Server,就会导致后一次请求的无法继续前一次的操作状态 ; 比如 , 前一次请求登录调度到Real Server1 , Real Server1保存了该用户的已登录状态 , 而再一次请求获取个人数据的时候调度到Real Server2 , Real Server2在自己的存储中没有找到用户已登录的状态信息 , 从而拒绝了该请求 ; 当然这也可以通过使用Redis、Mencache实现各Real Server间的共享存储来实现 ;

对于电子商务网站来说 , 用户在挑选商品的时候使用的是http:80端口来浏览的 , 当付款的时候则是通过https : 443端口加密的方式 ; 我们不希望http:80挑选商品的信息在Real Server1 , 而https:443商品付款的时候跳转到另外一台Real Server2 ; https:443需要交换SSL密钥 , 当启用持久性连接时 , 只需要做一次验证即可。

4.2 持久连接类型

  • 每端口持久(PPC、persistent port connections) : 每个端口定义一个集群服务,将来自于同一个客户端对同一个服务(端口)的请求 , 始终定向至此前选定的RS。

  • 每客户端持久(PCC、persistent client connections) : 将来自于同一个客户端的所有请求统统定向至此前选定的RS ; 也就是只要IP相同 , 分配的服务器始终相同。基于0端口(表示所有服务)定义集群服务 , 即将客户端对所有应用的请求都调度至后端主机 , 必须定义为持久模式

  • 每防火墙标记持久(PNMPP、Persistent Netfilter Marked Packet Persistence) : 基于防火墙标记的持久性连接 , 这种防火墙标记仅在数据包在分发器上时有影响 , 数据包一旦离开Director , 就不再被标记。

4.2.1 sh算法特殊说明

SH调度算法和持久连接的作用都是"将来自同一个IP的请求都转发到同一个Server" , 从而保证了session会话定位的问题。两者的不同是 :

  1. sh算法 : 使用SH算法 , SH算法在内核中会自动维护一个哈希表 ,此哈希表中用每一个请求的源IP地址经过哈希计算得出的值作为键 , 把请求所到达的RS的地址作为值。在后面的请求中 , 每一个请求会先经过此哈希表 ,如果请求在此哈希表中有键值 , 那么直接定向至特定Real Server , 如没有 ,则会新生成一个键值, 以便后续请求的定向。但是此种方法在时间的记录上比较模糊(依据TCP的连接时长计算) ,而且其是算法本身 , 所以无法与算法分离 ,并不是特别理想的方法。

  2. 持久连接 : 此种方法实现了无论使用哪一种调度方法 , 持久连接功能都能保证在指定时间范围之内 ,来自于同一个IP的请求将始终被定向至同一个RS , 还可以把多种服务绑定后统一进行调度。

session 绑定需要对共享同一组RS的多个集群服务 , 需要统一进行绑定 , lvs sh算法无法实现

ipvs内有一个LVS持久连接模板 , 模板中记录了每一个请求的来源、调度至的Real Server、维护时长等等 ,在新的请求进入时 , 首先在此模板中检查是否有记录 ( 有内置的时间限制 , 比如限制是300秒 , 当在到达300秒时依然有用户访问 , 那么持久连接模板就会将时间增加两分钟 , 再计数 , 依次类推 , 每次只延长2分钟) ,如果该记录未超时 , 则使用该记录所指向的Real Server , 如果是超时记录或者是新请求 , 则会根据调度算法先调度至特定RS , 再将调度的记录添加至此表中。这并不与SH算法冲突 , LVS持久连接会在新请求达到时 , 检查后端Real Server的负载状况 , 这就是比较精细的调度和会话保持方法。

4.2.2 超时时间

  • 把同一个client发来请求到同一台Real Server的持久超时时间。

    这个也就是上面所提到的LVS持久连接模板的超时时间 , ipvsadm -A|E ... -p timeout ;

    timeout: 持久连接时长 , 默认300秒 ;单位是秒。

  • 一个链接创建后空闲时的超时时间 , 这个超时时间分为3种

    ipvsadm --set tcp tcpfin udp设置 , 大的TCP会话超时值将会增加保留在director上的连接模板的时间。

    • tcp的空闲超时时间 ;

    • lvs收到客户端tcp fin的超时时间 ;

    • udp的超时时间。

    [root@lvs ~]# ipvsadm -Ln --timeout
    Timeout (tcp tcpfin udp): 900 120 300

4.2.3 配置

  • PPC配置

    ipvsadm -A -t 192.168.1.100:80 -s wrr –p 300
  • PCC配置

    配置Director时使用0号端口 , 加上-p timeout选项 , 这样把所有端口统统定义为集群服务 , 全部向Real Server 转发:

    ipvsadm -A -t 192.168.1.100:0 -s wrr –p 300
    ​
    ipvsadm -a -t 192.168.1.100:0 -r 192.168.1.102 -g -w 1
    ​
    ipvsadm -a -t 192.168.1.100:0 -r 192.168.1.103 -g -w 3
  • 配置PNMPP

    配置Director时先配置iptables的mangle表为数据包设置Mark标记 , 下面设置80和22(SSH)端口的数据包都加上标记10 , 然后ipvs配置就可用-f mask选项 , 将两个毫不相干的端口定义为一个集群服务:

    iptables -t mangle -A PREROUTING -d 192.168.1.100 -i eth0 -p tcp --dport 80 -j MARK --set-mark 10
    iptables -t mangle -A PREROUTING -d 192.168.1.100 -i eth0 -p tcp --dport 22 -j MARK --set-mark 10
    ipvsadm -A -f 10 -s wrr -p 600
    ipvsadm -a -f 10 -r 192.168.1.102 -g -w 1
    ipvsadm -a -f 10 -r 192.168.1.103 -g -w 3


参考链接

LVS安装使用详解 - MacoLee - 博客园 (cnblogs.com)

IPVS调度模式和Keepalived详解 - 自记小屋 (ziji.work)

LVS详解 | Linux运维部落 (178linux.com)

LVS原理详解以及部署 - konglingbin - 博客园 (cnblogs.com)

LVS-学习总结(ipvsadm工具)_csdnlb的博客-CSDN博客

应用负载均衡之LVS(一):基本概念和三种模式 - 骏马金龙 - 博客园 (cnblogs.com)

应用负载均衡之LVS(二):VS_TUN和VS_DR的arp问题 - 骏马金龙 - 博客园 (cnblogs.com)

FWM及LVS持久连接_weixin_33728268的博客-CSDN博客

LVS均衡负载(四) LVS持久连接-尐譽-CSDN博客


熊熊