本文主要讲述一下keepalived的工作原理,及如何实现双机热备

1. keepalived简介

keepalved软件完全是由C语言编写的。该项目的主要目标为Linux操作系统是提供一个简便、鲁棒的方式实现负载均衡和高可用性。负载均衡架构依赖于著名并被广泛使用的LVS四层负载均衡架构。keepalived实现了一系列的checkers,可以通过检查各负载均衡器的健康状况来动态的监测和管理各负载均衡服务。另一方面,高可用性是通过VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议协议)来实现的。VRRP是一种应对路由失败的基础设施。
此外,keepalived为VRRP有限状态机实现了一系列的钩子(hooks)以提供底层(low-level)和高速的协议交互。为了提供最快速的网络失败检测,keepalived实现了BFD协议。VRRP状态装换可以把BFD命中考虑在内以更快速的驱动状态机转换。keepalived框架可以被单独的使用,也可以配合LVS等一起使用以提供更富弹性的基础设施。
简而言之,keepalived提供了两个主要功能:

  • 对LVS系统进行健康检查
  • 实施VRRPv2堆栈以处理负载均衡器故障转移

健康检查和失败切换是keepalived的两大核心功能。所谓的健康检查,就是采用tcp三次握手、http请求、udp echo请求等方式对负载均衡器后面的实际服务器进行保活检测;而失败切换主要是应用于配置了主备模式的负载均衡器,利用VRRP(虚拟路由冗余协议,可参考RFC文档 )维持主备负载均衡器的心跳,当主负载均衡器出现问题时,由备负载均衡器承载对应的业务,从而在最大限度上减少流量损失,并保证服务的稳定性。

1.1 keepalived使用的内核组件

keepalived使用四个Linux内核组件:

  • LVS框架: 用于实现数据流量的负载均衡
  • Netfilter框架: 支持NAT和IP伪装
  • Netlink接口: 设置和删除网络接口上的VRRP虚拟IP
  • 组播: 将VRRP通告发送到保留的VRRP MULTICAST组(224.0.0.18)

image.png
上图是keepalived的功能体系结构,大致分为两层: 用户空间(user space)和内核空间(kernel space)。
1) 内核空间
主要包括IPVS(IP虚拟服务器,用于实现网络服务的负载均衡)和NETLINK(提供高级路由及其他相关的网络功能)两个部分。
2) 用户空间

  • WatchDog: 负责监控checkers以及VRRP进程的状况
  • VRRP Stack: 负责负载均衡器之间的失败切换Failover,如果只用一个负载均衡器,则VRRP不是必须的。
  • Checkers: 负责真实服务器的健康检查health checking,是keepalived最主要的功能。换言之,可以没有VRRP Stack,但健康检查health checking是一定要有的。
  • IPVS wrapper: 发送用户设置的规则到内核ipvs代码
  • Netlink Reflector: 用来设定vrrp的vip地址等

    2. VRRP协议

VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议。可以认为它是实现路由器高可用的容错协议,即将N台提供相同功能的路由器组成一个路由器组(Router Group),这个组里有一个master和多个backup,但在外界看来就像一台一样,构成虚拟路由器,拥有一个虚拟IP(vip,也就是路由器所在局域网内其他机器的默认路由),占有这个IP的master实际负责ARP响应和转发IP数据包,组中的其他路由器作为备份的角色处于待命状态。master会发送组播消息,当backup在超时时间内收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级来选举一个backup充当新的master,保证路由器的高可用。
在VRRP协议实现里,虚拟路由器使用00-00-5E-00-01-XX作为虚拟MAC地址,XX就是唯一的VRID(Virtual Router IDentifier),这个地址同一时间只有一个物理路由器占用。在虚拟路由器里面的物理路由器组通过多播IP地址224.0.0.18来定时发送通告消息。每个Router都有一个1-255之间的优先级别,级别最高的(highest priority)将成为主控(master)路由器。通过降低master的优先权可以让处于backup状态的路由器抢占主路由器的状态,两个backup优先级相同时IP地址较大者为master,接管虚拟IP。
image.png

3. 与heartbeat/corosync等比较

Heartbeat、Corosync、Keepalived这三个集群组件到底选哪个好? 首先我想说明的是,Keepalived与Heartbeat、Corosync根本不是同一类型的(Heartbeat、Corosync是属于同一类型)。Keepalived使用的是vrrp协议方式,即虚拟路由冗余协议(Virtual Router Redundancy Protocol,简写为VRRP); Heartbeat或CoroSync是基于主机或网络服务的高可用方式。简单的说就是,Keepalived的目的是模拟路由器的高可用,Heartbeat或Corosync的目的是实现Service的高可用
所以,一般keepalived是实现前端高可用,常用的前端高可用组合有:LVS+Keeplived、Nginx+Keepalived、HAproxy+keepalived。而Heartbeat或Corosync是实现服务的高可用,常见的组合有Heartbeat v3(Corosync) + Pacemaker + NFS + Httpd实现Web服务的高可用、Heartbeat v3(Corosync) + Pacemaker + NFS + MySQL实现MySQL服务的高可用。总结一下,Keepalived实现轻量级的高可用,一般用于前端高可用,且不需要共享存储,一般常用于两个节点之间的高可用; 而Heartbeat或Corosync一般用于服务的高可用,且需要共享存储,一般用于多个节点的高可用。

  1. 补充:
  2. 有博友可能会问,那heartbeatcorosync我们又应该选哪个好啊? 我想说我们一般选用corosync,因为corosync的运行机制更优于heartbeat
  3. 就连从heartbeat分离出来的pacemaker都说在以后的开发当中更倾向于corosync,所以现在corosync+pacemaker是最佳组合。

4. keepalived的安装

当前我们的操作系统环境为:

[admin@pd-common-haproxy-01 haproxy]$ uname -a
Linux pd-common-haproxy-01 3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:39:32 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
[admin@pd-common-haproxy-01 haproxy]$ cat /etc/redhat-release 
CentOS Linux release 7.6.1810 (Core)

如下介绍具体的安装步骤:
1) 下载软件安装包并解压

wget https://github.com/acassen/keepalived/archive/v2.1.5.tar.gz
tar zxf v2.1.5.tar.gz
cd keepalived-2.1.5

2) 安装依赖文件
查看keepalived的安装说明:

[admin@pd-common-haproxy-01 keepalived-2.1.5]$ cat INSTALL 
Kernel needs
==============
  Compile a kernel with the following options :
  Kernel/User netlink socket
  LinuxVirtualServer
  Keepalived supports all LVS code.
Library dependencies
====================
  In order to compile Keepalived needs the following libraries :
  * OpenSSL, <www.openssl.org>
Linux flavours
==============
RedHat based systems (RedHat Enterprise/CentOS/Fedora)
------------------------------------------------------
The following build packages are needed:
        make
        autoconf automake (to build from git source tree rather than tarball)
The following libraries need to be installed:
        openssl-devel libnl3-devel ipset-devel
For iptables support:
        libxtables-dev libip6tc-dev libip4tc-dev
          or on older installations:
        iptables-devel
For magic file identification support:
        file-devel
For SNMP support:
        net-snmp-devel
For DBUS support:
        glib2-devel
For PCRE support
        pcre2-devel
For nftables support
        libnftnl-devel libmnl-devel
For building the documentation, the following packages need to be installed:
        Fedora: python-sphinx (will pull in: python2-sphinx_rtd_theme)
        CentOS-and-friends: python-sphinx epel-release python-sphinx_rtd_theme
   For latex or pdf files, the following are also needed:
        Fedora: latexmk python-sphinx-latex
        CentOS-and-friends: latexmk texlive texlive-titlesec texlive-framed texlive-threeparttable texlive-wrapfig texlive-multirow

这里我们根据需要安装对应的依赖包(如果某些安装包直接采用yum install找不到的话,也可以到http://www.rpmfind.net/linux/rpm2html/search.php进行查找)。如下我们执行安装:

[admin@pd-common-haproxy-01 keepalived-2.1.5]$ yum list installed | grep openssl
openssl.x86_64                        1:1.0.2k-19.el7                  @base    
openssl-devel.x86_64                  1:1.0.2k-19.el7                  @base    
openssl-libs.x86_64                   1:1.0.2k-19.el7                  @base    
xmlsec1-openssl.x86_64                1.2.20-7.el7_4                   @anaconda
[admin@pd-common-haproxy-01 keepalived-2.1.5]$ yum list installed | grep pcre
pcre.x86_64                           8.32-17.el7                      @anaconda
pcre-devel.x86_64                     8.32-17.el7                      @base    
[admin@pd-common-haproxy-01 keepalived-2.1.5]$ yum list installed | grep iptables
iptables.x86_64                       1.4.21-35.el7                    @base    
iptables-devel.x86_64                 1.4.21-35.el7                    @base    
iptables-services.x86_64              1.4.21-35.el7                    @base    
[admin@pd-common-haproxy-01 keepalived-2.1.5]$ yum list installed | grep "snmp"
net-snmp-agent-libs.x86_64            1:5.7.2-49.el7                   @base    
net-snmp-libs.x86_64                  1:5.7.2-49.el7                   @base

3) 安装keepalived

[admin@pd-common-haproxy-01 keepalived-2.1.5]$ mkdir -p /usr/local/keepalived
[admin@pd-common-haproxy-01 keepalived-2.1.5]$ mkdir -p /etc/keepalived
[admin@pd-common-haproxy-01 keepalived-2.1.5]$ ./configure --prefix=/data/keepalived --sbindir=/usr/local/sbin --sysconfdir=/etc/keepalived/
[admin@pd-common-haproxy-01 keepalived-2.1.5]$ make install

安装完成之后,可以看到如下:

[admin@pd-common-haproxy-01 keepalived-2.1.5]$ tree /usr/local/sbin/
/usr/local/sbin/
├── haproxy
└── keepalived

0 directories, 2 files
[admin@pd-common-haproxy-01 keepalived-2.1.5]$ tree /data/keepalived/
/data/keepalived/
├── bin
│   └── genhash
└── share
    ├── doc
    │   └── keepalived
    │       └── README
    ├── man
    │   ├── man1
    │   │   └── genhash.1
    │   ├── man5
    │   │   └── keepalived.conf.5
    │   └── man8
    │       └── keepalived.8
    └── snmp
        └── mibs

10 directories, 5 files

[admin@pd-common-haproxy-01 keepalived-2.1.5]$ tree /etc/keepalived/
/etc/keepalived/
├── keepalived
│   ├── keepalived.conf
│   └── samples
│       ├── client.pem
│       ├── dh1024.pem
│       ├── keepalived.conf.conditional_conf
│       ├── keepalived.conf.fwmark
│       ├── keepalived.conf.HTTP_GET.port
│       ├── keepalived.conf.inhibit
│       ├── keepalived.conf.IPv6
│       ├── keepalived.conf.misc_check
│       ├── keepalived.conf.misc_check_arg
│       ├── keepalived.conf.PING_CHECK
│       ├── keepalived.conf.quorum
│       ├── keepalived.conf.sample
│       ├── keepalived.conf.SMTP_CHECK
│       ├── keepalived.conf.SSL_GET
│       ├── keepalived.conf.status_code
│       ├── keepalived.conf.track_interface
│       ├── keepalived.conf.UDP_CHECK
│       ├── keepalived.conf.virtualhost
│       ├── keepalived.conf.virtual_server_group
│       ├── keepalived.conf.vrrp
│       ├── keepalived.conf.vrrp.localcheck
│       ├── keepalived.conf.vrrp.lvs_syncd
│       ├── keepalived.conf.vrrp.routes
│       ├── keepalived.conf.vrrp.rules
│       ├── keepalived.conf.vrrp.scripts
│       ├── keepalived.conf.vrrp.static_ipaddress
│       ├── keepalived.conf.vrrp.sync
│       ├── root.pem
│       ├── sample.misccheck.smbcheck.sh
│       └── sample_notify_fifo.sh
├── keepalived.conf
└── sysconfig
    └── keepalived

3 directories, 33 files

这里将/etc/keepalived/keepalived/目录下的keepalived.conf文件移动到/etc/keepalived目录,以使后面通过systemd能够找到:
4) 设置keepalived开机启动
默认情况下,安装完成之后,已经在/usr/lib/systemd/system目录下为我们生成了一个keeepalived.service,如果没有可以在keepalived的源代码目录下将keepalived.server文件拷贝到该目录:

[admin@pd-common-haproxy-01 keepalived-2.1.5]$ ls -al /usr/lib/systemd/system/keepalived.service
-rw-r--r-- 1 root root 387 12月 14 17:00 /usr/lib/systemd/system/keepalived.service

5) keepalived的配置
这里我们暂时不讲解具体的keepalived各项配置,仅给出如下我们安装好后的默认配置,以作参考:

[admin@pd-common-haproxy-01 keepalived-2.1.5]$ cat /etc/keepalived/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 192.168.200.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.200.16
        192.168.200.17
        192.168.200.18
    }
}

virtual_server 192.168.200.100 443 {
    delay_loop 6
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    real_server 192.168.201.100 443 {
        weight 1
        SSL_GET {
            url {
              path /
              digest ff20ad2481f97b1754ef3e12ecd3a9cc
            }
            url {
              path /mrtg/
              digest 9b3a0c85a887a256d6939da88aabd8cd
            }
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }
}

virtual_server 10.10.10.2 1358 {
    delay_loop 6
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    sorry_server 192.168.200.200 1358

    real_server 192.168.200.2 1358 {
        weight 1
        HTTP_GET {
            url {
              path /testurl/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334d
            }
            url {
              path /testurl2/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334d
            }
            url {
              path /testurl3/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334d
            }
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }

    real_server 192.168.200.3 1358 {
        weight 1
        HTTP_GET {
            url {
              path /testurl/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334c
            }
            url {
              path /testurl2/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334c
            }
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }
}

virtual_server 10.10.10.3 1358 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    real_server 192.168.200.4 1358 {
        weight 1
        HTTP_GET {
            url {
              path /testurl/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334d
            }
            url {
              path /testurl2/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334d
            }
            url {
              path /testurl3/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334d
            }
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }

    real_server 192.168.200.5 1358 {
        weight 1
        HTTP_GET {
            url {
              path /testurl/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334d
            }
            url {
              path /testurl2/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334d
            }
            url {
              path /testurl3/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334d
            }
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }
}

这里我们简单说一下keepalived的配置文件:

  • 注释以#或者!开头,直到该行的结尾
  • 通常由global_defs、vrrp_instance、virtual_server这3大模块组成

上面的示例中,在real_server里面加上了针对HTTP的健康检查,另外其实我们可以加上针对TCP的监看检查,例如:

TCP_CHECK {
    connect_timeout 10
    nb_get_retry 3
    delay_before_retry 3
    connect_port 17443
}

5. Keepalived实现双机热备

keepalived的作用是检测后端TCP服务的状态。如果有一台提供TCP服务的后端节点死机,或者出现工作故障,keepalived会及时检测到,并将有故障的节点从系统中剔除;当提供TCP服务的节点恢复并且正常提供服务后keepalived会自动将TCP服务的节点加入到集群中。这些工作都是keepalived自动完成,不需要人工干涉,需要人工做的只是修复发生故障的服务器,以下通过示例来演示。测试环境如下:

keepalived主机:  172.17.50.73
keepalived备机:  172.17.50.74

haproxy服务器1:   172.17.50.74
haproxy服务器2:   172.17.50.74

vip:             172.17.50.75

5.1 安装keepalived及haproxy服务器

1) 安装keepalived
在172.17.50.73以及172.17.50.74这两台主机上安装keepalived,具体安装方法参看本文前面章节。
2) 安装haproxy
在172.17.50.73、172.17.50.74这2台主机上安装haproxy,具体安装方法这里不做介绍。安装完成之后启动haproxy服务。

5.2 keepalived配置

  • keepalived master配置

在172.17.50.73主机上备份原来的keepalived.conf文件,然后将配置修改为如下:

[admin@pd-common-haproxy-01 ~]$ cat /etc/keepalived/keepalived.conf  
! Configuration File for keepalived

global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
#   vrrp_strict
}

vrrp_script chk_haproxy {
   script "killall -0 haproxy"
   interval 2
   weight 2
}
vrrp_instance haproxy01 {       #vrrp实例定义部分
    state MASTER                #设置lvs的状态,MASTER和BACKUP两种,必须大写 
    interface ens192            #设置对外服务的接口
    virtual_router_id 100       #设置虚拟路由标示,这个标示是一个数字,同一个vrrp实例使用唯一标示 
    priority 100                #定义优先级,数字越大优先级越高,在一个vrrp——instance下,master的优先级必须大于backup
    advert_int 1                #设定master与backup负载均衡器之间同步检查的时间间隔,单位是秒
    authentication {            #设置验证类型和密码
        auth_type PASS          #主要有PASS和AH两种
        auth_pass 1111          #验证密码,同一个vrrp_instance下MASTER和BACKUP密码必须相同
    }
    #unicast_src_ip 173.17.50.73 #当前机器地址
    #unicast_peer {
    #  173.17.50.74              #peer中其它机器地址
    #}

    virtual_ipaddress {         #设置虚拟ip地址,可以设置多个,每行一个
        172.17.50.75
    }

    track_script {
        chk_haproxy
    }
}
  • keepalived backup配置

在 172.17.50.74 主机上备份原来的keepalived.conf文件,然后将配置修改为如下(主要修改了state以及priority两个字段):

[admin@pd-common-haproxy-02 ~]$ cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived

global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
   #vrrp_strict
}

vrrp_script chk_haproxy {
   script "killall -0 haproxy"
   interval 2
   weight 2
}
vrrp_instance haproxy01 {       #vrrp实例定义部分
    state BACKUP                #设置lvs的状态,MASTER和BACKUP两种,必须大写 
    interface ens192            #设置对外服务的接口
    virtual_router_id 100       #设置虚拟路由标示,这个标示是一个数字,同一个vrrp实例使用唯一标示 
    priority 99                 #定义优先级,数字越大优先级越高,在一个vrrp——instance下,master的优先级必须大于backup
    advert_int 1                #设定master与backup负载均衡器之间同步检查的时间间隔,单位是秒
    authentication {            #设置验证类型和密码
        auth_type PASS          #主要有PASS和AH两种
        auth_pass 1111          #验证密码,同一个vrrp_instance下MASTER和BACKUP密码必须相同
    }

    virtual_ipaddress {         #设置虚拟ip地址,可以设置多个,每行一个
        172.17.50.75
    }

    track_script {
    chk_haproxy
    }
}

5.3 启动keepalived服务

1) 启动keepalived
执行如下命令启动主备keepalived服务,并查看启动状态:

# 主keepalived
[admin@pd-common-haproxy-01 ~]$ sudo systemctl status keepalived
● keepalived.service - LVS and VRRP High Availability Monitor
   Loaded: loaded (/usr/lib/systemd/system/keepalived.service; disabled; vendor preset: disabled)
   Active: active (running) since 二 2020-12-15 09:34:36 CST; 1 day 5h ago
  Process: 10610 ExecStart=/usr/local/sbin/keepalived $KEEPALIVED_OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 10611 (keepalived)
   CGroup: /system.slice/keepalived.service
           ├─10611 /usr/local/sbin/keepalived -D
           └─10612 /usr/local/sbin/keepalived -D

12月 15 09:42:22 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:22 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:22 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:22 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:27 pd-common-haproxy-01 Keepalived_vrrp[10612]: (haproxy01) Sending/queueing gratuitous ARPs on ens192 for 172.17.50.75
12月 15 09:42:27 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:27 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:27 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:27 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:27 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75

# 备keepalived
[admin@pd-common-haproxy-02 ~]$ sudo systemctl status keepalived
● keepalived.service - LVS and VRRP High Availability Monitor
   Loaded: loaded (/usr/lib/systemd/system/keepalived.service; disabled; vendor preset: disabled)
   Active: active (running) since 二 2020-12-15 09:38:11 CST; 1 day 4h ago
  Process: 1309 ExecStart=/usr/local/sbin/keepalived $KEEPALIVED_OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 1310 (keepalived)
   CGroup: /system.slice/keepalived.service
           ├─1310 /usr/local/sbin/keepalived -D
           └─1311 /usr/local/sbin/keepalived -D

12月 15 09:39:30 pd-common-haproxy-02 Keepalived_vrrp[1311]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:39:35 pd-common-haproxy-02 Keepalived_vrrp[1311]: (haproxy01) Sending/queueing gratuitous ARPs on ens192 for 172.17.50.75
12月 15 09:39:35 pd-common-haproxy-02 Keepalived_vrrp[1311]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:39:35 pd-common-haproxy-02 Keepalived_vrrp[1311]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:39:35 pd-common-haproxy-02 Keepalived_vrrp[1311]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:39:35 pd-common-haproxy-02 Keepalived_vrrp[1311]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:39:35 pd-common-haproxy-02 Keepalived_vrrp[1311]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:22 pd-common-haproxy-02 Keepalived_vrrp[1311]: (haproxy01) Master received advert from 172.17.50.73 with higher priority 102, ours 101
12月 15 09:42:22 pd-common-haproxy-02 Keepalived_vrrp[1311]: (haproxy01) Entering BACKUP STATE
12月 15 09:42:22 pd-common-haproxy-02 Keepalived_vrrp[1311]: (haproxy01) removing VIPs.

可以看到在master keepalived主机上绑定了vip,同样我们可以查看backup keepalived主机,我们看到此时并没有绑定vip。
2) 查看keepalived主机IP
在172.17.50.74上查看主机IP:

[admin@pd-common-haproxy-01 ~]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:a9:68:58 brd ff:ff:ff:ff:ff:ff
    inet 172.17.50.73/24 brd 172.17.50.255 scope global noprefixroute ens192
       valid_lft forever preferred_lft forever
    inet 172.17.50.75/32 scope global ens192
       valid_lft forever preferred_lft forever
    inet6 fe80::a6b:f94a:5ad8:92d2/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::e48c:13d5:ea43:6c82/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

可以看到在master keepalived主机上绑定了vip,同样我们可以查看backup keepalived主机,我们看到此时并没有绑定vip。

5.4 测试keepalived

我们通过浏览器请求VIP上面的http服务:
# curl -X GET http://172.17.50.75:9188/haproxy-status

可以看到服务正常返回。
接着我们关掉master keepalived,即关掉172.17.50.73上的keepalived服务,执行如下命令:

[admin@pd-common-haproxy-01 ~]$ sudo systemctl stop keepalived
[admin@pd-common-haproxy-01 ~]$ sudo systemctl status keepalived
● keepalived.service - LVS and VRRP High Availability Monitor
   Loaded: loaded (/usr/lib/systemd/system/keepalived.service; disabled; vendor preset: disabled)
   Active: inactive (dead)

12月 15 09:42:27 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:27 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:27 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:27 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 15 09:42:27 pd-common-haproxy-01 Keepalived_vrrp[10612]: Sending gratuitous ARP on ens192 for 172.17.50.75
12月 16 14:41:22 pd-common-haproxy-01 Keepalived[10611]: Stopping
12月 16 14:41:22 pd-common-haproxy-01 systemd[1]: Stopping LVS and VRRP High Availability Monitor...
12月 16 14:41:22 pd-common-haproxy-01 Keepalived_vrrp[10612]: (haproxy01) sent 0 priority
12月 16 14:41:22 pd-common-haproxy-01 Keepalived_vrrp[10612]: (haproxy01) removing VIPs.
12月 16 14:41:23 pd-common-haproxy-01 systemd[1]: Stopped LVS and VRRP High Availability Monitor.

之后我们查看备机172.17.50.74主机上的keepalived服务:

[admin@pd-common-haproxy-02 ~]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:a9:d8:b0 brd ff:ff:ff:ff:ff:ff
    inet 172.17.50.74/24 brd 172.17.50.255 scope global noprefixroute ens192
       valid_lft forever preferred_lft forever
    inet 172.17.50.75/32 scope global ens192
       valid_lft forever preferred_lft forever
    inet6 fe80::e48c:13d5:ea43:6c82/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::a6b:f94a:5ad8:92d2/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::e28c:4d19:d4c5:3a06/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

可以看到vip绑定到了172.17.50.74主机上。然后我们再请求nginx服务,发现仍可以正常工作。
之后我们重启172.17.50.73主机上的keepalived服务,可以发现vip又回到了172.17.50.73这台master keepalived主机上,而在172.17.50.74这台backup keepalived主机上的vip解绑了。

5.5 查看vrrp数据包

我们在局域网内的三台主机上抓包:

  • keepalived主机: 172.17.50.73
  • keepalived备机: 172.17.50.74
  • haproxy服务器1: 172.17.50.73

执行以下命令抓包(keepalived默认多播地址是224.0.0.18,可以通过vrrp_mcast_group4选项进行修改):

[admin@pd-common-haproxy-01 ~]$ sudo tcpdump -i ens192 -nn host 224.0.0.18
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens192, link-type EN10MB (Ethernet), capture size 262144 bytes
14:45:27.492828 IP 172.17.50.73 > 224.0.0.18: VRRPv2, Advertisement, vrid 100, prio 102, authtype simple, intvl 1s, length 20
14:45:28.493077 IP 172.17.50.73 > 224.0.0.18: VRRPv2, Advertisement, vrid 100, prio 102, authtype simple, intvl 1s, length 20
14:45:29.493429 IP 172.17.50.73 > 224.0.0.18: VRRPv2, Advertisement, vrid 100, prio 102, authtype simple, intvl 1s, length 20
14:45:30.493658 IP 172.17.50.73 > 224.0.0.18: VRRPv2, Advertisement, vrid 100, prio 102, authtype simple, intvl 1s, length 20
14:45:31.493924 IP 172.17.50.73 > 224.0.0.18: VRRPv2, Advertisement, vrid 100, prio 102, authtype simple, intvl 1s, length 20
14:45:32.494125 IP 172.17.50.73 > 224.0.0.18: VRRPv2, Advertisement, vrid 100, prio 102, authtype simple, intvl 1s, length 20
14:45:33.494476 IP 172.17.50.73 > 224.0.0.18: VRRPv2, Advertisement, vrid 100, prio 102, authtype simple, intvl 1s, length 20
^C
7 packets captured
7 packets received by filter
0 packets dropped by kernel

可以看到每秒中产生一个多播数据包。

附件 keepalived+nginx配置
主keepalived:

! Configuration File for keepalived 

vrrp_instance VI_180{
    state MASTER             #指定该节点为主节点,备用节点设置为BACKUP
    interface ens33          #绑定虚拟IP的网络接口

    virtual_router_id 180    #VRRP组名,两个节点设置一样,以指明各个节点同属一VRRP组

    priority 102             #主节点优先级,数值在1~255,注意从节点必须必主节点的优先级低
    advert_int 1             #组播信息发送间隔,两个节点需一致

    #设置验证信息,两个节点需一致
    authentication{
        auth_type PASS
        auth_pass 1111
    }

    #指定虚拟IP,两个节点需设置一样
    virtual_ipaddress{
        192.168.79.180
    }
} 

!include conf/*.conf

#虚拟IP服务
virtual_server 192.168.79.180 80{
    delay_loop 6             #设定检查间隔
    lb_algo rr               #指定LVS算法
    lb_kind DR               #指定LVS模式
    persistence_timeout 10   #指定LVS持久连接设置
    protocol TCP             #转发协议为TCP

    #后端实际TCP服务配置
    real_server 192.168.79.128 80{
        weight 1
    }

    real_server 192.168.79.129 80{
        weight 1
    }

    real_server 192.168.79.131 80{
        weight 1
    }
}

备keepalived

! Configuration File for keepalived 

vrrp_instance VI_180{
    state BACKUP             #指定该节点为主节点,备用节点设置为BACKUP
    interface ens33          #绑定虚拟IP的网络接口

    virtual_router_id 180    #VRRP组名,两个节点设置一样,以指明各个节点同属一VRRP组

    priority 80             #主节点优先级,数值在1~255,注意从节点必须必主节点的优先级低
    advert_int 1             #组播信息发送间隔,两个节点需一致

    #设置验证信息,两个节点需一致
    authentication{
        auth_type PASS
        auth_pass 1111
    }

    #指定虚拟IP,两个节点需设置一样
    virtual_ipaddress{
        192.168.79.180
    }
} 

!include conf/*.conf

#虚拟IP服务
virtual_server 192.168.79.180 80{
    delay_loop 6             #设定检查间隔
    lb_algo rr               #指定LVS算法
    lb_kind DR               #指定LVS模式
    persistence_timeout 10   #指定LVS持久连接设置
    protocol TCP             #转发协议为TCP

    #后端实际TCP服务配置
    real_server 192.168.79.128 80{
        weight 1
    }

    real_server 192.168.79.129 80{
        weight 1
    }

    real_server 192.168.79.131 80{
        weight 1
    }
}

[参看]

  1. keepalived官网
  2. https://ivanzz1001.github.io/records/post/lb/2018/06/02/lb_keepalived#53-%E5%90%AF%E5%8A%A8keepalived%E6%9C%8D%E5%8A%A1
  3. keepalived实现双机热备
  4. VRRP协议与keepalived原理及功能实例演示