keepalived

keepalived

  • keepalived
  • Keepalived的介绍
  • Keepalived配置
    • 全局配置
    • VRRPD配置
    • LVS配置
    • real_server中的健康检查
  • Keepalived配置示例
    • brain split脑裂
      • vrrp协议
      • keepalived双主模型

keepalived的实现是依据vrrp协议,

Keepalived的介绍

  • LVS的缺点
1. Director的单点。只有一台Director,如果Director出现故障,无法提供服务。
2. Direct将所有的请求根据所指定的算法发送到后端服务器,如果后端服务器出现异常,则客户端的访问出现问题。Director无法提供对后端服务器的健康状态检查。
  • keepalived的体系结构
Keepalived大致分为两层空间:user space和kernel space。

watchdog:负责监控checkers和VRRP Stack进程的状况。
checkers:负责真实服务器的健康检查(health checking),是keepalived最主要的功能。换句话说,可以没有VRRP Stack,但是不能没有Checkers。
VRRP Stack:负责负载均衡器之间的失败切换FailOver,如果只有一个负载均衡器,则VRRP Stack不是必须的。
IPVS Wrappers:用来发送设定的规则(通过ipvsadm设置的规则)到内核ipvs的代码。
Netlink Reflector:用来设定VRRP的VIP等。

Keepalived配置

keepalived 版本为:1.3.2

全局配置

  • 全局配置
global_defs {
   notification_email {
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   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
}


说明:
notification_email:指定当keepalived出现问题时,发送邮件给哪些用户。
notification_emai_from:发送邮件时,邮件的来源地址。
smtp_server <DOMAIN|IP> [<PORT>]:smtp服务器的地址或域名。默认端口为25.如:smtp_server smtp.felix.com 25
smtp_helo_name <HOST_NAME>:指定在HELO消息中所使用的名称。默认为本地主机名。
smtp_connect_timeout:指定smtp服务器连接的超时时间。单位是秒。

router_id:指定标识该机器的route_id. 如:route_id LVS_01
vrrp_mcast_group4 224.0.0.18:指定发送VRRP组播消息使用的IPV4组播地址。默认是224.0.0.18
vrrp_mcast_group6 ff02::12 指定发送VRRP组播消息所使用的IPV6组播地址。默认是ff02::12
default_interface eth0:设置静态地址默认绑定的端口。默认是eth0。
lvs_sync_daemon <INTERFACE> <VRRP_INSTANCE> [id <SYNC_ID>] [maxlen <LEN>] [port <PORT>] [ttl <TTL>] [group <IP ADDR>]
    设置LVS同步服务的相关内容。可以同步LVS的状态信息。
    INTERFACE:指定同步服务绑定的接口。
    VRRP_INSTANCE:指定同步服务绑定的VRRP实例。
    id <SYNC_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 <username> [groupname]:设置运行脚本默认用户和组。如果没有指定,则默认用户为keepalived_script(需要该用户存在),否则为root用户。默认groupname同username。
enable_script_security:如果脚本路径的任一部分对于非root用户来说,都具有可写权限,则不会以root身份运行脚本。
nopreempt 默认是抢占模式 要是用非抢占式的就加上nopreempt
注意:上述为global_defs中的指令
  • 添加静态地址和静态路由
static_ipaddress
        {
        192.168.1.1/24 dev eth0 scope global
        ...
    }
    格式为:/ brd  dev  scope 

static_routes
        {
        192.168.2.0/24 via 192.168.1.100 dev eth0
        ...
    }

说明:
1. 使用该方式添加的静态地址、静态路由、静态规则,不会被VRRPD移除(不会飘来飘去),而是待在该机器上,除非keepaived停止。
2. 如果没有指定dev,则使用default_interface配置的接口,默认为eth0。

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  {
          ...
    }

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

解释:
weight: 
1. 如果脚本执行成功(退出状态码为0),weight大于0,则priority增加。
2. 如果脚本执行失败(退出状态码为非0),weight小于0,则priority减少。
3. 其他情况下,priority不变。
  • vrrp_sync_group
作用:将所有相关的VRRP实例定义在一起,作为一个VRRP Group,如果组内的任意一个实例出现问题,都可以实现Failover。
 vrrp_sync_group VG_1 {
    group {
     inside_network     # vrrp instance name
     outside_network    # vrrp instance name
     ...
    }
    ...
}

说明:
如果username和groupname没有指定,则以默认的script_user所指定的用户和组。
1. notify_master /path/to_master.sh [username [groupname]]
    作用:当成为MASTER时,以指定的用户和组执行脚本。
2. notify_backup /path/to_backup.sh [username [groupname]]
    作用:当成为BACKUP时,以指定的用户和组执行脚本。
3. notify_fault "/path/fault.sh VG_1" [username [groupname]]
    作用:当该同步组Fault时,以指定的用户和组执行脚本。
4. notify /path/notify.sh [username [groupname]]
    作用:在任何状态都会以指定的用户和组执行脚本。
    说明:该脚本会在notify_*脚本后执行。
    notify可以使用3个参数,如下:
    $1:可以是GROUP或INTANCE,表明后面是组还是实例。
    $2:组名或实例名。
    $3:转换后的目标状态。有:MASTER、BACKUP、FAULT。

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

注意:脚本文件要加上x权限,同时指令最好写绝对路径。
  • 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_interface {
  eth0
  eth1 weight <-254-254>
  ...
}:如果track的接口有任何一个出现故障,都会进入FAULT状态。

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

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

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

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位。
}

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
}:指定VIP地址。

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

LVS配置

  • 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  :添加一个备用服务器。当所有的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 or SSL_GET
 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
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
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
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_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,则关闭该功能。
}

Keepalived配置示例

[root@vm05 keepalived]# more keepalived.conf
! Configuration File for keepalived

global_defs {
   router_id LVS_PROD

   lvs_flush
   vrrp_garp_master_repeat 2
   vrrp_garp_master_delay 3
   vrrp_garp_interval 0.005

   vrrp_strict true

   lvs_sync_daemon eth0 LVS_APP_01 id 1
   vrrp_iptables

   vrrp_gna_interval 0
}

vrrp_instance LVS_APP_01 {
    state BACKUP
    interface eth0
    dont_track_primary
    virtual_router_id 1
    priority 100
    nopreempt
    advert_int 1
    strict_mode true
    authentication {
        auth_type PASS
        auth_pass felix
    }
    virtual_ipaddress {
        172.17.100.100 broadcast 172.17.100.100 dev eth0 label eth0:1
    }
}

virtual_server 172.17.100.100 80 {
    delay_loop 3
    lb_algo rr
    lb_kind DR
    persistence_timeout 0
    protocol TCP
    alpha

    real_server 172.17.100.1 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            delay_before_retry 2
        }
    }

    real_server 172.17.100.2 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            delay_before_retry 3
        }
    }

}

脑裂问题

brain split脑裂

当一个集群服务作为一个整体向外服务是可以提供高可用的,但是有时候可能出现故障,比如现有3台节点服务器,刚开始他们能够正常的运行,互相通报自己的心跳信息,确保自己很是正常运行,之后由于网络的问题,出现了网络分区(network partition),其中一个节点还能提供服务,但是向其他节点通报自己心跳信息的时候却ping不同了,其他节点收不到它的心跳信息,以为它挂了,这个时候就会把属于它的ip和mac抢过来(在主备模式下),这个时候这个由问题的节点却不能理解,它以为自己还活着,当自己的ip和mac被抢之后,也会把他重新抢过来,这个时候就发生了资源争夺战,要是发生了同时读写数据的情况,就会破坏数据完整性.

此时客户端就会发生错乱,不能理解,为了避免这样的情况,我们引入一种竞争机制,看脑裂分裂的情况.一个节点算是一票,票数大于总节点一半的那一方network partition就可以把资源抢过来,要是同票的话就引入第三方裁判机制,比如看看路由器是那方,一般来说,构建高可用服务的时候节点一般还是奇数的好,

HA cluster实现方案

  • vrrp协议的实现:keepalived
  • ais完备的HA集群 :heartbeat corosync

vrrp协议

虚拟路由冗余协议

VRRP的工作过程如下:

  1. 路由器开启VRRP功能后,会根据优先级确定自己在备份组中的角色。优先级高的路由器成为主用路由器,优先级低的成为备用路由器。主用路由器定期发送VRRP通告报文,通知备份组内的其他路由器自己工作正常;备用路由器则启动定时器等待通告报文的到来。

  2. VRRP在不同的主用抢占方式下,主用角色的替换方式不同:

    l在抢占方式下,当主用路由器收到VRRP通告报文后,会将自己的优先级与通告报文中的优先级进行比较。如果大于通告报文中的优先级,则成为主用路由器;否则将保持备用状态。

    l在非抢占方式下,只要主用路由器没有出现故障,备份组中的路由器始终保持主用或备用状态,备份组中的路由器即使随后被配置了更高的优先级也不会成为主用路由器。

  3. 如果备用路由器的定时器超时后仍未收到主用路由器发送来的VRRP通告报文,则认为主用路由器已经无法正常工作,此时备用路由器会认为自己是主用路由器,并对外发送VRRP通告报文。备份组内的路由器根据优先级选举出主用路由器,承担报文的转发功能。

在实际组网中一般会进行VRRP负载分担方式的设置。负载分担方式是指多台路由器同时承担业务,避免设备闲置,因此需要建立两个或更多的备份组实现负载分担。VRRP负载分担方式具有以下特点:

  • 每个备份组都包括一个主用路由器和若干个备用路由器。
  • 各备份组的主用路由器可以不相同。
  • 同一台路由器可以加入多个备份组,在不同备份组中有不同的优先级,使得该路由器可以在一个备份组中作为主用路由器,在其他的备份组中作为备用路由器

master:是活动的路由设备,也就是主设备,是ip地址的拥有者

gracious arp:免费报文,当ip地址和虚拟mac地址转移的时候,接收ip地址和mac的路由器会发出一个报文,广播询问谁拥有ip地址和虚拟mac地址,之后在自己回答说自己拥有,自问自答

虚拟mac地址:一个虚拟路由器拥有一个虚拟mac地址,虚拟mac格式地址是00-00-5E-00-01-{VRID},通常情况下,路由器回应arp请求使用的是虚拟mac地址

优先级:vrrp根据优先级来确认每台路由器的地位

非抢占式:如果backup路由器工作在非抢占模式下,则master路由器没有出现故障,即使backup分配到了更高的优先级,也不会抢占属于master的资源

抢占式:backup路由器在发出报文比较优先级的时候,发现自己被master优先级高,就会把属于master的资源抢过来,否则保存backup状态.

工作模式:

主备模式

主主模式:多个主备模式,为的是把空闲的路由器利用起来,比如有3台路由器,则虚拟路由1:master,backup,backup,虚拟路由器2可以配置为,backup,master,backup,虚拟路由器3:backup,backup,master. 如果是多个路由器,则以此类推

组件:

  • 控制组件:配置文件分析器
  • 内存管理
  • IO复用
  • 核心组件:vrrp stack , checker , ipvs wrapper , watch dog

心跳信息是组播来通知

认证机制:

  • 无认证
  • 简单字符认证
  • md5认证

keepalived双主模型

  1. keepalived1,keepalived2,node1,node2

你可能感兴趣的:(Linux)