LVS-ospf集群

LVS目前除了本身的NAT、DR和TUN模式,还有淘宝开源的fullnat模式,个人了解(待确认)LVS在各大公司的使用情况是:
百度 – BVS(现淘宝的 普空 之前在百度搞得类似fullnat项目,未开源) 结构是fullnat模式+ospf等价多路径
阿里 – LVS(fullnat模式,已开源)结构是fullnat模式+ospf等价多路径,通过交换机ospf的一直性hash来避免session不一致的情况
腾讯 – TWG(也是类似于fullnat的项目,未开源)结构是fullnat模式+ospf等价多路径,通过LVS集群定期同步来实现session一致

LVS在小米的业务前端已经使用几年时间,从最开始的DR模式,到现在部分使用fullnat模式,整体上还是不错的:

DR模式下:CPU E3-1230 V2 @ 3.30GHz + 32G + Intel 82580 Gb网卡 + sata盘:单台极限pps能跑到接近200W,应对电商的抢购活动完全没有压力

但最近也现一些问题:抢购时入站流量将Gb网卡跑满,导致丢包;在HA模式下,主机宕机之后需要advert_int 秒(keepalived 配置项)来切换至备机,也就是说在切换的过程中,服务是不可用的;而且现有结构下,无法线性横向扩展(一个VIP只能由一台服务来提供服务),只能通过提升机器配置来应对流量的上涨

为了解决上面这些问题,所以我们开始尝试LVS(DR)通过ospfd,做lvs集群,实现一个VIP,多台LVS同时工作提供服务,不存在热备机器,如图:

5

用户的访问过程是:

用户请求(VIP:42.xx.xx.100)到达三层交换机之后,通过对原地址、端口和目的地址、端口的hash,将链接分配到集群中的某一台LVS上,LVS通过内网(10.101.10.x)向后端转发请求,后端再将数据返回给用户,整个会话完成

Cluser模式的最大优势就在于:

  1. LVS调度机自由伸缩,横向线性扩展(最多机器数受限于三层设备允许的等价路由数目 maximum load-balancing );
  2. LVS机器同时工作,不存在备机,提高利用率;
  3. 做到了真正的高可用,某台LVS机器宕机后,不会影响服务(但因为华3设备ospfd调度算法的问题,一台宕机会使所有的长连接的断开重连,目前还无法解决;思科的设备已经支持一至性哈希算法,不会出现这个问题)。

部署过程:

1. 配置三层设备的ospf(这里以华3的设备为例):

交换机与LVS机器互连的端口号分别为2/9/0/19  2/9/0/20  2/9/0/21

interface GigabitEthernet2/9/0/19  //交换机与LVS机器连接的端口
  port link-mode route //路由接口
  ip address 10.21.21.1 255.255.255.252
  ospf timer hello 1
  ospf timer dead 4
  ospf network-type p2p //OSPF网络类型
  ospf 2 router-id 10.21.254.253 //进程ID 路由ID
  default-route-advertise always //始终下发默认路由
  maximum load-balancing 6 //定义最大的ECMP条目,也就是最多能连接的LVS数量
  area 0.0.0.0 //区域IP
    network 10.21.21.0 0.0.0.3
    network 10.21.21.4 0.0.0.3
    network 10.21.21.8 0.0.0.3

第二个端口:

port link-mode route //路由接口
  ip address 10.21.21.5 255.255.255.252
  ospf timer hello 1
  ospf timer dead 4
  ospf network-type p2p //OSPF网络类型
  ospf 2 router-id 10.21.254.253 //进程ID 路由ID
  default-route-advertise always //始终下发默认路由
  maximum load-balancing 6 //定义最大的ECMP条目
  area 0.0.0.0 //区域IP
    network 10.21.21.0 0.0.0.3
    network 10.21.21.4 0.0.0.3
    network 10.21.21.8 0.0.0.3

第三个端口:

port link-mode route //路由接口
  ip address 10.21.21.9 255.255.255.252
  ospf timer hello 1
  ospf timer dead 4
  ospf network-type p2p //OSPF网络类型
  ospf 2 router-id 10.21.254.253 //进程ID 路由ID
  default-route-advertise always //始终下发默认路由
  maximum load-balancing 6 //定义最大的ECMP条目
  area 0.0.0.0 //区域IP
    network 10.21.21.0 0.0.0.3
    network 10.21.21.4 0.0.0.3
    network 10.21.21.8 0.0.0.3

2. LVS的ospf配置:

LVS机器两张网卡,一个与交换机用做ospf互连,一个与内网连接
安装ospf软件:

yum –y install quagga

a.配置zerba.conf

vim /etc/quagga/zebra.con
hostname lvs-p1            ###这个名字每台要不一样,另外两台用的p2和p3
password xxxxxx 
enable password xxxxxx

b.配置ospfd.conf

与交换机的通讯主要是这个进程,通过它将自己的VIP(42.xx.xx.100)声明出去
vim /etc/quagga/ospfd.conf

hostname lvs-p1               ###   另外两台用的p2和p3
password 8 5ubmJdMAQxXbs      ###   这个密码是123456
enable password 8 4fcJB8NFa.0v6
log stdout
log syslog
service password-encryption
!
!
interface eth0
!
interface eth1
  ip ospf network point-to-point
  ip ospf hello-interval 1
  ip ospf dead-interval 4
!
interface lo
!
router ospf
  ospf router-id 10.21.21.2    ###各台的ID不能一样,这里我用的ospf互联地址做为ID,另外两台使用10.21.21.6 和10
  log-adjacency-changes
! Important: ensure reference bandwidth is consistent across all routers
  auto-cost reference-bandwidth 1000
  network 10.21.21.2/30 area 0.0.0.0     ###这里是宣告自己的ospf互连地址和VIP地址,新增地址就是在这里添加
  network 42.xx.xx.100/32 area 0.0.0.0
!
line vty
!

其它的LVS机器ospf的配置修改一下hostname和 ospf router-id就可以了

开启转发:

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl –p

开启服务:

/etc/init.d/zebra start
/etc/init.d/ospfd start
[root@lg-pt-lvs02 ~]# netstat -lntpu
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name   
tcp        0      0 127.0.0.1:2604           0.0.0.0:*                   LISTEN      27071/ospfd         
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1596/sshd           
tcp        0      0 127.0.0.1:2601              0.0.0.0:*                   LISTEN      27006/zebra

可以看到这两个进程都启起来了;系统日志里,可以看到


说明已经找到ospf邻居,正常宣告地址了
再在每台机器的LO上绑上宣告的VIP:

vi /etc/sysconfig/network-scripts/ifcfg-lo:01

DEVICE=lo:01
IPADDR=42.xx.xx.100
NETMASK=255.255.255.255
ONBOOT=yes
#


这时候可以ping一下42.xx.xx.100这个地址,能通就说明ospf已经配置成功了
在测试时遇到一个问题,我们在LVS机器上新添加地址时,需要Reload ospfd这个进程,查看启动脚本,他里面的Reload就是stop再start,所有宣告的IP会断开,再启起来

但是通过telnet 连接机器的ospfd管理端口添加新地址会立即生效,且不影响现有的IP,所以写了个脚本:

#!/bin/bash
$ip=$1
pswd="123456"
expect -c " set timeout 30
eval spawn -noecho telnet 127.0.0.1 2604
expect \"Password:\"
send \"$pswd\r\"
expect \" *>\"
send \"enable\r\"
expect \"Password:\"
send \"$pswd\r\"
expect \" *#\"
send \"configure t\r\"
expect \" *(config)#\"
send \"router ospf\r\"
expect \" *(config-router)#\"
send \"network $ip/32 area 0.0.0.0\r\"
expect \" *(config-router)#\"
send \"w\r\"
send \"exit\r\"
send \"exit\r\"
send \"exit\r\"
interact" >/dev/null

保存为addip.sh;

这里是需要先安装expect,再执行:

yum -y install expect
sh addip.sh x.x.x.x(IP)#就可以直接添加宣告VIP,不用Reload ospfd进程了

Quagga软件还提供了类似supervise的进程监控软件watchquagga,可以监控并重启本机的zebra和ospfd进程,下面使用watchquagga来启zebra和ospfd服务:

killall zebra ospfd                 #先把这两个进程停了
watchquagga -adz -r '/sbin/service %s restart' -s '/sbin/service %s start' -k '/sbin/service %s stop' zebra ospfd

大家可以手动kill掉ospf进程测试一下:


3. 接下来就是LVS(DR)的配置:

yum -y install keepalived ipvsadm

因为使用了ospf来选择路由,LVS上所有的VIP是用32位掩码绑在lo的网卡上的,所以在配置keepalived.conf时,主配置项vrrp_instance、等都不需要了,只需要配置virtual_server对应的后端就行了

我们服务器上就只配置了:
vi /etc/keepalived/keepalived.conf

virtual_server 42.xx.xx.100 80 {
    delay_loop 6
    lb_algo wlc
    lb_kind DR
 
    protocol TCP
 
    real_server 10.101.10.14 80 {
        weight 6
        TCP_CHECK {
                connect_port 80
                connect_timeout 20
                nb_get_retry 3
                delay_before_retry 5 
        }
    }
}

三台LVS的keepalived配置完全一至,再启动keepalived:
/etc/init.d/keepalived start
然后再到后端的realserver上把VIP绑到LO网卡上,
vi /etc/sysconfig/network-scripts/ifcfg-lo:01

#for lvs-dr-real-server
DEVICE=lo:01
IPADDR=42.xx.xx.100
NETMASK=255.255.255.255
ONBOOT=yes
#

ifup lo:01
再打开转发:

echo "net.ipv4.ip_forward = 1" >> etc/sysctl.conf
sysctl –p

到此就都配置完成了,用户访问42.xx.xx.100这个IP,会落到10.101.10.14这台realserver上,再直接返回给用户

还没有评论,快来抢沙发!

发表评论

  • 😉
  • 😐
  • 😡
  • 😈
  • 🙂
  • 😯
  • 🙁
  • 🙄
  • 😛
  • 😳
  • 😮
  • emoji-mrgree
  • 😆
  • 💡
  • 😀
  • 👿
  • 😥
  • 😎
  • ➡
  • 😕
  • ❓
  • ❗
  • 70 queries in 0.401 seconds