背景 公司有个项目,Web服务是.net开发的跑在IIS上,平时有2-3台一模一样的web服务器提供访问。最开始使用的是Nginx做反向代理实现负载均衡,公网IP和域名都指向的是这台Nginx服务器。最近改为LVS提供负载均衡,并使用keepalived来实现LVS的主备,这样从前到后实现了完整的高可用。
服务器
IP
操作系统
部署应用
lvsmaster
10.10.247.25 VIP:10.10.247.3
CentOS Linux release 7.7.1908
Keepalived v1.3.5 ipvsadm v1.27
lvsbackup
10.10.247.26
CentOS Linux release 7.7.1908
Keepalived v1.3.5 ipvsadm v1.27
后端Web01
10.10.247.23
Windows server 2012 R2
.net 4.6
后端Web02
10.10.247.24
Windows server 2012 R2
.net 4.6
LVS安装配置 直接使用yum在两台lvs服务器上安装keepalived和ipvsadm,LVS是集成在Linux内核里的,由IVPS模块实现的,安装ipvsadm工具来进行管理。
安装完成后直接对keepalived进行配置,主节点的配置文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 [root@lvsmaster ~] ! Configuration File for keepalived global_defs { notification_email { youremail@gmail.com.cn } notification_email_from user@system.com smtp_server 10.10.247.69 smtp_connect_timeout 30 router_id lvsmaster vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state MASTER interface ens160 virtual_router_id 31 vrrp_mcast_group4 224.0.0.31 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1133 } virtual_ipaddress { 10.10.247.3/24 brd 10.10.247.3 dev ens160 label ens160:0 } } virtual_server 10.10.247.3 80 { delay_loop 6 lb_algo sh lb_kind DR persistence_timeout 3 protocol TCP sorry_server 10.10.247.123 80 real_server 10.10.247.23 80 { weight 1 MISC_CHECK { misc_path /root/http_hc_check.sh http://10.10.247.23/Default.aspx } } real_server 10.10.247.24 80 { weight 1 MISC_CHECK { misc_path /root/http_hc_check.sh http://10.10.247.24/Default.aspx } } }
整个配置文件分为了三部分,global_defs、vrrp_instance、virtual_server。
全局定义块主要配置故障发生时的通知对象以及机器标识等。1 2 3 4 5 6 7 8 9 10 11 global_defs { notification_email { youremail@gmail.com.cn } notification_email_from user@system.com smtp_server 10.10.247.69 smtp_connect_timeout 30 router_id lvsmaster vrrp_garp_interval 0 vrrp_gna_interval 0 }
这块内容主要是配置故障通知,也可以不配使用其他监控告警手段。这里有一个重要的配置节:vrrp_strict
使用这个配置后,会强制严格遵守VRRP协议,必须在IPtable上配置相应的规则才能使VIP生效,所以一般情况下不是必要不要配置此项!
VRRP实例定义块主要用来定义对外提供服务的VIP区域及其相关属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 vrrp_instance VI_1 { state MASTER interface ens160 virtual_router_id 31 vrrp_mcast_group4 224.0.0.31 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1133 } virtual_ipaddress { 10.10.247.3/24 brd 10.10.247.3 dev ens160 label ens160:0 } }
一般VIP在这里只填写IP地址即可,查询官网可知有很多参数进行配置:
1 2 3 4 5 6 7 8 virtual_ipaddress { <IPADDR>[/<MASK>] [brd <IPADDR>] [dev <STRING>] [scope <SCOPE>] [label <LABEL>] [peer <IPADDR>] [home] [-nodad] [mngtmpaddr] [noprefixroute] [autojoin] [no_track] [preferred_lft nn|forever] 192.168.200.17/24 dev eth1 192.168.200.18/24 dev eth2 label eth2:1 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 virtual_server 10.10.247.3 80 { delay_loop 6 lb_algo sh lb_kind DR persistence_timeout 3 protocol TCP sorry_server 10.10.247.123 80 real_server 10.10.247.23 80 { weight 1 MISC_CHECK { misc_path /root/http_hc_check.sh http://10.10.247.23/Default.aspx } } real_server 10.10.247.24 80 { weight 1 MISC_CHECK { misc_path /root/http_hc_check.sh http://10.10.247.24/Default.aspx } } }
这块配置需要深入研究的很多,比如IVS有三种工作模式,本次配置使用了DR;后端的调度算法,一共有10种,本次配置使用了SH。网上的资料很多,可以根据实际情况来配置。
真实的后端服务器需要进行健康检查来确认服务是否存活,检查的方式也有很多种,最常用的TCP_CHECK,HTTP_CHECK,这里选择了MISC_CHECK,使用自定义脚本来检查网站状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #!/bin/bash if [ $# -ne 1 ];then echo "Warning: check_command error." exit 1 else CHECK_URL=$1 CMD=`/usr/bin/curl -IL "${CHECK_URL} " 2>/dev/null | grep "200 OK" | wc -l` if [ ${CMD} -eq 1 ];then exit 0 else exit 1 fi fi
后端服务器配置 通常后端服务器都是nginx或者Apache,这里的后端服务器是windows 2012 R2的系统,所以配置略微不同。需要将VIP配到后端服务器环回虚拟网卡上,这样才能正常使用DR模式。
首先添加环回虚拟网卡(Microsoft Loopback Adapter)
以管理员身份运行cmd后,在cmd命令窗口中执行:hdwwiz:
配置IP地址
安装完成以后,在网络连接里会多一块网卡,将网卡重命名为realserver,配置虚IP地址
一些其他需要注意的
网上的资料有很多针对旧版系统的配置,记录如下:
windows 2008的默认中,网卡的stronghost处于启用状态,这个设置可以防止跨接口转发数据包,这就表明:来自一个网络适配器的请求不会被环回适配器处理,因为这个请求来自于不同的网络适配器。为了将环回适配器从stronghost切换为weakhost,需要运行以上四条命令,要不然TCP的状态会一直处于SYN_RECV 状态。
将以下代码保存为bat执行,或直接在CMD中依次执行2~5行命令即可(双引号中需根据实际连线名称修改)
1 2 3 4 5 6 7 @echo off netsh interface ipv4 set interface "realserver" weakhostreceive=enabled netsh interface ipv4 set interface "realserver" weakhostsend=enabled netsh interface ipv4 set interface "本地连线" weakhostreceive=enabled netsh interface ipv4 set interface "本地连线" weakhostsend=enabled pause
子网掩码255.255.255.255但在MS NT/2K/XP会被认为是无效的。 可以有以下解决方法: 在MS NT/2K/XP中,网络界面(interfaces)在HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
找到适当的网络连接IP地址,修改subnetMask子网掩码,(注意修改方式)不需要重启,只需重新激活该网络连接即可。
LVS启动服务 启动keepalived服务,观察是否vip成功配置在master上。f访问后端服务器Web地址,看是否可以正常访问。然后停止主机的进程,观察VI是否正常切换。
使用ipvsadm命令来查看lvs的信息:
1 2 3 4 5 6 7 8 9 ipvsadm -Ln ipvsadm -lnc ipvsadm -Ln --stats ipvsadm -Ln --rate
配置监控LVS 使用zabbix平台来监控LVS服务器和keepalived的状态。基本思路是利用自定义脚本来获取LVS的一些状态信息,然后通过zabbix_sender定时推送给zabbix server端。自定义脚本使用网上大神的一个py脚本,稍作修改适用于当前的环境。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 import os,commands,sys,timezabbix_agent_file='/etc/zabbix/zabbix_agentd.conf' if not os.path.exists(zabbix_agent_file): sys.exit(4 ) zabbix_server=commands.getstatusoutput('''grep '^ServerActive' %s |awk -F[=] '{print $2}' ''' %zabbix_agent_file)[1 ].strip() zabbix_hostname=commands.getstatusoutput('''grep '^Hostname' %s |awk -F[=] '{print $2}' ''' %zabbix_agent_file)[1 ].strip() if not zabbix_server or not zabbix_hostname: sys.exit() zabbix_server_port=10054 timestamp = int(time.time()) keepalived_vip=['10.10.247.3' ] tmp_file_path='/tmp/lvs_status.txt' def monit_lvs () : status,lvs_packets_sec=commands.getstatusoutput('''tail -1 /proc/net/ip_vs_stats | /usr/bin/awk '{print strtonum("0x"$1),strtonum("0x"$2), strtonum("0x"$3), strtonum("0x"$4),strtonum("0x"$5)}'|awk '{print $2}' ''' ) status,lvs_bit_sec=commands.getstatusoutput('''tail -1 /proc/net/ip_vs_stats | /usr/bin/awk '{print strtonum("0x"$1),strtonum("0x"$2), strtonum("0x"$3),strtonum("0x"$4), strtonum("0x"$5)}'|awk '{print $4}' ''' ) status,lvs_conns_sec=commands.getstatusoutput('cat /proc/net/ip_vs_conn | wc -l' ) status,lvs_keepalived_vip_status=commands.getstatusoutput('/sbin/ip addr |grep %s |wc -l' %keepalived_vip[0 ]) if int(lvs_keepalived_vip_status) != 0 : status,result_ip=commands.getstatusoutput(''' echo %s |awk -F '.' '{print $NF}' ''' %keepalived_vip[0 ]) try : lvs_keepalived_vip_status =int(result_ip) except : pass with open(tmp_file_path,'wb' ) as f: f.write('%s %s %s %s\n' %(zabbix_hostname,'lvs_packets_sec' ,timestamp,lvs_packets_sec)) f.write('%s %s %s %s\n' %(zabbix_hostname,'lvs_bit_sec' ,timestamp,lvs_bit_sec)) f.write('%s %s %s %s\n' %(zabbix_hostname,'lvs_conns_sec' ,timestamp,lvs_packets_sec)) f.write('%s %s %s %s\n' %(zabbix_hostname,'lvs_keepalived_vip_status' ,timestamp,lvs_keepalived_vip_status)) if __name__=='__main__' : monit_lvs() send_data_cmd='zabbix_sender -vv -z %s -p %s -T -i %s' %(zabbix_server,zabbix_server_port,tmp_file_path) os.popen(send_data_cmd)
配置定时任务来执行脚本,crontab默认只能每分钟执行一次,所以写一个小脚本来每10秒跑一次。
1 2 3 4 5 6 7 8 9 10 11 #!/bin/bash step=10 for (( i = 0; i < 60; i=(i+step) )); do $(python '/root/lvs_status_sender.py' ) sleep $step done exit 0
1 2 * * * * * bash /root/lvs_status_sender.sh >>/var/log /crontab.log2>&1
然后就可以在Zabbix上配置模板,添加监控项和触发器。
注意:键值必须和脚本里的参数完全一致、类型必须是Zabbix采集器。
分别给VIP状态和每秒转发数设置一个触发器,当VIP切换时会发生警告,当每秒转发数大于10W的时候也会报警。
除此之外还配置了一个keepalived的进程监控,可以监控进程是否存活,一旦停止触发器就会告警动作。