一、集群与分布式
首先让我们来了解集群和分布式的概念:
集群:同一个业务系统,部署在多台服务器上,集群中,每一台服务器的访问内容没有差别,数据和代码都是一样的,有助于实现负载均衡。
分布式:一个业务被拆分成多个子业务,或者本身就是不同的业务,部署在多台服务器上。分布式中,每一台服务器实现的功能都是有差别的,数据和代码都是不一样的,分布式每台服务器加起来才是完整的业务。
对于大型网站,访问用户很多,实现一个集群,在前面部署一个负载均衡服务器,后面几台服务器完成同一个业务,如果有用户进行相应业务访问时,负载均衡服务器根据后端哪台服务器的负载情况,决定由哪一台去完成相应,如果那台服务器垮了,其他服务器还可以顶上来。分布式的每一个节点都完成不同的业务,如果一个节点垮了,那这个业务可能失败。
二、LVS(Linux Virtual Server)运行原理
LVS相关术语:
VS:virtual server,负责调度
RS:real server,真实提供服务的服务器
CIP:client ip,客户端的ip
VIP:virtual server外网的ip
DIP:director ip vs内网的ip
RIP:real server‘s ip
LVS集群类型:
lvs-nat:修改请求报文的目标ip,多目标ip的DNAT
lvs-dr:操纵封装新的mac地址
lvs-turn:在原请求ip报文之外新增一个ip首部
lvs-fullnat:修改请求报文的源和目标ip
nat模式的数据逻辑:
dr模式的数据逻辑:
三、LVS调度算法
1.lvs调度算法类型
ipvs scheduler:根据其调度时是否考虑RS当前的负载状态分为两种:静态方法和动态方法。
静态方法:仅根据算法本身调度,不考虑RS的负载情况
动态方法:主要根据RS当前负载状态和调度算法进行调度,Overhead=value较小的RS将优先调度
2.LVS静态调度算法
1、RR:roundrobin 轮询 RS分别被调度,当RS配置有差别时不推荐
2、WRR:Weighted RR,加权轮询根据RS的配置进行加权调度,性能差的RS被调度的次数少 3、SH:Source Hashing,实现session sticky,源IP地址hash;将来自于同一个IP地址的请求始终发往 第一次挑中的RS,从而实现会话绑定
4、DH:Destination Hashing;目标地址哈希,第一次轮询调度至RS,后续将发往同一个目标地址的请 求始终转发至第一次挑中的RS,典型使用场景是正向代理缓存场景中的负载均衡,如:宽带运营商
3.lvs动态调度算法
主要根据RS当前的负载状态及调度算法进行调度Overhead=value较小的RS会被调度
1、LC:least connections(最少链接发) 适用于长连接应用Overhead(负载值)=activeconns(活动链接数) x 256+inactiveconns(非活 动链接数)
2、WLC:Weighted LC(权重最少链接) 默认调度方法Overhead=(activeconns x 256+inactiveconns)/weight
3、SED:Shortest Expection Delay, 初始连接高权重优先Overhead=(activeconns+1+inactiveconns) x 256/weight 但是,当node1的权重为1,node2的权重为10,经过运算前几次的调度都会被node2承接
4、NQ:Never Queue,第一轮均匀分配,后续SED
5、LBLC:Locality-Based LC,动态的DH算法,使用场景:根据负载状态实现正向代理 6、LBLCR:LBLC with Replication,带复制功能的LBLC,解决LBLC负载不均衡问题,从负载重的复制 到负载轻的RS
四.LVS部署命令
1.LVS软件相关信息
程序包:ipvsadm Unit File: ipvsadm.service
主程序:/usr/sbin/ipvsadm
规则保存工具:/usr/sbin/ipvsadm-save
规则重载工具:/usr/sbin/ipvsadm-restore
配置文件:/etc/sysconfig/ipvsadm-config ipvs
调度规则文件:/etc/sysconfig/ipvsadm
2.NAT模式集群实验
- 实验准备:
- LVS:双网卡主机,开启内核路由功能,外网ip为172.25.254.100/24,内网ip为192.168.0.100/24
- RS1:单网卡主机,只有一个ip,192.168.0.10/24
- RS2:单网卡主机,只有一个ip,192.268.0.20/24
开启内核路由功能:
vim /etc/sysctl.conf
net.ipv4.ip forward=1
sysctl - a
net.ipv4.ip forward = 1
最后在curl上检测:
3.DR模式集群实验
- 实验准备:
- Client:nat模式,CIP为172.25.254.200,网关为172.25.254.100
- Router:nat模式,VIP为172.25.254.100,仅主机模式,DIP为192.168.0.100,开启内核路由功能
- LVS:仅主机模式,DIP为192.168.0.50,VIP为192.168.0.200,在回环上配置,网关为192.168.0.100
- RS1:仅主机模式,RIP为192.168.0.10,VIP为192.168.0.200,在回环上配置
- RS2:仅主机模式, RIP为192.168.0.20,VIP为192.168.0.200,在回环上配置
示意图如下:
准备一台母机,在/usr/bin/编写一个vmset.sh用于配置ip,vmset.sh脚本内容如下:
#!/bin/bash
rm -fr /etc/NetworkManager/system-connections/$1.nmconnection
cat > /etc/NetworkManager/system-connections/$1.nmconnection <<EOF
[connection]
id=$1
type=ethernet
interface-name=$1
[ipv4]
address1=$2/24,172.25.254.2
method=manual
dns=114.114.114.114;
EOF
chmod 600 /etc/NetworkManager/system-connections/$1.nmconnection
nmcli connection reload
nmcli connection up $1
hostnamectl hostname $3
cat > /etc/hosts <<EOF
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
$2 $3
EOF
写完之后不要忘记了给脚本一个可执行权限:
chmod +x /usr/bin/vmset.sh
之后清除历史命令保存并退出,维持母机一个纯净的实验环境
然后使用链接克隆克隆出五台主机,在client上使用脚本具体传参如下:
[root@client ~]# vmset.sh eth0 172.25.254.200 client.karl.org
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/3)
其中vmset.sh 中 $1是网卡名称,即ifname(填写你自己真实看到的网卡名称,$2(ip地址),$3(主机名)
如果你也想改成和我一样的网卡名称,可以用以下命令更新内核中的ifnames参数:
grubby --update-kernel ALL --args net.ifnames=0
写完之后别忘记了重启,最好在母机上就做好:
reboot
以router路由器为例,添加第二块网络模式为仅主机模式的网卡:
打开wmware->右键router选择设置->添加->网络适配器->仅主机模式->确定(一定要点!!)
关于网段的规划也需要注意:
编辑->虚拟网络编辑器->VMnet1 仅主机>子网地址192.168.0.0->确定(一定要点!!)
->VMnet8 nat模式>子网地址172.25.254.0->确定(一定要点!!)
大功告成之后,根据我们规划好的ip从client到rs进行配置
这里在lvs,和两台real server上配置VIP的目的是:
- 在Linux Virtual Server (LVS) 的 Direct Routing (DR) 模式中,配置虚拟IP地址(VIP)对于实现负载均衡和高可用性至关重要。在 DR 模式下,LVS 的主要组件包括 Director(调度器)和 Real Servers(真实服务器)。下面详细解释为什么需要在 LVS、RS1 和 RS2 上配置 VIP:
- 1. **创建统一的入口点**:
- VIP 提供了一个统一的入口点,客户端只看到这个 VIP 地址,而不知道后端的真实服务器。这使得 LVS 能够透明地分发客户端请求到多个真实服务器,从而提高性能和可靠性。
- 2. **负载均衡**:
- 当客户端向 VIP 发起连接请求时,LVS 的调度器会根据预设的算法(如轮询、最少连接等)选择一个真实服务器并将请求转发过去。通过这种方式,负载可以在多个服务器之间均衡分配。
- 3. **故障转移和高可用性**:
- 在 DR 模式中,LVS 和所有 RS 都需要配置相同的 VIP。当某一台 RS 出现故障时,LVS 会检测到并停止向这台服务器发送请求,而不会影响到其他 RS 的正常服务。同时,如果 LVS 自身出现故障,通过心跳机制,VIP 可以被转移到另一个 LVS 实例上,保证服务的连续性。
- 4. **隐藏真实服务器**:
- 客户端只知道 VIP,而不直接与 RS 通信,这增加了系统的安全性,因为 RS 的实际 IP 地址对外界是隐藏的。
- 5. **简化客户端配置**:
- 对于客户端而言,只需要知道 VIP,不需要关心后端服务器的变动。这使得在扩展或缩减后端服务器数量时,客户端无需重新配置。
- 6. **直接路由**:
- 在 DR 模式中,数据包从 LVS 到 RS 的转发是通过 MAC 地址改写实现的,而不是通过 IP 重写。这意味着数据包在整个过程中保持原始 IP,提高了网络效率和性能。
- 总之,配置 VIP 在 LVS 和 RS 上是 DR 模式下实现高效、可靠和安全的负载均衡的关键。通过 VIP,LVS 能够智能地管理后端服务器集群,同时对外提供一致的服务质量。
需要注意的是,在lvs,rs1,rs2上配置的VIP推荐用临时命令配置,且子网掩码为32
ip a a 192.168.0.200/32 dev lo
之后再在rs1,rs2上关闭VIP对外响应,也是临时的,重启失效
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
在路由器上开启主机内核通信功能
[root@router ~]# sysctl -a | grep ip_forward
net.ipv4.ip_forward = 0
net.ipv4.ip_forward_update_priority = 1
net.ipv4.ip_forward_use_pmtu = 0
使用vim命令,把net.ipv4.ip_forward = 1复制到/etc/sysctl.conf的最后一行:
vim /etc/sysctl.conf
改完之后刷新:
[root@router ~]# sysctl -p
net.ipv4.ip_forward = 1
可以看到此时内核路由通信功能已经开启
此时我们就可以在lvs上配置我们的ipvsadm策略了
下载ipvsadm,下载完不要启动,要不然更改的策略不会生效
dnf install ipvsadm -y
在我们两台rs上安装http服务并写入一些东西到默认发布目录,在真实的生产环境中,两台rs集群应当提供给客户的内容是一致的,在实验环境中为了效果明显,我们可以不同
dnf install httpd -y
[root@rs1 ~]# echo web1 - 192.168.0.10 > /var/www/html/index.html
[root@rs1 ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
输入好之后启动httpd服务,rs2上也是如此
现在我们可以回到lvs负载调度器上配置我们的ipvsadm策略了
ipvsadm -A -t 192.168.0.200:80 -s wrr
ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10:80 -g -w 1
ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.20:80 -g -w 2
配置好之后查看下我们的策略:
[root@lvs ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.200:80 wrr
-> 192.168.0.10:80 Route 1 0 0
-> 192.168.0.20:80 Route 2 0 0
最后在客户端上测试一下,模拟客户访问服务器的请求,由于wrr算法调度,会根据服务器的权重给定访问次数,可以看到效果如下:
[root@client ~]# for i in {1..10}
> do
> curl 192.168.0.200
> done
web1 - 192.168.0.10
web2 - 192.168.0.20
web2 - 192.168.0.20
web1 - 192.168.0.10
web2 - 192.168.0.20
web2 - 192.168.0.20
web1 - 192.168.0.10
web2 - 192.168.0.20
web2 - 192.168.0.20
web1 - 192.168.0.10
4.防火墙标签解决轮询错误
以http和https为例,当我们在RS中同时开放80和443端口,那么默认控制是分开轮询的,这样我们就出 现了一个轮询错乱的问题,当我第一次访问80被轮询到RS1后下次访问443仍然可能会被轮询到RS1上
在rs1和rs2上安装mod_ssl让apache支持https
yum install mod_ssl -y
systemctl restart httpd
在lvs中设置调度,因为我们要调度80和443两个端口所以我们需要设定两组策略
ipvsadm -C
ipvsadm -A -t 192.168.0.100:80 -s rr
ipvsadm -A -t 192.168.0.100:443 -s rr
ipvsadm -a -t 192.168.0.100:80 -r 192.168.0.101:80 -g
ipvsadm -a -t 192.168.0.100:80 -r 192.168.0.102:80 -g
ipvsadm -a -t 192.168.0.100:443 -r 192.168.0.102:80 -g
ipvsadm -a -t 192.168.0.100:443 -r 192.168.0.101:80 -g
此时我们查看一下调度情况
[root@lvs ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.100:80 rr
-> 192.168.0.101:80 Route 1 0 0
-> 192.168.0.102:80 Route 1 0 0
TCP 192.168.0.100:443 rr
-> 192.168.0.101:443 Route 1 0 0
-> 192.168.0.102:443 Route 1 0 0
测试一下:
[root@node10 ~]# curl http://192.168.0.100;curl -k https://192.168.0.100
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
此时我们访问VIP后两次调度都到了RS1上,增大了RS1的负载,我们需要使用防火墙标签解决这个问题
清空一下之前的调度:
ipvsadm -C
在vs调度器中设定端口标签,把80和443视作一个整体
iptables -t mangle -A PREROUTING -d 192.168.0.100 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 66
设定调度规则
ipvsadm -A -f 66 -s rr
ipvsadm -a -f 66 -r 192.168.0.10 -g
ipvsadm -a -f 66 -r 192.168.0.20 -g
我们现在来测试一下,看看会不会发生轮询错乱的问题:
[root@node10 ~]# curl -k https://192.168.0.100
RS2 server - 192.168.0.102
[root@node10 ~]# curl -k https://192.168.0.100;curl 192.168.0.100
RS1 server - 192.168.0.10
RS2 server - 192.168.0.20
5.lvs持久链接
在进行调度时,不管用什么算法,只要相同源过来的数据包我们就把他的访问记录在内存中,也就是把 这个源的主机调度到了那个RS上 如果在短期(默认360S)内同源再来访问我仍然按照内存中记录的调度信息,把这个源的访问还调度到 同一台RS上。 如果过了比较长的时间(默认最长时间360s)同源访问再次来访,那么就会被调度到其他的RS上
在lvs调度器中设定
ipvsadm -E -f 66 -s rr -p [3000]
ipvsadm -LnC