基于LVS的Linux负载均衡技术实现(第二篇:基本NAT和DR结构的LVS集群构建)

本文涉及的产品
公网NAT网关,每月750个小时 15CU
简介:

下面是第一个实际的LVS配置的例子,整个的结构是基于NAT操作。在该例子中的结构比较简单:

 

 

上面的例子中,我暂时没有添加备份LVS Router,而只是通过一个主LVS Router来充当调度器。
配置步骤如下:
首先配置网络参数:
在LVS Router上的基本参数:
[root@localhost ~]# ifconfig | grep inet
inet addr:192.168.1.10 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe08:a162/64 Scope:Link
inet addr:10.0.0.10 Bcast:10.0.255.255 Mask:255.255.0.0
inet6 addr: fe80::20c:29ff:fe08:a16c/64 Scope:Link
[root@localhost ~]# sysctl -a | grep ip_forward
net.ipv4.ip_forward = 1
[root@localhost ~]# sysctl –p

在Real Server上的基本参数:
第一台:
[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
# Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE]
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=static
HWADDR=00:0c:29:b2:60:a5
IPADDR=10.0.0.100
NETMASK=255.255.0.0
GATEWAY=10.0.0.254
第二台:
[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
# Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE]
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=static
HWADDR=00:0c:29:b2:60:a5
IPADDR=10.0.0.200
NETMASK=255.255.0.0
GATEWAY=10.0.0.254

然后在LVS Router上安装piranha工具:
[root@localhost ~]# rpm -ihv ipvsadm-1.24.8.1.i386.rpm
[root@localhost ~]# rpm -ihv piranha-0.8.4-7.el5.i386.rpm
完成之后为piranha-gui设置密码并启动服务:
[root@localhost ~]# /usr/sbin/piranha-passwd 
New Password: 
Verify: 
Updating password for user piranha

[root@localhost ~]# service piranha-gui restart
Shutting down piranha-gui: [ OK ]
Starting piranha-gui: [ OK ]
[root@localhost ~]# chkconfig piranha-gui on

完成之后进入图形界面并在浏览器中输入:http://localhost:3636,输入用户名:piranha和刚才定义的密码,即可进入piranha configuration tool的配置界面:
在该界面中第一个要设置的地方是CONTROL/MONITORING,在该界面中将MONITOR中的选项:
Auto update勾选上,Update Interval将自动定义为10s,在服务没有启动之前LVS ROUTING TABLE和LVS PROCESS都不可见。完成之后选择Update information now。

在该界面的第二个要设置的地方是GLOBAL SETTINGS,在该界面中:
Primary server public IP:192.168.1.10 (真实外部地址)
Primary server private IP:10.0.0.10 (真实内部地址)
Use network type: NAT (LVS方式)
NAT Router IP: 10.0.0.254 (内部浮动IP)
NAT Router MASK: 255.255.0.0 (内部浮动掩码)
NAT Router Device: eth1:1 (运行浮动IP的设备)
选择接受配置

在该界面的第三个要设置的地方是REDUNDANCY,在该界面中:
由于没有在这个结构中加入冗余配置,所以可以将其DISABLE掉或者将其设置为ENABLE但是保持配置为空。在该例子中我的配置为空:
Redundant server public IP: 0.0.0.0
Redundant server private IP:
Heartbeat Interval (seconds): 6
Assume dead after (seconds): 18
Heartbeat runs on port: 539
Monitor NIC links for failure: 不勾选
选择接受配置

在该界面的第四个要设置的地方是VIRTUAL SERVERS:
每一个Virtual Servers代表所提供的一种服务,由于目前只有一种服务HTTP,所以选择ADD在提示中输入下面的信息:
Name: HTTP
Application port: 80
Protocal: TCP
Virtual Server Address: 192.168.1.250
Virtual IP Network Mask: 255.255.255.0
Firewall Mark: 
Device: eth0:1
Re-entry Time: 15
Service Timeout: 6
Quiesce: No
Load Monitor Tool: none
Scheduling: Weighted least-connections --加权最小连接法(默认)
Persistence: 
Persistence Network Mask: Unused
选择接受,并开启服务

在该界面的第五个要设置的地方是REAL SERVERS:
Name: localhost.localdomain
Address: 10.0.0.100
Weighted: 1
Name: localhost.localdomain
Address: 10.0.0.200
Weighted: 1
选择接受,并开启服务

在该界面的第六个要设置的地方是MONITORING SCRIPTS,保持默认即可

完成之后确认所有的配置都已经保存,这个LVS基本上就配置完成。最后的工作是在LVS的Router上启动主服务:
# service pulse start
# chkconfig pulse on
这个时候可以看到eth0:1和eth1:1已经自动建立:
[root@localhost ~]# ifconfig
eth0:1 Link encap:Ethernet HWaddr 00:0C:29:08:A1:62 
inet addr:192.168.1.250 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
eth1:1 Link encap:Ethernet HWaddr 00:0C:29:08:A1:6C 
inet addr:10.0.0.254 Bcast:10.0.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
Interrupt:19 Base address:0x2080
并且相关服务也开启了:
[root@localhost ~]# service ipvsadm status
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddressort Scheduler Flags
-> RemoteAddressort Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 wlc
-> 10.0.0.200:80 Masq 1 0 0 
-> 10.0.0.100:80 Masq 1 0 15 
[root@localhost ~]# ps -ef | grep nanny
root 3614 3596 0 23:09 ? 00:00:03 /usr/sbin/nanny -c -h 10.0.0.100 -p 80 -s GET / 
HTTP/1.0\r\n\r\n -x HTTP -a 15 -I /sbin/ipvsadm -t 6 -w 1 -V 192.168.1.250 -M m -U none --lvs
root 3615 3596 0 23:09 ? 00:00:03 /usr/sbin/nanny -c -h 10.0.0.200 -p 80 -s GET / 
HTTP/1.0\r\n\r\n -x HTTP -a 15 -I /sbin/ipvsadm -t 6 -w 1 -V 192.168.1.250 -M m -U none --lvs
root 4078 3632 0 23:56 pts/1 00:00:00 grep nanny

同时开启两台真实服务器上的http服务,并在两台主机上的服务目录中分别建立同样的测试页面。
# chkconfig httpd on
# service httpd start

现在通过在客户端上访问LVS服务器进行测试:http://192.168.1.250,可以看到real server给出了页面。

这个时候piranha configuration tool界面刷新之后看到的当前ROUTER TABLE信息已经发生了改变:
CURRENT LVS ROUTING TABLE
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddressort Scheduler Flags
-> RemoteAddressort Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 wlc
-> 10.0.0.200:80 Masq 1 0 0
-> 10.0.0.100:80 Masq 1 0 0
而在当前LVS进程列表中也出现了内容:
CURRENT LVS PROCESSES
root 3678 0.0 0.1 1880 332 ? Ss 22:09 0:00 pulse
root 3702 0.0 0.2 1872 596 ? Ss 22:10 0:00 /usr/sbin/lvsd --nofork -c /etc/sysconfig/ha/lvs.cf
root 3720 0.0 0.2 1852 628 ? Ss 22:10 0:00 /usr/sbin/nanny -c -h 10.0.0.100 -p 80 -s GET / HTTP/1.0\r\n\r\n 
-x HTTP -a 15 -I /sbin/ipvsadm -t 6 -w 1 -V 192.168.1.250 -M m -U none --lvs
root 3721 0.0 0.2 1852 628 ? Ss 22:10 0:00 /usr/sbin/nanny -c -h 10.0.0.200 -p 80 -s GET / HTTP/1.0\r\n\r\n 
-x HTTP -a 15 -I /sbin/ipvsadm -t 6 -w 1 -V 192.168.1.250 -M m -U none --lvs

而在数次刷新页面之后就可以看到CURRENT LVS ROUTING TABLE的内容有所更新:
[root@localhost Desktop]# cat lvs
CURRENT LVS ROUTING TABLE
IP Virtual Server version 1.2.1 (size=4096)
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddressort Scheduler Flags
-> RemoteAddressort Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 wlc
-> 10.0.0.200:80 Masq 1 0 7
-> 10.0.0.100:80 Masq 1 0 6

也就是说访问量被平均分配到了两台主机上,如果我们找另外一个客户端做简单的压力测试:
命令:# ab -c 1000 -n 100000 http://192.168.1.250/index.html
获得的LVS ROUTING TABLE如下:
[root@localhost ~]# cat Desktop/lvs
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddressort Scheduler Flags
-> RemoteAddressort Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 wlc
-> 10.0.0.200:80 Masq 1 0 317
-> 10.0.0.100:80 Masq 1 0 1007

由于采用的是加权最小连接算法,所以负载不可能均分到两台服务器上。
此时配置文件的内容:
[root@localhost ~]# cat /etc/sysconfig/ha/lvs.cf 
serial_no = 67
primary = 192.168.1.10
primary_private = 10.0.0.10
service = lvs
backup_active = 1
backup = 0.0.0.0
heartbeat = 1
heartbeat_port = 539
keepalive = 6
deadtime = 18
network = nat
nat_router = 10.0.0.254 eth1:1
nat_nmask = 255.255.0.0
debug_level = NONE
monitor_links = 0
virtual HTTP {
active = 1
address = 192.168.1.250 eth0:1
vip_nmask = 255.255.255.0
port = 80
send = "GET / HTTP/1.0\r\n\r\n"
expect = "HTTP"
use_regex = 0
load_monitor = none
scheduler = wlc
protocol = tcp
timeout = 6
reentry = 15
quiesce_server = 0
server localhost.localdomain {
address = 10.0.0.100
active = 1
weight = 1
}
server localhost.localdomain {
address = 10.0.0.200
active = 1
weight = 1
}
}
实验到此成功。

现在我将这个实验的结构稍微做一下扩展,按照红帽所推荐的方案在结构中加入一备份 LVS ruoter,该备份LVS router的真实外网IP地址是192.168.1.20,真实内网IP是10.0.0.20。
按照上述的结构完成基本的网络配置:
[root@localhost ~]# ifconfig | grep inet
inet addr:192.168.1.20 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fecb:dd0b/64 Scope:Link
inet addr:10.0.0.20 Bcast:10.0.255.255 Mask:255.255.0.0
inet6 addr: fe80::20c:29ff:fecb:dd15/64 Scope:Link
开启IP转发:
[root@localhost ~]# sysctl -a | grep ip_forward
net.ipv4.ip_forward = 1

安装lvs相关软件包并进行基本配置:
[root@localhost ~]# rpm -ihv ipvsadm-1.24.8.1.i386.rpm
[root@localhost ~]# rpm -ihv piranha-0.8.4-7.el5.i386.rpm
完成之后为piranha-gui设置密码并启动服务:
[root@localhost ~]# /usr/sbin/piranha-passwd 
New Password: 
Verify: 
Updating password for user piranha 

[root@localhost ~]# service piranha-gui restart
Shutting down piranha-gui: [ OK ]
Starting piranha-gui: [ OK ]
[root@localhost ~]# chkconfig piranha-gui on

这里我偷了一个懒,因为不想再向第一台LVS Router那样一个一个通过piranha configuration tool配置参数,所以用scp将lvs.cf同步过来,并且开启服务:
# service pulse start
# chkconfig pulse on
完成之后进入图形界面,在浏览器中登录piranha configuration tools,需要修改的地方实际上有两处:
在该界面的第三个要设置的地方REDUNDANCY添加冗余配置:
Redundant server public IP: 192.168.1.20
Redundant server private IP: 10.0.0.20
Heartbeat Interval (seconds): 6
Assume dead after (seconds): 18
Heartbeat runs on port: 539
Monitor NIC links for failure: 不勾选
选择接受配置
另外在第一台LVS Router上也要做这方面的定义。

在该界面的第二个要设置的地方是GLOBAL SETTINGS,在该界面中:
Primary server public IP: 192.168.2.10 (真实外部地址)
Primary server private IP:10.0.0.20 (真实内部地址)
Use network type: NAT (LVS方式)
NAT Router IP: 10.0.0.254 (内部浮动IP)
NAT Router MASK: 255.255.0.0 (内部浮动掩码)
NAT Router Device: eth1:1 (运行浮动IP的设备)
选择接受配置

这样的话,配置文件的内容为:
[root@localhost ~]# cat /etc/sysconfig/ha/lvs.cf 
serial_no = 73
primary = 192.168.1.20
primary_private = 10.0.0.20
service = lvs
backup_active = 1
backup = 192.168.1.20
backup_private = 10.0.0.20
heartbeat = 1
heartbeat_port = 539
keepalive = 6
deadtime = 18
network = nat
nat_router = 10.0.0.254 eth1:1
nat_nmask = 255.255.0.0
debug_level = NONE
monitor_links = 0
virtual HTTP {
active = 1
address = 192.168.1.250 eth0:1
vip_nmask = 255.255.255.0
port = 80
send = "GET / HTTP/1.0rnrn"
expect = "HTTP"
use_regex = 0
load_monitor = none
scheduler = wlc
protocol = tcp
timeout = 6
reentry = 15
quiesce_server = 0
server localhost.localdomain {
address = 10.0.0.100
active = 1
weight = 1
}
server localhost.localdomain {
address = 10.0.0.200
active = 1
weight = 1
}
}

测试的方法很简单,第一台LVS Router现在是primary,那么正常情况下他提供服务,而备份lvs router开启pulse进程对第一台状态进行监控。现在将第一台LVS Router关闭,在短时间内客户端访问虚拟服务器将受到影响。但是在大概十秒左右的时间就可以访问成功,此时可以看到备份LVS Router已经成为primary并提供服务。如果此时再将已经关闭的第一台LVS Router开启,那么他将再次成为主LVS Router。
 

和NAT结构所不同的是,该LVS集群通过DR也就是direct route来实现。所谓direct route指的是LVS Router会将请求转发到真实服务器上,而每一台真实服务器都有能力通过一个特定的网关直接将外部请求转发出去。也就是说反馈的应答不会再通过原路即LVS Router走,而是通过其他出口出去。
这样做的好处是可以防止在大规模的LVS集群中因为调度器的性能问题而产生瓶颈,因此效率方面肯定要比NAT高。下面是一个基于DR实现的LVS结构图。我主要是在沿用上一个实验的一些结果。而DR和NAT的结构会有所改变。

下面的结构图是一个采用DR结构的实例:

 

 

 

如上图所示,我用一台windows主机做客户端,他的请求通过一台Linux路由器发送到LVS Router上。然后LVS Router再将请求转发到real server。而real server为了能够将请求不通过LVS Router转发出去则将网关直接指向了Router的内部接口。相当于每台real server都有直接将请求转发出去的能力,这样可以从很大程度上减少LVS Router的负载。

配置上面和刚才不同的地方是:
1.建立一台双网卡的Linux Router,并且开启ip_forward。
2.建立windows机器,配置地址为192.168.100.111,网关为192.168.100.30。
3.在主/备LVS Router上将网关指向Router的内部接口,并且重启网络和LVS相关服务。
4.比较关键的修改是real server上,需要将网关都指向Router的内部接口,这里是192.168.1.30。
5.必须在所有的real server上建立一个ifcfg-lo:1的接口,该接口的内容如下:
[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-lo:1
DEVICE=lo:1
IPADDR=192.168.1.250
NETMASK=255.255.255.255
NETWORK=192.168.1.250
ARP=no
TYPE=Ethernet
并且两台主机的ifcfg-lo:1文件内容是一样的。
(当时我曾经将子网掩码更改为255.255.255.0,结果出乎我意料,两台realserver只有一台能够启动网络,另外一台real server在启动网络的时候报错,提示地址被占用)
我猜测,添加这个接口的目的是要real server在收到请求之后能够冒充LVS Router对外部请求应答。

那么通过piranha所需要修改的地方包括:
a.取消private的地址;
b.更改real server地址为192.168.1.111和192.168.1.222
c.更改LVS类型为DR
完成之后保存,这是我在主LVS Router上获取的配置文件:
[root@localhost ha]# cat /etc/sysconfig/ha/lvs.cf
serial_no = 122
primary = 192.168.1.10
service = lvs
backup_active = 1
backup = 192.168.1.20
heartbeat = 1
heartbeat_port = 539
keepalive = 6
deadtime = 18
network = direct
nat_nmask = 255.255.255.0
debug_level = NONE
monitor_links = 1
virtual HTTP {
active = 1
address = 192.168.1.250 eth0:1
vip_nmask = 255.255.255.0
port = 80
send = "GET / HTTP/1.0\r\n\r\n"
expect = "HTTP"
use_regex = 0
load_monitor = none
scheduler = wlc
protocol = tcp
timeout = 6
reentry = 15
quiesce_server = 0
server localhost.localdomain {
address = 192.168.1.111
active = 1
weight = 1
}
server localhost.localdomain {
address = 192.168.1.222
active = 1
weight = 1
}
}

同时对备份LVS Router在原来基础上进行了一些修改,配置文件内容为:
[root@localhost ~]# cat /etc/sysconfig/ha/lvs.cf
serial_no = 122
primary = 192.168.1.20
service = lvs
backup_active = 1
backup = 192.168.1.20
heartbeat = 1
heartbeat_port = 539
keepalive = 6
deadtime = 18
network = direct
nat_nmask = 255.255.255.0
debug_level = NONE
monitor_links = 1
virtual HTTP {
active = 1
address = 192.168.1.250 eth0:1
vip_nmask = 255.255.255.0
port = 80
send = "GET / HTTP/1.0\r\n\r\n"
expect = "HTTP"
use_regex = 0
load_monitor = none
scheduler = wlc
protocol = tcp
timeout = 6
reentry = 15
quiesce_server = 0
server localhost.localdomain {
address = 192.168.1.111
active = 1
weight = 1
}
server localhost.localdomain {
address = 192.168.1.222
active = 1
weight = 1
}
}
注意我用蓝色标出的地方。有些人的配置中主/备LVS Router的配置文件是完全不一样的。尽管我没有测试过但是我总认为这样可能会导致一些问题的出现。
完成之后重启network以及lvs相关服务:pulse和ipvsadm。
检查服务:
主LVS Router上的信息:
[root@localhost ha]# service pulse status
pulse (pid 3664) is running...
[root@localhost ha]# service ipvsadm status
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddressort Scheduler Flags
-> RemoteAddressort Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 wlc
-> 192.168.1.111:80 Route 1 0 0 
-> 192.168.1.222:80 Route 1 0 0 
备份LVS Router上的信息:
[root@localhost ~]# service pulse status
pulse (pid 17459 17457 2260) is running...
[root@localhost ~]# service ipvsadm status
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddressort Scheduler Flags
-> RemoteAddressort Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 wlc
-> 192.168.1.111:80 Route 1 0 0 
-> 192.168.1.222:80 Route 1 0 0 

测试的时候可以在主/备LVS Router上开启wireshark并抓包。和NAT一样的是,如果default情况下有数据通过主LVS Router上过来的话,临时关闭主LVS Router,备份LVS Router会立刻通过heartbeat发现主LVS Router状态为失效,所以在这个时候如果在备份LVS Router上抓包会发现备份LVS Router此时会调用系统中的一个send_arp的命令向Router发送一个arp初始化信息,宣告原来的virtual server所对应的MAC地址改变,这个时候router会重新初始化mac-address-table。后续的外部请求将通过备份LVS Router进行转发。

另外在LVS配置的时候,real server上需要在启动系统之后检查自身的地址192.168.1.111和192.168.1.222是否能起来。我碰到的问题是192.168.1.111和192.168.1.222这两台真实服务器在正常重启之后这两个地址无法生效。而需要执行命令ifup eth0命令将这两个网卡带起来。也就是说白了,这两个地址不是很稳定。我的做法是可以将其加到/etc/rc.local文件中。在启动的时候确保网络接口启动。

(全文完)
 


本文转自 Bruceweien 51CTO博客,原文链接:http://blog.51cto.com/bruceweien/1068562


相关文章
|
1月前
【技术干货连载 二】SLB 408问题排查
SLB 408问题排查思路和方法
12 0
|
18天前
|
负载均衡 算法 应用服务中间件
面试题:Nginx有哪些负载均衡算法?Nginx位于七层网络结构中的哪一层?
字节跳动面试题:Nginx有哪些负载均衡算法?Nginx位于七层网络结构中的哪一层?
32 0
|
4月前
|
网络协议 Linux 网络架构
Linux三种网络模式 | 仅主机、桥接、NAT
Linux三种网络模式 | 仅主机、桥接、NAT
177 0
|
4月前
|
负载均衡 算法 NoSQL
聊聊分布式应用中负载均衡技术和Session一致性
聊聊分布式应用中负载均衡技术和Session一致性
41 0
|
4月前
|
负载均衡 前端开发 应用服务中间件
【Linux】Nginx安装使用负载均衡及动静分离(前后端项目部署),前端项目打包
【Linux】Nginx安装使用负载均衡及动静分离(前后端项目部署),前端项目打包
381 0
|
4天前
|
负载均衡 监控 Linux
CentOS6.5高可用集群LVS+Keepalived(DR模式)
CentOS6.5高可用集群LVS+Keepalived(DR模式)
|
5天前
|
负载均衡 监控 网络协议
使用haproxy实现负载均衡集群
【4月更文挑战第14天】HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,快速并且可靠的一种解决方案。
8 1
|
18天前
|
负载均衡 Java 关系型数据库
linux 下amoeba实现数据库的负载均衡
linux 下amoeba实现数据库的负载均衡
13 1
|
1月前
|
负载均衡 网络协议 安全
技术浅析:基于云的DNS负载均衡如何实现?
技术浅析:基于云的DNS负载均衡如何实现?
43 6
|
2月前
|
存储 负载均衡 算法
后端技术之负载均衡
【2月更文挑战第4天】随着互联网应用的不断增长,访问量也越来越大,如何高效地处理这些请求成为了一个必须考虑的问题。负载均衡是一种重要的技术手段,它可以将请求分配到多个服务器上,从而提高系统的可用性和稳定性。本文将介绍负载均衡的基本原理、实现方式以及优化方法。
40 3