欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

马哥 37_01 _Linux集群系列之四——LVS DR详解及配置演示 有大用

ipvs 工作在input链上,一旦发觉到访问的是集群服务,就让请求转到postrouting链(不经过 forward链的),,,,这是马哥查资料得到的

INPUT-->POSTROUTING


ipvsadm            # 这个命令都是在 director 上执行的 

        管理服务

                -A
                -E

                -D

        管理RS

                -a
                -e

                -d

        查看

                -L|-l
                          -n

                          --stats

                          --rate

                          --timeout

                          --sort

                          --daemon

                          -c (--connection)

        规则管理

                -C

                -S

                -R


DR:

image.png


DR:

      director 和 rs 上都有  vip, 路由器如何确定请求是发给director的

          1) VIP:  =>MAC(DVIP)    在 路由上绑定一个静态的解析地址 ,,,当然路由器也有绑定的权限,,路由器是运营商的,我就没有权限了

          2) 红帽系列的主机上(包括cenos,fedroa),引进了arptables,有点类似于upshetables,这是基于arp或mac地址作访问控制的,在每个rs上,定义一下arptables规则,如果用户arp广播请求的目标地址是本机的VIP,则不予响应(或者响应的报文不允许出去,则路由的gateway就接受不到了),意味着只有director响应的报文才可以到达

          3)linux内核 2.4.23(26)以后, 2.6.4以后,它们在内核中引入两个新的内核参数(kernel parameter)(kernel arguments),          arp_ignore 和 arp_announce : linux主机对arp广播请求的响应级别,以及向外通告自己ip地址的通告级别



linux 开机时,会向周围的网络通告,我的ip地址(几个ip地址都通告)以及对应的mac地址,这样子网络内的其它主机都知道了,其它主机把别人的ip与mac对应关系缓存下来,缓存时长是300秒(rfc规定的),如果缓存失效了,那么请求找ip,只能向网络内所有主机请求解析,得到mac地址,进行通信

image.png


虽然ip是属于主机的,但是ip一定是绑定在某个网卡上的,

image.png

image.png



这里把 rs2 的 lo加个别名,配成 VIP地址,  当请求从路由器过来,进行arp地址请求的解析的时候,发觉了rs2上有VIP地址,所以响应, 但请求和响应是从 rs2的 eth0接口(配置的ip地址是RIP)进来的,我们可以配置 广播请求进来的网卡上所请求的目标地址VIP没有配置在 eth0上,我们就不予响应,,,这就是 arp_ignore 的意义,就是我们只对什么样的级别的网卡请求响应的

image.png



下图,虽然 远程主机 ping ip2,,能ping 通,,,但响应的mac地址不是mac3,而是跟它连通的那个mac1 (因为ip地址是属于内核的,属于系统的,不是属于网卡的)

image.png


arp_announce 通告级别,用来定义向外通告本机源地址的时候,它的通告级别的,主动告诉别人,我的ip地址,对应的mac地址,   默认级别是 0 ,表示尽可能向外通告

arp_ignore 响应级别,定义当接受到别人请求的时候,我的响应级别    默认级别是 0  表示尽可能进行响应 

image.png



arp_announce:

        级别:  0 (默认级别):将本地任何接口上的任何地址向外通告,而且可能是交叉通告的

                  1  : 试图 (不是100%的一定) 仅向目标网络通告与其网络匹配的地址

                  2  : 仅向与本地接口上地址匹配的网络进行通告  集群中应使用2

image.png

image.png



arp_ignore:

        级别:  0 (默认级别): 只要本地配置有相应的ip地址,就给予响应,无论在哪个接口上

                  1  : 仅在请求的目标地址ip配置在请求到达的接口上(网卡上 mac地址上)的时候才给予响应   集群中应使用1

                  2  :及之后不解释

image.png



现在我们的系统一般内核中都支持 arp_ignore 和 arp_announce,

不依赖于arptables,不依赖于外部路由

所以通常用  kernel parameter  :  arp_ignore  为1 和 arp_announce为2 ,





默认情况下linux路由策略中,有这样一种行为,响应报文的源地址,一般要配置为报文流出接口上所配置的地址

如果接口上的IP地址(比如RIP),与网关不在同一个网段内,就使用这个接口上的别名地址,(所以下图二eth0上必有一个地址

与网关在同一个网段内);;;


添加独特的路由条目,目的是为了防止从 rs 的 eth0上出去的响应的TCP/IP首部不能是eth0上的ip地址(即rip),,,应该是 VIP地址

由下图二,所以响应必须为 RIP2??但是我们又必须响应报文源IP为VIP,我们只需要在real server上

再添加一个独特的路由条目即可,这个路由条目就保证用户请求报文的地址VIP一定是通过eth0接口响应报文作为它的源地址

(因为VIP配置在lo上,那么响应报文一定要使用对应的接口上(请求的接口上)对应的地址作为源地址才行,我们只需要定义一个特定的路由条目,,,,如果不限定的话,会使用eth0上的ip(RIP)作为源地址的)

我们要求 VIP DIP RIP 一定要在同一个网络内的;;;;但是在现实应用当中,我们实现的未必都在同一个网络内(比如VIP是唯一的公网地址,而DIP,RIP都是私有地址)(如果VIP与DIP RIP 不在同一个网段内,我们的real server上(eth0 RIP)响应到路由的网关接口是不可以的)(所以我们的rs的eth0的RIP要通过另外一个网关出去才可以,换句话说 出去的网关不是 请求进来的路由器)


图一

image.png

图二

image.png

image.png


image.png

image.png

上图 可以如下图理解  一个路由器 有三个网卡 (一个是外网进来的 接口1 ) (一个是发到director 的VIP接口2,一个是从rs上接收的接口3)

下图 当然也可以把 接口3配成接口2的别名


image.png


VIP DIP RIP 一定要在同一个网段内,(如果不在,要改网络结构的)

    VIP: 172.16.100.1

    DIP: 172.16.100.2

    RIP: 172.16.100.8  (其中一个RIP的地址)




image.png

做一下配置规划,先让它们处于同一网络吧

我的规划

Director:

eth0,DIP:192.168.0.75    (DIP)

eth0:0,VIP:192.168.0.77  (VIP)


RS1:

eth0,DIP:192.168.0.45     (RIP)

lo:0,VIP:192.168.0.77  (VIP)



RS2:

eth0,DIP:192.168.0.55     (RIP)

lo:0,VIP:192.168.0.77  (VIP)



步骤如下:

一)director的网络配置

    禁用掉Host-Only的网卡,只留桥接那一张网卡    

      image.png

[root@mail ~]# ifconfig eth1 down        # down掉 eth1

[root@mail ~]# ifconfig      #没有了eth1  ##eth0就是director 的 DIP

eth0      Link encap:Ethernet  HWaddr 00:0C:29:EC:30:EF

          inet addr:192.168.0.75  Bcast:192.168.0.255  Mask:255.255.255

          inet6 addr: fe80::20c:29ff:feec:30ef/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:86872 errors:2 dropped:2 overruns:0 frame:0

          TX packets:35006 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:8343012 (7.9 MiB)  TX bytes:4589791 (4.3 MiB)

          Interrupt:67 Base address:0x2000


lo        Link encap:Local Loopback

          inet addr:127.0.0.1  Mask:255.0.0.0

          inet6 addr: ::1/128 Scope:Host

          UP LOOPBACK RUNNING  MTU:16436  Metric:1

          RX packets:4246 errors:0 dropped:0 overruns:0 frame:0

          TX packets:4246 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:0

          RX bytes:437179 (426.9 KiB)  TX bytes:437179 (426.9 KiB)


[root@mail ~]#


[root@mail ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth1        

# Advanced Micro Devices, Inc. [AMD] 79c970 [PCnet32 LANCE]

DEVICE=eth1

BOOTPROTO=none

ONBOOT=no  #让它不启动吧

HWADDR=00:0c:29:ec:30:f9

PEERDNS=no

NETMASK=255.255.0.0

IPADDR=172.16.0.10

TYPE=Ethernet



[root@mail ~]# service network restart        #重启

正在关闭接口 eth0:                                        [确定]

关闭环回接口:                                             [确定]

禁用 IPv4 包转送: net.ipv4.ip_forward = 0

                                                           [确定]

弹出环回接口:                                             [确定]

弹出界面 eth0:                                            [确定]

[root@mail ~]#

[root@mail ~]# ifconfig eth0:0 192.168.0.77/24        #配置一下别名 ( director 的 VIP  192.168.0.77 )

[root@mail ~]#


[root@mail ~]# ifconfig

eth0      Link encap:Ethernet  HWaddr 00:0C:29:EC:30:EF

          inet addr:192.168.0.75  Bcast:192.168.0.255  Mask:255.255.255.0

          inet6 addr: fe80::20c:29ff:feec:30ef/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:87339 errors:2 dropped:0 overruns:0 frame:0

          TX packets:35368 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:8389154 (8.0 MiB)  TX bytes:4637112 (4.4 MiB)

          Interrupt:67 Base address:0x2000


eth0:0    Link encap:Ethernet  HWaddr 00:0C:29:EC:30:EF

          inet addr:192.168.0.77  Bcast:192.168.0.255  Mask:255.255.255.0

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          Interrupt:67 Base address:0x2000


lo        Link encap:Local Loopback

          inet addr:127.0.0.1  Mask:255.0.0.0

          inet6 addr: ::1/128 Scope:Host

          UP LOOPBACK RUNNING  MTU:16436  Metric:1

          RX packets:4246 errors:0 dropped:0 overruns:0 frame:0

          TX packets:4246 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:0

          RX bytes:437179 (426.9 KiB)  TX bytes:437179 (426.9 KiB)


[root@mail ~]#



二)real server 的网络配置 rs1 和 rs2 都要设一下

        1)把唯一的网卡 eth0改成桥接  rs要与 director 在同一个交换机上

        image.png

        2)记住,一定要先配 RIP ,关闭  arp_ignor,arp_announce, 再配 VIP

                a)配置 RIP  (把 RIP为 192.168.0.45 和  192.168.0.55 都配置下吧 ) (关于192.168.0.55 的就不截图了,因为是一模一样的 )

                    i)查看ip

            [root@rs1~]# ifconfig

            image.png

                    ii)配置ip

             [root@rs1~]# vim /etc/sysconfig/network-scripts/ifcfg-eth0

            image.png

           image.png

                   iii)重启网络服务

            image.png

                 iv)看是否可与 DIP通信 与 RS2通信

            [root@rs1 ~]# ping 192.168.0.75  # 与DIP通信

            image.png

            [root@rs1 ~]# ping 192.168.0.55     # 与RIP通信

            image.png

            b)配置 arp_ignore 为1 ,,,arp_announce 为2   (关于192.168.0.55 的就不写了,因为是一模一样的 )

            

            [root@rs1 ~]# cd /proc/sys/net/ipv4

            [root@rs1 ipv4]# cd conf

            [root@rs1 conf]# pwd

            /proc/sys/net/ipv4/conf

            [root@rs1 conf]#


            

            [root@rs1 conf]# ls all  #看到 arp_ignore          arp_announce         

            accept_local         arp_ignore          log_martians         secure_redirects

            accept_redirects     bootp_relay         mc_forwarding        send_redirects

            accept_source_route  disable_policy      medium_id            shared_media

            arp_accept           disable_xfrm        promote_secondaries  tag

            arp_announce         force_igmp_version  proxy_arp

            arp_filter           forwarding          rp_filter

            [root@rs1 conf]# ls eth0         #看到 arp_ignore          arp_announce         

            accept_local         arp_ignore          log_martians         secure_redirects

            accept_redirects     bootp_relay         mc_forwarding        send_redirects

            accept_source_route  disable_policy      medium_id            shared_media

            arp_accept           disable_xfrm        promote_secondaries  tag

            arp_announce         force_igmp_version  proxy_arp

            arp_filter           forwarding          rp_filter

            [root@rs1 conf]#

            [root@rs1 conf]# ls lo     #看到 arp_ignore          arp_announce         

            accept_local         arp_ignore          log_martians         secure_redirects

            accept_redirects     bootp_relay         mc_forwarding        send_redirects

            accept_source_route  disable_policy      medium_id            shared_media

            arp_accept           disable_xfrm        promote_secondaries  tag

            arp_announce         force_igmp_version  proxy_arp

            arp_filter           forwarding          rp_filter

            [root@rs1 conf]#

            lo 接口 或 eth0 接口,只需要配置一个,再配置下 all 接口,,,哎这种配置方式看不懂,难道仅仅配置all不行,


            


            [root@rs1 ~]# sysctl -w net.ipv4.conf.eth0.arp_announce = 2

            error: "net.ipv4.conf.eth0.arp_announce" must be of the form name=value

            error: Malformed setting "="

            error: "2" must be of the form name=value

            

            [root@rs1 ~]# sysctl -w net.ipv4.conf.eth0.arp_announce=2        #(用 echo 2 > 文件 输出重定向也可以) 改 eth0 设置 arp_announce=2

            net.ipv4.conf.eth0.arp_announce = 2

            [root@rs1 ~]#

            [root@rs1 ~]# cat /proc/sys/net/ipv4/conf/eth0/arp_announce      # 看到了结果是 2 

            2

            [root@rs1 ~]#

            [root@rs1 ~]# sysctl -w net.ipv4.conf.all.arp_announce=2        #改 all  设置 arp_announce=2

            net.ipv4.conf.all.arp_announce = 2

            [root@rs1 ~]# cat /proc/sys/net/ipv4/conf/all/arp_announce        # 看到了结果是 2 

            2

            [root@rs1 ~]#

            

            

            [root@rs1 ~]# echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore         # 用echo 输出重定向改eth0的 arp_ignore=1 

            [root@rs1 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore         # 用echo 输出重定向改all的 arp_ignore=1 

            

            3)配置 rs 的上 VIP                    

                    [root@rs1 ~]# ifconfig lo:0 192.168.0.77/24  up     # up 表示启用,其实可加可不加

                    [root@rs1 ~]#


            windows 可以 ping 通 192.168.0.77  (director),它是

            image.png

            > arp -a         # 查看 arp 协议的所有数据  看 mac 对应的是 director

                        image.png

            > arp -d  *               #删除(刷新)arp的解析的所有的数据

            image.png

            > arp -a      

            image.png

            

            ping 一下 192.168.0.77

            > ping 192.168.0.77

            image.png

            > arp -a            # 看这里 192.168.0.77 的mac 仍然是 director 的

            image.png


独特的路由条目        这里 VIP DIP RIP 在同一个网段,所以报文从 RIP 出来的时候,是以RIP作为报文响应的源地址,

我们的目的是要以VIP作为响应的源地址


        director 脚本,加不加都可以

/sbin/route add -host $VIP dev eth0:0  # 到达地址为VIP的,我们要通过设备 eth0:0    这样一个接口出去,,,当然这个未必是特定的,未必是必须的?

        image.png

        image.png

        image.png


        real server脚本

    image.png

image.png

上图是严格意义上的格式,不一定非要严格意义上的格式,但是建议按照规范来走

    第一  ,/sbin/ifconfig lo:0 $VIP broadcast $VIP netmask 255.255.255.255,

配置广播地址是自己的地址, netmask  是 4个 255   就是只跟自己在同一个网段内,不能跟其它人在同一个网段内 ,,,因为全是网络地址

    第二  ,/sbin/route add -host $VIP dev lo:0        到达某个主机的路由,如果目标地址是VIP的话,那么一定要通过lo:0进来和出去,意味着,目标地址是 lo:0 上的地址,那么通过lo:0上的地址出去的时候,一定得把lo:0上的地址作为源地址



三)对rs 一些修改,修改下 real  server 的网络吧,        ( 两个 real server 都要设置一下吧,这里只记下 192.168.0.45 这个  real server )

[root@mail ~]# ifconfig lo:0

[root@mail ~]# ifconfig lo:0 192.168.0.77 broadcast  192.168.0.77 netmask 255.255.255.255 up

[root@rs1 ~]# ifconfig        # ifconfig 查看一下吧

eth0      Link encap:Ethernet  HWaddr 00:0C:29:3D:B0:3C

          inet addr:192.168.0.45  Bcast:192.168.0.255  Mask:255.255.255.0

          inet6 addr: fe80::20c:29ff:fe3d:b03c/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:10190 errors:0 dropped:0 overruns:0 frame:0

          TX packets:1552 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:875655 (855.1 KiB)  TX bytes:168831 (164.8 KiB)

          Interrupt:67 Base address:0x2000


lo        Link encap:Local Loopback

          inet addr:127.0.0.1  Mask:255.0.0.0

          inet6 addr: ::1/128 Scope:Host

          UP LOOPBACK RUNNING  MTU:16436  Metric:1

          RX packets:76 errors:0 dropped:0 overruns:0 frame:0

          TX packets:76 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:0

          RX bytes:5960 (5.8 KiB)  TX bytes:5960 (5.8 KiB)


lo:0      Link encap:Local Loopback

          inet addr:192.168.0.77  Mask:255.255.255.255

          UP LOOPBACK RUNNING  MTU:16436  Metric:1


[root@rs1 ~]#

[root@mail ~]# route add -host 192.168.0.77 dev lo:0         # (192.168.0.77是VIP)


三)对director作 一些修改吧

[root@mail ~]# route add -host 192.168.0.77 dev eth0:0        # (192.168.0.77是VIP)

[root@mail ~]#



四)在directoy 上通过 RIP 来访问 rs (real server) 看看

先把两个 rs 上的防火墙关掉

# iptables -F


directoy 上

[root@mail ~]# curl http://192.168.0.45/index.html        #这个是好的,可以访问了

RS1.magedu.com

[root@mail ~]# curl http://192.168.0.55/index.html        # 为啥不行

curl: (7) couldn't connect to host


directoy 上

[root@mail ~]# ping 192.168.0.45        # 可以ping 通

PING 192.168.0.45 (192.168.0.45) 56(84) bytes of data.

64 bytes from 192.168.0.45: icmp_seq=1 ttl=64 time=0.137 ms

64 bytes from 192.168.0.45: icmp_seq=2 ttl=64 time=0.227 ms

[root@mail ~]# ping 192.168.0.55            # 不能ping 通

PING 192.168.0.55 (192.168.0.55) 56(84) bytes of data.

From 192.168.0.75 icmp_seq=2 Destination Host Unreachable

From 192.168.0.75 icmp_seq=3 Destination Host Unreachable

经查 ,应该rs  192.168.0.55  上 设的是  #  ifconfig lo:0 192.168.0.75 broadcast  192.168.0.75 netmask 255.255.255.255 up   我设成 75 了 ,

应该是 #  ifconfig lo:0 192.168.0.77 broadcast  192.168.0.77 netmask 255.255.255.255 up

先执行 # ifconfig lo:0 down   再执行 #  ifconfig lo:0 192.168.0.77 broadcast  192.168.0.77 netmask 255.255.255.255 up  吧 


directoy 上

[root@mail ~]# ping 192.168.0.55  # 可以ping 通了

PING 192.168.0.55 (192.168.0.55) 56(84) bytes of data.

64 bytes from 192.168.0.55: icmp_seq=1 ttl=64 time=0.146 ms

64 bytes from 192.168.0.55: icmp_seq=2 ttl=64 time=0.188 ms

64 bytes from 192.168.0.55: icmp_seq=3 ttl=64 time=0.190 ms


directoy 上

[root@mail ~]# curl http://192.168.0.55/index.html        #这个好了,可以访问了

RS2.magedu.com


五) 配置集群

在 director 上配置

[root@mail ~]# ipvsadm -C    #清空此前的规则

[root@mail ~]#

[root@mail ~]# ipvsadm -A -t 192.168.0.77:80 -s wlc        #在director 上添加集群服务 (192.168.0.77 是 VIP)

[root@mail ~]# ipvsadm -a -t 192.168.0.77:80 -r 192.168.0.45 -g -w 2        # 添加 rs ,-g 表示 gateway(DR direct routing),-g 可以省略,-w 表示权重

[root@mail ~]# ipvsadm -a -t 192.168.0.77:80 -r 192.168.0.55 -g -w 1

[root@mail ~]#


[root@mail ~]# 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.0.77:80 wlc (表示加权最少连接)

  -> 192.168.0.55:80              Route (表示是 DR 直接路由吧)  1      0          0

  -> 192.168.0.45:80              Route   2      0          0

[root@mail ~]#

打开浏览器看看        马哥刷新两次马上看到变化了,我刷新了五六次,都没有看到变化,,,刷多了才看到变化,不知啥原因,,难道是长连接???

image.png



[root@mail ~]# ipvsadm -L -n            # 这里看权重比例是近似于 2:1 的,,,而且刷新多次,连接少,难道是长连接???

IP Virtual Server version 1.2.1 (size=4096)

Prot LocalAddress:Port Scheduler Flags

  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  192.168.0.77:80 wlc

  -> 192.168.0.55:80              Route   1      1          2

  -> 192.168.0.45:80              Route   2      2          5

[root@mail ~]#


万一其中某一个 rs 宕机了

在 rs2 上(192.168.0.55) 写个 iptables 让 拒绝访问80端口

[root@rs2 ~ ]# iptables -A INPUT -P tcp --dport 80 -j REJECT


当浏览器访问时,,当 rs 为 rs2 时,就会访问不到了

image.png

rs1 是可以访问到的

image.png

rs2 坏了, director 不知道,没法做健康状况检查

lvs 的 director 可以添加一个模块 lDirectorD就可以做健康状况检查,但是lDirectorD是在高可用集群当中,做高可用模型的时候才用得上,

我们可以在director上运行一个脚本,此脚本每隔两秒钟,检查一个real server是否在线,如果在线,不做任何操作,,,

如果不在线,就从当前的ipvs列表中剔除

,,,如果两个 rs 全坏了,都剔除了,那就添加另外一个 rs,这个rs是工作在本机的特殊端口上的服务(应该不是80端口???,防止有冲突吧),显示 你所访问的网站正在修复



普通分类: