欢迎各位兄弟 发布技术文章
这里的技术是共享的
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:
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地址,进行通信
虽然ip是属于主机的,但是ip一定是绑定在某个网卡上的,
这里把 rs2 的 lo加个别名,配成 VIP地址, 当请求从路由器过来,进行arp地址请求的解析的时候,发觉了rs2上有VIP地址,所以响应, 但请求和响应是从 rs2的 eth0接口(配置的ip地址是RIP)进来的,我们可以配置 广播请求进来的网卡上所请求的目标地址VIP没有配置在 eth0上,我们就不予响应,,,这就是 arp_ignore 的意义,就是我们只对什么样的级别的网卡请求响应的
下图,虽然 远程主机 ping ip2,,能ping 通,,,但响应的mac地址不是mac3,而是跟它连通的那个mac1 (因为ip地址是属于内核的,属于系统的,不是属于网卡的)
arp_announce 通告级别,用来定义向外通告本机源地址的时候,它的通告级别的,主动告诉别人,我的ip地址,对应的mac地址, 默认级别是 0 ,表示尽可能向外通告
arp_ignore 响应级别,定义当接受到别人请求的时候,我的响应级别 默认级别是 0 表示尽可能进行响应
arp_announce:
级别: 0 (默认级别):将本地任何接口上的任何地址向外通告,而且可能是交叉通告的
1 : 试图 (不是100%的一定) 仅向目标网络通告与其网络匹配的地址
2 : 仅向与本地接口上地址匹配的网络进行通告 集群中应使用2
arp_ignore:
级别: 0 (默认级别): 只要本地配置有相应的ip地址,就给予响应,无论在哪个接口上
1 : 仅在请求的目标地址ip配置在请求到达的接口上(网卡上 mac地址上)的时候才给予响应 集群中应使用1
2 :及之后不解释
现在我们的系统一般内核中都支持 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要通过另外一个网关出去才可以,换句话说 出去的网关不是 请求进来的路由器)
图一
图二
上图 可以如下图理解 一个路由器 有三个网卡 (一个是外网进来的 接口1 ) (一个是发到director 的VIP接口2,一个是从rs上接收的接口3)
下图 当然也可以把 接口3配成接口2的别名
VIP DIP RIP 一定要在同一个网段内,(如果不在,要改网络结构的)
VIP: 172.16.100.1
DIP: 172.16.100.2
RIP: 172.16.100.8 (其中一个RIP的地址)
做一下配置规划,先让它们处于同一网络吧
我的规划
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的网卡,只留桥接那一张网卡
[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 在同一个交换机上
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
ii)配置ip
[root@rs1~]# vim /etc/sysconfig/network-scripts/ifcfg-eth0
iii)重启网络服务
iv)看是否可与 DIP通信 与 RS2通信
[root@rs1 ~]# ping 192.168.0.75 # 与DIP通信
[root@rs1 ~]# ping 192.168.0.55 # 与RIP通信
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),它是
> arp -a # 查看 arp 协议的所有数据 看 mac 对应的是 director
> arp -d * #删除(刷新)arp的解析的所有的数据
> arp -a
ping 一下 192.168.0.77
> ping 192.168.0.77
> arp -a # 看这里 192.168.0.77 的mac 仍然是 director 的
独特的路由条目 这里 VIP DIP RIP 在同一个网段,所以报文从 RIP 出来的时候,是以RIP作为报文响应的源地址,
我们的目的是要以VIP作为响应的源地址
director 脚本,加不加都可以
/sbin/route add -host $VIP dev eth0:0 # 到达地址为VIP的,我们要通过设备 eth0:0 这样一个接口出去,,,当然这个未必是特定的,未必是必须的?
real server脚本
上图是严格意义上的格式,不一定非要严格意义上的格式,但是建议按照规范来走
第一 ,/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 ~]#
打开浏览器看看 马哥刷新两次马上看到变化了,我刷新了五六次,都没有看到变化,,,刷多了才看到变化,不知啥原因,,难道是长连接???
[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 时,就会访问不到了
rs1 是可以访问到的
rs2 坏了, director 不知道,没法做健康状况检查
lvs 的 director 可以添加一个模块 lDirectorD就可以做健康状况检查,但是lDirectorD是在高可用集群当中,做高可用模型的时候才用得上,
我们可以在director上运行一个脚本,此脚本每隔两秒钟,检查一个real server是否在线,如果在线,不做任何操作,,,
如果不在线,就从当前的ipvs列表中剔除
,,,如果两个 rs 全坏了,都剔除了,那就添加另外一个 rs,这个rs是工作在本机的特殊端口上的服务(应该不是80端口???,防止有冲突吧),显示 你所访问的网站正在修复