路漫漫其修远兮
吾将上下而求索

lvs学习:简介和配置

这里先介绍一些高可用的概念

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服务器。

image.png

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可以是任意系统

image.png

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页面显示,而且要能区分是不同的主机

image.png

image.png

下面是简单页面测试

[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返回给客户机

image.png

这时,虚拟主机(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,找不到路由器

image.png

lvs.zip

保存及重载规则

保存:建议保存至/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

未经允许不得转载:江哥架构师笔记 » lvs学习:简介和配置

分享到:更多 ()

评论 抢沙发

评论前必须登录!