Keepalived 实现 Nginx 负载均衡的高可用

摘要:keepalived 实现 nginx 负载均衡的高可用,生产环境中我们有必要保证负载均衡的分发服务器的高可用性,如果出现宕机,我们要立刻进行采取补救措施,我们可以利用 keepalived 来帮助我们完成这项任务。

什么是 Keepalived

keepalived 翻译过来就是“保持活力”。主要作用是就是检测服务器的状态,如果有一台 web 服务器宕机或出现故障,keepalived 将检测到,并将故障服务器从系统中剔除,同时使用其它服务器替代该服务器的工作,当服务器工作正常后 keepalived 自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。


Keepalived 实现 Nginx 的负载均衡高可用

nginx 负载均衡的原理就是通过 nginx 的反向代理实现的。就是通过一台服务器做反向代理然后将客户端请求分发到后面的负载均衡服务器。

比如现在有 4 台服务器 a、b、c、d,然后 a 服务器作为分发服务器,然后将请求分发到 b、c、d 三台服务器。但是如果 a 服务器挂掉,那整个负载均衡就瘫了。

其实最简单的方法,我们可以利用 crontab 命令执行一个 shell 脚本来定时检测 nginx 服务,如果发现 nginx 关闭了,就把它重新拉起来,但是假如我们拉了一遍,没有拉起来怎么办?这时候 nginx 负载均衡还是宕机的。我们这时候需要一台或者多台的备用 nginx 分发武器来自动的顶上这个艰巨任务。这时候就 keepalived 就可以帮助我们完成这个任务,不需要人为干预,一切都是自动完成的。

我们可以使用 keepalived 来配置两台,甚至多台分发服务器,比如 a1、a2,a3 等,然后 a1 作为主分发服务器。然后通过 keepalived 来监控这些服务器,如果主分发服务器挂掉后,从分发服务器 a2 顶上继续工作。


Keepalived 工作原理

keepalived 是以 vrrp 协议为实现基础的,vrrp 全称 virtual router redundancy protocol,即虚拟路由冗余协议。

虚拟路由冗余协议可以简单理解为,由 n 台提供相同功能的路由器组成一个路由器组,这组里面有一个 master 和多个 backup 服务器,master 上面有一个对外提供服务的 vip(该路由器所在局域网内其他机器的默认路由为该 vip),master 会发组播,当 backup 收不到 vrrp 包时就认为 master 宕机了,这时就需要根据 vrrp 的优先级来选出一个新的 backup 来当 master。这样的话就可以保证路由器的高可用了。

虚拟路由器组

虚拟路由器是 vrrp 备份组中所有路由器的集合,它是一个逻辑概念,并不是正真存在的。从备份组外面看备份组中的路由器,感觉组中的所有路由器就像一个 一样,可以理解为在一个组中:主路由器 + 所有备份路由器 = 虚拟路由器。

主服务器

我们访问的是虚拟路由器的 ip,而在虚拟路由器内部同时只有一台物理路由器对外提供服务。而在虚拟路由器内部同一时间只有一台物理路由器对外提供服务,这台提供服务的物理路由器被称为主路由器。

备份路由器

虚拟路由器中的其他物理路由器不拥有对外的虚拟 ip,也不对外提供网络功能,仅接受 master 的 vrrp 状态通告信息,这些路由器被称为备份路由器。当主路由器失败时,处于 backup 角色的备份路由器将重新进行选举,产生一个新的主路由器进入 master 角色,继续提供对外服务。


搭建操作演示

1、准备两台负载均衡分发服务器

A 服务器:192.168.23.130(主)

B 服务器:192.168.23.133(备)


2、在两台服务器上分别安装 Keepalived

yum install -y keepalived

配置文件位置

/etc/keepalived/keepalived.conf

日志文件位置

/var/log/messages


3、修改 A 服务器的 keepalived 配置文件

! 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.23.130 # 当前服务器 ip
    smtp_connect_timeout 30
    router_id LVS_DEVEL # 标识机器的字符串,默认是主机名。
}

# 检测 nginx 服务器是否在运行
vrrp_script chk_http_port {
    script "/usr/local/src/nginx_check.sh" # 检测脚本
    interval 2 # 每隔 2 秒检测一次
    weight 2
}

vrrp_instance VI_1 {
    state MASTER # 主机是 MASTER 备机是 BACKUP
    interface eno16777736
    virtual_router_id 51 # 从0到255的任意唯一数字,但是主备机数字必须相同。
    priority 150 # 数字大的为主机,主机要比备机高于50。比如主机:150,备机 100。
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.23.50 # vrrp 虚拟地址,我们在浏览器中访问的就是这个虚拟 ip
    }
   
    track_script {
        chk_http_port
    }
}


4、修改 B 服务器的 keepalived 配置文件

! 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.23.133 # 当前服务器 ip
	smtp_connect_timeout 30
	router_id LVS_DEVEL # 标识机器的字符串,默认是主机名。
}

# 检测 nginx 服务器是否在运行
vrrp_script chk_http_port {
	script "/usr/local/src/nginx_check.sh" # 检测脚本
	interval 2 # 每隔 2 秒检测一次
	weight 2
}

vrrp_instance VI_1 {
    state BACKUP # 主机是 MASTER 备机是 BACKUP
    interface eno16777736
    virtual_router_id 51 # 从0到255的任意唯一数字,但是主备机数字必须相同。
    priority 100 # 数字大的为主机,主机要比备机高于50。比如主机:150,备机 100。
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.23.50 # vrrp 虚拟地址,我们在浏览器中访问的就是这个虚拟 ip
    }
   
    track_script {
		chk_http_port
    }
}

其实主备服务器的配置文件基本上一样,唯一不同的就是要区分出主备机的那几个参数。其他参数详见官方文档:https://www.keepalived.org/manpage.html


5、编写  /usr/local/src/nginx_check.sh  检测脚本,分别放在 A 和 B 服务器中在 A 服务器中

#!/bin/bash
if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then
    /usr/local/nginx/sbin/nginx
    sleep 2
    if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then
        pkill keepalived
    fi
fi

这个脚本的路径就是刚才配置文件中检测脚本的那个路径。

脚本的大致意思就是:检测 nginx 服务是否正在运行,如果没有运行,则尝试重新启动。启动之后,我得确定是否真正的启动了。然后 sleep 2 秒后,查看是否启动成功了。如果启动成功了,就成功了正常运行什么事情都没有发生。如果没有启动成功,直接 kill 掉当前的 keepalived 服务,然后当前组中的其他的从 keepalived 服务就会收到通知,知道大哥挂了,我们根据投票来重新选一个大哥吧。


关于演示

其实演示很简单,我们在浏览器中访问刚才设置的虚拟 ip 地址,然后一切正常访问。

我们先 kill 掉 master 的 nginx 服务,这时候 keepalived 会检测到 nginx 服务挂掉了,然后立刻把 nginx 服务器拉起来,一切正常。那个脚本的任务其实就是看能不能拉起来 nginx 服务,如果拉不起来就同 kill 掉 keepalived 服务,来通知组中其它路由,让他们接班。

与其这样,我们不如直接把 keepalived 干掉,然后来测试是否虚拟 ip 漂移到从服务上。演示之前我们应该先通过浏览器访问下虚拟 ip 地址,显示一切正常,然后打开 nginx 的 access.log 日志文件,利用 tail -f 命令确认下我们访问的是否 master 上的 nginx 服务。确认无误后,我们直接把 master 上的 keepalived 服务干掉,然后再次访问浏览器中的虚拟 ip 地址,如果没有问题,现在也是可以正常访问的,证明 backup 已经接班了。最后再利用 tail -f 命令确认下,现在访问日志已经全部输出在了 B 服务器上的 access.log 日志中,A 服务器的 access.log 已经停止输出了。

如果我们把 A 服务器的 keepalived 重新拉起来,这时候就会发现访问请求又重新回到了 A 服务器上。证明,如果 master 的 keepalived 服务挂掉重启后,会再次把主动权要回来。

以上的配置和演示只是针对一台 master 和一台 backup 服务器,如果是多台的话,就按照以上配置 backup 服务的形式再多配置几台就可以了,只不过 master 挂掉后会根据一定的选举机制重新从多台中选择一台新的出来。


参考:

keepalived工作原理和配置说明

Keepalived原理与实战精讲

nginx+keepalived实现双机热备的高可用

结束语:感谢您对本网站文章的浏览,欢迎您的分享和转载,但转载请说明文章出处。
Top