完成了LVS的性能优化,DR模式的线上验证后。我们来开始LVS的NAT之旅吧!
调度机上使用Keepalived管理IPVS:
yum -y install ipvsadm keepalived sendmail chkconfig keepalived on chkconfig sendmail on
Keepalived配置文件`/etc/keepalived/keepalived.conf`示例如下:
global_defs {
notification_email {
admin@higkoo.org
}
notification_email_from lvs@higkoo.org
smtp_server 127.0.0.1
router_id DEMO
}
vrrp_sync_group HK_GRP1 {
group { # NAT 模式下内外网虚拟IP必须在同一台机上
LVS_WAN
LVS_LAN
}
smtp_alter # 主备切换时给出通知
}
vrrp_instance LVS_WAN {
state MASTER # 备份服务器上将MASTER改为BACKUP
interface eth0 # VIP 捆绑网卡
virtual_router_id 100 # LVS_ID 在同一个网络中,LVS_ID是唯一的
priority 100 # 选举的优先级,优先级大的为MASTER 备份服务上将100改为99
advert_int 1 # 发送vrrp的检查报文的间隔,单位秒
authentication { # 认证信息。可以是PASS或者AH
auth_type PASS
auth_pass 1c7f545a
}
virtual_ipaddress {
113.226.77.88
}
}
vrrp_instance LVS_LAN { # 虚拟网关
state MASTER
interface eth1
virtual_router_id 100
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 9aa614f7
}
virtual_ipaddress {
192.168.168.11
}
}
virtual_server 113.226.77.88 80 {
delay_loop 6 # 每隔10秒查询realserver状态
lb_algo wrr # lvs 算法,wrr是带权轮询
lb_kind NAT # lvs模式,这里为DR
persistence_timeout 60 # 同一IP的连接60秒内被分配到同一台realserver
protocol TCP # 用TCP协议检查realserver状态
real_server 192.168.168.238 80 {
weight 1 # 权重
inhibit_on_failure # 故障会修改权重为零
TCP_CHECK {
connect_timeout 10 # 10秒无响应超时
nb_get_retry 3 # 重连次数
delay_before_retry 3 # 重连间隔,单位为秒
connect_port 80 # 检测端口
}
}
# ……
}
注意:NAT模式下内外网IP必须位于同一台机,所以这里vrrp_sync_group将它们归为一组。这样只要其中任何一个IP故障了,整组IP都会被迁移。可以用ifdown eth1验证。
RealServer上需要有内网虚拟IP(192.168.168.238)同网段的IP地址,默认网关要设置成上面的虚拟IP(192.168.168.11)即可。上例中RealServer是使用TCP检测,只要TCP端口能通就认为存活。简单,但不容易发现错误。比如,后端节点已经502了、后端节点系统被重装但80端口是启动的、等等问题。可以使用HTTP的检测方法,示例如下:
real_server 192.168.168.238 80 {
weight 1
inhibit_on_failure
HTTP_GET {
url {
path /
digest 3ef1267da49c9567b0243dc4be39653a
}
connect_port 80
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
}
}
Digest的值实际是HTTP返回BODY的MD5SUM,可以使用genhash或curl计算获得(跳转除外):
genhash -s 192.168.168.238 -p 80 -u / curl -s 192.168.168.238 | md5sum
好,默认网关是内网虚拟IP,LVS是通了。但RealServer就无法正常上网了,因为虚拟IP本身并不是完整的NAT功能。你可以在调度机上开启iptables的nat功能,但这样性能损耗相当大。
解决思路:
让调度机和真实服务器拥有一段新的虚拟IP(比如上文中的192.168.168.11),这些IP专用于LVS的包转发。在真实服务器上配置IP路由策略,让这些IP默认使用LVS做网关从而不影响其它网络功能。
实现如下:
一、给RealServer添加虚拟IP
ifconfig eth1:1 192.168.168.238 netmask 255.255.255.0 up
# 命令行添加,重启网络时虚拟网卡就丢了。推荐使用配置文件:
cat /etc/sysconfig/network-scripts/ifcfg-eth1:1
DEVICE="eth1:1"
BOOTPROTO="none"
ONBOOT="yes"
IPADDR=192.168.168.238
NETMASK=255.255.255.0
TYPE="Ethernet"
二、在rt_tables末尾添加路由表
echo "100 lvs_nat" >> /etc/iproute2/rt_tables
三、指定从虚拟IP出去的流量都LVS的虚拟网关:
# 执行并追加到 /etc/rc.local
ip route add to 0.0.0.0/0 via 192.168.168.11 dev eth3 table lvs_nat
ip rule add from 192.168.168.238/32 table lvs_nat
# 用命令管理最大问题是网卡重启时 ip route 的 table 信息会被丢掉,所以还是建议用配置文件管理:
cat /etc/sysconfig/network-scripts/route-eth1
default table lvs_nat via 192.168.168.11
cat /etc/sysconfig/network-scripts/rule-eth1
from 192.168.168.238/32 table lvs_nat
OK,到此NAT已经配置完毕。从/etc/init.d/network脚本里我们可以看到/etc/sysconfig/static-routes也可以配置静态路由,但route无法完成ip route table工作。在/etc/sysconfig/network-scripts/ifup-routes脚本里可以看到,使用route-X和rule-X可以配置IP策略。这样配置后网卡关闭时策略将失效,网卡开启会自动加载。所以,使用命令行管理并写在rc.local里开机自启动,是不科学的管理方法!
然后启动Keepalived验证可用性吧。NAT的最大好处就可支持修改目的端口了,可以突破Accept单队列的问题,也可以草木皆兵:
ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=1048576)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight
TCP 113.226.77.88:80 wrr persistent 60
-> 192.168.168.236:8001 Masq 2
-> 192.168.168.236:8002 Masq 6
-> 192.168.168.238:8003 Masq 3
-> 192.168.168.238:8004 Masq 8
好吧,说说问题吧!用NAT模式你可能会遇到“在RealServer上无法虚拟IP”的情况。
问:什么情况呢?
答:当后端的RealServer有外网IP且和虚拟IP同网段时,从这台RealServer访问虚拟IP将有可能无法连接。
A. 由于RealServer本机有外网IP,从RealServer访问虚拟IP时,它将携带外网IP去访问虚拟IP
B. 调度机收到请求后把它转发给后端的RealServer,刚好就转给它自己时
C. 这时候RealServer发现源自己就是它自己,就不会走LVS网关而直接从本地回路返回了
简例说明:
1、集群的虚拟IP是113.226.77.88
2、后端RealServer的外网IP是113.226.77.138,内网IP就是示例中的192.168.168.238
3、当在192.168.168.238上访问113.226.77.88,且刚好这时调度机命中它自己时;奇迹发生了,超时了,无响应了……
OK,有兴趣的朋友可以截包看一下:
tcpdump -i eth1 tcp port 80 and host 192.168.168.238 -n -nn -N -t -v -XX -f
你会发现LVS调度机收到1次正常请求和重试,RealServer上也收到了这2次请求,但偏不回应!
实际上,RealServer是无辜的,它乖乖的回应了,也到了目的机器,只是来和回的路径变化了。截取RealServer外网IP对应的网卡,你会看到有2个响应包。什么原因呢?我们来看下IP规则表:
ip rule list
0: from all lookup local
32765: from 192.168.168.238 lookup lvs_nat
32766: from all lookup main
32767: from all lookup default
由于本地回路的规则是最先匹配的,命中它自已时它不会再走LVS虚拟网关,而是直接回复到本机的外网网卡上了。
虽然rt_tables的ID可以定制,但local为0是最高级,无法超越。本地的规则查看方法:
ip route list table local
当然了,如果RealServer上根本就没有外网IP。就不会有上述问题。