第 10-2 章 Linux Keepalived 服务配置

作者: Brinnatt 分类: ARM64 Linux 进阶架构 发布时间: 2022-01-21 16:29

KeepAlived 主要有两个功能:

  1. 能够对 RealServer 进行健康状况检查,支持 4 层、5 层和 7 层协议进行健康检查;
  2. 对负载均衡调度器实现高可用,防止 Director 单点故障。

在 keepalived 设计之初,它只是 LVS 周边的一个辅助工具,用于 LVS 的监控状况检查,因此它和 LVS 的兼容性非常好。

  • 如果某一个 realserver 节点宕了,keepalived 会将此节点从管理列表中踢出去,当此节点恢复后又将此节点加回管理列表,这样能够让 realserver 负载均衡变的智能化。
  • 但是,此时的调度器存在单点故障的可能性,因此有必要对其实现高可用。

实现 LVS 高可用可以使用多种软件来实现,如 heartbeat,但是 heartbeat 本身不能实现 ipvs 的健康状况检查,需要搭配 Ldirectord(安装完 heartbeat 就有了)来进行健康检查。

所幸的是 keepalived 后来也加入了高可用的功能,而且配置起来也相当简单。相比于 heartbeat+Ldirectord,keepalived 的检查速度极快,故障转移也极快,布置也简单的多。所以一般来说,要管理 ipvs,都会选择使用 keepalived。

keepalived 实现故障转移的功能是通过 VRRP(virtual router redundancy protocol 虚拟路由器冗余协议) 协议来实现的。

  • 在 keepalived 正常工作的时候,主节点(master)会不断的发送心跳信息给备节点(backup),当备节点不能在一定时间内收到主节点的心跳信息时,备节点会认为主节点宕了,然后会接管主节点上的资源,并继续向外提供服务保证其可用性。
  • 当主节点恢复的时候,备节点会自动让出资源并再次自动成为备节点。

注意:使用 keepalived 监控、高可用 LVS 集群时(即常说的 keepalived+lvs),并不需要在 Director 上使用 ipvsadm 等管理工具额外配置 ipvs 规则。因为 keepalived 中集合了管理 ipvs 规则的组件(即稍后模型图中的 ipvs wrapper),可以直接在 keepalived 的配置文件中配置 ipvs 相关规则,在解析配置文件时会通过特定的组件将规则发送到内核中的 ipvs 模块。

10.1、VRRP 协议

VRRP 协议的出现是为了解决静态路由的单点故障,它是通过一种竞选机制来将路由任务交给某个 vrrp 路由器的。

在 VRRP 物理结构中,有多个物理的 VRRP 路由器,其中有一台称为 "master" 即主节点路由器,其他的都是 "backup" 备节点路由器,谁是 master 谁是 backup,这是通过他们的优先级来定义竞选的。

在 VRRP 虚拟结构中,虚拟路由器是通过 "MAC+VRID" 的形式来标识的,如 "00-00-5E-00-01-{VRID}"。在 VRRP 虚拟结构中,不管是 master 还是 backup,VRID 必须一致。它们对外都是相同的 VIP,客户端并不需要因为 master 的切换而修改自己的路由配置。

VRRP 结构中路由器之间的通信是通过 IP 多播的方式实现的(也可以配置为其它通信方式)。但是,只有 master 节点才会发送 VRRP 广告包(vrrp advertisement message)。当 master 节点宕掉的时候,backup 中优先级最高的 VRRP 设备会抢占并升级为 master。

10.2、keepalived 架构模型

Keepalived 服务启动的时候,将产生三个相关进程,一个父进程和两个子进程。

PID    111     Keepalived  <-- Parent process fork and monitor children
       112     \_ Keepalived   <-- VRRP child
       113     \_ Keepalived   <-- Healthchecking child
  • 父进程负责 fork 和监控子进程,因此父进程也称为 WatchDog。两个子进程都会开启本地套接字 Unix Domain Socket。
  • 当 keepalived 服务启动后,父进程会通过 unxi domain socket 每隔 5 秒发送一个 "Hello" 消息给子进程,如果父进程无法发送消息给子进程,将认为子进程出现问题,于是会重启子进程。

下图是 keepalived 设计架构图:

keepalived

  • Checkers 组件:负责 RealServer 的健康状况检查,并在 LVS 的拓扑中移除、添加 RealServer。它支持 layer4/5/7 层的协议检查。该组件使用独立的子进程负责,但被父进程监控。
  • VRRP 组件:提供 Director 的故障转移功能从而实现 Director 的高可用。该组件可独立提供功能,无需 LVS 的支持。该组件使用独立的子进程负责,但被父进程监控。
  • System Call 组件:提供读取自定义脚本的功能。该组件在使用时,将临时产生一个子进程来执行任务。
  • IPVS wrapper 组件:负责将配置文件中 IPVS 相关规则发送到内核的 ipvs 模块。
  • Netlink Reflector:用来设定、监控 vrrp 的 vip 地址。

10.3、安装 keepalived

使用 keepalived,完全可以 yum 安装。本文仅给出编译安装的方法,后文的所有配置都使用 yum 安装的 keepalived。

官方各版本源码下载地址:http://www.keepalived.org/download.html。以下是编译安装 keepalived-2.2.4 版本的过程:

[root@director ~]# wget --no-check-certificate https://www.keepalived.org/software/keepalived-2.2.4.tar.gz
[root@director ~]# yum install gcc libnl3-devel openssl-devel -y
[root@director ~]# tar xf keepalived-2.2.4.tar.gz 
[root@director ~]# cd keepalived-2.2.4/
[root@director keepalived-2.2.4]# ./configure --prefix=/usr/local/keepalived-2.2.4
[root@director keepalived-2.2.4]# make && make install
  • 其中 ./configure--with-kernel-dir 是在管理 LVS 时需要使用的,如果不用配合 LVS,则可以不用此选项。

再做一下编译安装的规范行为:

[root@director ~]# ln -sv /usr/local/keepalived-2.2.4/ /usr/local/keepalived
‘/usr/local/keepalived’ -> ‘/usr/local/keepalived-2.2.4/’
[root@director ~]# echo "MANPATH /usr/local/keepalived/share/man" >>/etc/man.config
[root@director ~]# echo "export PATH=/usr/local/keepalived/sbin:$PATH" > /etc/profile.d/keepalived.sh
[root@director ~]# chmod +x /etc/profile.d/keepalived.sh
[root@director ~]# . /etc/profile.d/keepalived.sh
[root@director ~]#

编译安装后,在安装目录下生成以下一些目录,其中 keepalived 程序在 sbin 目录下:

[root@director ~]# tree /usr/local/keepalived -d
/usr/local/keepalived
├── bin
├── etc
│   ├── keepalived
│   │   └── samples
│   └── sysconfig
├── sbin
└── share
    ├── doc
    │   └── keepalived
    ├── man
    │   ├── man1
    │   ├── man5
    │   └── man8
    └── snmp
        └── mibs

15 directories
[root@director ~]#

在 etc 目录下,有配置文件和大量配置文件示例,而且自动生成了 keepalived systemd 服务文件,可以直接启动 keepalived 服务:

[root@director ~]# mkdir /etc/keepalived
[root@director ~]# cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived
[root@director ~]# systemctl start keepalived
[root@director ~]# 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 Thu 2022-01-06 16:31:19 CST; 5s ago
     Docs: man:keepalived(8)
           man:keepalived.conf(5)
           man:genhash(1)
           https://keepalived.org
  Process: 13858 ExecStart=/usr/local/keepalived-2.2.4/sbin/keepalived $KEEPALIVED_OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 13859 (keepalived)
   CGroup: /system.slice/keepalived.service
           ├─13859 /usr/local/keepalived-2.2.4/sbin/keepalived -D
           ├─13860 /usr/local/keepalived-2.2.4/sbin/keepalived -D
           └─13861 /usr/local/keepalived-2.2.4/sbin/keepalived -D

Jan 06 16:31:23 director Keepalived_vrrp[13861]: Sending gratuitous ARP on eth0 for 192.168.200.16
Jan 06 16:31:23 director Keepalived_vrrp[13861]: Sending gratuitous ARP on eth0 for 192.168.200.17
Jan 06 16:31:23 director Keepalived_vrrp[13861]: Sending gratuitous ARP on eth0 for 192.168.200.18
Jan 06 16:31:24 director Keepalived_healthcheckers[13860]: HTTP_CHECK on service [192.168.200.4]:t...s.
Jan 06 16:31:24 director Keepalived_healthcheckers[13860]: Removing service [192.168.200.4]:tcp:13...58
Jan 06 16:31:24 director Keepalived_healthcheckers[13860]: Remote SMTP server [192.168.200.1]:25 c...d.
Jan 06 16:31:25 director Keepalived_healthcheckers[13860]: HTTP_CHECK on service [192.168.201.100]...s.
Jan 06 16:31:25 director Keepalived_healthcheckers[13860]: Removing service [192.168.201.100]:tcp:...43
Jan 06 16:31:25 director Keepalived_healthcheckers[13860]: Lost quorum 1-0=1 > 0 for VS [192.168.2...43
Jan 06 16:31:25 director Keepalived_healthcheckers[13860]: Remote SMTP server [192.168.200.1]:25 c...d.
Hint: Some lines were ellipsized, use -l to show in full.
[root@director ~]#
  • 注意,启动 keepalived 服务需要 keepalived.conf 配置文件,手动拷贝过去即可。

10.4、配置 keepalived 日志

默认 keeepalived 的日志会记录到 /var/log/messages 中。可以配置 keepalived 使其记录到其它文件中。

先将编译安装生成的 /usr/local/keepalived-2.2.4/etc/sysconfig/keepalived 修改一下:

# 这是原内容
[root@director ~]# cat /usr/local/keepalived-2.2.4/etc/sysconfig/keepalived
# Options for keepalived. See `keepalived --help' output and keepalived(8) and
# keepalived.conf(5) man pages for a list of all options. Here are the most
# common ones :
#
# --vrrp               -P    Only run with VRRP subsystem.
# --check              -C    Only run with Health-checker subsystem.
# --dont-release-vrrp  -V    Dont remove VRRP VIPs & VROUTEs on daemon stop.
# --dont-release-ipvs  -I    Dont remove IPVS topology on daemon stop.
# --dump-conf          -d    Dump the configuration data.
# --log-detail         -D    Detailed log messages.
# --log-facility       -S    0-7 Set local syslog facility (default=LOG_DAEMON)
#

KEEPALIVED_OPTIONS="-D"

# 修改后的内容
[root@director ~]# cat /usr/local/keepalived-2.2.4/etc/sysconfig/keepalived | grep -v "^#"

KEEPALIVED_OPTIONS="-D -S 0"

上面配置使用 local0 这个设备来记录日志,因此去修改 rsyslog 的配置文件 /etc/rsyslog.conf,添加该设备记录日志的级别和路径:

# Keepalived log config
local0.*                           /var/log/keepalived.log

再重启 rsyslog:

[root@director ~]# systemctl restart rsyslog

10.5、keepalived 配置文件详解

keepalived 配置文件按层级模块划分的,每层由 "{ }" 来界定。 在主配置文件中可以通过 include 来涵盖多个子配置文件。配置文件包括以下几个模块:

  • GLOBAL CONFIGURATION
  • VRRPD CONFIGURATION
  • LVS CONFIGURATION
  • BFD CONFIGURATION(从未用过)

10.5.1、全局配置模块

! Configuration File for keepalived
global_defs {                                   # 全局定义部分
    notification_email {                        # 设置报警邮件地址,可设置多个
        acassen@firewall.loc                    # 接收通知的邮件地址
        failover@firewall.loc
    }                        
    notification_email_from test0@163.com       # 设置 发送邮件通知的地址
    smtp_server smtp.163.com                    # 设置 smtp server 地址,可是ip或域名.可选端口号(默认25)
    smtp_connect_timeout 30                     # 设置 连接 smtp server的超时时间
    router_id LVS_DEVEL                         # 主机标识,用于邮件通知
    vrrp_strict                                 # 严格执行VRRP协议规范,此模式不支持节点单播
    script_user keepalived_script               # 指定运行脚本的用户名和组。默认使用用户的默认组。
                                                # 如未指定,默认为keepalived_script 用户,如无此用户,则使用root
    enable_script_security                      # 如过路径为非root可写,不要配置脚本为root用户执行。
}
  • 可用参数说明

    default_interface eth0:   设置静态地址默认绑定的端口。默认是eth0。
    
    # 设置LVS同步服务的相关内容。可以同步LVS的状态信息。
    lvs_sync_daemon   [id ] [maxlen ] [port ] [ttl ] [group ]
    INTERFACE:          指定同步服务绑定的接口。
      VRRP_INSTANCE:    指定同步服务绑定的VRRP实例。
      id :     指定同步服务所使用的SYNCID,只有相同的SYNCID才会同步。范围是0-255.
      maxlen:           指定数据包的最大长度。范围是1-65507
      port:             指定同步所使用的UDP端口。
      group:            指定组播IP地址。
    
    lvs_flush:                                在keepalived启动时,刷新所有已经存在的LVS配置。
    vrrp_garp_master_delay 10:                当转换为MASTER状态时,延迟多少秒发送第二组的免费ARP。默认为5s,0表示不发送第二组免的免费ARP。
    vrrp_garp_master_repeat 1:                当转换为MASTER状态时,在一组中一次发送的免费ARP数量。默认是5.
    vrrp_garp_lower_prio_delay 10:            当MASTER收到更低优先级的通告时,延迟多少秒发送第二组的免费ARP。
    vrrp_garp_lower_prio_repeat 1:            当MASTER收到更低优先级的通告时,在一组中一次发送的免费ARP数量。
    vrrp_garp_master_refresh 60:              当keepalived成为MASTER以后,刷新免费ARP的最小时间间隔(会再次发送免费ARP)。默认是0,表示不会刷新。
    vrrp_garp_master_refresh_repeat 2:        当keepalived成为MASTER以后,每次刷新会发送多少个免费ARP。默认是1.
    vrrp_garp_interval 0.001:                 在一个接口发送的两个免费ARP之间的延迟。可以精确到毫秒级。默认是0.
    vrrp_lower_prio_no_advert true|false:     默认是false。如果收到低优先级的通告,不发送任何通告。
    vrrp_version 2|3:                         设置默认的VRRP版本。默认是2.
    vrrp_check_unicast_src:                   在单播模式中,开启对VRRP数据包的源地址做检查,源地址必须是单播邻居之一。
    vrrp_skip_check_adv_addr:                 默认是不跳过检查。检查收到的VRRP通告中的所有地址可能会比较耗时。
                                            设置此命令的意思是,如果通告与接收的上一个通告来自相同的master路由器,则不执行检查(跳过检查)。
    
    vrrp_strict:                              严格遵守VRRP协议。
                                            下列情况将会阻止启动Keepalived:1. 没有VIP地址。2. 单播邻居。3. 在VRRP版本2中有IPv6地址。
    
    vrrp_iptables:                            不添加任何iptables规则。默认是添加iptables规则的。
    
    # 如果vrrp进程或check进程超时,可以用下面的4个选项。
    # 可以使处于BACKUP状态的VRRP实例变成MASTER状态,即使MASTER实例依然在运行。
    # 因为MASTER或BACKUP系统比较慢,不能及时处理VRRP数据包。
    vrrp_priority <-20 -- 19>:                设置VRRP进程的优先级。
    checker_priority <-20 -- 19>:             设置checker进程的优先级。
    vrrp_no_swap:                             vrrp进程不能够被交换。
    checker_no_swap:                          checker进程不能够被交换。
    
    script_user  [groupname]:       设置运行脚本默认用户和组。
                                            如果没有指定,则默认用户为keepalived_script(需要该用户存在),否则为root用户。
                                            默认groupname同username。
    
    enable_script_security:                   如果脚本路径的任一部分对于非root用户来说,都具有可写权限,则不会以root身份运行脚本。
    nopreempt:                                默认是抢占模式 要是用非抢占式的就加上nopreempt

10.5.2、VRRPD 配置模块

VRRPD 的配置包括如下子块:

  1. vrrp_script
  2. vrrp_sync_group
  3. garp_group
  4. vrrp_instance

vrrp_script 配置

# 添加一个周期性执行的脚本。脚本的退出状态码会被调用它的所有的VRRP Instance记录。
# 至少有一个VRRP实例调用它并且优先级不能为0.优先级范围是1-254.
vrrp_script <SCRIPT_NAME> {
          ...
    }

选项说明:
script "/path/to/somewhere":  指定要执行的脚本的路径。
interval <INTEGER>:               指定脚本执行的间隔。单位是秒。默认为1s。
timeout <INTEGER>:                指定在多少秒后,脚本被认为执行失败。
weight <-254 --- 254>:            调整优先级。默认为2.
rise <INTEGER>:                   执行成功多少次才认为是成功。
fall <INTEGER>:                   执行失败多少次才认为失败。
user <USERNAME> [GROUPNAME]:  运行脚本的用户和组。
init_fail:                      假设脚本初始状态是失败状态。

解释 weight: 
1. 如果脚本执行成功(退出状态码为0),weight大于0,则priority增加。
2. 如果脚本执行失败(退出状态码为非0),weight小于0,则priority减少。
3. 其他情况下,priority不变。

vrrp_instance

命令说明:
state MASTER|BACKUP:            指定该keepalived节点的初始状态。
interface eth0:                 vrrp实例绑定的接口,用于发送VRRP包。
use_vmac [<VMAC_INTERFACE>]:  在指定的接口产生一个子接口,如vrrp.51,该接口的MAC地址为组播地址,通过该接口向外发送和接收VRRP包。
vmac_xmit_base:                 通过基本接口向外发送和接收VRRP数据包,而不是通过VMAC接口。
native_ipv6:                    强制VRRP实例使用IPV6.(当同时配置了IPV4和IPV6的时候)
dont_track_primary:             忽略VRRP接口的错误,默认是没有配置的。

# 如果track的接口有任何一个出现故障,都会进入FAULT状态。
track_interface {
  eth0
  eth1 weight <-254-254>
  ...
}

# 添加一个track脚本(vrrp_script配置的脚本。)
track_script {
  <SCRIPT_NAME>
  <SCRIPT_NAME> weight <-254-254>
}

mcast_src_ip <IPADDR>:            指定发送组播数据包的源IP地址。默认是绑定VRRP实例的接口的主IP地址。
unicast_src_ip <IPADDR>:      指定发送单薄数据包的源IP地址。默认是绑定VRRP实例的接口的主IP地址。
version 2|3:                    指定该实例所使用的VRRP版本。

# 采用单播的方式发送VRRP通告,指定单播邻居的IP地址。
unicast_peer {
   <IPADDR>
   ...
}

virtual_router_id 51:           指定VRRP实例ID,范围是0-255.
priority 100:                   指定优先级,优先级高的将成为MASTER。
advert_int 1:                   指定发送VRRP通告的间隔。单位是秒。
authentication {
  auth_type PASS|AH:            指定认证方式。PASS简单密码认证(推荐),AH:IPSEC认证(不推荐)。
  auth_pass 1234:               指定认证所使用的密码。最多8位。
}

# 指定VIP地址。
virtual_ipaddress {
   <IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
   192.168.200.17/24 dev eth1
   192.168.200.18/24 dev eth2 label eth2:1
}

nopreempt:      设置为不抢占。默认是抢占的,当高优先级的机器恢复后,会抢占低优先级的机器成为MASTER。
                而不抢占,则允许低优先级的机器继续成为MASTER,即使高优先级的机器已经上线。
                如果要使用这个功能,则初始化状态必须为BACKUP。

preempt_delay:  设置抢占延迟。单位是秒,范围是0---1000,默认是0.发现低优先级的MASTER后多少秒开始抢占。

通知脚本:
notify_master <STRING>|<QUOTED-STRING> [username [groupname]]
notify_backup <STRING>|<QUOTED-STRING> [username [groupname]]
notify_fault <STRING>|<QUOTED-STRING> [username [groupname]]
notify <STRING>|<QUOTED-STRING> [username [groupname]]

# 当停止VRRP时执行的脚本。
notify_stop <STRING>|<QUOTED-STRING> [username [groupname]]
smtp_alert

vrrp_sync_group

# 作用:将所有相关的VRRP实例定义在一起,作为一个VRRP Group,如果组内的任意一个实例出现问题,都可以实现Failover。
 vrrp_sync_group VG_1 {
    group {
     inside_network     # vrrp instance name
     outside_network    # vrrp instance name
     ...
    }
    ...
}

# 注意:脚本文件要加上x权限,同时指令最好写绝对路径。
# 说明:如果username和groupname没有指定,则以默认的script_user所指定的用户和组。

# 作用:当成为MASTER时,以指定的用户和组执行脚本。
1. notify_master /path/to_master.sh [username [groupname]]

# 作用:当成为BACKUP时,以指定的用户和组执行脚本。
2. notify_backup /path/to_backup.sh [username [groupname]]

# 作用:当该同步组Fault时,以指定的用户和组执行脚本。
3. notify_fault "/path/fault.sh VG_1" [username [groupname]]

# 作用:在任何状态都会以指定的用户和组执行脚本。
# 说明:该脚本会在notify_*脚本后执行。
4. notify /path/notify.sh [username [groupname]]
    notify 可以使用3个参数,如下:
    $1:可以是GROUP或INTANCE,表明后面是组还是实例。
    $2:组名或实例名。
    $3:转换后的目标状态。有:MASTER、BACKUP、FAULT。

5. smtp_alert:          当状态发生改变时,发送邮件。
6. global_tracking:     所有的VRRP实例共享相同的tracking配置。

10.5.3、LVS 配置

LVS模块结构:

virtual_server{
    … ...
    real_server{
        … ...
    }
}

virtual_server

virtual_server IP Port | virtual_server fwmark int | virtual_server group string {
  delay_loop <INT>:                   健康检查的时间间隔。
  lb_argo rr|wrr|lc|wlc|lblc|sh|dh: LVS调度算法。
  lb_kind NAT|DR|TUN:               LVS模式。
  persistence_timeout 360:          持久化超时时间,单位是秒。默认是6分钟。
  persistence_granularity:          持久化连接的颗粒度。
  protocol TCP|UDP|SCTP:            4层协议。
  ha_suspend:                       如果virtual server的IP地址没有设置,则不进行后端服务器的健康检查。
  virtualhost <STRING>:               为HTTP_GET和SSL_GET执行要检查的虚拟主机。如virtualhost www.felix.com
  sorry_server <IPADDR> <PORT>:     添加一个备用服务器。当所有的RS都故障时。
  sorry_server_inhibit:             将inhibit_on_failure指令应用于sorry_server指令。

  alpha:                            在keepalived启动时,假设所有的RS都是down,以及健康检查是失败的。
                                    有助于防止启动时的误报。默认是禁用的。

  omega:                            在keepalived终止时,会执行quorum_down指令所定义的脚本。

  quorum <INT>:                       默认值1. 所有的存活的服务器的总的最小权重。
  quorum_up <STRING>:             当quorum增长到满足quorum所定义的值时,执行该脚本。
  quorum_down <STRING>:               当quorum减少到不满足quorum所定义的值时,执行该脚本。
}

real_server

real_server IP Port {
  weight <INT>:           给服务器指定权重。默认是1.
  inhibit_on_failure:   当服务器健康检查失败时,将其weight设置为0,而不是从Virtual Server中移除。
  notify_up <STRING>: 当服务器健康检查成功时,执行的脚本。
  notify_down <STRING>:   当服务器健康检查失败时,执行的脚本。
  uthreshold <INT>:       到这台服务器的最大连接数。
  lthreshold <INT>:       到这台服务器的最小连接数。
}

real_server 监控检查

HTTP_GET | SSL_GET {
url {
  path <STRING>:          指定要检查的URL的路径。如path / or path /mrtg2
  digest <STRING>:            摘要。计算方式:genhash -s 172.17.100.1 -p 80 -u /index.html
  status_code <INT>:      状态码。
}
nb_get_retry <INT>:           get尝试次数。
delay_before_retry <INT>: 在尝试之前延迟多长时间。

connect_ip <IP ADDRESS>:  连接的IP地址。默认是real server的ip地址。
connect_port <PORT>:      连接的端口。默认是real server的端口。
bindto <IP ADDRESS>:      发起连接的接口的地址。
bind_port <PORT>:         发起连接的源端口。
connect_timeout <INT>:        连接超时时间。默认是5s。
fwmark <INTEGER>:         使用fwmark对所有出去的检查数据包进行标记。
warmup <INT>:             指定一个随机延迟,最大为N秒。可防止网络阻塞。如果为0,则关闭该功能。
} 

TCP_CHECK {
connect_ip <IP ADDRESS>:  连接的IP地址。默认是real server的ip地址。
connect_port <PORT>:      连接的端口。默认是real server的端口。
bindto <IP ADDRESS>:      发起连接的接口的地址。
bind_port <PORT>:         发起连接的源端口。
connect_timeout <INT>:        连接超时时间。默认是5s。
fwmark <INTEGER>:         使用fwmark对所有出去的检查数据包进行标记。
warmup <INT>:             指定一个随机延迟,最大为N秒。可防止网络阻塞。如果为0,则关闭该功能。
retry <INIT>:             重试次数。默认是1次。
delay_before_retry <INT>: 默认是1秒。在重试之前延迟多少秒。
}

SMTP_CHECK {
connect_ip <IP ADDRESS>:  连接的IP地址。默认是real server的ip地址。
connect_port <PORT>:      连接的端口。默认是real server的端口。 默认是25端口
bindto <IP ADDRESS>:      发起连接的接口的地址。
bind_port <PORT>:         发起连接的源端口。
connect_timeout <INT>:        连接超时时间。默认是5s。
fwmark <INTEGER>:         使用fwmark对所有出去的检查数据包进行标记。
warmup <INT>:             指定一个随机延迟,最大为N秒。可防止网络阻塞。如果为0,则关闭该功能。

retry <INT>:              重试次数。
delay_before_retry <INT>: 在重试之前延迟多少秒。
helo_name <STRING>:           用于SMTP HELO请求的字符串。
}

DNS_CHECK {
connect_ip <IP ADDRESS>:  连接的IP地址。默认是real server的ip地址。
connect_port <PORT>:      连接的端口。默认是real server的端口。 默认是25端口
bindto <IP ADDRESS>:      发起连接的接口的地址。
bind_port <PORT>:         发起连接的源端口。
connect_timeout <INT>:        连接超时时间。默认是5s。
fwmark <INTEGER>:         使用fwmark对所有出去的检查数据包进行标记。
warmup <INT>:             指定一个随机延迟,最大为N秒。可防止网络阻塞。如果为0,则关闭该功能。

retry <INT>:              重试次数。默认是3次。
type <STRING>:                DNS query type。A/NS/CNAME/SOA/MX/TXT/AAAA
name <STRING>:                DNS查询的域名。默认是(.)
}

MISC_CHECK {
 misc_path <STRING>:      外部的脚本或程序路径。
 misc_timeout <INT>:      脚本执行超时时间。
 user USERNAME [GROUPNAME]: 指定运行该脚本的用户和组。如果没有指定GROUPNAME,则GROUPNAME同USERNAME。
 misc_dynamic:              根据退出状态码动态调整权重。
                                0,健康检查成功,权重不变。
                                1,健康检查失败。
                                2-255,健康检查成功。权重设置为退出状态码减去2.如退出状态码是250,则权重调整为248
   warmup <INT>:          指定一个随机延迟,最大为N秒。可防止网络阻塞。如果为0,则关闭该功能。
}

10.5.4、示例

网上抄的示例,仅供参考:

! Configuration File for keepalived
global_defs {                                     # 全局定义部分
    notification_email {                          # 设置报警邮件地址,可设置多个
        acassen@firewall.loc                      # 接收通知的邮件地址
    }                        
    notification_email_from test0@163.com         # 设置 发送邮件通知的地址
    smtp_server smtp.163.com                      # 设置 smtp server 地址,可是ip或域名.可选端口号(默认25)
    smtp_connect_timeout 30                       # 设置 连接 smtp server的超时时间
    router_id LVS_DEVEL                           # 主机标识,用于邮件通知
    vrrp_skip_check_adv_addr                   
    vrrp_strict                                   # 严格执行VRRP协议规范,此模式不支持节点单播
    vrrp_garp_interval 0                       
    vrrp_gna_interval 0     
    script_user keepalived_script                 # 指定运行脚本的用户名和组。默认使用用户的默认组。
                                                  # 如未指定,默认为keepalived_script 用户,如无此用户,则使用root
    enable_script_security                        # 如过路径为非root可写,不要配置脚本为root用户执行。
}       

vrrp_script chk_nginx_service {                   # VRRP 脚本声明
    script "/etc/keepalived/chk_nginx.sh"         # 周期性执行的脚本
    interval 3                                    # 运行脚本的间隔时间,秒
    weight -20                                    # 权重,priority值减去此值要小于备服务的priority值
    fall 3                                        # 检测几次失败才为失败,整数
    rise 2                                        # 检测几次状态为正常的,才确认正常,整数
    user keepalived_script                        # 执行脚本的用户或组
}                                             

vrrp_instance VI_1 {                              # vrrp 实例部分定义,VI_1自定义名称
    state MASTER                                  # 指定 keepalived 的角色,必须大写 可选值:MASTER|BACKUP
    interface ens33                               # 网卡设置,lvs需要绑定在网卡上,realserver绑定在回环口。
                                                  # 区别:lvs对访问为外,realserver为内不易暴露本机信息

    virtual_router_id 51                          # 虚拟路由标识,是一个数字,同一个vrrp 实例使用唯一的标识,
                                                  # MASTER和BACKUP 的同一个 vrrp_instance 下 这个标识必须保持一致

    priority 100                                  # 定义优先级,数字越大,优先级越高。
    advert_int 1                                  # 设定 MASTER 与 BACKUP 负载均衡之间同步检查的时间间隔,单位为秒,两个节点设置必须一样
    authentication {                              # 设置验证类型和密码,两个节点必须一致
        auth_type PASS                        
        auth_pass 1111                        
    }                                         
    virtual_ipaddress {                           # 设置虚拟IP地址,可以设置多个虚拟IP地址,每行一个
        192.168.119.130                       
    }
    track_script {                                # 脚本监控状态
        chk_nginx_service                         # 可加权重,但会覆盖声明的脚本权重值。chk_nginx_service weight -20
    }
        notify_master "/etc/keepalived/start_haproxy.sh start"  # 当前节点成为master时,通知脚本执行任务
        notify_backup "/etc/keepalived/start_haproxy.sh stop"   # 当前节点成为backup时,通知脚本执行任务
        notify_fault  "/etc/keepalived/start_haproxy.sh stop"   # 当当前节点出现故障,执行的任务; 
}                                             

virtual_server 192.168.119.130 80  {          # 定义RealServer对应的VIP及服务端口,IP和端口之间用空格隔开
    delay_loop 6                              # 每隔6秒查询realserver状态
    lb_algo rr                                # 后端调试算法(load balancing algorithm)
    lb_kind DR                                # LVS调度类型NAT/DR/TUN
    # persistence_timeout 60                  # 同一IP的连接60秒内被分配到同一台realserver
    protocol TCP                              # 用TCP协议检查realserver状态
    real_server 192.168.119.120 80 {          
        weight 1                              # 权重,最大越高,lvs就越优先访问
        TCP_CHECK {                           # keepalived的健康检查方式HTTP_GET | SSL_GET | TCP_CHECK | SMTP_CHECK | MISC
            connect_timeout 10                # 10秒无响应超时
            retry 3                           # 重连次数3次
            delay_before_retry 3              # 重连间隔时间
            connect_port 80                   # 健康检查realserver的端口
        }                                     
    }                                         
    real_server 192.168.119.121 80 {          
        weight 1                              # 权重,最大越高,lvs就越优先访问
        TCP_CHECK {                           # keepalived的健康检查方式HTTP_GET | SSL_GET | TCP_CHECK | SMTP_CHECK | MISC
            connect_timeout 10                # 10秒无响应超时
            retry 3                           # 重连次数3次
            delay_before_retry 3              # 重连间隔时间
            connect_port 80                   # 健康检查realserver的端口
        }                                     
    }                                         
}

10.6、综合生产实例

实验环境如下拓扑,一张图胜过千言万语:

keepalived_lvs

这张图是我生产环境的架构设计,我当时建设的是云平台环境,比这个要复杂得多,每个环节都使用高可用部署,可供生产借鉴。

下面我们要实现的是 keepalived 双主多实例高可用模型,也就是两个 Director 互为主备;另外 VIP(192.168.122.9) 对应 172.16.4.203/204 这两个主机,VIP(192.168.122.10) 对应 172.16.4.205/206 这两个主机。

两台 Directors 配置:

# director1 上的 keepalived 配置                   |# director2 上的 keepalived 配置
! Configuration File for keepalived                |! Configuration File for keepalived
                                                   |
global_defs {                                      |global_defs {
   router_id LVS_1                                 |   router_id LVS_2           
}                                                  |}
                                                   |
vrrp_instance VI_1 {                               |vrrp_instance VI_1 {         
    state MASTER                                   |    state BACKUP             
    interface eth0                                 |    interface eth0
    virtual_router_id 51                           |    virtual_router_id 51     
    priority 100                                   |    priority 50              
    advert_int 1                                   |    advert_int 1
    authentication {                               |    authentication {
        auth_type PASS                             |        auth_type PASS       
        auth_pass 12345678                         |        auth_pass 12345678   
    }                                              |    }
    virtual_ipaddress {                            |    virtual_ipaddress {
        192.168.122.9/32 dev eth0 label eth0:0     |        192.168.122.9/32 dev eth0 label eth0:0
    }                                              |    }
}                                                  |}
# 不同vrrp实例绑定在同一接口上,vrid必须不能相同    |# 不同vrrp实例绑定在同一接口上,vrid必须不能相同
vrrp_instance VI_2 {                               |vrrp_instance VI_2 {         
    state BACKUP                                   |    state MASTER             
    interface eth0                                 |    interface eth0
    virtual_router_id 55                           |    virtual_router_id 55     
    priority 50                                    |    priority 100              
    advert_int 1                                   |    advert_int 1
    authentication {                               |    authentication {
        auth_type PASS                             |        auth_type PASS       
        auth_pass 12345678                         |        auth_pass 12345678   
    }                                              |    }
    virtual_ipaddress {                            |    virtual_ipaddress {
        192.168.122.10/32 dev eth0 label eth0:1    |        192.168.122.10/32 dev eth0 label eth0:1
    }                                              |    }
}                                                  |}

#########################################################################################
# 以下是两台 Director 上相同部分的内容
virtual_server 192.168.122.9 80 {
        delay_loop 6
        lb_algo wrr
        lb_kind DR
        protocol TCP

        real_server 172.16.4.203 80 {
                weight 2
                TCP_CHECK {
                        connect_port 80
                        connect_timeout 1
                        nb_get_retry 2
                        delay_before_retry 1
                }
        }

        real_server 172.16.4.204 80 {
                weight 1
                TCP_CHECK {
                        connect_port 80
                        connect_timeout 1
                        nb_get_retry 2
                        delay_before_retry 1
                }
        }
}

virtual_server 192.168.122.10 80 {
        delay_loop 6
        lb_algo wrr
        lb_kind DR
        protocol TCP

        real_server 172.16.4.205 80 {
                weight 2
                TCP_CHECK {
                        connect_port 80
                        connect_timeout 1
                        nb_get_retry 2
                        delay_before_retry 1
                }
        }

        real_server 172.16.4.206 80 {
                weight 1
                TCP_CHECK {
                        connect_port 80
                        connect_timeout 1
                        nb_get_retry 2
                        delay_before_retry 1
                }
        }
}

四台 RealServers 的配置:

# 1.提供web服务和测试页面
yum -y install httpd
echo "VIP(192.168.122.9): This is page from RS1:172.16.4.203" > /var/www/html/index.html   # 在RS1上操作
echo "VIP(192.168.122.9): This is page from RS2:172.16.4.204" > /var/www/html/index.html   # 在RS2上操作
echo "VIP(192.168.122.10): This is page from RS3:172.16.4.205" > /var/www/html/index.html      # 在RS3上操作
echo "VIP(192.168.122.10): This is page from RS4:172.16.4.206" > /var/www/html/index.html      # 在RS4上操作
service httpd start

# 2.设置arp参数
echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce

# 3.设置VIP
# RS1和RS2设置
ifconfig lo:0 192.168.122.9 netmask 255.255.255.255 up
route add -host 192.168.122.9 dev lo:0
# RS3和RS4设置
ifconfig lo:0 192.168.122.10 netmask 255.255.255.255 up
route add -host 192.168.122.10 dev lo:0

# 4.一定要注意,网关不能指向director,而是要指向router,我在网络配置文件中写好了,按照上面拓扑去设置

两台 Routers 设置,我实验中用的是一台 linux 主机,生产环境上我会使用两台华为 S6857 进行堆叠,相当于一个 linux 主机。只不过路由器不用设置 rp_filter,但是这里的 linux 主机必须设置,否则无法实现该环境。关于 rp_filter 可以参见 Linux LVS Service

[root@router ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
[root@router ~]# echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter

以上配置完成后,就可以实现拓扑中的环境,下面找一个客户端测试一下:

[root@yidam ~]# curl 192.168.122.9
<h1>VIP(192.168.122.9): This is page from RS1:172.16.4.203</h1>
[root@yidam ~]# curl 192.168.122.9
<h1>VIP(192.168.122.9): This is page from RS2:172.16.4.204</h1>
[root@yidam ~]# curl 192.168.122.9
<h1>VIP(192.168.122.9): This is page from RS1:172.16.4.203</h1>
[root@yidam ~]# curl 192.168.122.10
<h1>VIP(192.168.122.10): This is page from RS3:172.16.4.205</h1>
[root@yidam ~]# curl 192.168.122.10
<h1>VIP(192.168.122.10): This is page from RS3:172.16.4.205</h1>
[root@yidam ~]# curl 192.168.122.10
<h1>VIP(192.168.122.10): This is page from RS4:172.16.4.206</h1>
[root@yidam ~]#
标签云