实验环境搭建:
Director :VIP192.168.0.127 桥接
DIP192.168.10.1 仅主机
Real Server 1:RIP 192.168.10.2 仅主机 网关指向:192.168.10.1
Real Server 2:RIP 192.168.10.3 仅主机 网关指向:192.168.10.1
Client:192.168.0.1 物理机
每台Real Server上分别安装有http服务。我们这里为了演示效果,每个http服务的页面不同。
Real Server 1
[root@station39 html]# ifconfig eth0 192.168.10.2
[root@station39 html]# route add default gw 192.168.10.1
Real Server 2
[root@station26 html]# ifconfig eth0 192.168.10.3
[root@station26 html]# route add default gw 192.168.10.1
Director :
[root@server27 ~]# ifconfig eth1 192.168.10.1
打开内核路由功能
[root@server27 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
确保永久有效:
[root@server27 ~]# vim /etc/sysctl.conf
# Controls IP packet forwarding
net.ipv4.ip_forward = 1
[root@server27 ~]# sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 4294967295
kernel.shmall = 268435456
OK,准备工作已经就绪,下面开始实验的关键步骤:
[root@server27 ~]# yum install ipvsadm -y
使用步骤:1.定义服务 2 .为服务定义Real Server
[root@server27 ~]# ipvsadm -A -t 192.168.0.127:80 -s rr
[root@server27 ~]# 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.127:80 rr
[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.10.2 -m -w 2
[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.10.3 -m -w 5
-g, --gatewaying Use gatewaying (direct routing). This is the default.
-i, --ipip Use ipip encapsulation (tunneling).
-m, --masquerading Use masquerading (network access transla-tion, or NAT).
PS:在这里设定的权重对于RR算法来说并没有什么意义,我们只是为后面的实验而设定的。
[root@server27 ~]# 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.127:80 rr
-> 192.168.10.3:80 Masq 5 0 16
-> 192.168.10.2:80 Masq 2 0 15
此时,我们使用物理机访问192.168.0.127就会发现页面交替变化,这是由RR算法的特性决定的。
我们改变为WRR算法试试:
[root@server27 ~]# ipvsadm -E -t 192.168.0.127:80 -s wrr
[root@server27 ~]# 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.127:80 wrr
-> 192.168.10.3:80 Masq 5 0 86
-> 192.168.10.2:80 Masq 2 0 43
改变为LBLC算法试试:
LBLC:基于本地状态的最少连接,在DH算法的基础上还要考虑服务器上的活动连接数。
[root@server27 ~]# ipvsadm -E -t 192.168.0.127:80 -s lblc
[root@server27 ~]# 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.127:80 lblc
-> 192.168.10.3:80 Masq 5 0 112
-> 192.168.10.2:80 Masq 2 0 41
此时无论客户端怎么刷新,访问页面都不会改变。
保存规则:
ipvsadm -S >>/etc/sysconfig/ipvs-config == ipvsadm-save
ipvsadm -R < /etc/sysconfig/ipvs-config == ipvsadm-restore
Director routing (LVS-DR ):
PS:Director分发到Real Server的过程中,数据包的源地址和目标地址都没有发生改变,Director仅仅是将目标mac地址转换成某台Real Server的mac地址,源mac地址改为Director内网网卡的mac地址。
两个技术难题:
1 Real Server要避免对客户端发来的对VIP的arp地址解析请求;
解决方法
1) 修改内核的两个参数:arp_announce, arp_ignore。
arp_announce :定义不同级别:当ARP请求通过某个端口进来是否利用这个接口来回应。
0 - (default) Use any local address, configured on any interface.
利用本地的任何地址,不管配置在哪个接口上去响应ARP请求;
1 - Try to avoid local addresses that are not in the target's subnet for this interface.
避免使用另外一个接口上的mac地址去响应ARP请求;
2 - Always use the best local address for this target.
尽可能使用能够匹配到ARP请求的最佳地址。
arp_ignore:当ARP请求发过来后发现自己正是请求的地址是否响应;
0 - (default): reply for any local target IP address, configured on any interface
利用本地的任何地址,不管配置在哪个接口上去响应ARP请求;
1 - reply only if the target IP address is local address configured on the incoming
interface.
哪个接口上接受ARP请求,就从哪个端口上回应。
PS:对linux来说IP地址属于系统而不属于某个接口。
2) Red Hat 提供了arptables工具,利用arp防火墙也可以实现。
2 当Real Server内网网卡响应客户端请求时,要以VIP作为源地址,不能以RIP作为源地址。
解决方法:
添加一条路由:route add -host 192.168.0.127 dev lo:0使客户端访问VIP,就让VIP来响应客户端。这样避免了使用RIP作为源地址。
Director:VIP响应客户端请求;
DIP:与RIP彼此间实现arp解析,并将客户端的请求转发给Real Server。
实验环境搭建:
Director :eth0:0 VIP192.168.0.127
eth0 DIP192.168.0.10 桥接
Real Server 1: eth0 RIP 192.168.0.12 桥接
lo:0 VIP 192.168.0.127
Real Server 2: eth0 RIP 192.168.0.13 桥接
lo:0 VIP 192.168.0.127
Client:192.168.0.1 物理机
Real Server 1
[root@station39 ~]# vim /etc/sysctl.conf
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
[root@station39 ~]# sysctl -p
[root@station39 ~]# ifconfig eth0 192.168.0.12/24
[root@station39 ~]# ifconfig lo:0 192.168.0.127 broadcast 192.168.0.127 netmask 255.255.255.255
[root@station39 ~]# route add -host 192.168.0.127 dev lo:0
Real Server 2
[root@station26 ~]# vim /etc/sysctl.conf
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
[root@station26 ~]# sysctl -p
[root@station26 ~]# ifconfig eth0 192.168.0.13/24
[root@station26 ~]# ifconfig lo:0 192.168.0.127 broadcast 192.168.0.127 netmask 255.255.255.255
[root@station26 ~]# route add -host 192.168.0.127 dev lo:0
Director
[root@server27 ~]# ifconfig eth0 192.168.0.10/24
[root@server27 ~]# ifconfig eth0:0 192.168.0.127 broadcast 192.168.0.127 netmask 255.255.255.255
[root@server27 ~]# route add -host 192.168.0.127 dev eth0:0
[root@server27 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
[root@server27 ~]# ipvsadm -C
[root@server27 ~]# ipvsadm -A -t 192.168.0.127:80 -s wlc
[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.0.12 -g -w 5
[root@server27 ~]# ipvsadm -a -t 192.168.0.127:80 -r 192.168.0.13 -g -w 8
[root@server27 ~]# 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.127:80 wlc
-> 192.168.0.13:80 Route 8 0 18
-> 192.168.0.12:80 Route 5 0 11
PS:如果要保持访问的页面一致,我们可以另外准备一台服务器专门用来存放网页文件,然后通过NFS共享的方式挂载到Real Server的网页目录下,就可以实现真正的负载均衡了。
实现持久连接:
[root@server27 ~]# ipvsadm -E -t 192.168.0.127:80 -s wlc -p 3600
[root@server27 ~]# 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.127:80 wlc persistent 3600
-> 192.168.0.13:80 Route 8 0 62
-> 192.168.0.12:80 Route 5 0 0
此时,你会发现无论访问页面怎么刷新都不会再改变,这就是LVS持久性。
LVS Persistence 持久性
尽管我们选择了LVS的分发方法,但是大多时候我们要保证返回给客户端的所有响应请求必须来自于同一台Real Server,这里我们就要用到LVS Persistence(持久性)。
当使用SSL会话的时候,我们常常期望只交换一次密钥就可以建立永久连接,因此,LVS持久性在SSL会话中经常被用到。
当使用LVS持久性的时候,Director在内部使用一个连接根据记录称之为“持久连接模板”来确保所有来自同一个客户端的请求被分发到同一台Real Server上。
LVS 持久性类型:PCC PPC PNMP 混合类型。
Persistent client connections (PCC), cause all services a client is accessing to persist. (Also called zero port connections.)
来自同一客户端所有服务的请求都被重定向到同一台Real Server上,以IP地址为准。
PCC是一个虚拟服务没有端口号(或者端口号为0),以"-p" 来标识服务。
缺陷:定向所有服务,期望访问不同的Real Server无法实现。
假设一个用户在访问购物网站时同时使用HTTP(80)和HTTPS(443)两种协议,就需要这样定义:
ipvsadm -A -t 192.168.0.220:0 -s rr -p
ipvsadm -a -t 192.168.0.220.3:0 -r 192.168.10.11 -m
ipvsadm -a -t 192.168.0.220:0 -r 192.168.10.11 -m
Persistent port connections (PPC), which cause a single service to persist.
来自同一服务的请求都被重定向到同一台Real Server上,以端口号为准。
例如:client---->LVS(80,22)------>RS1 client----->LVS(23)----->RS2
缺陷:期望访问不同的端口到同一台RS上,无法实现。
Persistent Netfilter Marked Packet persistence, which causes packets that have been marked with the iptables utility to persist.
根据iptables 的规则,将对于某类服务/几个不同端口的访问定义为一类。
先对某一特定类型的数据包打上标记,然后再将基于某一类标记的服务送到后台的Real Server上去,后台的Real Server 并不识别这些标记。
PS:在LVS-NAT的环境下做这个实验,由于前边的DR模型使用了网卡别名,所以并不适合这个实验。
[root@server27 ~]# iptables -t mangle -A PREROUTING -i eth0 -d 192.168.0.127 -p tcp --dport 80 -j MARK --set-mark 2
[root@server27 ~]# ipvsadm -A -f 2 -s wlc -p 3600
[root@server27 ~]# ipvsadm -a -f 2 -r 192.168.10.2 -m -w 2
[root@server27 ~]# ipvsadm -a -f 2 -r 192.168.10.3 -m -w 5
将持久和防火墙标记结合起来就能够实现端口姻亲功能,只要是来自某一客户端的对某一特定服务(需要不同的端口)的访问都定义到同一台Real Server上去。
假设这样一种场景:一个用户在访问购物网站时同时使用HTTP(80)和HTTPS(443)两种协议,我们需要将其定义到同一台Real Server上,而其他的服务不受限制,我们可以这样做:
实验基于LVS-NAT的环境。
先做一个自签名的证书
Real Server 1:
[root@station39 ~]# cd /etc/pki/tls/certs/
[root@station39 ~]# cd /etc/pki/tls/certs/
[root@station39 certs]# make httpd.pem
[root@station39 certs]# mv httpd.pem /etc/httpd/
[root@station39 httpd]# yum install mod_ssl -y
[root@station39 httpd]# cd conf.d/
[root@station39 conf.d]# vim ssl.conf
SSLCertificateFile /etc/httpd/httpd.pem //** line 112
SSLCertificateKeyFile /etc/httpd/httpd.pem //** line 119
重启httpd 服务。
[root@station39 ~]# vim /etc/hosts
192.168.10.2 web1.a.com web1
Real Server 2 :
[root@station26 ~]# yum install mod_ssl -y
[root@station26 certs]# cd /etc/httpd
[root@station26 httpd]# make -C /etc/pki/tls/certs httpd.pem
[root@station26 httpd]# mv /etc/pki/tls/certs/httpd.pem ./
[root@station26 httpd]# cd conf.d/
[root@station26 conf.d]# vim ssl.conf
SSLCertificateFile /etc/httpd/httpd.pem //** line 112
SSLCertificateKeyFile /etc/httpd/httpd.pem //** line 119
重启httpd 服务。
[root@station26 ~]# vim /etc/hosts
192.168.10.3 web2.a.com web2
Director:
[root@server27 ~]# iptables -t mangle -A PREROUTING -i eth0 -d 192.168.0.127 -p tcp --dport 80 -j MARK --set-mark 5
[root@server27 ~]# iptables -t mangle -A PREROUTING -i eth0 -d 192.168.0.127 -p tcp --dport 443 -j MARK --set-mark 5
[root@server27 ~]# ipvsadm -A -f 5 -s wlc -p
[root@server27 ~]# ipvsadm -a -f 5 -r 192.168.10.2 -m -w 2
[root@server27 ~]# ipvsadm -a -f 5 -r 192.168.10.3 -m -w 5
这里我们是为了演示实验的效果,使用的不同的证书,不同的页面。真实的生产环境中要求这些必须是一致的。
FTP connections (FTP connections require careful handling due to the complex nature of FTP connections).
PS:指定一个范围,将范围内的端口打上标记。然后使VSFTPD在被动模式下不再使用随机端口,而是使用范围内的随机端口,从而实现FTP的负载均衡。
1 Limiting the port range for passive connections, you must also configure the VSFTP server to use a matching port range:
vim /etc/vsftpd.conf:
pasv_min_port=10000
pasv_max_port=20000
2 You must also control the address that the server displays to the client for passive FTP connections. In a NAT routed LVS system, add the following line to /etc/vsftpd.conf to override the real server IP address to the VIP, which is what the client sees upon connection. For example:
pasv_address=n.n.n.n
3 iptables定义端口姻亲:
iptables -t mangle -A PREROUTING -p tcp -d n.n.n.n/32 --dport 21 -j MARK --set-mark 21
iptables -t mangle -A PREROUTING -p tcp -d n.n.n.n/32 --dport 10000:20000 -j MARK --set-mark 21
Expired persistence, which is used internally by the Director to expire connection tracking entries when the persistent connection template expires.