LVS可以实现负载均衡,但是不能够进行健康检查,比如一个rs出现故障,LVS 仍然会把请求转发给故障的rs服务器,这样就会导致请求的无效性。keepalive 软件可以进行健康检查,而且能同时实现 LVS 的高可用性,解决 LVS 单点故障的问题。
1.1、Keepalived简介 Keepalived是Linux下一个轻量级别的高可用解决方案。高可用(High Avalilability,HA),其实两种不同的含义:广义来讲,是指整个系统的高可用行,狭义的来讲就是之主机的冗余和接管,
它与HeartBeat RoseHA 实现相同类似的功能,都可以实现服务或者网络的高可用,但是又有差别,HeartBeat是一个专业的、功能完善的高可用软件,它提供了HA 软件所需的基本功能,比如:心跳检测、资源接管,检测集群中的服务,在集群节点转移共享IP地址的所有者等等。HeartBeat功能强大,但是部署和使用相对比较麻烦,
与HeartBeat相比,Keepalived主要是通过虚拟路由冗余来实现高可用功能,虽然它没有HeartBeat功能强大,但是Keepalived部署和使用非常的简单,所有配置只需要一个配置文件即可以完成。
1.2、Keepalived是什么? Keepalived起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态,它根据TCP/IP参考模型的第三、第四层、第五层交换机制检测每个服务节点的状态,如果某个服务器节点出现异常,或者工作出现故障,Keepalived将检测到,并将出现的故障的服务器节点从集群系统中剔除,这些工作全部是自动完成的,不需要人工干涉,需要人工完成的只是修复出现故障的服务节点。
后来Keepalived又加入了VRRP的功能,VRRP(Vritrual Router Redundancy Protocol,虚拟路由冗余协议)出现的目的是解决静态路由出现的单点故障问题,通过VRRP可以实现网络不间断稳定运行,因此Keepalvied 一方面具有服务器状态检测和故障隔离功能,另外一方面也有HA cluster功能,下面介绍一下VRRP协议实现的过程。
1.3、VRRP协议与工作原理 在现实的网络环境中。主机之间的通信都是通过配置静态路由或者(默认网关)来完成的,而主机之间的路由器一旦发生故障,通信就会失效,因此这种通信模式当中,路由器就成了一个单点瓶颈,为了解决这个问题,就引入了VRRP协议。
VRRP协议是一种主备模式的协议,通过VRRP可以在网络发生故障时透明的进行设备切换而不影响主机之间的数据通信,这其中涉及到两个概念:物理路由器和虚拟路由器。
VRRP可以将两台或者多台物理路由器设备虚拟成一个虚拟路由,这个虚拟路由器通过虚拟IP(一个或者多个)对外提供服务,而在虚拟路由器内部十多个物理路由器协同工作,同一时间只有一台物理路由器对外提供服务,这台物理路由设备被成为:主路由器(Master角色),一般情况下Master是由选举算法产生,它拥有对外服务的虚拟IP,提供各种网络功能,如:ARP请求,ICMP 数据转发等,而且其它的物理路由器不拥有对外的虚拟IP,也不提供对外网络功能,仅仅接收MASTER的VRRP状态通告信息,这些路由器被统称为“BACKUP的角色”,当主路由器失败时,处于BACKUP角色的备份路由器将重新进行选举,产生一个新的主路由器进入MASTER角色,继续提供对外服务,整个切换对用户来说是完全透明的。
每个虚拟路由器都有一个唯一的标识号,称为VRID,一个VRID与一组IP地址构成一个虚拟路由器,在VRRP协议中,所有的报文都是通过IP多播方式发送的,而在一个虚拟路由器中,只有处于Master角色的路由器会一直发送VRRP数据包,处于BACKUP角色的路由器只会接受Master角色发送过来的报文信息,用来监控Master运行状态,一般不会发生BACKUP抢占的情况,除非它的优先级更高,而当MASTER不可用时,BACKUP也就无法收到Master发过来的信息,于是就认定Master出现故障,接着多台BAKCUP就会进行选举,优先级最高的BACKUP将称为新的MASTER,这种选举角色切换非常之快,因而保证了服务的持续可用性。
1.4、Keepalvied的工作原理 上面我们介绍了Keepalived通过VRRP实现高可用性的工作原理,而Keepalived作为一个高性能集群软件,它还能实现对集群中服务器运行状态的监控以及故障隔离,下面我们介绍一下Keepalived对服务器运行状态和故障隔离的工作原理。
Keepalived工作在TCP/IP 参考模型的 三层、四层、五层,也就是分别为:网络层,传输层和应用层,根据TCP、IP参数模型隔层所能实现的功能,Keepalived运行机制如下:
在网络层:我们知道运行这4个重要的协议,互联网络IP协议,互联网络可控制报文协议ICMP、地址转换协议ARP、反向地址转换协议RARP,在网络层Keepalived在网络层采用最常见的工作方式是通过ICMP协议向服务器集群中的每一个节点发送一个ICMP数据包(有点类似与Ping的功能),如果某个节点没有返回响应数据包,那么认为该节点发生了故障,Keepalived将报告这个节点失效,并从服务器集群中剔除故障节点。
在传输层:提供了两个主要的协议:传输控制协议TCP和用户数据协议UDP,传输控制协议TCP可以提供可靠的数据输出服务、IP地址和端口,代表TCP的一个连接端,要获得TCP服务,需要在发送机的一个端口和接收机的一个端口上建立连接,而Keepalived在传输层里利用了TCP协议的端口连接和扫描技术来判断集群节点的端口是否正常,比如对于常见的WEB服务器80端口。或者SSH服务22端口,Keepalived一旦在传输层探测到这些端口号没有数据响应和数据返回,就认为这些端口发生异常,然后强制将这些端口所对应的节点从服务器集群中剔除掉。
在应用层:可以运行FTP,TELNET,SMTP,DNS等各种不同类型的高层协议,Keepalived的运行方式也更加全面化和复杂化,用户可以通过自定义Keepalived工作方式,例如:可以通过编写程序或者脚本来运行Keepalived,而Keepalived将根据用户的设定参数检测各种程序或者服务是否允许正常,如果Keepalived的检测结果和用户设定的不一致时,Keepalived将把对应的服务器从服务器集群中剔除
实验:keepalive实现lvs_dr模式高可用
四台主机node1(192.168.91.139),node2(192.168.91.133)为lvs和keepalived服务器,node3(192.168.91.137),node4(192.168.91.132)为后端real server。vip为192.168.91.200
配置前提: 1 各节点时间必须同步 ntp chrony 2 确保iptables和selinux不会成为阻碍 3 各节点之间可通过主机名通信,使用/etc/hosts文件 4 各节点之间的root用户基于密钥认证的ssh服务完成互相通信(非必须) 5 确保各节点的用于集群服务的接口支持MULTICAST(多播)通信 (传递heartbeat) ip link set multicast on dev 地址范围:224-239
在node3,node4上 [root@localhost ~]#vim rs.sh #!/bin/bash vip='192.168.91.200' mask='255.255.255.255' iface='lo:0' yum install -y httpd &> /dev/null systemctl start httpd cat > /var/www/html/index.html <<END node3 #node4上改为node4 END case $1 in start) echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce ifconfig $iface $vip netmask $mask broadcast $vip up route add -host $vip dev $iface &> /dev/null ;; stop) ifconfig $iface down echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce ;; *) echo "usage:$(basename $0)" start or stop exit 1 ;; esac 在node1,node2 [root@node1 ~]#yum install -y ipvsadm keepalived 在node1上 [root@node1 ~]#vim /etc/keepalived/keepalived.conf global_defs { notification_email { root@localhost #接受邮件地址 } notification_email_from keepalived@localhost #发邮件地址 smtp_server 127.0.0.1 #邮件服务器 smtp_connect_timeout 30 #邮件服务器链接超时时长 router_id node1 #设置lvs的id,在一个网络内应该是唯一的 vrrp_mcast_group4 225.0.0.100 #广播地址 } vrrp_instance VI_1 { state MASTER #master interface eth0 #vip配置在eth0上 virtual_router_id 51 #虚拟路由器编号,主备要一致 priority 100 #优先级 advert_int 1 #心跳探测间隔 authentication { #加入广播域验证方式 auth_type PASS auth_pass 11111111 } virtual_ipaddress { 192.168.91.200 #vip,可以有多个 } } virtual_server 192.168.91.200 80 { #vip地址和端口 delay_loop 5 lb_algo rr #调度算法 lb_kind DR #lvs_DR模型 protocol TCP sorry_server 127.0.0.1 80 #sorry server,本机需要提供http服务 real_server 192.168.91.137 80 { #rs地址和端口 weight 1 #权重 HTTP_GET { #rs健康检测方式 url { path /index.html status_code 200 #访问index.html,当返回码为200表示rs服务在线 } nb_get_retry 3 #健康检测重试试间 delay_before_retry 2 connect_timeout 3 } } real_server 192.168.91.132 80 { weight 1 HTTP_GET { url { path /index.html status_code 200 } nb_get_retry 3 delay_before_retry 2 connect_timeout 3 } } } [root@node1 ~]#systemctl start keepalived [root@node1 ~]#ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.91.200:80 rr -> 192.168.91.132:80 Route 1 0 0 -> 192.168.91.137:80 Route 1 0 0 可以看到lvs集群规则已生成 [root@node1 ~]#ip a 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:96:ea:88 brd ff:ff:ff:ff:ff:ff inet 192.168.91.139/24 brd 192.168.91.255 scope global noprefixroute dynamic eth0 valid_lft 1724sec preferred_lft 1724sec inet 192.168.91.200/32 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::ccf9:2449:681f:b4a3/64 scope link noprefixroute valid_lft forever preferred_lft forever vip已配置到eth0上 把ndoe1上/etc/keepalived/keepalived.conf复制到node2上 在node2上 [root@node2 ~]#vim /etc/keepalived/keepalived.conf router_id node2 state BACKUP priority 90 [root@node2 ~]#systemctl start keepalived 可以看到lvs集群规则已生成 [root@node2 ~]#ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.91.200:80 rr -> 192.168.91.132:80 Route 1 0 0 -> 192.168.91.137:80 Route 1 0 0 因为master正常工作,所以eth0上没有vip [root@node2 ~]#ip a 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:67:fe:92 brd ff:ff:ff:ff:ff:ff inet 192.168.91.134/24 brd 192.168.91.255 scope global noprefixroute dynamic eth0 valid_lft 1514sec preferred_lft 1514sec inet6 fe80::cf4e:cc5b:d538:d744/64 scope link noprefixroute valid_lft forever preferred_lft forever 此时停掉master,发现vip自动配置到backup的eth0上 [root@node2 ~]#ip a 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:67:fe:92 brd ff:ff:ff:ff:ff:ff inet 192.168.91.134/24 brd 192.168.91.255 scope global noprefixroute dynamic eth0 valid_lft 1298sec preferred_lft 1298sec inet 192.168.91.200/32 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::cf4e:cc5b:d538:d744/64 scope link noprefixroute valid_lft forever preferred_lft forever 抓包发现eth1每秒向广播地址中报告自己的优先级 [root@node2 ~]#tcpdump -i eth0 -nn host 225.0.0.100 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 16:26:21.787343 IP 192.168.91.134 > 225.0.0.100: VRRPv2, Advertisement, vrid 51, prio 90, authtype simple, intvl s, length 20 16:26:22.788610 IP 192.168.91.134 > 225.0.0.100: VRRPv2, Advertisement, vrid 51, prio 90, authtype simple, intvl s, length 20 后端健康性检测 [root@centos7 ~]#for i in {1..10};do curl http://192.168.91.200 ;done node4 node3 node4 node3 node4 node3 node4 node3 node4 node3 当两个rs服务停掉,发现sorry server上线 [root@centos7 ~]#for i in {1..10};do curl http://192.168.91.200 ;done sorry server sorry server sorry server sorry server sorry server sorry server sorry server sorry server sorry server sorry server [root@node1 ~]#ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.91.200:80 rr -> 127.0.0.1:80 Route 1 0 10keepalived高可用nginx
在node1,node2上安装nginx,keepalived [root@node1 ~]#yum install -y nginx keepalived 配置nginx反代 [root@node1 ~]#vim /etc/nginx/nginx.conf http { ... upstream www.kej.com { server 192.168.91.132:80; server 192.168.91.136:80; } [root@node1 ~]#vim /etc/nginx/conf.d/vhost.conf server { listen 80; server_name www.kej.com; location / { proxy_pass http://www.kej.com; } } [root@node1 ~]#systemctl start nginx 在node3,node4安装httpd,并提供页面文件 在node1,node2配置keepalived [root@node1 ~]#vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node1 vrrp_mcast_group4 225.0.0.100 } vrrp_script chk_ngx { #定义检测脚本 script "killall -0 nginx && exit 0 || exit 1" weight -10 #nginx探测失败优先权减10 interval 1 #一秒探测一次 fall 1 #探测失败一次就算失败 rise 1 #探测成功一次就算成功 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 122333 } virtual_ipaddress { 192.168.91.200 } track_script { #调用脚本 chk_ngx } } [root@node1 ~]#scp /etc/keepalived/keepalived.conf 192.168.91.137:/etc/keepalived/ 在node2 [root@node2 ~]#vim /etc/keepalived/keepalived.conf router_id node2 priority 95 state BACKUP [root@node2 ~]#systemctl start keepalived 测试: [root@centos7 ~]#vim /etc/hosts 192.168.91.200 www.kej.com [root@centos7 ~]#for i in {1..10};do curl http://www.kej.com;done node3 node4 node3 node4 node3 node4 node3 node4 node3 node4 把node1上nginx服务停掉,vip漂移到node2上 [root@node2 ~]#ip a 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:2b:e8:9c brd ff:ff:ff:ff:ff:ff inet 192.168.91.137/24 brd 192.168.91.255 scope global noprefixroute dynamic eth0 valid_lft 1249sec preferred_lft 1249sec inet 192.168.91.200/32 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::9001:68a9:b341:8006/64 scope link noprefixroute valid_lft forever preferred_lft forever [root@centos7 ~]#for i in {1..10};do curl http://www.kej.com;done node3 node4 node3 node4 node3 node4 node3 node4 node3 node4