两台服务器既做LVS主备又做realserver的配置方法

我们有一个简单便宜的 LVS-DR 的设置。二台机器(服务器),二台都运行着数据库的服务。外面请求过来的这些流量导向本地机器的服务器或其他服务器。因为纯 4 层调度,这是我最喜欢的方式。因为节约,我这次想直接要这二台服务器上运行 LVS 的服务。不在通过其它的机器。

所以使用 keepalived 来配置,做个主从,也同时在这个机器上。是个很完美的方案。

但是,我让同事帮着配置,一直不能正常的工作。下面是简单的架构图,和配置输出:

结构如下:

  ip_vs() balances on VIP:port
                    CIP
             CIP    |
              v     | CIP->MAC of eth0 on backup  normal packet
             VIP    | MAC of eth0 on active<-CIP  spurious packet
              |—————-————— |
              |            |
           eth0 VIP    eth0 VIP
           _______       _______
          |       |     |       |
active    |       |     |       | backup
          |_______|     |_______|
#  ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
FWM  6 rr
  -> 192.168.1.233:3306           Local   1      0          0
  -> 192.168.1.213:3306           Route   1      0          0

二台机器上的配置都是这样(^-^上面其实有小修改),。在这种架构中,我只要停止我的备份的 keepalived ,就能正常的工作,不然一定有其中一台数据库连接到最后就中断停止在那个地方不动了。通过抓包,大量包被不断的转发来转发去。
我们来详细分析一下。

  1. 客户端发送连接的请求到 VIP 的指定的端口
  2. 当前的 director 会选择二个 realserver 来转发请求,会传送数据给 localnode 的本机网卡或者备份的机器上指定的那个 MAC 的 eth0 (同时他也做为 realserver) 。 正常的 LVS ,这些数据包会被监听这个 VIP 的程序接收。
  3. 如果数据包是发送给备份的 director 服务器的 eth0 接口。它会不能正常的被监听指定端口的程序所接收,因为数据包会首先先经过 ip_vs()。
  4. 这时,有 50% 的机会,这个包被转发给监听VIP指定端口的程序所接收,这时会生成标准的回应数据包给客户端。 因为能正常的回应客户端,这时 LVS 的功能是正常的,我们想所有的包都直接给监听程序来处理。并不想直接通过 ip_vs() 来转发。
  5. 这时还有 50% 的数据包会直接再次转给主 LVS 的 eth0/VIP。
  6. 我们不想数据包从备份的 LVS 再次转回去给主 LVS 这样会形成死循环。
  7. 所以我们要让 eth0 上发到给 VIP 的包, 只要不是其它 LVS 发的,才使用 ip_vs() 来处理。

简单来讲:当客户端发送数据包给 VIP 。比如我们的 Director1 (Master 主)这个接口正在工作,这时 LVS 能接收到这个包,然后根据 keepalived 的配置进行 load balance 。这时 Director1 会使用 LVS-DR 的功能给包路由给自己或者 Director2 (Backup)。
这时有个问题。在这个例子中因为我们使用了 keepalived 。这时 Director2 这台是一台 VIP 的备份服务器。这时 keepalived 默认会立即启动使用 ipvsadm 的规则来配置这台服务器怎么样做备份的处理。来使得更快的故障转移。所以这时这些规则在这台备份的 Director2 主机都会存在。
这就有问题了。当 Director1 (Master 主),比如使用 rr 。会转发大约 50% 的包从 Director1 到 Director2 (Backup)的 3306 的端口。这时 Director2 因为这些 LVS-DR 的配置规则会接着给这些包,再做一次 load balance 。又发回去给 Director1。这时会产生一个死的循环。
随着时间的推移,不但不能正常的处理连接,您的服务器也会崩溃,在他们中间或后端不断的反复连接。

解决方案: 给进入 eth0 的包打上 mark 的标记,当数据包是发给 VIP:80 并且 MAC 不是其它 LVS 服务器的话。 才做个 mark ,这样才会对指定的 fwmark 进行 loadbalance 放入到 LVS 中处理。只要数据包是从任意其它的 MAC 地址(非 LVS 的转发)会被发往 VIP:port, 会不再进行 loadbalanced 而是直接转给后面监听的 demon 程序进行应用的处理。实际就是我们使用 iptables 来对进入的流量设置 MARK。然后配置 keepalived 只处理有 MARK 过的流量。不在使用以前绑定 VIP 和端口。
iptables 的配置如下:
同时服务于 LVS-DR,又要做为数据库的后端。所以我们要注意,只接收一个 director 的数据包。
这时我们在 Director1 中设置($MAC_Director2 是指我在 Director1 上所能见到从 Director2 发过来包的 MAC 地址) :

iptables  -t mangle -I PREROUTING -d $VIP -p tcp -m tcp --dport $VPORT -m mac ! --mac-source $MAC_Director2 -j MARK --set-mark 0x3

$VIP 为VIP地址
$VPORT 为服务端口
$MAC_Director2 是备机的MAC (keepalived 之间互相监听的那块网卡)

并在备份的 keepalived 的服务器 Director2 中设置:

iptables  -t mangle -I PREROUTING -d $VIP -p tcp -m tcp --dport $VPORT -m mac ! --mac-source $MAC_Director1 -j MARK --set-mark 0x4

$VIP 为VIP地址
$VPORT 为服务端口
$MAC_Director1 是主 的MAC (keepalived 之间互相监听的那块网卡)

查看添加的规则是否生效:
iptables -t mangle --list

使添加的规则永久生效
# 保存iptables规则
service iptables save

# 重启iptables服务
service iptables restart

查看当前规则:
cat /etc/sysconfig/iptables

接着在 keepalived 中分别配置这二个。

Director1: virtual_server fwmark 3 {
Director2: virtual_server fwmark 4 {

其实这个的完整配置类似如下:

keepalived 根据 MARK 来配置的方法
## 配置fwmark转发
virtual_server fwmark 3  {	# 另一台备库是fwmark 4
    delay_loop 10
    lb_algo rr
    lb_kind DR
    protocol TCP

    real_server 192.168.1.213 3306 {
    weight 1
    MISC_CHECK {
        misc_path "/etc/keepalived/check_slave.pl 192.168.1.213"
        misc_dynamic
    }
    }

    real_server 192.168.1.233 3306 {
    weight 1
    MISC_CHECK {
        misc_path "/etc/keepalived/check_slave.pl 192.168.1.233"
        misc_dynamic
        }
    }
}

注意:
通过以上设置后,在网站运行过程中还发现了另一个问题,就是RealServer发起对虚拟IP的请求时就会出问题。当RealServer对VIP的请求被分发给自己时,访问正常,当RealServer对VIP的请求被分发给备LVS上的RealServer时,就没有响应。具体的现象如下图:
1
source IP 和 virtual IP都是VIP,当VIP 和destination IP 在同一台服务器上时访问正常,当VIP 和destination IP 不在同一台服务器上时访问不正常。我想这应该是两台RealServer同时响应为VIP时,造成响应混乱,从而请求失败。我也偿试过通过对RealServer防火墙的设置,在上文中的规则中再加一条,就是目标地址是VIP地址,并且MAC地址不等于当前RealServer自己的MAC地址时,才加fwmark 标记。但是测试未成功,不知道是什么原因。另一个解决方案是:通过在Hosts文件中,把RealServer对解析到VIP的域名直接绑定到自己的IP,或是另一台RealServer的IP,即自己访问的域名不解析到VIP,这样设置后一切正常。

上面的这个问题,后来也在独立的RealServer(即纯粹的RealServer,不安装LVS)上测试了,还存在一样的问题。由此断定,在RealServer中,对VIP的访问是不正常的,除非访问VIP时被LVS分发到发出请求的RealServer自己。

参考资料:
怎么样让 LVS 和 realserver 工作在同一台机器上:http://www.php-oa.com/2012/05/27/lvs-realserver-one-machine.html
LVS+Keepalived实现MySQL写高可用和读负载均衡:http://blog.chinaunix.net/uid-22163222-id-3781194.html
在同一台服务器上部署LVS和WEB:http://www.linuxyw.com/a/fuzaijunheng/20130429/146.html
LVS-HOWTO:http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/index.html

发表评论?

0 条评论。

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据