第 1 章 keepalived 服务说明

1.1 keepalived 是什么?

Keepalived 软件起初是专为 LVS 负载均衡软件设计的,用来管理并监控 LVS 集群系统中各个服务节点的状态,后来又加入了可以实现高可用的 VRRP 功能。因此,Keepalived 除了能够管理 LVS 软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL 等)的高可用解决方案软件。

Keepalived 软件主要是通过 VRRP 协议实现高可用功能的。VRRP 是 Virtual Router RedundancyProtocol(虚拟路由器冗余协议)的缩写,VRRP 出现的目的就是为了解决静态路由单点故障问题的,它能够保证当个别节点宕机时,整个网络可以不间断地运行。

所以,Keepalived 一方面具有配置管理 LVS 的功能,同时还具有对 LVS 下面节点进行健康检查的功能,另一方面也可实现系统网络服务的高可用功能。

keepalived 官网 http://www.keepalived.org

1.2 keepalived 服务的三个重要功能

  • 管理 LVS 负载均衡软件
  • 实现 LVS 集群节点的健康检查中
  • 作为系统网络服务的高可用性(failover)

1.3 Keepalived 高可用故障切换转移原理

Keepalived 的原理主要基于VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)来实现高可用性。在这个协议中,有两台或多台服务器组成一个服务器组,其中一台作为主服务器(Master),其余的作为备份服务器(Backup)。主服务器对外提供服务,并且会定期发送VRRP通告信息给备份服务器。备份服务器在正常情况下不会抢占主服务器的资源,但当检测不到主服务器发送的VRRP通告信息时,备份服务器会接管主服务器的IP资源及服务,以保证业务的连续性。

在Keepalived中,故障切换转移是通过VRRP来实现的。正常情况下,主节点会不断向备节点发送心跳消息,告诉备节点自己还活着。当主节点发生故障时,由于无法发送心跳消息,备节点会检测到这种情况并启动接管程序,接管主节点的IP资源及服务。当主节点恢复后,备节点会释放接管的IP资源及服务,恢复到原来的备用角色。

此外,Keepalived还可以通过配置LVS(Load Balancer Virtual Server,负载均衡器虚拟服务器)的节点IP和相关参数实现对LVS的直接管理。在LVS集群中,如果某个节点服务器发生故障,Keepalived会自动将其从正常转发队列中清除,并将请求调度到其他正常的节点服务器上,以保证用户访问不受影响。当故障节点修复后,Keepalived会将其重新加入到正常转发队列中,恢复正常服务。

那么,什么是 VRRP 呢?

VRRP , 全 称 Virtual Router Redundancy Protocol , 中文名为虚拟路由冗余协议 ,VRRP 的出现就是为了解决静态踣甶的单点故障问题,VRRP 是通过一种竞选机制来将路由的任务交给某台 VRRP 路由器的。

1.4 keepalived 原理

1.4.1keepalived 高可用架构示意图

1.4.2 Keepalived 的工作原理:

Keepalived 高可用对之间是通过 VRRP 通信的,因此,我们从 VRRP 开始了解起:

  1. VRRP, 全称 Virtual Router Redundancy Protocol, 中文名为虚拟路由冗余协议,VRRP 的出现是为了解决静态路由的单点故障。
  2. VRRP 是通过一种竟选协议机制来将路由任务交给某台 VRRP 路由器的。
  3. VRRP 用 IP 多播的方式(默认多播地址(224.0_0.18)) 实现高可用对之间通信。
  4. 工作时主节点发包,备节点接包,当备节点接收不到主节点发的数据包的时候,就启动接管程序接管主节点的开源。备节点可以有多个,通过优先级竞选,但一般 Keepalived 系统运维工作中都是一对。
  5. VRRP 使用了加密协议加密数据,但 Keepalived 官方目前还是推荐用明文的方式配置认证类型和密码。

介绍完 VRRP, 接下来我再介绍一下 Keepalived 服务的工作原理:

Keepalived 高可用对之间是通过 VRRP 进行通信的, VRRP 是通过竞选机制来确定主备的,主的优先级高于备,因此,工作时主会优先获得所有的资源,备节点处于等待状态,当主挂了的时候,备节点就会接管主节点的资源,然后顶替主节点对外提供服务。

在 Keepalived 服务对之间,只有作为主的服务器会一直发送 VRRP 广播包, 告诉备它还活着,此时备不会枪占主,当主不可用时,即备监听不到主发送的广播包时,就会启动相关服务接管资源,保证业务的连续性. 接管速度最快可以小于 1 秒。

1.4.3 虚拟IP—VIP

kekepalived的工作原理中,提到了一个很重要的概念,虚拟ip——vip。

如果你已经理解了前面所讲的VRRP虚拟路由,那么虚拟ip对你来说就很简单了,因为虚拟ip和VRRP虚拟路由其实是一个道理,前面的VRRP虚拟路由都是铺垫,对于学过NA的同学来说,VRRP虚拟路由和虚拟ip不难理解,所以不要嫌我啰嗦,这里照顾一下网络不是特别好的同学,我们慢慢来解释虚拟ip是个什么东西。

一般我们使用的电脑都有一个网卡,在网卡上绑定一个ip地址就可以开始上网了,那么大家有没有想过一个问题:网卡可以绑定多个ip吗?答案是一个网卡是可以绑定多个ip地址的,只是一般来说我们只绑定一个ip而已。

虚拟ip跟VRRP虚拟路由器也是类似的,虚拟出来的,一个逻辑上的ip地址,也是由多个机器的真实有效的ip“绑定”组合而成的一个虚拟ip,但是访问虚拟ip跟访问真实ip的效果是一样的。

来看一个例子:

假设我们通过服务器上运行的keepalived软件根据真实ip绑定了一个192.168.1.2的vip,然后client1通过真实ip访问服务器是可以成功的,同理,client2通过vip去访问服务器同样可以成功,其实本质上client2还是访问的真实ip,vip只是一个虚拟出来的假象而已。所以叫虚拟ip,即virtual ip,简称vip。

注意,在虚拟vip的时候,最好虚拟同一个网段下的ip,这样方便管理,例如:
假设在这个局域网下有三台机器:两台nginx服务器,一台tomcat服务器
nginx主机ip为:192.168.1.21
nginx备机ip为:192.168.1.22
tomcat服务器ip为:192.168.1.23

主机和备机的ip前三部分都相同,说明它们是处于同一网段下的,因此在虚拟vip时,前三部分要相同,最后一部分则不能跟同一局域网下的任一主机的ip冲突,也就是说虚拟ip的最后一部分不能是21,22,23,因为这些已经被其他机器占用了。那么虚拟的vip可以是:192.168.1.24或192.168.1.25,只要保持ip的最后一部分不相同就行。

第 2 章 keepalived 软件使用

2.1 软件的部署

2.1.1 第一个里程碑 keepalived 软件安装

yum install keepalived -y

/etc/keepalived
/etc/keepalived/keepalived.conf     #keepalived服务主配置文件
/etc/rc.d/init.d/keepalived         #服务启动脚本
/etc/sysconfig/keepalived
/usr/bin/genhash
/usr/libexec/keepalived
/usr/sbin/keepalived

第二个里程碑: 进行默认配置测试

2.1.2 配置文件说明

1-13 行表示全局配置

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        #标识当前Keepalived节点。相同局域网唯一,主机名称或者是ip
 }

15-30 行 虚拟 ip 配置 brrp

vrrp_instance VI_1 {   #定义实例
    state MASTER         #指定当前节点为master节点,只能有一个master,其余只能是backup
    interface eth0       #虚IP地址放置的网卡位置
    virtual_router_id 51 #同一个集群id一致。指定虚拟路由id,虚拟路由的唯一标识,范围是0-255,mater和backup节点需要指定一样的,相同id为一组
    priority 100         # 优先级决定是主还是备    越大越优先
    advert_int 1        #主备通讯时间间隔
    authentication {     # ↓
        auth_type PASS    #↓
        auth_pass 1111    #认证
    }                        #↑ 
    virtual_ipaddress {  #↓ vip 虚拟IP列表,可以配置多个
        192.168.200.16    指定虚拟ip,自己定义的虚拟ip
        192.168.200.17
        192.168.200.18
    }
    
    virtual_server{
    
    }
}

配置管理 LVS

关于 LVS 详情参考 http://www.cnblogs.com/clsn/p/7920637.html#_label7

2.1.3 最终配置文件

主负载均衡服务器配置

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

global_defs {
   router_id lb01
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0      # 网卡
    virtual_router_id 51  # 唯一ID
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.3
    }
}

备负载均衡服务器配置

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

global_defs {
   router_id lb02
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
     10.0.0.3
    }
}

2.1.4 启动 keepalived

[root@lb02 ~]# systemctl start keepalived
Starting keepalived:                                       [  OK  ]

2.1.5 【说明】在进行访问测试之前要保证后端的节点都能够单独的访问。

测试连通性.    后端节点

[root@lb01 conf]# curl -H host:www.etiantian.org  10.0.0.8
web01 www
[root@lb01 conf]# curl -H host:www.etiantian.org  10.0.0.7
web02 www
[root@lb01 conf]# curl -H host:www.etiantian.org  10.0.0.9
web03 www
[root@lb01 conf]# curl -H host:bbs.etiantian.org  10.0.0.9
web03 bbs
[root@lb01 conf]# curl -H host:bbs.etiantian.org  10.0.0.8
web01 bbs
[root@lb01 conf]# curl -H host:bbs.etiantian.org  10.0.0.7
web02 bbs

2.1.6 查看虚拟 ip 状态

[root@lb01 conf]# ip a
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:90:7f:0d brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.5/24 brd 10.0.0.255 scope global eth0
    inet 10.0.0.3/24 scope global secondary eth0:1
    inet6 fe80::20c:29ff:fe90:7f0d/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:90:7f:17 brd ff:ff:ff:ff:ff:ff
    inet 172.16.1.5/24 brd 172.16.1.255 scope global eth1
    inet6 fe80::20c:29ff:fe90:7f17/64 scope link 
       valid_lft forever preferred_lft forever

2.1.7 【总结】配置文件修改

Keepalived 主备配置文件区别:

    1. router_id 信息不一致
    1. state 状态描述信息不一致
    1. priority 主备竞选优先级数值不一致

2.2 脑裂

在高可用(HA)系统中,当联系 2 个节点的 “心跳线” 断开时,本来为一整体、动作协调的 HA 系统,就分裂成为 2 个独立的个体。由于相互失去了联系,都以为是对方出了故障。两个节点上的 HA 软件像 “裂脑人” 一样,争抢 “共享资源”、争起“应用服务”,就会发生严重后果——或者共享资源被瓜分、2 边“服务” 都起不来了;或者 2 边 “服务” 都起来了,但同时读写“共享存储”,导致数据损坏(常见如数据库轮询着的联机日志出错)。

对付 HA 系统 “裂脑” 的对策,目前达成共识的的大概有以下几条:

1)添加冗余的心跳线,例如:双线条线(心跳线也 HA),尽量减少 “裂脑” 发生几率;

2)启用磁盘锁。正在服务一方锁住共享磁盘,“裂脑”发生时,让对方完全 “抢不走” 共享磁盘资源。但使用锁磁盘也会有一个不小的问题,如果占用共享盘的一方不主动 “解锁”,另一方就永远得不到共享磁盘。现实中假如服务节点突然死机或崩溃,就不可能执行解锁命令。后备节点也就接管不了共享资源和应用服务。于是有人在 HA 中设计了“智能” 锁。即:正在服务的一方只在发现心跳线全部断开(察觉不到对端)时才启用磁盘锁。平时就不上锁了。

3)设置仲裁机制。例如设置参考 IP(如网关 IP),当心跳线完全断开时,2 个节点都各自 ping 一下参考 IP,不通则表明断点就出在本端。不仅 “心跳”、还兼对外“服务” 的本端网络链路断了,即使启动(或继续)应用服务也没有用了,那就主动放弃竞争,让能够 ping 通参考 IP 的一端去起服务。更保险一些,ping 不通参考 IP 的一方干脆就自我重启,以彻底释放有可能还占用着的那些共享资源。

2.2.1 脑裂产生的原因

一般来说,裂脑的发生,有以下几种原因:

😶 高可用服务器对之间心跳线链路发生故障,导致无法正常通信。

因心跳线坏了(包括断了,老化)。

因网卡及相关驱动坏了,ip 配置及冲突问题(网卡直连)。

因心跳线间连接的设备故障(网卡及交换机)。

因仲裁的机器出问题(采用仲裁的方案)。

😶  高可用服务器上开启了 iptables 防火墙阻挡了心跳消息传输。

😶 高可用服务器上心跳网卡地址等信息配置不正确,导致发送心跳失败。

😶 其他服务配置不当等原因,如心跳方式不同,心跳广插冲突、软件 Bug 等。

提示: Keepalived 配置里同一 VRRP 实例如果 virtual_router_id 两端参数配置不一致也会导致裂脑问题发生。

2.2.2 常见的解决方案

在实际生产环境中,我们可以从以下几个方面来防止裂脑问题的发生:

🎑 同时使用串行电缆和以太网电缆连接,同时用两条心跳线路,这样一条线路坏了,另一个还是好的,依然能传送心跳消息。

🎑 当检测到裂脑时强行关闭一个心跳节点(这个功能需特殊设备支持,如 Stonith、feyce)。相当于备节点接收不到心跳消患,通过单独的线路发送关机命令关闭主节点的电源。

🎑  做好对裂脑的监控报警(如邮件及手机短信等或值班). 在问题发生时人为第一时间介入仲裁,降低损失。例如,百度的监控报警短倍就有上行和下行的区别。报警消息发送到管理员手机上,管理员可以通过手机回复对应数字或简单的字符串操作返回给服务器. 让服务器根据指令自动处理相应故障,这样解决故障的时间更短.

当然,在实施高可用方案时,要根据业务实际需求确定是否能容忍这样的损失。对于一般的网站常规业务. 这个损失是可容忍的。

2.3 如何进行脑裂情况监控

2.3.1 在什么服务器上进行监控?

在备服务器上进行监控,可以使用 zabbix 监控,参考 http://www.cnblogs.com/clsn/p/7885990.html

2.3.2 监控什么信息?

备上面出现 vip 情况:

1)脑裂情况出现

2)正常主备切换也会出现

2.3.3 编写监控脑裂脚本

[root@lb02 scripts]# vim check_keepalived.sh
#!/bin/bash

while true
do
if [ `ip a show eth0 |grep 10.0.0.3|wc -l` -ne 0 ]
then
    echo "keepalived is error!"
else
    echo "keepalived is OK !"
fi
done

编写完脚本后要给脚本赋予执行权限

2.3.4 测试 确保两台负载均衡能够正常负载

[root@lb01 ~]# curl -H Host:www.etiantian.org 10.0.0.5
web01 www
[root@lb01 ~]# curl -H Host:www.etiantian.org 10.0.0.6
web01 www
[root@lb01 ~]# curl -H Host:bbs.etiantian.org 10.0.0.6
web02 bbs
 [root@lb01 ~]# curl -H Host:www.etiantian.org 10.0.0.5
web03 www 

2.4 排错过程

1)利用负载均衡服务器,在服务器上 curl 所有的节点信息(web 服务器配置有问题)

2)curl 负载均衡服务器地址,可以实现负载均衡

3)windows 上绑定虚拟 IP,浏览器上进行测试

keepalived 日志文件位置 /var/log/messages

2.5 更改 nginx 反向代理配置 只监听 vip 地址

修改 nginx 监听参数  listen 10.0.0.3:80;

修改内核参数,实现监听本地不存在的 ip

echo 'net.ipv4.ip_nonlocal_bind = 1' >>/etc/sysctl.conf
sysctl -p

[root@lb02 conf]# cat /proc/sys/net/ipv4/ip_nonlocal_bind
 

2.6 让 keepalived 监控 nginx

ps -ef |grep nginx |grep -v grep |wc -l

编写执行脚本

#!/bin/bash

while true
do
if [ `ps -ef |grep nginx |grep -v grep |wc -l` -lt 2 ]
then
   /etc/init.d/keepalived stop
   exit
fi
done

注意脚本的授权

[root@lb01 scripts]# chmod +x check_www.sh

2.6.1 使用 keepalived 的监控脚本

说明 执行的脚本名称尽量不要和服务名称相同或相似

[root@lb01 scripts]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   router_id lb01
}

vrrp_script check {     #定义脚本
   script "“/server/scripts/check_web.sh"  --- 表示将一个脚本信息赋值给变量check_web
   interval 2    --- 执行监控脚本的间隔时间
   weight 2  ---利用权重值和优先级进行运算,从而降低主服务优先级使之变为备服务器(建议先忽略)
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.3/24 dev eth0 label eth0:1
    }
    track_script {     #调用脚本
       check
    }
}

2.7 多实例的配置

2.7.1 lb01 的 keepalived 配置文件

[root@lb01 scripts]# cat  /etc/keepalived/keepalived.conf 
! Configuration File for keepalived

global_defs {
   router_id lb01
}

vrrp_script check {
   script "/server/scripts/check_www.sh"
   interval 2 
   weight 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.3/24 dev eth0 label eth0:1
    }
    track_script {
       check
    }
}
vrrp_instance VI_2 {
    state BACKUP
    interface eth0
    virtual_router_id 52
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.4/24 dev eth0 label eth0:2
    }
}

2.7.2 修改 lb02 的 keepalived 配置文件

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

global_defs {
   router_id lb02
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
     10.0.0.3 dev eth0 label eth0:1
    }
}
vrrp_instance VI_2 {
    state MASTER
    interface eth0
    virtual_router_id 52
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
     10.0.0.4 dev eth0 label eth0:2
    }
}

修改 nginx 配置文件,让 bbs 与 www 分别监听不同的 ip 地址

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;                           
    upstream server_pools {
      server 10.0.0.7:80;
      server 10.0.0.8:80;
      server 10.0.0.9:80;
    }
    server {
        listen 10.0.0.3:80;
        server_name www.etiantian.org;
        location / {
            proxy_pass http://server_pools;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    } 
    server {
        listen 10.0.0.4:80;
        server_name bbs.etiantian.org;
        location / {
            proxy_pass http://server_pools;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    } 
}

lb01

[root@lb01 scripts]# netstat -lntup |grep nginx
tcp        0      0 10.0.0.3:80                 0.0.0.0:*                   LISTEN      84907/nginx         
tcp        0      0 10.0.0.4:80                 0.0.0.0:*                   LISTEN      84907/nginx

lb02

[root@lb02 conf]# netstat -lntup |grep nginx
tcp        0      0 10.0.0.3:80                 0.0.0.0:*                   LISTEN      12258/nginx         
tcp        0      0 10.0.0.4:80                 0.0.0.0:*                   LISTEN      12258/nginx

2.8 keepalived 双主模式示意图

本文出自 “惨绿少年”,欢迎转载,转载请注明出处!http://blog.nmtui.com

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐