完成了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 { [email protected] } notification_email_from [email protected] 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。就不会有上述问题。