0%

LVS 集群负载器的原理和配置

关于 LVS 系列其他文章的传送门

  1. 《 LVS 集群负载器的原理和配置 》      您当前所在位置

  2. 《 LVS 的 DR 模式中 VIP 和 RIP 跨网段的实现方案 》



lvs

一、负载均衡器

为了缓解集群中服务器的单点压力,生产环境中会使用各种各样的负载均衡器。

负载均衡器工作方式

市面上比较流行的负载均衡器大体可以分为 两种工作方式
1. 基于通信子网(4层调度器)
数据报文到达内核,由内核根据 3、4 层的信息进行调度。在这里加入一个软件机制,对 3、4 层报文进行调度后,再发出,报文不会进入用户空间。
2. 基于资源子网(7层调度器)
数据报文通过路由、内核最后到用户空间,由工作在用户空间的应用程序,对报文拆包进行分析后,再调度发出。

可以实现负载均衡的产品

1. 软负载

  • 4层:LVS,Nginx(stream)伪,HAProxy(modetcp)伪,…
  • 7层:Nginx,HAProxy,ATS,Envoy,Traefik,Kong,…

2. 硬负载

  • F5 公司的 --> BigIp
  • NetScaler --> Citrix

二、LVS 介绍

Linux virtual server

本文主要介绍其中一种负载均衡器,那就是 LVS,目前已被收录进 Linux 内核。

LVS 全称为 Linux virtual server,作者是 章文嵩

程序主要有两部分组成:

  • IPVS:内核中框架。
  • IPVSadm:用户空间中的工具。

工作方式

那么 LVS 是怎么工作的呢?我们先来回顾下 Linux 中 netfilter 的工作模式。

正常情况下

  1. 数据报文到达 ①PREROUTING,先判断目的地是否为本机。
  2. 如果是,由 ②INPUT 进入用户空间发给程序。
  3. 如果不是本机,则从 ③FORWORD 转发出去。

LVS

  1. 数据报文到达 ①PREROUTING,先判断目的地是否为本机。
  2. 如果不是本机,则从 ③FORWORD 转发出去。
  3. 如果是,报文进入 ②INPUT 时,LVS 会强行拦截,LVS 就工作在 ②INPUT 上。
  4. 经过 LVS 一系列的调度计算后,不发给用户空间,而是直接转发给 ⑥POSTROUTING 离开本机。
    iptables

LVS 中的一些术语

  1. Client 客户端:

    • CIP (Client Ip):客户端 IP。
  2. Director 调度器:

    • VIP (virtual Ip):调度器公开访问的 IP。
    • DIP (Director Ip):调度器中用于和 Realserver 通信的 IP。
  3. Realserver 服务器:

    • RIP (Realserver Ip):真正运行业务的服务器。

在工作模式中对应的位置

name

LVS 的十种调度算法

LVS 共有 10 种调度算法,都是内建在内核中的模块。

name

主要有两类:静态算法动态算法

1. 静态算法

主要关注起点公平:仅根据算法本身和请求报文特征进行调度

  1. RR (轮叫调度)

    • 原理:通过“轮叫"调度算法将外部请求按顺序轮流分配到 server。
    • 不足:均等地对待每一台服务器,而不管服务器上实际的连接数和系统负载。
  2. WRR (加权轮叫)

    • 根据不同服务器设置的权重来调度访问请求。
    • 适用场景:短连接、无状态的服务,如 html、css 等纯静态资源。
  3. SH (源地址散列)

    • 原理:源 IP 做 hash 后,通过取模方式计算,选出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器。
    • 适用场景:在没有使用 session 共享的又需要保存 session 的环境下(如电子商务网站)。
    • 不足:多用户会识别为 1 个 IP。
  4. DH (目标地址散列)

    • 原理:目标 IP 做 hash 后,通过取模方式计算,选出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器。
    • 适用场景:主要用于缓存服务器的场景。

取模方式详解

hash

2. 动态算法

主要关注结果公平:额外考虑后端各 RS 的当前负载状态

  1. LC (最少链接)

    • 原理:负载最低则优先级高,如负载一样选第一个。
    • 算法:overhead=activeconn*256+inactive (256 的由来:活动连接对资源的消耗,是非活动资源的 256 倍)
    • 不足:没有考虑权重。
  2. WLC (加权最少链接)LVS 默认调度算法

    • 原理:具有较高权值的服务器将承受较大比例的活动连接负载。
    • 算法:overhead=(activeconn*256+inactive)/wtight
    • 适用场景:有状态,长连接服务; 服务器性能有差异的情况。
    • 不足:当算法的结果一样时,会自上而下分配,这样可能会分配给权重小的,无法平均分配。
  3. SED (最短的期望的延迟)

    • 原理:基于 WLC 算法的,只是其计算方法不同。
    • 算法:overhead=(activeconn+1)*256/wtight
    • 不足:某种连接少时,性能高的忙死,性能低没有连接。
  4. NQ (最少队列)

    • 原理:无需队列,永不排队,如果有连接数为 0 的 server,就直接分配。如果没有连接数为 0 的 server,则使用 SED 算法。
  5. LBLC (基于局部性的最少链接)

    • 原理:根据请求的目标 IP 地址找出该目标 IP 地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器。若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用“最少链接”的原则选出一个可用的服务器,将请求发送到该服务器。
  6. LBLCR (带复制的基于局部性最少链接)

    • 原理:它与 LBLC 算法的不同之处是它要维护从一个目标 IP 地址到一组服务器的映射,而 LBLC 算法维护从一个目标 IP 地址到一台服务器的映射。该算法根据请求的目标 IP 地址找出该目标 IP 地址对应的服务器组,按“最小连接"原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器。若服务器超载,则按“最小连接"原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。

LVS 的四种调度模式

1. NAT

多目标 IP 的 DNAT,通过将请求报文中的目标地址和目标端口修改为某个挑出的 RS 的 RIP 和 PORT 实现转发。

工作方式

  • (1). Client 发请求报文给 Director,此时报文的 目标 IPVIP
  • (2). Director 根据算法选出 Realserver,把报文的 目标 IP 改为 RIP
  • (3). Realserver 收到报文后处理请求,然后把响应报文发回给 Client 的 CIP,但是 Realserver 并没有 CIP 的路由,所以 Realserver 的网关需要指向 DIP
  • (4). Director 收到响应报文后,根据连接追踪机制,把 源 IPRIP 改为 VIP 后,发给 Client。
  • (5). Client 收到响应报文,此时 源 IPVIP, 目标 IPCIP

nat

要求

  • RS 的网关必须指向 DIP
  • 因为 Realserver 的网关要指向 DIP,所以 RIPDIP 必须使用同一个 IP 网络,也就是同一个 VLAN,不能跨网段。
  • Director 必须是 Linux 系统,但 RS 可以是任意系统。

优点

  • 支持端口映射。
  • 节省公有 IP 地址。
  • 使用 nat 另外一个好处就是后端的主机相对比较安全。

缺点

  • 请求和响应报文都要经过 Director 转发,极高负载时,Director 可能成为系统瓶颈。


2. DR

上面说过,因为 NAT 的调度模式,来回都需要经过 Director,在负载极高时,Director 就会成为瓶颈。而 DR 刚好解决了这个问题。

DR 的调度模式是通过在请求报文中,重新封装一个二层网络的 MAC 首部 再转发。源 MACDIP 所在的接口的 MAC,目标 MAC 是某挑选出的 Realserver 的 RIP 所在接口的 MAC 地址,而 源 IP/PORT,以及 目标 IP/PORT 均保持不变。

这样 Realserver 收到请求后交给程序处理,到此和 NAT 报文路线是一样的,但是程序处理完后,Realserver 不用再发回 Director,而是自己直接发回给 Client,甚至走的路由和来时都可以不一样,只要能到达 Client 就可以,这样大大缓解了高负载下 Director 的压力。

就像这样子:NAT 和 DR 调度路线的对比

natvsdr

但是这样会带来一个新的问题,Client 请求报文的 目标 IPVIP,所以响应报文的 源 IP 也应该是 VIP,但是由于 Realserver 处理完请求没有发回 Director,而是直接发给 Client,所以 Client 收到的报文的 源 IP 却是 RIP。这下麻烦了。
给我答案的人并不是我当初问的人,我不信可他。

所以为了解决这个问题,DR 调度模式有个先提条件:那就是 VIP 必须也同时配置在所有 Realserver 的网络接口上,这样发回 Client 的报文 源 IP 才能和来时的一样 VIP

那么在同一个网络中,就有 3 相同的 VIP,这下不就 IP 冲突了嘛,所以怎样才能防止 IP 冲突呢?

3vip

首先分析 IP 冲突会发生在何时

  1. ARP 通告:服务器加入一个网络时,会通过广播发送 ARP 通告,我的 IP 地址是 XXX,对应的 MAC 地址是 XXX。默认情况下,为了让大家充分了解自己,如果一个服务器上配置了多个不同网段的 IP,则会把自己所拥有的每一个 IP 地址的每一个对应的 MAC 信息通告到每一个网络,默认 ARP 信息缓存 5 分钟。
  2. ARP 查询:交换机转发报文时,会广播 ARP 查询,谁的 IP 地址是 XXX 啊,给我你的 MAC 地址吧

所以根据这两个关键点,解决办法有三个:

  1. 交换机做 IP <--> MAC 绑定,缺点是灵活性差,LVS 如果发生变化需要更改。
  2. 使用 ARPtables,类似于 iptables 的软件,缺点就是需要安装额外的软件。
  3. 通过修改内核参数的方式,让服务器不发送 ARP 通告,和不应答 ARP 查询,比较轻量,推荐 使用。

工作方式

dr

要求

  • RS 的 RIP 既可以使用私网地址,也可以是公网地址。
  • 因为通过 MAC 转发,RS 跟 Dirctory 要在同一物理网络内(不能由路由器分隔,因为 VIPServer 要通过封装 MAC 地址到 RIPServer)。
  • RIP 的网关不能指向 DIP,以确保响应报文不会经由 Director。
  • 请求报文要经由 Director,但响应不能经由 Director,而是由 RS 直接发往 Client。

优点

  • 缓解了 Director 节点的压力。

缺点

  • 不支持端口映射。


3. TUN

无论是 NAT,还是 DR,都有一个共同的缺点,就是 Director 和 所有的 Realserver 必须同在一个网络内,这样是无法实现异地容灾的。

而下面要说的 TUN 模式,基于隧道封装技术。在 IP 报文的外面再包一层 IP 报文,即使 Director 和 Realserver 相隔十万八千里,只要能路由到达即可。

TUN 不修改请求报文的 IP 首部(源 IP 为 CIP,目标 IP 为 VIP),而是在原 IP 报文之外再封装一个 IP 首部(源 IP 是 DIP,目标 IP 是 RIP),将报文发往挑选出的目标 RS,RS 处理完请求,直接响应给客户端(源 IP 是 VIP,目标 IP 是 CIP)。

工作方式

tun

要求

  • DIPVIPRIP 都应该是公网地址。
  • RS 的网关不能,也不可能指向 DIP
  • 请求报文要经由 Director,但响应不能经由 Director。

缺点

  • 不支持端口映射
  • Director 只接受进站请求,减少负载。
  • RS 的 OS 必须支持隧道功能。
  • 因为 MTU 限制,隧道技术会额外花费性能,增大开销。
  • 必须人为指定最大 MTU 值,不能是 1500,必须留出隧道首部的位置。


4. FULL-NAT

由于 TUN 需要人为指定 MTU,而 DR 又要求每个 RS 都需要改内核参数,而且拓扑很独特,所以,最简单的还是 NAT 类型。

但是 NAT 中各 RS 的网关必须指向 DIP ,中间不能有网关隔离,所以 NAT 不能较远距离的传输,为了解决这样的问题,便研发了 FULL-NAT 类型。

FULL-NATNAT 类型的区别并不大,NAT 是修改 目标 IP,而 FULL-NAT 是既修改 目标 IP,也修改 源 IP。这样 RS 收到的数据报文的 源 IPDIP,所以 RS 网关可以不用再指向 DIP,这样就大大增加了 NAT 的灵活性。

但是此类型默认是不支持的,需要为内核打补丁。

工作方式

fullnat

要求

  • VIP 是公网地址,RIPDIP 是私网地址,且通常不在同一个三层 IP 网络,因此,RIP 的网关一般不会指向 DIP
  • RS 收到的请求报文源地址是 DIP,因此只能响应给 DIP,由 Director 将其发往 Client。

优点

  • 支持端口映射。
  • 兼顾 NAT 的优点。
  • 可以不在同一个三层 IP 网络,灵活性高。

缺点

  • 请求和响应报文都经由 Director,压力高时易成为瓶颈。
  • 支持端口映射。
  • 注意:此类型默认是不支持的,需要为内核打补丁。

三、LVS 的配置

LVS 配置起来还是很简单的,也是属于 90% 的概念 + 10% 的操作。

1. 安装 LVS

首先确认内核是否支持 ip_vs。
grep_ip_vs

安装 LVS 用户空间的工具 ipvsadm

1
yum install ipvsadm

查看安装了哪些文件 rpm -ql ipvdadm

ipvsadm

  • 主程序包/usr/sbin/ipvsadm
  • 规则保存工具/usr/sbin/ipvsadm-save
  • 规则重载工具/usr/sbin/ipvsadm-restore
  • 配置文件/etc/sysconfig/ipvsadm-config
  • Unit 文件/usr/lib/systemd/system/ipvsadm.service

2. ipvsadm 命令的使用

管理集群服务的命令

  • 增、改:ipvsadm -A|E -t|u|f service-address:port [-s scheduler] [-p [timeout]]
  • 删:ipvsadm -D -t|u|f service-address
    • -A:添加集群
    • -E:修改集群
    • -D:删除集群
    • -L:查看集群
    • -t:tcp vip:port
    • -u:udp vip:port
    • -f:防火墙标记 MARK
    • -s:调度算法,默认为 WLC
    • -C:清空所有规则
    • -S:保存所有规则到文件
    • -R:从文件载入所有规则
    • -p:持久连接模式

管理集群服务上的 RS 的命令

  • 增、改:ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight]
  • 删:ipvsadm -d -t|u|f service-address -r server-address
    • -a:添加一个 RS 主机
    • -e:修改一个 RS 主机
    • -d:删除一个 RS 主机
    • -L:查看 RS
    • -mmasquereadLVS NAT 调度模式
    • -gGATAWAY DR 调度模式
    • -iIPIP TUN 调度模式
    • -w:weight 权重

其他命令

ipvsadm

  • -L --rate:速率值
  • -L --stats:总计数器
  • --zero -Z [-t|u|f server-address]:清空上面两个计数器

四、构建 LVS 集群

NAT 的构建

我们使用 Docker 先来构建 LVS 中 NAT 的模型。

宿主机扮演 Client 角色,请求虚拟机扮演的 Dirctor,在虚机内部利用 Docker 创建 web1、2 两个容器作为 Realserver,由 Dirctor 向后调度到 Realserver

架构图

nat_deploy

1. 配置容器

先创建 mybr0 网桥,网段是 10.10.0.0/24,网关为 10.10.0.1

1
2
[root@centos_1 ~]# docker network create -d bridge --subnet 10.10.0.0/24 --gateway 10.10.0.1 mybr0
1b186ed990775a8d7e6f5bde31dfadf64db91a2a0ee82139734e44abb3cae5ad

创建 nginx 的测试页文件

1
2
3
4
5
6
7
8
9
10
11
[root@centos_1 ~]# cat /data/nginx1/index.html
nginx1 test page
[root@centos_1 ~]# cat /data/nginx2/index.html
nginx2 test page

[root@centos_1 ~]# tree /data
/data
├── nginx1
│   └── index.html
└── nginx2
└── index.html

创建容器 nginx1nginx2,分别挂载存储卷,到刚才创建的主页文件目录 nginx1nginx2下。指定使用刚才创建的 mybr0 网桥,并指定 IP 为 10.10.0.1110.10.0.12

1
2
docker run -d --name nginx1 -v /data/nginx1/:/usr/share/nginx/html/ --network mybr0 --ip 10.10.0.11 nginx
docker run -d --name nginx2 -v /data/nginx2/:/usr/share/nginx/html/ --network mybr0 --ip 10.10.0.12 nginx

2. 配置 ipvsadm

安装 ipvsadm

1
[root@centos_1 ~]# yum install ipvsadm

加载 IP_VS 内核模块。

1
2
3
4
5
[root@centos_1 ~]# modprobe  ip_vs
[root@centos_1 ~]# lsmod |grep ip_vs
ip_vs 145497 0
nf_conntrack 133095 7 ip_vs,nf_nat,nf_nat_ipv4,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_netlink,nf_conntrack_ipv4
libcrc32c 12644 4 xfs,ip_vs,nf_nat,nf_conntrack

创建集群。

1
2
3
4
5
6
7
8
9
10
11
ipvsadm -A -t 192.168.50.11:80 -s wlc  # 调度算法 wlc
ipvsadm -a -t 192.168.50.11:80 -r 10.10.0.11 -m # -m 指定使用 NAT 模式
ipvsadm -a -t 192.168.50.11:80 -r 10.10.0.12 -m # -m 指定使用 NAT 模式

[root@centos_1 ~]# ipvsadm -L
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP centos_1:http wrr
-> 10.10.0.11:http Masq 1 0 0
-> 10.10.0.12:http Masq 1 0 0

集群创建好了,使用宿主机访问 Director,可以看到已经可以访问,是轮询模式。

1
2
3
4
5
6
7
8
9
10
11
le@DESKTOP-TTY:~$ while true ; do curl 192.168.50.11 ; sleep .2 ; done
nginx1 test page
nginx2 test page
nginx1 test page
nginx2 test page
nginx1 test page
nginx2 test page
nginx1 test page
nginx2 test page
nginx1 test page
nginx2 test page

然后加上权重再看看效果

1
2
3
4
5
6
7
8
9
ipvsadm -e -t 192.168.50.11:80 -r 10.10.0.11 -m -w3   # 权重为 3

[root@centos_1 ~]# ipvsadm -L
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP centos_1:http wrr
-> 10.10.0.11:http Masq 3 0 0
-> 10.10.0.12:http Masq 1 0 0

再次使用宿主机访问,可以看到比例是 3:1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
le@DESKTOP-TTY:~$ while true ; do curl 192.168.50.11 ; sleep .2 ; done
nginx1 test page
nginx1 test page
nginx1 test page
nginx2 test page
nginx1 test page
nginx1 test page
nginx1 test page
nginx2 test page
nginx1 test page
nginx1 test page
nginx1 test page
nginx2 test page
nginx1 test page
nginx1 test page
nginx1 test page
nginx2 test page

DR 的构建

DR 类型的构建使用 3 台虚拟机完成,Director,Realserver 1 和 Realserver 2。

hostname HOST IP VIP
Director host: 192.168.50.100 ens33:0 192.168.50.11
Realserver 1 RIP: 192.168.50.12 lo:0 192.168.50.11
Realserver 2 RIP: 192.168.50.13 lo:0 192.168.50.11

1. 配置 Realserver

首先要确定防火墙和 SELinux 已经关闭!!!

经测试,VIP 必须配置在子接口上,如 lo:0。不能配置在 lo 上,不然会调度失败。

Realserver 的配置脚本,在 R1R2 执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/bin/bash
#
#

vip=192.168.50.11
mask='255.255.255.255'
vipni=lo

case $1 in
start)
# 关闭 ARP 应答和响应
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/$vipni/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/$vipni/arp_announce

# 清空防火墙规则
iptables -X
iptables -F

# 把 VIP 配置在 lo:0 接口 防止和其他主机沟通 掩码 32 只广播给自己
ifconfig $vipni:0 $vip netmask $mask broadcast $vip up

# 配置路由 只要是到 VIP 的报文,就走 vipin 网卡
route add -host $vip dev $vipni:0
;;
stop)
# 关闭网卡
ifconfig $vipni down

# 恢复 ARP 应答和响应
echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/$vipni/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/$vipni/arp_announce

# 清空防火墙规则
iptables -X
iptables -F
;;
*)
echo "Usage $(basename $0) start|stop"
exit 1
;;
esac

分别在 RS 1 和 RS 2 上安装 httpd,并放置首页文件,RS 就准备好了。

1
2
3
4
5
# RS 1
[root@Realserver_1 ~]# yum install httpd -y && echo 'Realserver 1 test page' > /var/www/html/index.html

# RS 2
[root@Realserver_2 ~]# yum install httpd -y &&echo 'Realserver 2 test page' > /var/www/html/index.html

2. 配置 Director

首先要确定防火墙和 SELinux 已经关闭!!!

经测试,VIP 必须配置在子接口上,如 ens33:0,不然会调度失败,所以 Director 不能直接在物理网卡上配置 IP。需要有一个主机 IP 用来和外界通信,另一个 VIP 配置在子接口上。

Director 的配置脚本,在 Director 节点执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/bin/bash
#
#
vip='192.168.50.11'
iface='ens33:0'
mask='255.255.255.255'
port='80'
rs1='192.168.50.12'
rs2='192.168.50.13'
scheduler='wrr'
type='-g'

case $1 in
start)

# 配置 VIP
ifconfig $iface $vip netmask $mask broadcast $vip up

# 清空防火墙规则
iptables -X
iptables -F

# 配置集群
ipvsadm -A -t ${vip}:${port} -s $scheduler
ipvsadm -a -t ${vip}:${port} -r ${rs1} $type -w 1
ipvsadm -a -t ${vip}:${port} -r ${rs2} $type -w 1
;;
stop)

ipvsadm -C
ifconfig $iface down

# 清空防火墙规则
iptables -X
iptables -F
;;
*)
echo "Usage $(basename $0) start|stop"
exit 1
;;
esac

3. 测试访问

在一台客户端上访问 VIP,可以看到是轮询的方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root@mirrors [08:18:50 PM] [~]
-> # while true ; do curl -m1 192.168.50.11 && sleep .5 ; done
Realserver 2 test page
Realserver 1 test page
Realserver 2 test page
Realserver 1 test page
Realserver 2 test page
Realserver 1 test page
Realserver 2 test page
Realserver 1 test page
Realserver 2 test page
Realserver 1 test page
Realserver 2 test page
Realserver 1 test page
Realserver 2 test page
Realserver 1 test page
Realserver 2 test page

五、防火墙标记和持久连接

1. 防火墙标记

FWM,是 firewall mark 的缩写,借助于防火墙标记来分类报文,而后 LVS 根据此防火墙标记来将相应报文归类到指定的集群服务中。使用 FWM 可将多个不同的应用定义为同一个集群服务来进行调度。

报文的 firewall mark 是在报文进入到 Director 的 PREROUTING 时打上的指定标记,随后 LVS 就根据此 mark 标记来进行调度。

打标记

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

基于 FWM 定义集群

1
2
ipvsadm -A -f MARK_NUM -s SCHEDULER
ipvsadm -a -f MARK_NUM -r server-address -g|-i|-m -w

示例

配置 FWM

1
2
3
4
5
6
7
8
# http 和 sshd 服务定义为一类标签
iptables -t mangle -A PREROUTING -d 192.168.0.11 -p tcp --dport 80 -j MARK --set-mark 3
iptables -t mangle -A PREROUTING -d 192.168.0.11 -p tcp --dport 22 -j MARK --set-mark 3

# 根据标签定义集群
ipvsadm -A -f 3 -s rr
ipvsadm -a -f 3 -r 10.10.0.12
ipvsadm -a -f 3 -r 10.10.0.13

从 Client 访问,查看效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@Client ~]# curl 192.168.0.11
This is Realserver 11111 test page

[root@Client ~]# curl 192.168.0.11
This is Realserver 22222 test page

[root@Client ~]# curl 192.168.0.11
This is Realserver 11111 test page

[root@Client ~]# curl 192.168.0.11
This is Realserver 22222 test page

[root@Client ~]# curl 192.168.0.11
This is Realserver 11111 test page

# 从上面可以看出是轮询机制在调度
# 那么按照顺序即将调度的应该是 Realserver_2 的 http
# 但是这时改为请求 ssh 协议,连上后看到是 Realserver_2 的 ssh
# 因为 MASK 的原因,http 和 ssh 被当做同一类集群整体调度了
[root@Client ~]# ssh 192.168.0.11
Last login: Mon Jul 29 18:48:46 2019 from 172.16.0.100
[root@Realserver_2 ~]# hostname
Realserver_2

2. 持久连接

LVS 的持久连接是指,无论使用哪一种调度方法,都能保证在指定的时间范围内,将来自于同一个 IP 的请求始终被调度到同一个 RS 服务器上。

LVS 的持久连接配置参数为:

1
ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]]

持久连接的类型

  • PPC(端口持久):每个端口对应定义为一个集群服务,每集群服务单独调度。
  • PCC(客户端持久):基于端口 0 来定义集群服务,即客户端对 Director 上 VIP 的所有请求统统调度至后端主机,必须定义为持久模式,不然会报错 Memory allocation problem
  • PFWM(防火墙标记持久):基于防火墙标记定义集群服务,可实现将多个端口上的应用统一调度,即所谓的 port Affinity

PPC 端口持久:

1
ipvsadm -A -t 192.168.0.11:80 -s rr -p

PCC 客户端持久:

1
2
# 注意 0 端口和 -p 选项需同时使用
ipvsadm -A -t 192.168.0.11:0 -s rr -p

PFWM 防火墙标记持久:

1
ipvsadm -A -f 3 -s rr -p

参考:
https://www.jianshu.com/p/a3d33f903d87
https://www.jianshu.com/p/8a61de3f8be9