这里先介绍一些高可用的概念
linux cluster: 一束,集群
cluster:计算机集合,为解决某个特定的问题组合起来的单个系统。
linux cluster类型:
LB:load balancing,负载均衡集群,处理多个独立的请求,每个机器完成一部分请求计算,每个机器可以单独处理一部分请求。 HA:high avaliablity,高可用。A=MTBF/(MTBF+MTTR):平均无故障时间/(平均无故障时间+修复时间),范围(0,1) 90%:一年有10%不可用,三十几天不可用,可用性极低 99%:(5天不可用), 99.999%:(不在线5分钟,非常高的可用性)要付出的代价也非常大 HP:high preformance,高性能,解决复杂的单一的问题,超算就属于高性能计算机,可以用来破解秘钥,穷举等功能
系统扩展方式:
scale up:向上扩展,提升单台机器的性能 scale out:向外扩展,多台性能不高的机器并行工作
LB cluster(负载均衡)的实现方式:
用硬件来实现:
F5 big-ip citrix netscaler A10
用软件来实现:
lvs:linux virtual server:单纯的调度器,没有额外的功能,也不能像nginx一样能自动检测其他服务器的健康状况 nginx:stream和upstream haporxy ats:apache traffic server perlbal
根据工作的协议层次划分
传输层进行工作:(DIP:DPORT)只要符合对应的IP和端口,就能自动分发,应用层的内容不管。
lvs:工作在系统的内核中,不用进入用户空间,就可以完成报文的转发。 nginx:根据(stream)用户层要监听对应的套接字,到达用户进程后,再作为源地址向后转发。 haproxy:根据(mode tcp)
应用层进行工作:根据应用层的不同报文来进行分发,比如将图片请求发往一组服务器,其他的请求内容发往一组服务器。
proxy sferver http:nginx,httpd,haporxy fastcgi:nginx,httpd mysql:mysql-proxy,,,
站点的指标:
pv:page vier,页面浏览,必须打开对应的链接才算打开,来自浏览器的一次html内容请求会被看作一个PV uv:unique vistor,一个用户可能会浏览多个页面,单独的访问者是一个uv, IP:多个用户在一个局域网,对外只有一个公共IP,指的是这个IP,
ha需要考虑的问题:服务器端有多台主机,客户端访问服务器,通过调度器调度到第1台服务器,用户加入购物车一个商品,一刷新,可能会被调度到第二台服务器上面,这样购物车里面的数据就会没有了,因此服务器端要能够追踪客户的会话,当用户刷新后,服务器能够识别用户,将对应的会话调度到之前访问的那个服务器上面,才能正常工作。
会话保持:
(1)session sticky:会话粘性,可以通过几种方式来识别用户的会话 调度器上通过源IP来区分那个用户,不好,局域网内的用户对外都是同一个IP,会被识别成同一个用户 通过cookie来识别用户,即使同一个IP,cookie也会不一样,但是要识别cookie,要工作在应用层解析http报文才能办到,这时lvs工作在网络层,就无能为力了。 (2)session replication session cluster:后台的服务器通过多播的方式同步会话数据,以防某台主机宕机,会话丢失。 (3)session server master/slave:将后端服务器的会话单独保存在一个服务器上面,需要的话去查询调用,会话数据保存在内存中,定时存储到硬盘上, 数据库分为主从数据库,主数据库可以读写操作,从数据库只能从主数据库那里复制,服务器可以从主从数据库中读取,保证了数据的唯一性。 可以当做是四层路由器,四层交换机,vs根据请求的报文的目标IP和目标协议及端口将其调度转发至某个realserver,根据调度算法来挑选rs,
iptables:
流入报文:prerouting->input 流入报文:output-> postrouting 转发报文:prerouting-> forward ->postrouting DNAT:目标地址转换,放置在prerouting链中。
lvs:linux virtual server 包含的命令:ipvsadm/ipvs
ipvsadm:用户控制的命令行工具,规则管理器,用于管理集群服务及realserver
ipvs:工作于内核空间的netfilter的INPUT钩子之上的框架。互联网客户端的报文先经过lvs的网卡,经过prerouting链本来是要进入forward链中进行转发,这里被强行转发,送到了input链上,经过lvs进程对报文的处理后直接送到了postrouting链上送出去,发送给后端的rs服务器。
lvs集群类型中的术语:下面的所有说明都是使用的简称
vs:virtual server,director,dispatcher,balancer rs:real server,upstream server,backend server cip:client ip vip:virtual ip rip:real server ip dip:director ip 报文流程过程:cip <-->vip==dip<-->rip
lvs集群的类型,原理:
lvs-nat:修改请求报文的目标ip,其实就是多目标ip的DNAT,通过将请求报文中的目标地址和目标端口修改为某挑选出的rs的rip和port实现转发 (1)rip和dip必须在同一个ip网络,而且应该是私网地址,rs的网关要指向dip (2)请求报文和响应报文都必须经由director转发,director易成为系统的瓶颈 (3)支持端口映射功能,可修改请求报文的目标端口 (4)vs必须是linux系统,rs可以是任意系统
lvs-dr:
补充知识点:linux多网卡的广播,响应方式
linux默认响应模式,如果系统有多块网卡连接在不同的网络中,A,B网卡各有一个网络地址,当网卡A收到arp请求的目标地址是B网卡的ip地址,linux为了提高系统的可用性,会从网卡A发送(B网卡ip对应的mac地址)给其响应。只要本机有这个地址,无论谁请求,从哪个网卡进来,都会响应。
linux对外通告的默认模式,当有多个网卡的主机接入到网络中,linux会向这个网络通告自己系统所有的网卡信息(mac,ip)到这个网络中
可以通过修改内核网络参数,限制每块网卡只向本网卡对应的网络通告本网卡的ip,和地址信息。即使A网卡收到目标地址为B网卡的arp请求,也不会对其响应,其实这应该是正常的行为。
流程:
在rs主机上面,将vip配置在lo网卡上面,lo网卡有两个ip地址:一个是127的ip,一个是vip,而lo网卡只连接本主机。当路由发送vip的arp请求,rs主机即使有vip这个地址,但是也不会通过外接的网卡响应回复,而是vs主机对应的网卡回复响应。
操纵封装新的mac地址来转发,进入的报文不变,只是在报文外面再修改数据链路层首部,源mac为dip所在接口的mac,目标mac为后端某一个rs主机的mac,vs根据rs上的物理网卡的ip来找到对应的mac地址。源ip/port,以及目标ip/port均保持不变。把请求报文封装好mac地址,发送给对应的rs主机
rs主机去掉mac地址后发现报文中有本机ip,将报文接收下来,(lo网卡上有vip),
rs主机把报文处理后发送响应报文,因为进来的请求报文源ip为用户的ip,目标ip为vip。响应报文的源ip为vip,目标ip为用户的ip,封装后的报文经过lo网卡发出,经过路由转发后就直接发送给用户,而不再经过vs主机。
下面也是一种原理描述:客户端访问服务器的web站点,通过运营商的dns查询到服务器的ip地址,即vs主机的vip,报文到达路由器e,路由器发现vip属于这个网络内的主机,通过arp广播来查找vip对应的mac地址。arp广播后,网络内的所有的主机都可以收到广播消息,网络内的所有主机(vs和rs)都配置有vip,但是由于rs上面的vip是配置在lo网卡上面的,而且在内核中设置了广播和响应参数,lo不在连接的网络内,所以所有的rs主机都不会响应arp请求,但是vs主机的vip是配置在连接网络的网卡上面,可以正常响应arp报文,这样,路由器会将请求报文发送给vs主机。vs主机必须和rs主机在同一个网络内,vs主机收到请求后,处理返回
客户端一般都是从服务器请求资源,请求报文的内容为空,而响应报文的内容很多。为了减少vs的压力,响应报文直接由rs服务器发送给客户端,不经由vs服务器。
director和各rs都得配置使用vip
(1)确保前端路由器将目标ip为vip的请求报文发送给director,能够实现的方法: (a)在前端网关做静态mac绑定,不好 (b)在rs上使用arptables,不好 (c)在rs上修改内核参数来限制通告及应答的级别,好,废话,不然这篇文章怎么写下去 arp_announce arp_ignore (2)rs的rip可以使用私网地址,也可以使用公网地址,rip与dip在同一网络,rip的网关不能指向dip,确保响应报文不会经由director (3)rs跟director要在同一个物理网络内 (4)请求报文要经过director,但响应不能经由director,而是由rs直接发送给client (5)不支持端口映射
lvs-tun:在原请求ip报文之外新加一个ip首部来进行转发,进入的报文都不变,在报文的网络层外面再添加一个网络层首部
转发方式:不修改请求报文的ip首部(源ip为cip,目标ip为vip),而在原ip报文之外再封装一个ip首部(源ip为cip,目标ip为vip),将报文发往挑选出的目标rs,
(1)dip,vip,rip都应该是公网地址 (2)rs的网关不能也不可能指向dip (3)请求报文要经由director,但响应报文不能经由director (4)不支持端口映射 (5)rs的os要支持隧道功能。
lvs-fullnat:修改请求报文的源和目标ip,通过同时修改请求报文的源ip地址和目标ip地址进行转发
cip --> dip vip --> rip vip是公网地址,rip和dip是私网地址,且通常不在同一个ip网络,因此,rip的网关一般不会指向dip rs收到的请求报文源地址是dip,因此,只需要响应给dip,但director还要将其发往client 请求和响应报文都经过director 支持端口映射 注意默认不支持。
ipvs scheduler:调度算法,根据其调度时是否考虑当前的各rs的负载状态,可分为静态方法和动态方法两种。
静态方法:仅根据算法本身进行调度;
RR:roundrobin,轮询; WRR:weighted RR,加权轮询; SH:source hashing,实现session sticy;不能识别cookie,只能通过源地址进行保存会话,进行会话保持,通过ip来绑定的方法有些粗暴, DH:destination hashing,当此服务器是反代缓存服务器,当客户端访问的网站(搜狐)内容已经在一个缓存服务器中缓存过,则所有用户 访问(搜狐)都转发到那台缓存服务器,提高响应速度。
动态方法:主要进行根据每rs当前的负载状况及调度算法进行调度。
LC:least connections,发送给计算数值较小的服务器。当计算结果是相同的时候,从上往下发送请求。 overhead=activeconns*256+inactiveconns 后台有两台服务器,每台服务器连接数都是50个,一台服务器1活动的连接数40个,非活动连接数10个。 另一台服务器2活动的连接数10个,非活动连接数40个,计算下来请求应该发送给服务器2 WLC:weighted LC 有的服务器能力强,所承受的请求大(默认的调度算法) overhead=(activeconns*256+inactiveconns)/weighted,假如第一台服务器的权重是10,能力强。第二台服务器的权重是1, 后台有两台服务器,每台服务器连接数都是50个,一台服务器1活动的连接数10个,非活动连接数40个。另一台服务器2活动的 连接数40个,非活动连接数10个,计算下来请求应该发送给服务器1 SED:shortest expection delay:最小延迟计算方法, overhead=(activeconns*256+1)/weighted,
负载均衡集群的设计要点:
(1) 是否需要会话保持; (2) 是否需要共享存储; 共享存储:NAS, SAN, DS(分布式存储) 数据同步:rsync+inotify实现数据同步
lvs-nat:
设计要点: (1) RIP与DIP在同一IP网络, RIP的网关要指向DIP; (2) 支持端口映射; 实践:实现一个负载均衡一个php应用;要考虑到(1) 是否需要会话保持;(2) 是否需要共享存储;
—ipvsadm命令解析—
ipvsadm/ipvs:
查看内核是否支持 ipvsadm
#/sbin/modprobe -l | grep ipvs
ipvs集群:
先定义集群服务
再定义服务上的RS
端口不同,对应的服务不同
包内容查看
#rpm -ql ipvsadm /etc/rc.d/init.d/ipvsadm /etc/sysconfig/ipvsadm-config /sbin/ipvsadm /sbin/ipvsadm-restore /sbin/ipvsadm-save
ipvsadm命令:
ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask] [--pe persistence_engine] [-b sched-flags] ipvsadm -D -t|u|f service-address ipvsadm -C 清空规则链 ipvsadm -R 重载规则 ipvsadm -S [-n] ipvsadm -a|e -t|u|f service-address -r server-address [options] ipvsadm -d -t|u|f service-address -r server-address ipvsadm -L|l [options] ipvsadm -Z [-t|u|f service-address]
管理集群服务:增、改、删;
增、改: ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] 删: ipvsadm -D -t|u|f service-address service-address: -t|u|f: -t: TCP协议的端口,VIP:TCP_PORT -u: UDP协议的端口,VIP:UDP_PORT -f:firewall MARK,防火墙标记,是一个数字; [-s scheduler]:指定集群的调度算法,默认为wlc;
管理集群上的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 server-address: rip[:port] 选项: lvs类型: -g: gateway, dr类型 -i: ipip, tun类型 -m: masquerade, nat类型 -w weight:权重; 清空定义的所有内容: ipvsadm -C 查看: ipvsadm -L|l [options] --numeric, -n:numeric output of addresses and ports --exact:expand numbers (display exact values) --connection, -c:output of current IPVS connections --stats:output of statistics information --rate :output of rate information 保存和重载: ipvsadm -S = ipvsadm-save ipvsadm -R = ipvsadm-restore
====当当当,下面是实践,将每种都实验一下===
首先确认后台的两台rs服务器是正常工作的,并且可以提供php页面显示,而且要能区分是不同的主机
下面是简单页面测试
[root@localhost ~]#curl 192.168.175.13/index.html <h1>host:13 index.html</h1> [root@localhost ~]#curl 192.168.175.14/index.html <h1>host:14 index.html</h1>
查看系统支持哪些调度算法
[root@localhost ~]#/sbin/modprobe -l | grep ipvs kernel/net/netfilter/ipvs/ip_vs.ko kernel/net/netfilter/ipvs/ip_vs_rr.ko kernel/net/netfilter/ipvs/ip_vs_wrr.ko kernel/net/netfilter/ipvs/ip_vs_lc.ko kernel/net/netfilter/ipvs/ip_vs_wlc.ko kernel/net/netfilter/ipvs/ip_vs_lblc.ko kernel/net/netfilter/ipvs/ip_vs_lblcr.ko kernel/net/netfilter/ipvs/ip_vs_dh.ko kernel/net/netfilter/ipvs/ip_vs_sh.ko kernel/net/netfilter/ipvs/ip_vs_sed.ko kernel/net/netfilter/ipvs/ip_vs_nq.ko kernel/net/netfilter/ipvs/ip_vs_ftp.ko kernel/net/netfilter/ipvs/ip_vs_pe_sip.ko
为了保证测试正常,先将防火墙全部关闭,等测试通过,再添加
基于lvs-nat模式
先将后端主机的每台机器的默认网关指向vs主机:192.168.175.11,主机12和主机13同时操作
[root@localhost ~]#route add default gw 192.168.175.11 [root@localhost ~]#route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.175.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0 0.0.0.0 192.168.175.11 0.0.0.0 UG 0 0 0 eth0
主机11设置
[root@localhost ~]#ifconfig eth0 Link encap:Ethernet HWaddr 00:50:56:3F:AC:4D inet addr:192.168.175.11 Bcast:192.168.175.255 Mask:255.255.255.0 eth1 Link encap:Ethernet HWaddr 00:0C:29:E9:AD:3D inet addr:192.168.1.10 Bcast:192.168.1.255 Mask:255.255.255.0
然后在主机:192.168.175.11 上面配置lvs-nat
[root@localhost ~]#yi ipvsadm [root@localhost ~]#ipvsadm -A -t 192.168.1.10:80 -s rr [root@localhost ~]#ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.10:80 rr [root@localhost ~]#ipvsadm -a -t 192.168.1.10:80 -r 192.168.175.13 -m [root@localhost ~]#ipvsadm -a -t 192.168.1.10:80 -r 192.168.175.14 -m [root@localhost ~]#ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.10:80 rr -> 192.168.175.13:80 Masq 1 0 0 -> 192.168.175.14:80 Masq 1 0 0 [root@localhost ~]#echo 1 > /proc/sys/net/ipv4/ip_forward [root@localhost ~]#cat /proc/sys/net/ipv4/ip_forward 1
然后找一台主机:192.168.1.20 主机测试,这台主机位于192.168.1.0网段内
[root@localhost ~]#for i in {1..10}; do curl 192.168.1.10; done <h1>host:13 index.html</h1> <h1>host:14 index.html</h1> <h1>host:13 index.html</h1> <h1>host:14 index.html</h1> <h1>host:13 index.html</h1> <h1>host:14 index.html</h1> <h1>host:13 index.html</h1> <h1>host:14 index.html</h1> <h1>host:13 index.html</h1> <h1>host:14 index.html</h1>
同时在主机:192.168.175.13上面进行抓包
[root@localhost ~]#tcpdump -n ip host 192.168.175.13 and ! 192.168.175.30 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 23:55:12.058233 IP 192.168.1.20.58891 > 192.168.175.13.http: 23:55:12.058444 IP 192.168.175.13.http > 192.168.1.20.58891: 23:55:12.058910 IP 192.168.1.20.58891 > 192.168.175.13.http: 23:55:12.059088 IP 192.168.1.20.58891 > 192.168.175.13.http:
可以从抓包的内容看到,nat模型其实就是dnat,用户(192.168.1.20)访问(192.168.1.0)主机的http服务,(192.168.1.10)主机将请求报文的目标ip由自己的ip更改为(192.168.175.13)然后转发到后端的主机,后端主机处理完成后,转发到网关,这里网关设置的是(192.168.175.11),由网关再次更改回复报文的源ip返回给客户机
这时,虚拟主机(192.168.175.13)虽然网关指向了(192.168.175.11),但是依然可以上网,因为网关开启了转发功能,只要不是本段的ip,都会转发出去
将上面的调度模式更改为wrr模式,即加权轮询
[root@localhost ~]#ipvsadm -E -t 192.168.1.10:80 -s wrr [root@localhost ~]#ipvsadm -e -t 192.168.1.10:80 -r 192.168.175.13 -m -w 2 [root@localhost ~]#ipvsadm -e -t 192.168.1.10:80 -r 192.168.175.14 -m -w 1 [root@localhost ~]#ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.10:80 wrr -> 192.168.175.13:80 Masq 2 0 0 -> 192.168.175.14:80 Masq 1 0 0
然后使用测试机(192.168.1.20)进行测试
[root@localhost ~]#for i in {1..10}; do curl 192.168.1.10; done <h1>host:13 index.html</h1> <h1>host:14 index.html</h1> <h1>host:13 index.html</h1> <h1>host:13 index.html</h1> <h1>host:14 index.html</h1> <h1>host:13 index.html</h1> <h1>host:13 index.html</h1> <h1>host:14 index.html</h1> <h1>host:13 index.html</h1> <h1>host:13 index.html</h1>
将上面的模式改为sh,实现会话绑定,访问的都是第一次访问的rs服务器
[root@localhost ~]#ipvsadm -E -t 192.168.1.10:80 -s sh [root@localhost ~]#ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.10:80 sh -> 192.168.175.13:80 Masq 2 0 7 -> 192.168.175.14:80 Masq 1 0 3
然后使用测试机(192.168.1.20)进行测试
[root@localhost ~]#for i in {1..10}; do curl 192.168.1.10; done <h1>host:14 index.html</h1> <h1>host:14 index.html</h1> <h1>host:14 index.html</h1> <h1>host:14 index.html</h1> <h1>host:14 index.html</h1> <h1>host:14 index.html</h1> <h1>host:14 index.html</h1> <h1>host:14 index.html</h1> <h1>host:14 index.html</h1> <h1>host:14 index.html</h1>
基于lvs-dr模式
dr模型中,各主机上均需要配置VIP,解决地址冲突的方式有三种:
(1) 在前端网关做静态绑定;
(2) 在各RS使用arptables;
(3) 在各RS修改内核参数,来限制arp响应和通告的级别;
限制响应级别:arp_ignore
0:默认值,表示可使用本地任意接口上配置的任意地址进行响应;
1: 仅在请求的目标IP配置在本地主机的接收到请求报文接口上时,才给予响应;(应该使用这种模式)
限制通告级别:arp_announce
0:默认值,把本机上的所有接口的所有信息向每个接口上的网络进行通告;
1:尽量避免向非直接连接网络进行通告;
2:必须避免向非本网络通告;(应该使用这种模式)
通常情况下,用户请求网页资源,请求报文比较小,都由vs主机来进行分发。响应报文很大,rs主机处理后直接返回给用户,而不再经过vs主机,可以减小vs主机的压力,能够更多的增加rs主机,实现更强的负载均衡。 而上面的nat模型不管是请求报文,还是响应报文都经过vs主机,vs主机要转发两边的报文,压力很大
在rs主机上:先配置参数,再配置vip,不然先配置vip后就有可能先通告出去了,再配置参数就没有意义了。
根据下面的框图来说原理
先说下虚拟机配置,关闭防火墙,便于测试
在虚拟机配置两个虚拟网络,和外界的网络是分离的,net4代表公网,net2代表服务器所在的私网
用户的的ip地址为(192.168.200.30),只需用一个网卡,桥接到net4网络上面
代理服务器的vip为(192.168.200.10),配置在eth1上面,桥接到net4网络上面
还有一个路由器的一个网卡eth1,ip为(192.168.200.15),桥接在net4网络上面,
内网net2上面有两台rs服务器(192.168.175.13)和(192.168.175.14)
代理服务器的dip为(192.168.175.10),配置在eth0上面,桥接在net2网络上面
路由器的另外一个网卡eth0,ip为(192.168.175.15),桥接在net2网络上面
—
报文传送的具体过程,用户(192.168.200.30)访问服务器,请求报文经过网络发送给服务器(192.168.200.10),
服务器(192.168.200.10)收到报文,根据lvs算法,vs根据rs上的物理网卡的ip来找到对应的mac地址,把用户的请求报文封装好mac地址,发送给对应的rs主机,rs主机去掉mac地址后发现报文中有本机ip,将报文接收下来,(lo网卡上有vip)。rs主机把报文处理后发送响应报文,因为进来的请求报文源ip为用户的ip,目标ip为vip。响应报文的源ip为vip,目标ip为用户的ip,封装后的报文经过lo网卡发送到网关,经过路由转发后,经过互联网发送给用户,而不再经过vs主机。
主机:192.168.175.13 [root@localhost ~]#ifconfig eth0 Link encap:Ethernet HWaddr 00:50:56:2A:10:83 inet addr:192.168.175.13 Bcast:192.168.175.255 Mask:255.255.255.0 [root@localhost ~]#cat lvs_dr_slave.sh #!/bin/bash # vip=192.168.200.10 mask='255.255.255.255' gw_ip="192.168.175.15" 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 lo:0 $vip netmask $mask broadcast $vip up route add -host $vip dev lo:0 #vip必须从lo网卡进来,从lo网卡出去 route del default route add default gw $gw_ip ;; stop) ifconfig lo:0 down 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 ;; *) echo "Usage $(basename $0) start|stop" exit 1 ;; esac [root@localhost ~]#bash lvs_dr_slave.sh start [root@localhost ~]#ifconfig eth0 Link encap:Ethernet HWaddr 00:50:56:2A:10:83 inet addr:192.168.175.13 Bcast:192.168.175.255 Mask:255.255.255.0 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 lo:0 Link encap:Local Loopback inet addr:192.168.200.10 Mask:255.255.255.255 UP LOOPBACK RUNNING MTU:65536 Metric:1 [root@localhost ~]#route -n #网关指向路由器的内网ip Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.200.10 0.0.0.0 255.255.255.255 UH 0 0 0 lo 192.168.175.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0 0.0.0.0 192.168.175.15 0.0.0.0 UG 0 0 0 eth0 [root@localhost ~]#curl 192.168.200.10 #请求报文可以正常响应 host 13 index.html
–
主机:192.168.175.14 [root@localhost ~]#cat lvs_dr_slave.sh #!/bin/bash # vip=192.168.200.10 mask='255.255.255.255' gw_ip="192.168.175.15" 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 lo:0 $vip netmask $mask broadcast $vip up route add -host $vip dev lo:0 #vip必须从lo网卡进来,从lo网卡出去 route del default route add default gw $gw_ip ;; stop) ifconfig lo:0 down 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 ;; *) echo "Usage $(basename $0) start|stop" exit 1 ;; esac [root@localhost ~]#ifconfig eth0 Link encap:Ethernet HWaddr 00:50:56:34:80:1B inet addr:192.168.175.14 Bcast:192.168.175.255 Mask:255.255.255.0 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 lo:0 Link encap:Local Loopback inet addr:192.168.200.10 Mask:255.255.255.255 UP LOOPBACK RUNNING MTU:65536 Metric:1 [root@localhost ~]#route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.200.10 0.0.0.0 255.255.255.255 UH 0 0 0 lo 192.168.175.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0 0.0.0.0 192.168.175.15 0.0.0.0 UG 0 0 0 eth0 [root@localhost ~]#curl 192.168.200.10 #请求报文可以正确响应 host 14 index.html
–
主机:192.168.200.10 [root@localhost ~]#cat lvs_dr_master.sh #!/bin/bash # vip='192.168.200.10' port='80' rs1='192.168.175.13' rs2='192.168.175.14' scheduler='wrr' lvs_type='-g' case $1 in start) iptables -F ipvsadm -C ipvsadm -A -t ${vip}:${port} -s $scheduler ipvsadm -a -t ${vip}:${port} -r ${rs1} $lvs_type -w 1 ipvsadm -a -t ${vip}:${port} -r ${rs2} $lvs_type -w 1 # echo 1 > /proc/sys/net/ipv4/ip_forward #lvs的dr模式不用开启网络转发功能 ;; stop) ipvsadm -C ;; *) echo "Usage $(basename $0) start|stop" exit 1 ;; esac [root@localhost ~]#bash lvs_dr_master.sh start [root@localhost ~]#ifconfig eth0 Link encap:Ethernet HWaddr 00:50:56:39:87:7F inet addr:192.168.175.10 Bcast:192.168.175.255 Mask:255.255.255.0 eth1 Link encap:Ethernet HWaddr 00:0C:29:56:18:20 inet addr:192.168.200.10 Bcast:192.168.200.255 Mask:255.255.255.0 [root@localhost ~]#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.200.10:80 wrr -> 192.168.175.13:80 Route 1 0 0 -> 192.168.175.14:80 Route 1 0 0
–
主机:192.168.200.15 路由器设置 [root@localhost ~]#ifconfig eth0 Link encap:Ethernet HWaddr 00:50:56:3F:AC:4D inet addr:192.168.175.15 Bcast:192.168.175.255 Mask:255.255.255.0 eth1 Link encap:Ethernet HWaddr 00:0C:29:E9:AD:3D inet addr:192.168.200.15 Bcast:192.168.200.255 Mask:255.255.255.0 [root@localhost ~]#echo 1 > /proc/sys/net/ipv4/ip_forward #开启转发功能 [root@localhost ~]#cat /proc/sys/net/ipv4/ip_forward 1 [root@localhost ~]#ll /proc/sys/net/ipv4/conf/ total 0 dr-xr-xr-x 0 root root 0 Jul 24 18:58 all dr-xr-xr-x 0 root root 0 Jul 24 18:52 default dr-xr-xr-x 0 root root 0 Jul 24 18:58 eth0 dr-xr-xr-x 0 root root 0 Jul 24 18:58 eth1 dr-xr-xr-x 0 root root 0 Jul 24 18:58 lo [root@localhost ~]#echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter [root@localhost ~]#echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter [root@localhost ~]#echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter [root@localhost ~]#echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter [root@localhost ~]#echo 0 > /proc/sys/net/ipv4/conf/lo/rp_filter #0 就是对进来的包完全不作检查,这样有被dos 攻击的风险。 #1 就是严格检查,只要不是这个interface 的包,就不返回。 #2 就是不太严格,只要本机配置了这个ip ,还是可以返回的。 #对于lvs 来说,用2 也是可以的。
–
主机:192.168.200.30 客户机测试 [root@localhost ~]#for i in {1..100};do curl 192.168.200.10;sleep 1;done host 14 index.html host 13 index.html host 14 index.html 成功 #更改权重 [root@localhost ~]#ipvsadm -e -t 192.168.200.10:80 -r 192.168.175.13 -g -w 2 [root@localhost ~]#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.200.10:80 wrr -> 192.168.175.13:80 Route 2 0 1 -> 192.168.175.14:80 Route 1 0 0 #客户机测试 [root@localhost ~]#for i in {1..100};do curl 192.168.200.10;sleep 1;done host 13 index.html host 13 index.html host 14 index.html host 13 index.html host 13 index.html host 14 index.html
dr模式下的防火墙
在vs主机和rs主机上面都要放行80端口的请求,整个报文才是通的
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
路由器不设防火墙,因为报文里面没有路由器的ip,找不到路由器
保存及重载规则
保存:建议保存至/etc/sysconfig/ipvsadm
ipvsadm-save > /PATH/TO/IPVSADM_FILE ipvsadm -S > /PATH/TO/IPVSADM_FILE systemctl stop ipvsadm.service
重载:
ipvsadm-restore < /PATH/FROM/IPVSADM_FILE ipvsadm -R < /PATH/FROM/IPVSADM_FILE systemctl restart ipvsadm.service
注意
不成功的时候,抓包是很好的调试方法,ping一下后端的rs主机,然后(arp -n)查看下arp缓存的mac地址是否是后端主机命令行显示的mac地址,dr模式是靠mac地址来进行工作的,这个很重要,都是虚拟环境,可以保证不会受到物理网卡的干扰
同一网段的测试不存在路由的问题,不同网段测试,路由要配置内核参数,将所有报文转发。不然路由会将可疑的报文丢弃,造成客户机一直发送握手包
当vs,rs,vip,rip都在同一个网段的时候,必须要设置arp参数,不然网关路由发送的arp请求会乱,但是浪费公网ip,所有机器用的ip都是公网ip地址
当vs,vip在公网段,rs,rip在内网段,则设置arp参数不是必要的
参考文档:lvs+keepalived
–
–
–
评论前必须登录!
注册