HA Cluster和KeepAlived

=============================================================================

概述:

 本章我们将介绍Linux Clister中的高可用集群,将主要讲解keepalived如何高可用。

  • HA Cluster想关介绍及提高系统可用性的方法

      ·高可用集群的定义及衡量标准;

      ·提高高可用的方法及实现方案(vrrp实现,ais实现)

  • vrrp协议的原理及工作过程;

  • keepalived的核心组件及工作原理;

  • keepalived的安装配置;

  • 案例一:单主模型配置实现keepalived高可用;

  • 案例二:双主模型配置实现keepalived高可用

==============================================================================

HA Cluster:

 1.介绍

Linux Cluster类型:

LB:Load Balancing,负载均衡集群;

  • 存在SPoF(单点故障)

HA:High Availiablity,高可用集群;

HP:High Performance,高性能集群;

什么是高可用集群(HA)?

  • 高可用集群就是当某一个节点或服务器发生故障时,另一个节点能够自动且立即向外提供服务,即将有故障节点上的资源转移到另一个节点上去,这样另一个节点有了资源既可以向外提供服务。高可用集群是用于单个节点发生故障时,能够自动将资源、服务进行切换,这样可以保证服务一直在线。在这个过程中,对于客户端来说是透明的。

高可用集群的衡量标准

  • 高可用集群一般是通过系统的可靠性(reliability)系统的可维护性(maintainability)来衡量的。

  • 通常用平均无故障时间(MTTF)来衡量系统的可靠性,

  • 平均维护时间(MTTR)来衡量系统的可维护性。

  • 因此,一个高可用集群服务可以这样来定义:HA=MTTF/(MTTF+MTTR)*100%。

一般高可用集群的标准有如下几种:

  • 99%:表示 一年宕机时间不超过4天;

  • 99.9% :表示一年宕机时间不超过10小时;

  • 99.99%: 表示一年宕机时间不超过1小时;

  • 99.999% :表示一年宕机时间不超过6分钟

注意:

  • 99%: %1---> 99.9%, 0.1%(提升了10倍)

 2.提高系统可用性方式,降低MTTR:冗余(redundant)

降低MTTR:冗余(redundant)

active/passive (主/被模型)

  • active(活动节点)--> HEARTBEAT(心跳信息)--> backup(备用节点)

  • 解释:活动节点在固定的周期内,向备用节点发送自己的心跳状态信息,使得备用节点能够获知其健康状态与否;如果在活动节点规定的周期之外备用节点依然没有获得对方的心跳信息,就将其取而代之。

问题:

  • passive node(备用节点)的数量?

  • 资源有哪些,怎样切换?

shared storage:(节点之间可以共享存储)

  • NAS:文件共享服务器(NFS,Samba);

  • SAN:存储区域网络,块级别的共享;

Network partition(网络分区)采取的措施:

隔离设备:

  • node隔离:STONITH (关闭其他节点(Shoot The Other Node In The Head);电源交换机;隔离整个节点)

  • 资源隔离:fence 

quorum:投票机制

  • with quorum: > total/2(拥有法定票数要大于半数)

  • without quorum: <= total/2 (拥有法定票数要小于等于半数)

HA Service:

   例如:nginx service:ip/nginx(高可用服务的资源)

TWO nodes Cluster?

  • 辅助设备:ping node, quorum disk; 

HA Cluster实现方案:

vrrp协议的实现

  • keepalived

ais:完备HA集群;

  • heartbeat

  • corosync

keepalived:

 1.vrrp协议

vrrp协议Virtual Redundant Routing Protocol(虚拟路由冗余协议)

术语:

  • 虚拟路由器:Virtual Router 

  • 虚拟路由器标识:VRID(0-255)

  • 物理路由器:

         master:主设备(一个)

         backup:备用设备(可以多个)

         priority:优先级

  • VIP:Virtual IP (转移的资源)

  • VMAC:Virutal MAC (00-00-5e-00-01-VRID)

通告(主节点-->备用节点):心跳,优先级等;周期性进行通告;

工作方式

  • 抢占式,非抢占式;

安全工作:

  • 认证:无认证、简单字符认证、MD5

工作模式:

  • 主/备:单虚拟路径器;

  • 主/主:主/备(虚拟路径器1),备/主(虚拟路径器2)

VRRP的工作过程为:

    1)虚拟路由器中的路由器根据优先级选举出Master。Master 路由器通过发送免费ARP 报文,将自己的虚拟MAC 地址通知给与它连接的设备或者主机,从而承担报文转发任务;

    2)Master 路由器周期性发送VRRP 报文,以公布其配置信息(优先级等)和工作状况;

    3)如果Master 路由器出现故障,虚拟路由器中的Backup 路由器将根据优先级重新选举新的Master;

    4)虚拟路由器状态切换时,Master 路由器由一台设备切换为另外一台设备,新的Master 路由器只是简单地发送一个携带虚拟路由器的MAC 地址和虚拟IP地址信息的免费ARP 报文,这样就可以更新与它连接的主机或设备中的ARP 相关信息。网络中的主机感知不到Master 路由器已经切换为另外一台设备。

    5)Backup 路由器的优先级高于Master 路由器时,由Backup 路由器的工作方(抢占方式和非抢占方式)决定是否重新选举Master。

由此可见,为了保证Master路由器和Backup路由器能够协调工作,VRRP需要实现以下功能:

  • Master 路由器的选举;

  • Master 路由器状态的通告;

  • 同时,为了提高安全性,VRRP 还提供了认证功能;

 2.keepalived:

vrrp协议的软件实现,原生设计的目的为了高可用ipvs服务:

  • vrrp协议完成地址流动;

  • 为vip地址所在的节点生成ipvs规则(在配置文件中预先定义);

  • 为ipvs集群的各RS做健康状态检测;

  • 基于脚本调用接口通过执行脚本完成脚本中定义的功能,进而影响集群事务;

组件:

核心组件:

  • vrrp stack

  • ipvs wrapper

  • checkers

控制组件:配置文件分析器

IO复用器

内存管理组件

附图:

  keepalived组件及原理

wKiom1gcV-6iNSOXAADF0zPjHNA902.png  

 3.keepalived安装配置

HA Cluster的配置前提:

  • 各节点时间必须同步;ntp, chrony实现

  • 确保iptables及selinux不会成为阻碍;

  • 各节点之间可通过主机名互相通信(对Keepalived并非必须,建议使用/etc/hosts文件实现

  • 各节点之间的root用户可以基于密钥认证的ssh服务完成互相通信;(并非必须)

安装:

  • CentOS 6.4+ 之后的版本直接随光盘发行,所以直接yum安装即可;

程序环境:

  • 配置文件:/etc/keepalived/keepalived.conf

  • 主程序:/usr/sbin/keepalived

  • Unit Filekeepalived.service

配置文件组件部分:

wKioL1gceiWR4fu8AABg3s440Xs654.png


配置虚拟路由器语法:

wKioL1gdZ2iRFaH3AAFkPC4gUeI324.png


   案例一:单主模型配置keepalived实现高可用

1.配置前环境准备

  我这里准备了两台CentOS 7 的虚拟主机,分别作为node1,和node2,因为要做为高可用集群,所以,配置前必须要保证两台主机节点的时间同步,确保iptables的规则允许,关闭selinux;最好各节点能通过主机名并基于密钥认证的ssh服务完成通信。

 这里以node1为例,演示配置前环境准备

 1)首先编辑/etc/hosts文件使各节点能够通过名称解析

wKiom1gccffSWi20AAAb1hxJods600.png

 2)基于ssh服务首先生成密钥对

[root@node1 ~]# ssh-keygen -t rsa -P ''
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
17:b0:35:1e:3b:b3:ed:a2:8d:c5:5d:a0:a9:9c:2f:1c root@node1
The key's randomart p_w_picpath is:
+--[ RSA 2048]----+
|        . +      |
|         = +     |
|        . * .    |
|           O .   |
|        S = . .  |
|       .E= o .   |
|       .+.+ o    |
|        o* .     |
|        o.o      |
+-----------------+

 把生成的秘钥对复制到node2

[root@node1 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@node2
The authenticity of host 'node2 (10.1.249.203)' can't be established.
ECDSA key fingerprint is cb:36:da:6b:15:d6:60:25:a7:28:f1:bf:b3:22:ce:c0.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@node2's password:   # 第一次需要输入密码

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@node2'"
and check to make sure that only the key(s) you wanted were added.

# 连接node2节点,发现可以不需要通过输入密码后就可以连接
[root@node1 ~]# ssh node2  'ifconfig'
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.1.249.203  netmask 255.255.0.0  broadcast 10.1.255.255
        inet6 fe80::20c:29ff:fe2b:b6e7  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:2b:b6:e7  txqueuelen 1000  (Ethernet)
        RX packets 9524  bytes 883990 (863.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 783  bytes 149357 (145.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 140  bytes 11244 (10.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 140  bytes 11244 (10.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

 3)同步时间

[root@node1 ~]# date;ssh node2 'date'
Fri Nov  4 19:43:37 CST 2016
Fri Nov  4 19:43:37 CST 2016
[root@node1 ~]# date;ssh node2 'date'
Fri Nov  4 19:43:44 CST 2016
Fri Nov  4 19:43:44 CST 2016
[root@node1 ~]# date;ssh node2 'date'
Fri Nov  4 19:43:50 CST 2016
Fri Nov  4 19:43:50 CST 2016

 2.安装keepalived,并编辑节点1的配置文件/etc/keepalived/keepalived.conf

如下:

[root@node1 ~]# cd /etc/keepalived/
[root@node1 keepalived]# ls
keepalived.conf
[root@node1 keepalived]# cp keepalived.conf{,.bak} # 首先备份
[root@node1 keepalived]# ls
keepalived.conf  keepalived.conf.bak

[root@node1 keepalived]# vim keepalived.conf  # 编辑配置文件
! Configuration File for keepalived

global_defs {
   notification_email {                          # 邮件接收者
       root@localhost
   }
   notification_email_from keepalived@localhost  # 谁发送的邮件
   smtp_server 127.0.0.1                         # 邮件服务器
   smtp_connect_timeout 30                       # 超时时长
   router_id node1                               # 路由标识
   vrrp_mcast_group4 224.0.100.19                # 添加ipv4 的多播地址,并确保多播功能启用
}

vrrp_instance VI_1 {
    state MASTER
    interface eno16777736
    virtual_router_id 17
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass f7111b2e
    }
    virtual_ipaddress {
        10.1.252.73/16 dev eno16777736   # 要转移的ip地址,掩码,以及要配置在哪个网卡接口之上
    }
}

 节点node1已经编辑好了,节点2和1除了state和priority不同外,其余的都相同,所以这里我把节点1的配置文件复制到node2,然后编辑,如下:

[root@node1 keepalived]# scp keepalived.conf node2:/etc/keepalived/
keepalived.conf  

[root@node2 keepalived]# vim keepalived.conf
! Configuration File for keepalived

global_defs {
   notification_email {
       root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id node1
   vrrp_mcast_group4 224.0.100.19
}

vrrp_instance VI_1 {
    state BACKUP             # 备用节点
    interface eno16777736
    virtual_router_id 17            #  一定不能改变
    priority 98             # 优先级要比主节点低
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass f7111b2e   # 要转移的ip地址和认证方式一定不能修改
    }
    virtual_ipaddress {
        10.1.252.73/16 dev eno16777736   # 要转移的ip地址,掩码,以及要配置在哪个接口之上
    }
}

注意:

  节点1和节点2就是为了转移同一个资源(ip地址)的,所以ip和认证方式两个节点一定要相同,不同的是两节点的状态和优先级。

3.如上,两个节点就已经配置好了,接下来我们进行测试,验证ip在主备节点上的转移。

 1)首先启动节点1的keepalived,查看日志文件,可以看到node1现在为主节点(master),并且发通告,要使用转移的10.1.252.73地址,如下:

wKiom1gdWUWTsjJyAABsQ4LAMbw714.png 

 然后查看node1,发现已经在使用转移的ip地址

[root@node1 ~]# ip a l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    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: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:d7:41:ed brd ff:ff:ff:ff:ff:ff
    inet 10.1.252.161/16 brd 10.1.255.255 scope global dynamic eno16777736
       valid_lft 79252sec preferred_lft 79252sec
    inet 10.1.252.73/16 scope global secondary eno16777736   # 要转移的ip
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fed7:41ed/64 scope link

 2)然后我们启动备用节点node2,查看日志发现,只有读取配置文件,并没有其他多余的信息,如下:

wKiom1gdWqmzIonyAABPivBmMLY500.png

 3)现在我们让主节点node1,出现故障(关闭服务),再来观察发现主备节点,发现ip地址由主节点转移到了备用节点node2上,如下:

  主节点node1状态日志如下:

wKiom1gdXDKyddUtAABRtE0aDXU897.png

  备用节点node2,如下

wKioL1gdXHjSbIEFAABu4G1rl_w386.png 

 备用节点ip如下:

[root@node2 ~]# ip a l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    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: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:2b:b6:e7 brd ff:ff:ff:ff:ff:ff
    inet 10.1.249.203/16 brd 10.1.255.255 scope global dynamic eno16777736
       valid_lft 78392sec preferred_lft 78392sec
    inet 10.1.252.73/16 scope global secondary eno16777736  # 转移的ip
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe2b:b6e7/64 scope link 
       valid_lft forever preferred_lft forever

 4)因为默认keepalived工作在抢占模式下,所以,我们现在再启动节点1(node1),发现node2发现更高优先级的广播,又转为备用节点,node1又成为主节点,负责转移IP地址。

  node2 日志状态

wKiom1gdXgmB1j36AAAxXSViOKg379.png


 如上,即为单主虚拟路由器配置实现keepalived高可用的过程,总结配置示例,如下:

wKioL1gdZgLQmXf4AAEE85ABFBA883.png

============================================================================


实验二:双主模型配置keepalived实现高可用

1.直接编辑节点node1的配置文件,再添加一个虚拟路由器,如下:

[root@node1 ~]# cat  /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   notification_email {
       root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id node1
   vrrp_mcast_group4 224.0.100.19
}

vrrp_instance VI_1 {
    state MASTER
    interface eno16777736
    virtual_router_id 17
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass f7111b2e
    }
    virtual_ipaddress {
        10.1.252.73/16 dev eno16777736 
    }
}
vrrp_instance VI_2 {         # 虚拟路由名称为VI_2
    state BACKUP             # 为第二个虚拟路由的备用节点
    interface eno16777736    # 仍然绑定在同一物理网卡上
    virtual_router_id 18     # 路由id号一定不能和上面的相同
    priority 98              # 因为是作为备用节点,所以优先级要低
    advert_int 1
    authentication {
        auth_type PASS       # 认证不要和上面的相同
        auth_pass f8101b2e
    }
    virtual_ipaddress {
        10.1.252.79/16 dev eno16777736   # 另外一个要转移的ip 
    }
}

2.节点2同样也在原有的基础上添加为一个主节点,除了修改优先级和state,其余的和node1的第二个虚拟路由相同,如下:

[root@node2 ~]# cat  /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   notification_email {
       root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id node1
   vrrp_mcast_group4 224.0.100.19
}

vrrp_instance VI_1 {
    state BACKUP
    interface eno16777736
    virtual_router_id 17
    priority 98
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass f7111b2e
    }
    virtual_ipaddress {
        10.1.252.73/16 dev eno16777736 
    }
}

vrrp_instance VI_2 {
    state MASTER             # 为第二个虚拟路由的主节点
    interface eno16777736
    virtual_router_id 18
    priority 100             # 因为为主节点,所以优先级要高
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass f8101b2e
    }
    virtual_ipaddress {
        10.1.252.79/16 dev eno16777736 
    }
}

3.测试主/备,备/主

  1)现在启动(没有先后顺序),我这里先启动node2,查看日志发现,两个node2先把作为主节点的虚拟路由2,启动起来,然后把作为备用节点的虚拟路1由启动起来,因为虚拟络1的主节点还没启动,所以,目前为主节点,如下:

wKiom1gdbmjTqlNqAAB-p30k_ik650.png

 查看node2的ip,发现两个转移的ip都在node2的物理网卡上。如下:

wKiom1gdbxDB6IS0AABkw0nL9DM170.png

 2)现在启动node1的keepalived,发现,作为虚拟路由1主节点的node1,因为工作在抢占模式下,所以,把虚拟路由1要转移的ip抢了过来,而虚拟路由2,node1作为备用节点,优先级低于虚拟路由2node2的主节点,所以没有抢占过来

wKioL1gdcJGg7zxRAABYf4TS-wU395.png

  节点node2的日志显示,虚拟路由1的转移ip被移除

wKioL1gdcQDSETOdAAAxcxmZuZ4005.png   node2的ip如下:

wKiom1gdcTvAW9LvAABaxiUlEvg400.png

 3)现在假设node2节点出现故障,发现虚拟路由2的ip由主(master)被转移到了备用节点node1上的备,如下:

wKioL1gdee7Td2f1AACjLLBIy0Y917.png  

 此时,两个转移的ip资源都在node1的物理网卡上

wKiom1gdenDwWPqgAABjuFeZ5WY038.png

如上,即为双主模型配置keepalived实现高可用的方法,配置示例如下:

wKioL1gdfybijIX3AABgkka1BqM540.png


==============================================================================

现在我们编辑通知脚本使其在主备节点发生转换时发送邮件,脚本如下:

[root@node1 ~]# cat /etc/keepalived/notify.sh 
#!/bin/bash
#

contact='root@localhost'

notify() {
         mailsubject="$(hostname) to be $1,vip floating"
	 mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
	 echo "$mailbody" |mail -s "$mailsubject" $contact
}

case $1 in
master)
       notify master
       ;;
backup)
       notify backup
       ;;
fault)
       notify fault
       ;;
*)
       echo "Usage: $(basename $0) {master|backup|fault}"
       exit 1
       ;;
esac

# 并且给脚本一个执行权限,让它可以运行
[root@node1 ~]#chmod +x /etc/keepalived/notify.sh

然后编辑配置文件定义同通知脚本,如下:

[root@node1 keepalived]# cat keepalived.conf
! Configuration File for keepalived

global_defs {
   notification_email {
       root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id node1
   vrrp_mcast_group4 224.0.100.19
}

vrrp_instance VI_1 {
    state MASTER
    interface eno16777736
    virtual_router_id 17
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass f7111b2e
    }
    virtual_ipaddress {
        10.1.252.73/16 dev eno16777736 
    }
    notify_master "/etc/keepalived/notify.sh master"   # 定义的脚本文件
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
}
vrrp_instance VI_2 {
    state BACKUP
    interface eno16777736
    virtual_router_id 18
    priority 98
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass f8101b2e
    }
    virtual_ipaddress {
        10.1.252.79/16 dev eno16777736 
    }
}

 测试,现在同时开启node1和node2的keepalived,查看邮件发现node1收到邮件为mastrt,node2为backup,然后停掉node1的服务,node2受到邮件变为master,如下:

wKioL1gdjbyDq1c4AAA8Wuogu7M242.png


如上,就为定义通知脚本和调用通知脚本实现发送邮件的过程,总结如下:

wKioL1gdjlfAHK2XAAB5O_UqYQM514.png