Keepalived实现LVS-DR高可用

2018-05-08|Categories: Cluster, Linux, Network|Tags: , |

What is Keepalived

Keepalived官网的项目介绍如下:

Keepalived项目的主要目标是:为Linux系统和基于Linux的基础设施提供简单而强健的负载均衡、高可用服务

负载均衡框架依赖于知名的、被广泛使用的LVS(IPVS)内核模块提供四层负载均衡。Keepalived实现了一系列的检查器(checker)检查后端服务器的健康状况,以此来动态的、自适应的维护负载均衡服务器池。

高可用通过VRRP协议来实现。VRRP是路由器实现高可用的基石。Keepalived也实现了一系列针对VRRP有限状态机的钩子,以此提供底层但高速的协议交互。

What is VRRP

VRRP = Virtual Router Redundancy Protocol,虚拟路由器冗余协议。这个协议最初是在路由器上实现的。

工作原理

支持VRRP的多个物理路由器可以组成一个虚拟路由器组(Virtual Router Group,以下简称VR组),组中的每一个虚拟路由器(VR)属于同一个多播组,共同拥有同一个虚拟路由器ID(VRID)和虚拟IP(VIP),但每一个VR有不同的优先级,优先级最高的VR被选举为Master,将获得VIP,负责转发发往这个VIP的数据包,并定时向多播组发送通知消息,证明自己在正常工作。

为了最小化网络流量,VRRP被设计为只有Master设备可以按照指定的时间间隔(默认1秒)发送VRRP通知。Backup设备只有在成为Master之后才可以发送通知。如果Master停机,将无法向多播组发送通知,VR组中次高优先级的VR成为Master,VIP自动飘移(floating)到新的Master。

VRRP默认工作模式是preempt(抢占式),高优先级的Backup VR上线后总是从低优先级Master VR那里抢占Master角色。

下图是VRRP双主模型(Master & Master)示意图,用两个物理路由器定义了两个虚拟路由器组V1和V2,各自拥有一个VRID和VIP:

  • 在V1中,VRID是49,VIP是192.168.1.253,物理路由器R1是Master,R2是Backup。
  • 在V2中,VRID是77,VIP是192.168.1.254,物理路由器R2是Master,R1是Backup。
  • 左边局域网的电脑设置V1的VIP为默认网关。
  • 右边局域网的电脑设置V2的VIP为默认网关。

vrrp_schemati

VRID vs VIP

  • VRID和VIP二者结合才可以定义一个VR。
  • VRID是VR的标识符,是一个0-255之间的十进制数字。
  • 同一个VR组的所有VR必须使用相同的VRID和VIP。
  • 一个VR组可以设置不止一个VIP。

VR优先级

优先级默认值是100,取值范围从低到高是1-255

  • 一旦Master因为故障等各种原因将要从VR组退出,它会把自己的优先级设为0,并向多播组发送通知,触发Backup立即过渡为Master。
  • 如果把优先级的值设为大于255,Keepalived会以默认值100运行。

如何选择多播组

前面提到,VR组需要依靠多播组通信,进而实现地址自动飘移,但具体选择哪一个多播组是有讲究的。

224.0.0.0 - 239.255.255.255这个范围内的地址全部属于多播地址(也称为多播组地址,因为一个多播地址通常对应一组主机),但其中许多地址已经由权威机构IANA(Internet Assigned Numbers Authority,互联网号码分配机构)指定了明确用途,就像端口号一样,用户不能随便使用这些「名花有主」的多播组:

224.0.0.0 - 224.0.0.255本地网络控制块(Local Network Control Block),支持多播的路由器不转发目标地址属于此范围的多播报文。

  • 224.0.0.0:IANA保留,不做分配。
  • 224.0.0.1:子网中所有主机的地址(包括所有多播路由器地址)。
    • 所有支持多播的主机上所有支持多播的网卡在启动时必须加入这个组。
    • 如果ping这个组,网络中所有多播主机都会响应。
  • 224.0.0.2:子网中所有多播路由器的地址
  • 此范围的其它地址大多数交给路由协议使用。

224.0.1.0 - 224.0.1.255网际控制块(Internetwork Control Block),支持多播的路由器可以通过互联网转发目标地址属于此范围的多播报文。

239.0.0.0 - 239.255.255.255管理范围块(Administratively Scoped Block),用于本地管理的多播地址,仅在特定的本地范围内有效。

用户可以相对比较安全的使用的多播组地址位于「临时块(AD-HOC Blocks)」,临时块包含三个地址段:

之所以说「相对比较安全」,原因是:

In general, the IANA SHOULD NOT assign addresses in the AD-HOC blocks. However, the IANA MAY, under special circumstances, assign addresses from these blocks.

IANA Guidelines for IPv4 Multicast Address Assignments

事实上,三个临时块中的地址都有很多已经被分配出去,一号临时块的分配很杂乱,就不截图了,二号临时块的分配情况如下图:

三号临时块的分配情况如下图:

上面两张截图中,地址段对应的「Description」是「Reserved」的,表示被IANA保留、不会被分配,「Unassigned」表示还没有被分配。理论上这两类地址段最保险,但如果只是在虚拟机搭建的局域网中使用Keepalived这种场景,实际上不需要这么小心翼翼,用户只需要确保一点:避免和子网中已经在使用的多播组地址冲突

我在后面的配置文件中使用的224.1.1.1属于保留地址:

了解了必要的理论,接下来就是实际应用。

Keepalived & LVS-DR

网络拓扑

为了简化配置步骤,减少虚拟机的数量,此次实验的LVS-DR没有配置路由器,所有的实验机器全部连接到同一个交换机:

network topology of keepalived 1 master makes lvs-dr high available

客户端的IP和路由

网卡 网卡模式 IP地址 地址获取方式
eth2 host only 172.16.125.61/24 static
eth2:1 192.168.11.61/24 manual

「static」表示网卡配置文件内已写入BOOTPROTO=staticBOOTPROTO=none,以及IPADDR。「manual」表示通过ipconfig eth2:1 192.168.11.61/24这种方式配置IP地址。更多内容详见《实现LVS-DR和Session绑定》,此处不再赘述。

VS1的IP和路由

网卡 网卡模式 IP地址 地址获取方式
ens34 host only 172.16.125.71/24 static

VIP由Keepalived来配置。

VS2的IP和路由

网卡 网卡模式 IP地址 地址获取方式
ens34 host only 172.16.125.74/24 static

RS1的IP和路由

网卡 网卡模式 IP地址 地址获取方式
lo:1 loopback 192.168.11.200/24 script
ens34 host only 172.16.125.72/24 static

在RS上绑定VIP的脚本详见《实现LVS-DR和Session绑定》,只需要修改第二行为vip='192.168.11.200'。其它诸如安装配置httpd、单机测试的步骤同样也记录在链接的文章中,此处不再赘述。

RS2的IP和路由

网卡 网卡模式 IP地址 地址获取方式
lo:1 loopback 192.168.11.200/24 script
ens34 host only 172.16.125.73/24 static

配置Keepalived

安装Keepalived

yum install keepalived -y

备份配置文件

cp -v /etc/keepalived/keepalived.conf{,.bak}

编辑配置文件

# 清空原有内容
> /etc/keepalived/keepalived.conf

vim /etc/keepalived/keepalived.conf

粘贴以下内容:

# Configuration File for keepalived     # 感叹号、井号开头的行都是注释

global_defs {                       # 全局配置
   notification_email {             # 接收Keepalived状态提醒邮件的地址
     root@localhost                 # 可以设置多个接收地址
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1            # 邮件发送服务器就是本机
   smtp_connect_timeout 30
   router_id vs_1                   # 物理路由器在VR组中的ID,不要和VRID混淆
   vrrp_mcast_group4 224.1.1.1      # 指定当前VR组通信的多播组,非常重要
}

vrrp_instance VI_1 {                # 配置VR组
    #state BACKUP                   # 状态分为MASTER和BACKUP,可以不设置,根据优先级决定
    interface ens34                 # 用哪一块网卡绑定VIP
    virtual_router_id 16            # VRID,取值范围:0-255
    priority 100                    # 优先级,如果不设置这一行,将使用默认值:100
    advert_int 1                    # 向多播组发送通知的时间间隔,默认值:1(秒)
    virtual_ipaddress {             # 用于自动飘移的VIP
        192.168.11.200/24
    }
}

virtual_server 192.168.11.200 80 {  # 配置LVS调度器,VIP必须和自动飘移的VIP相同
    delay_loop 3                       # 检查后端RS健康状态的时间间隔
    lb_algo wrr                        # LVS调度算法
    lb_kind DR                         # LVS工作模式
    protocol TCP                       # LVS调度协议,可选参数:TCP|UDP|SCTP

    real_server 172.16.125.72 80 {     # 通过指定RIP配置RS
        weight 1                          # 权重
        HTTP_GET {                        # 健康状态检查方式,常用参数:HTTP_GET|SSL_GET|TCP_CHECK
            url {
                path /                      # 用GET方法访问网站根目录
                status_code 200             # 如果返回状态码为200,表示RS工作正常
            }
        }
        connect_timeout 1                 # 必须在1秒内返回状态检查结果
        nb_get_retry 3                    # 如果检查失败,重试3次
        delay_before_retry 1              # 每次重试前,等待1秒
    }

    real_server 172.16.125.73 80 {
        weight 2                          # 权重为2
        HTTP_GET {
            url {
                path /
                status_code 200
            }
        }
        connect_timeout 1
        nb_get_retry 3
        delay_before_retry 1
    }
}

第二台VS也需要同样的配置,只有两处需要修改:

  • 一是router_id,设置为router_id vs_2
  • 二是优先级,设置为和第一台的priority 100不同就可以了。

启动Keepalived

systemctl start keepalived

查看Keepalived工作状态

能否自动生成ipvs规则

在Keepalived的配置文件正确配置virtual_server参数之后,Keepalived一启动就会自动生成ipvs规则,然后定期检查RS的健康状况,动态更新RS服务器池。

$ 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.11.200:80 wrr
  -> 172.16.125.72:80             Route   1      0          0
  -> 172.16.125.73:80             Route   2      0          0

可以在任意一台RS上停止httpd服务,看Keepalived是否会及时更新RS列表。

能否自动飘移VIP

Keepalived启动后,检查本机是否获取到VIP:

$ ip a | grep 192.168.11.200
    inet 192.168.11.200/24 scope global secondary ens34

如果已经获取VIP,就停止Keepalived服务,检查VIP是否自动飘移到另一台VS。

整体测试

VS和RS都就绪之后,在客户端上做整体测试,结果完全符合预期:

$ for i in {1..45}; do curl -s --interface 172.16.125.61 192.168.11.200; done | sort | uniq -c
     15 Real server at 172.16.125.72
     30 Real server at 172.16.125.73

在Master VR上停止Keepalived服务,如果上面的测试仍然可以得到正确结果,就证明Keepalived实现了LVS-DR的高可用。

指定curl的源地址

注意,这里的测试语句是curl -s --interface 172.16.125.61 192.168.11.200,指定curl通过172.16.125.61这个源地址去访问192.168.11.200,为什么要这样做呢?

因为RS只有一个可以和局域网通信的IP地址:

$ ip -4 a | grep -E 'inet\b' | awk '{ printf("%-10s %s\n", $NF, $2) }'
lo         127.0.0.1/8
lo:1       192.168.11.200/24
ens34      172.16.125.72/24

而且没有设置默认网关:

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
172.16.125.0    0.0.0.0         255.255.255.0   U     100    0        0 ens34

如果客户端访问时不指定源地址为172.16.125.61,默认会使用和目标地址相同网段的192.168.11.61/24作为源地址发送请求,RS能收到请求,但无法送出响应包,因为源地址与环回网卡绑定的VIP属于同一网段,响应包其实到达了环回网卡,结果只能永远在本机转圈:

$ tcpdump -i any -nnc 5 tcp and dst port 80 and host not \(172.16.125.71 or 172.16.125.74\)
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
01:32:05.366469 IP 192.168.11.61.54900 > 192.168.11.200.80: Flags [S], seq 2737053386, win 14600, options [mss 1460,sackOK,TS val 113795195 ecr 0,nop,wscale 6], length 0
01:32:06.368025 IP 192.168.11.61.54900 > 192.168.11.200.80: Flags [S], seq 2737053386, win 14600, options [mss 1460,sackOK,TS val 113796196 ecr 0,nop,wscale 6], length 0
01:32:08.368933 IP 192.168.11.61.54900 > 192.168.11.200.80: Flags [S], seq 2737053386, win 14600, options [mss 1460,sackOK,TS val 113798197 ecr 0,nop,wscale 6], length 0
01:32:12.369369 IP 192.168.11.61.54900 > 192.168.11.200.80: Flags [S], seq 2737053386, win 14600, options [mss 1460,sackOK,TS val 113802197 ecr 0,nop,wscale 6], length 0
01:32:20.371220 IP 192.168.11.61.54900 > 192.168.11.200.80: Flags [S], seq 2737053386, win 14600, options [mss 1460,sackOK,TS val 113810199 ecr 0,nop,wscale 6], length 0
5 packets captured
5 packets received by filter
0 packets dropped by kernel

一旦指定源地址为172.16.125.61,双方就可以正常通信了:

$ tcpdump -i any -nnc 5 tcp and dst port 80 and host not \(172.16.125.71 or 172.16.125.74\)
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
01:30:25.092603 IP 172.16.125.61.51954 > 192.168.11.200.80: Flags [S], seq 2200534645, win 14600, options [mss 1460,sackOK,TS val 113694921 ecr 0,nop,wscale 6], length 0
01:30:25.093233 IP 172.16.125.61.51954 > 192.168.11.200.80: Flags [.], ack 2323479369, win 229, options [nop,nop,TS val 113694921 ecr 113329410], length 0
01:30:25.093816 IP 172.16.125.61.51954 > 192.168.11.200.80: Flags [P.], seq 0:186, ack 1, win 229, options [nop,nop,TS val 113694922 ecr 113329410], length 186: HTTP: GET / HTTP/1.1
01:30:25.095083 IP 172.16.125.61.51954 > 192.168.11.200.80: Flags [.], ack 291, win 245, options [nop,nop,TS val 113694923 ecr 113329412], length 0
01:30:25.095096 IP 172.16.125.61.51954 > 192.168.11.200.80: Flags [F.], seq 186, ack 291, win 245, options [nop,nop,TS val 113694923 ecr 113329412], length 0
5 packets captured
5 packets received by filter
0 packets dropped by kernel

Leave A Comment