高可用集群-keepalived
高可用集群
高可用集群简介
高可用的概念
高可用集群( High Availability Cluster, HA 集群),其中高可用的含义是最大限度地可以使用。从集群的名字上可以看出,此类集群实现的功能是保障用户的应用程序持久、不间断地提供服务。
当应用程序出现故障或者系统硬件、网络出现故障时,应用可以自动、快速从一个节点切换到另一个节点,从而保证应用持续、不间断地对外提供服务,这就是高可用集群实现的功能 .
常见的HA 集群
我们常说的双机热备、双机互备、多机互备等都属于高可用集群的范畴,这类集群一般都由两个或两个以上节点组成。典型的双机热备结构如下图所示 :
高可用集群软件
高可用集群一般是通过高可用软件来实现的。在 Linux 下常用的高可用软件有开源HeartBeatHA、 RedHat 提供的 RHCS、商业软件 ROSE、Keepalived、pacemaker 等。
心跳监测与漂移 IP 地址
- 心跳监测
为了能实现负载均衡、提供高可用服务和执行错误恢复,集群系统提供了心跳监测技术。心跳监测是通过心跳线实现的,可以做心跳线的设备有 RS232 串口线,也可以用独立的一块网卡来跑心跳,还可以共享磁盘阵列等。心跳线的数量应该为集群节点数减 I。需要注意的是,如果通过网卡来做心跳,每个节点需要两块网卡。其中,一块作为私有网络直接连接到对方机器相应的网卡,用来监测对方心跳。另外一块连接到公共网络对外提供服务,同时心跳网卡和服务网卡的 IP地址尽量不要在一个网段内。心跳监控的效率直接影响故障切换时间的长短,集群系统正是通过心跳技术保持节点间内部通信的有效性 。
- 漂移 IP 地址
在集群系统中,除了每个服务节点自身的真实 IP 地址外,还存在一个漂移 1P 地址。为什么说是漂移 IP地址呢?因为这个 IP 地址并不固定。例如,在两个节点的双机热备中,正常状态下,这个漂移 1P 地址位于主节点上,当主节点出现故障后,漂移 IP 地址自动切换到备用节点。因此,为了保证服务的不间断性,在集群系统中,对外提供的服务 IP 地址一定要是这个漂移 IP 地址。虽然节点本身的 IP 地址也能对外提供服务,但是当此节点失效后,服务切换到了另一个节点,连接服务的 IP 地址仍然是故障节点的 IP地址,此时,服务就随之中断。
keepalived
Keepalived高可用集群介绍
Keepalived服务介绍
Keepalived起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态,后来有加入VRRP的功能,VRRP是Virtual Router Redundancy protocol(虚拟路由器冗余协议)的缩写,VRRP出现的目的就是为了解决静态路由器出现的单点故障问题,它能偶保证网络的不间断、稳定的运行。所有,keepalived一方面具有LVS cluster nodes healthchecks功能,另一方面也具有LVS directors faiover功
能。
- Keepalived服务两大用途healthcheck & failover
- Healthcheck(健康检查)
- 作用:Keepalived 通过健康检查机制来实时监测服务器或服务的运行状态,以确定其是否正常工作。这有助于及时发现潜在的故障,为故障转移提供依据。
- 实现方式:Keepalived 可以通过多种方式进行健康检查。
- 网络连接检查:尝试与服务器的特定端口建立连接,如果连接成功,则认为服务器在网络层面是可达的。例如,通过向 Web 服务器的 80 端口发送连接请求,若能成功建立连接,说明 Web 服务器的网络服务正常。
- 进程状态检查:监测服务器上特定进程的运行状态。它可以通过检查进程的 PID(进程标识符)是否存在来判断进程是否正在运行。比如,检查 MySQL 数据库进程是否在运行,如果进程不存在,说明 MySQL 服务可能出现了故障。
- 应用层检查:对服务进行更深入的应用层检查。例如,对于 Web 服务,可以发送 HTTP 请求并检查返回的状态码。如果返回的是 200 OK 状态码,说明 Web 应用程序正常响应;如果返回 500 Internal Server Error 等错误状态码,则表示 Web 服务可能存在问题。
- Failover(故障转移)
- 作用:当健康检查发现主服务器出现故障时,Failover 机制会自动将服务切换到备份服务器上,以确保服务的连续性,减少停机时间,保证业务的正常运行。
- 实现过程:
- 故障检测:Keepalived 的健康检查模块持续监测主服务器的状态。当主服务器出现故障,例如网络中断、进程崩溃或服务无法正常响应时,健康检查机制会检测到这些异常情况,并将主服务器的状态标记为不可用。
- 选举新的主服务器:在主服务器被标记为不可用后,Keepalived 会根据预先配置的优先级和选举算法,从备份服务器中选举出一个新的主服务器。通常,优先级较高的备份服务器会被优先选中。
- 切换服务:选举出的新主服务器会接管原主服务器的工作,包括 IP 地址、网络服务等。Keepalived 会通过修改网络配置等方式,将原本发送到故障主服务器的流量重新路由到新的主服务器上,实现服务的无缝切换。
- 通知与恢复:在故障转移过程中,Keepalived 可以通过配置好的通知机制,如发送邮件或执行脚本,通知管理员发生了故障转移事件。同时,当故障的主服务器恢复正常后,Keepalived 也可以根据配置,决定是否将服务切回原主服务器,或者让新主服务器继续承担服务任务,直到下次故障发生
- Healthcheck(健康检查)
Keepalived故障切换转移原理介绍
Keepalived 故障切换转移主要基于 VRRP 协议,通过优先级选举和状态监测来实现。以下是其详细原理介绍:
-
VRRP 协议基础
- VRRP 协议定义了虚拟路由器的概念,一个虚拟路由器由一个主路由器和多个备份路由器组成。虚拟路由器有一个虚拟 IP 地址和虚拟 MAC 地址,在外部看来,虚拟路由器是一个具有唯一 IP 和 MAC 地址的逻辑实体。
- MASTER(主路由器)
- 职责
- 转发数据:负责接收发往虚拟 IP 地址的数据包,并将其转发到相应的目的地。所有发送到虚拟 IP 地址的网络流量都由 MASTER 路由器进行处理和转发,就好像它是实际的默认网关一样。
- 发送通告:定期发送 VRRP 通告消息,以告知 BACKUP 路由器自己的运行状态。通告消息中包含了 MASTER 路由器的优先级、虚拟路由器的状态等信息,通过这些消息,BACKUP 路由器可以实时监测 MASTER 路由器的工作情况。
- 选举方式:在 VRRP 组中,路由器根据优先级进行选举。优先级最高的路由器成为 MASTER。如果多个路由器的优先级相同,则 IP 地址较大的路由器会被选举为 MASTER。例如,在一个包含三个路由器的 VRRP 组中,路由器 A 的优先级为 200,路由器 B 的优先级为 150,路由器 C 的优先级为 180,那么路由器 A 将成为 MASTER。如果路由器 A 和路由器 C 的优先级都为 200,而路由器 A 的 IP 地址大于路由器 C 的 IP 地址,那么路由器 A 仍然会被选举为 MASTER。
- 职责
- BACKUP(备份路由器)
- 职责
- 监测状态:接收 MASTER 路由器发送的 VRRP 通告消息,通过分析这些消息来监测 MASTER 路由器的运行状态。一旦发现 MASTER 路由器出现故障,例如在规定时间内没有收到 MASTER 的通告消息,BACKUP 路由器将启动故障切换流程。
- 准备接管:在 MASTER 路由器正常工作时,BACKUP 路由器处于待命状态,随时准备在 MASTER 路由器出现故障时接管其工作。当 BACKUP 路由器检测到 MASTER 路由器故障后,会根据优先级进行选举,优先级最高的 BACKUP 路由器将成为新的 MASTER 路由器,接管虚拟 IP 地址和网络流量的转发工作。
- 职责
-
优先级与选举
-
优先级设置:在 Keepalived 配置中,每个参与 VRRP 组的路由器都会被分配一个优先级。优先级通常是一个 0 - 255 之间的数字,数值越高表示优先级越高。例如,主路由器的优先级可以设置为 200,备份路由器的优先级则设置为 100。
-
选举主路由器:VRRP 组中的路由器在启动时会根据优先级进行选举。优先级最高的路由器会被选举为 Master(主路由器),其他路由器则成为 Backup(备份路由器)。如果多个路由器的优先级相同,那么 IP 地址较大的路由器会被选举为 Master。
-
-
状态监测与通告
-
状态监测:Keepalived 通过多种方式监测服务器和网络的状态,包括前面提到的网络连接检查、进程状态检查和应用层检查等。以网络连接检查为例,Keepalived 会定期向服务器的特定端口发送探测数据包,根据服务器的响应来判断其是否正常运行。
-
VRRP 通告:Master 路由器会定期发送 VRRP 通告消息,告知 Backup 路由器自己的状态。通告消息中包含了 Master 路由器的优先级、虚拟路由器的状态等信息。默认情况下,通告间隔通常为 1 秒。
-
-
故障切换过程
-
检测到故障:如果 Backup 路由器在一定时间内(通常是多个通告间隔,可配置)没有收到 Master 路由器的 VRRP 通告消息,就会认为 Master 路由器出现故障。例如,连续 3 秒没有收到通告消息,Backup 路由器就会触发故障切换流程。
-
重新选举:Backup 路由器在确认 Master 路由器故障后,会根据优先级重新进行选举。优先级最高的 Backup 路由器会成为新的 Master 路由器。
-
切换 IP 和服务:新的 Master 路由器会接管虚拟 IP 地址和相关服务。它会将自己的网络接口配置为虚拟 IP 地址,并开始提供服务。同时,Keepalived 会通过相应的机制通知网络中的其他设备,使其将流量发送到新的 Master 路由器上,实现故障切换。
-
-
抢占与非抢占模式
-
抢占模式:在抢占模式下,当原来故障的 Master 路由器恢复正常后,如果它的优先级仍然是最高的,那么它会重新抢占 Master 角色,将当前的 Master 路由器切换回 Backup 状态。
-
非抢占模式:在非抢占模式下,即使原来的 Master 路由器恢复正常,它也不会主动抢占 Master 角色,而是继续作为 Backup 路由器,直到当前的 Master 路由器再次出现故障。
-
-
Keepalived 具有以下主要特点:
- 与 LVS 兼容性好:作为 LVS 的扩展项目,Keepalived 与 LVS 之间有着良好的兼容性,能在 LVS 相关场景中稳定高效运行,为基于 LVS 的负载均衡系统提供有力支持。
- 配置相对简单:相较于 Heartbeat 等 HA 软件,Keepalived 的部署更为简洁。Heartbeat 复杂的配置流程让不少人望而却步,而 Keepalived 在这方面具有明显优势,降低了运维成本和技术门槛。
- 健康检查与故障隔离:通过对服务器池对象进行健康检查,Keepalived 能够及时发现失效的机器或服务,并将其隔离,确保整个系统的稳定性和可靠性,避免因单点故障影响业务的正常运行。
- 基于 VRRP 的故障切换:负载均衡器之间的失败切换是通过 VRRPv2 stack 实现的。VRRP 最初就是为解决静态路由器的单点故障问题而设计,Keepalived 借助这一成熟的协议,实现了高效、快速的故障切换,保障网络服务的连续性。
- 与 iptables 兼容性佳:在实际线上项目中可知,iptables 的启用不会影响 Keepalived 的运行。不过,为了追求更好的性能,通常会将整套系统内所有主机的 iptables 停用,以减少系统开销,提升整体性能。
- VIP 设置与灵活组网:Keepalived 产生的 VIP 作为整个系统对外的 IP,方便进行统一的网络配置和管理。如果最外端的防火墙采用路由模式,还可将此内网 IP 映射为公网 IP,实现内外网的灵活组网和通信,适应不同的网络环境和应用需求。
keepalive配置文件说明
整体结构
Keepalived 配置文件主要由 3 个部分构成:
- 全局配置(Global Configuration):这部分定义了与 Keepalived 进程相关的全局参数。
- VRRP 实例配置(VRRP Instance Configuration):用于配置 VRRP 实例,实现虚拟路由冗余。
- 虚拟服务器配置(Virtual Server Configuration):若要使用 Keepalived 作为负载均衡器,可通过这部分配置虚拟服务器。
示例配置文件及说明
! Configuration File for keepalived
# 全局配置部分
global_defs {
# 路由器的标识,同一网络内必须唯一
router_id LVS_DEVEL
# 通知脚本,当 Keepalived 状态发生变化时执行
notify_master "/path/to/master.sh"
notify_backup "/path/to/backup.sh"
notify_fault "/path/to/fault.sh"
# 发送邮件通知的配置
smtp_server 192.168.200.1
smtp_connect_timeout 30
email_from keepalived@example.com
email_to admin@example.com
}
# VRRP 实例配置部分
vrrp_instance VI_1 {
state MASTER # 实例的运行模式,MASTER 表示主服务器,BACKUP 表示备用服务器
interface ens160 # 绑定的网络接口
virtual_router_id 51 # VRRP 组的 ID,同一 VRRP 组内的实例必须相同
priority 100 # 优先级,数值越高越优先成为主服务器
advert_int 1 # 发送 VRRP 通告的时间间隔,单位为秒
# nopreempt 设置为非抢占模式
authentication { # VRRP 认证信息,同一 VRRP 组内的实例必须相同
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { # 虚拟 IP 地址,多个 IP 可换行添加
192.168.200.100
}
track_script { # 跟踪脚本,用于监测应用程序状态
chk_httpd {
script "/path/to/check_httpd.sh"
interval 2
weight -20
}
}
}
# 虚拟服务器配置部分
virtual_server 192.168.200.100 80 {
delay_loop 6 # 健康检查的时间间隔,单位为秒
lb_algo rr # 负载均衡算法,常用的有 rr(轮询)、wrr(加权轮询)等
lb_kind NAT # 负载均衡模式,常用的有 NAT、DR 等
persistence_timeout 50 # 持久连接的超时时间,单位为秒
protocol TCP # 协议类型,通常为 TCP
sorry_server 192.168.1.111:80 #添加一个备用服务器,当所有RS故障时启用
# 真实服务器配置
real_server 192.168.200.102 80 {
weight 1 # 权重,数值越高分配的请求越多
SSL_GET { # 健康检查方式
url {
path /
digest ff20ad2481f8d06864272493e926a9cf
}
url {
path /mrtg/
digest 9b3a0c85a887a 256d6939da88aabd8cd
}
connect_timeout 3 # 连接超时时间,单位为秒
retry 3 # 重试次数
delay_before_retry 3 # 重试间隔时间,单位为秒
}
}
}
各部分详细解释
-
全局配置(
global_defs
)-
router_id
:用于标识 Keepalived 实例,在同一网络内必须唯一。 -
notify_master
、notify_backup
、notify_fault
:分别为切换到主、备用、故障状态时执行的脚本路径。 -
smtp_server
、smtp_connect_timeout
、email_from
、email_to
:邮件通知相关配置。
-
-
VRRP 实例配置(
vrrp_instance
)-
state
:实例的初始状态,有MASTER
和BACKUP
两种。 -
interface
:绑定的网络接口。 -
virtual_router_id
:VRRP 组的 ID,同一组内必须相同。 -
priority
:优先级,数值越高越优先成为主服务器。 -
advert_int
:发送 VRRP 通告的时间间隔。 -
authentication
:VRRP 认证信息,包括认证类型和密码。 -
virtual_ipaddress
:虚拟 IP 地址列表。 -
track_script
:用于监测应用程序状态的脚本配置。
-
-
虚拟服务器配置(
virtual_server
)-
virtual_server
:指定虚拟服务器的 IP 地址和端口。 -
delay_loop
:健康检查的时间间隔。 -
lb_algo
:负载均衡算法。 -
lb_kind
:负载均衡模式。 -
persistence_timeout
:持久连接的超时时间。 -
protocol
:协议类型。 -
real_server
:真实服务器的配置,包括 IP 地址、端口、权重和健康检查方式。 -
nopreempt
:非抢占模式。
-
keepalived高可用简单应用
配置keepalived实现服务高可用功能
keepalived的官方站点是http://www.keepalived.org,官方文档是
http://www.keepalived.org/documentation.html,通过官方地址可以获取到keepalived软件包
-
准备两台机器
IP 主机名 说明 172.25.254.100 openEuler-1 MASTER(主路由器) 172.25.254.200 openEuler-2 BACKUP(备份路由器) -
安装keepalived
# 1.在线安装 [root@openEuler-1 ~]# yum install keepalived -y [root@openEuler-2 ~]# yum install keepalived -y
-
配置web站点
[root@openEuler-1 ~]# yum install nginx -y [root@openEuler-1 ~]# echo "web1 test,`hostname -I`." > /usr/share/nginx/html/index.html [root@openEuler-1 ~]# systemctl start nginx [root@openEuler-2 ~]# yum install nginx -y [root@openEuler-1 ~]# echo "web2 test,`hostname -I`." > /usr/share/nginx/html/index.html [root@openEuler-1 ~]# systemctl start nginx
-
配置keepalived
# 172.25.254.100,MASTER [root@openEuler-1 ~]# cd /etc/keepalived/ [root@openEuler-1 keepalived]# cp keepalived.conf{,.bak} [root@openEuler-1 keepalived]# vim keepalived.conf [root@openEuler-1 keepalived]# cat keepalived.conf ! Configuration File for keepalived global_defs { router_id LVS_MASTER } vrrp_instance VI_1 { state MASTER interface ens160 #设置为自己的网卡 virtual_router_id 100 priority 200 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 172.25.254.10 } } # 172.25.254.200,BACKUP [root@openEuler-2 ~]# cd /etc/keepalived/ [root@openEuler-2 keepalived]# cp keepalived.conf{,.bak} [root@openEuler-2 keepalived]# vim keepalived.conf [root@openEuler-2 keepalived]# cat keepalived.conf ! Configuration File for keepalived global_defs { router_id LVS_BACKUP } vrrp_instance VI_1 { state BACKUP interface ens160 #设置为自己的网卡 virtual_router_id 100 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 172.25.254.10 } }
-
测试
# 两台机器启动keepalived [root@openEuler-1 keepalived]# systemctl start keepalived [root@openEuler-2 keepalived]# systemctl start keepalived # 访问vip [root@openEuler-1 keepalived]# curl 172.25.254.10 web1 test,172.25.254.100 . # 模拟MASTER故障 [root@openEuler-1 keepalived]# systemctl stop keepalived [root@openEuler-1 keepalived]# curl 172.25.254.10 web2 test,172.25.254.200 . # 默认是抢占模式 [root@openEuler-1 keepalived]# systemctl start keepalived [root@openEuler-1 keepalived]# curl 172.25.254.10 web1 test,172.25.254.100 .
-
注意:
- keepalived起初是为lvs量身定做的;
- 本次小实验基于keepalived+nginx的应用,没有对nginx的应用做健康检查,当nginx出现问题时,VIP不能自动漂移,实现故障转移。
-
解决方法
-
方法1:编写脚本:脚本持续监测应用,一旦异常并重启失败,则停止keepalived。
#!/bin/bash # function: monitor nginx process status and handle exceptions # Define log file LOG_FILE="/var/log/check_nginx.log" # Function to log messages log_message() { local message="$1" echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$LOG_FILE" } while true do nginxpid=$(ps -C nginx --no-header | wc -l) if [ "$nginxpid" -eq 0 ]; then log_message "nginx process is not running. Trying to start it..." /etc/init.d/nginx start sleep 5 nginxpid=$(ps -C nginx --no-header | wc -l) if [ "$nginxpid" -eq 0 ]; then log_message "Failed to start nginx process. Stopping keepalived..." /etc/init.d/keepalived stop log_message "Keepalived service has been stopped." break else log_message "nginx process has been successfully started." fi fi sleep 5 done
-
方法2:VRRP scripts的实现,简单演示
# 在配置文件中添加 vrrp_script check_nginx { script "killall -0 nginx" interval 2 } # 在vrrp_instance VI_1中添加,引用上面的nginx监测 track_script { check_nginx }
-
keepalived的vrrp_script
vrrp_script
是 Keepalived 配置文件里极为关键的一部分,它的主要作用是对特定脚本进行监测与执行,进而依据脚本的执行结果来动态调整 VRRP 实例的优先级。这一功能有助于实现服务的高可用性,当监测的服务出现故障时,能够自动切换到备用节点。
基本语法
vrrp_script <SCRIPT_NAME> {
script "<STRING>|<QUOTED-STRING>"
interval <SECONDS>
weight <INTEGER>
fall <COUNT>
rise <COUNT>
timeout <SECONDS>
init_fail
}
参数解释
<SCRIPT_NAME>
:为脚本监测项自定义的名称,此名称要保证在配置文件中是唯一的。script
:要执行的脚本命令或者脚本文件的路径。interval
:执行脚本的时间间隔,单位为秒。weight
:当脚本执行结果表明服务异常时,VRRP 实例优先级的调整值[-254,254]。若为正数,则提高优先级;若为负数,则降低优先级。- weight 为正数
- 脚本检测失败:当 Master 节点的
vrrp_script
脚本检测失败,若其priority
值小于 Backup 节点的weight
值与priority
值之和,会发生主备切换。 - 脚本检测成功:当 Master 节点的
vrrp_script
脚本检测成功,若其weight
值与priority
值之和大于 Backup 节点的weight
值与priority
值之和,主节点不变,不发生切换。
- 脚本检测失败:当 Master 节点的
- weight 为负数
- 脚本检测失败:当 Master 节点的
vrrp_script
脚本检测失败,若其priority
值与weight
值之差小于 Backup 节点的priority
值,会发生主备切换。 - 脚本检测成功:当 Master 节点的
vrrp_script
脚本检测成功,若其priority
值大于 Backup 节点的priority
值,主节点不变,不发生切换。
- 脚本检测失败:当 Master 节点的
- weight 为正数
fall
:判定服务处于故障状态所需的连续失败次数。rise
:判定服务恢复正常所需的连续成功次数。timeout
:脚本执行的最大时长,超过该时长则视为执行失败。init_fail
:若添加该参数,Keepalived 启动时若脚本执行失败,会直接降低优先级。
示例配置
以下是一个监测 Nginx 服务状态的 vrrp_script
示例:
vrrp_script chk_nginx {
script "/usr/local/bin/check_nginx.sh"
interval 2
weight -20
fall 2
rise 2
timeout 3
init_fail
}
配置文件引用示例
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 100
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.10
}
track_script {
chk_nginx
}
}
脚本示例(check_nginx.sh
)
## vim /usr/local/bin/check_nginx.sh
#!/bin/bash
if systemctl is-active --quiet nginx; then
exit 0
else
exit 1
fi
## systemctl is-active --quiet nginx
作用:此命令用于检查 nginx 服务是否处于活跃(正在运行)状态。is-active 是 systemctl 的子命令,用于查询服务的运行状态;--quiet 选项表示不输出详细信息,仅通过命令的退出状态码来反映结果。
可能的结果:
退出状态码为 0:这表明 nginx 服务正在运行,即上一条 systemctl start nginx 命令成功启动了 nginx 服务。
退出状态码为 3:意味着 nginx 服务未处于活跃状态,可能是启动过程中出现了故障,或者服务启动后又异常停止了。
退出状态码为 4:表示指定的服务(这里是 nginx)不存在,可能是 nginx 没有正确安装。
##或者
#!/bin/bash
#代码一定注意空格,逻辑就是:如果nginx进程不存在则启动nginx,如果nginx无法启动则kill掉
keepalived所有进程
A=`ps -C nginx --no-header |wc -l`
if [ $A -eq 0 ];then
systemctl start nginx
sleep 3
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
systemctl stop keepalived
fi
fi
实战案例:
实现Keepalived 状态切换的通知脚本
## 在所有keepalived节点配置如下
[root@openEuler-1 ~]# cat /usr/local/bin/notify.sh
#!/bin/bash
contact='2221585257@qq.com'
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@openEuler-1 ~]# chmod +x /usr/local/bin/notify.sh
[root@openEuler-1 ~]# cat /etc/keepalived/keepalived.conf
......
vrrp_instance VI_1 {
......
virtual_ipaddress {
172.25.254.10
}
notify_master "/usr/local/bin/notify.sh master"
notify_backup "/usr/local/bin/notify.sh backup"
notify_fault "/usr/local/bin/notify.sh fault"
}
利用子配置文件实现master/master的Keepalived双主架构
# 172.25.254.100
[root@openEuler-1 ~]# vim /etc/keepalived/keepalived.conf
......
include /etc/keepalived/conf.d/*.conf
[root@openEuler-1 ~]# mkdir /etc/keepalived/conf.d/
[root@openEuler-1 ~]# vim /etc/keepalived/conf.d/cluster1.conf
[root@openEuler-1 ~]# cat /etc/keepalived/conf.d/cluster1.conf
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 66
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
172.25.254.10
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
[root@openEuler-1 ~]# vim /etc/keepalived/conf.d/cluster2.conf
[root@openEuler-1 ~]# cat /etc/keepalived/conf.d/cluster2.conf
vrrp_instance VI_2 {
state BACKUP
interface ens160
virtual_router_id 88
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
172.25.254.11
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
[root@openEuler-1 ~]# tree /etc/keepalived/
/etc/keepalived/
├── conf.d
│ ├── cluster1.conf
│ └── cluster2.conf
├── keepalived.conf
└── keepalived.conf.bak
## 172.25.254.200
[root@openEuler-2 ~]# vim /etc/keepalived/keepalived.conf
......
include /etc/keepalived/conf.d/*.conf
[root@openEuler-2 ~]# mkdir /etc/keepalived/conf.d/
[root@openEuler-2 ~]# vim /etc/keepalived/conf.d/cluster1.conf
[root@openEuler-2 ~]# cat /etc/keepalived/conf.d/cluster1.conf
vrrp_instance VI_1 {
state BACKUP
interface ens160
virtual_router_id 66
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
172.25.254.10
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
[root@openEuler-2 ~]# vim /etc/keepalived/conf.d/cluster2.conf
[root@openEuler-2 ~]# cat /etc/keepalived/conf.d/cluster2.conf
vrrp_instance VI_2 {
state MASTER
interface ens160
virtual_router_id 88
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
172.25.254.11
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
##重启服务,测试
#systemctl restart keepalived
[root@openEuler-3 ~]# curl 172.25.254.10
web1 test,172.25.254.100 .
[root@openEuler-3 ~]# curl 172.25.254.11
web2 test,172.25.254.200 .
## 在172.25.254.100上模拟故障
[root@openEuler-1 ~]# systemctl stop keepalived
[root@openEuler-3 ~]# curl 172.25.254.10
web2 test,172.25.254.200 .
[root@openEuler-3 ~]# curl 172.25.254.11
web2 test,172.25.254.200 .
LVS+Keepalived实现Nginx集群配置案例
LVS+Keepalived配置
机器 | 接口/IP | 说明 |
---|---|---|
openEuler-1 | ens160:172.25.254.100/24 ens192:10.10.10.1/24 | ens192用于心跳检测 |
openEuler-2 | ens160:172.25.254.200/24 ens192:10.10.10.2/24 | |
openEuler-3 | 172.25.254.201 | web1 |
openEuler-4 | 172.25.254.202 | web2 |
## 在openEuler-1和openEuler-2上分别安装ipvsadm和keepalived
# yum install ipvsadm -y
# yum install keepalived -y
## openEuler-1
[root@openEuler-1 ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id LVS_1
}
vrrp_instance VI_1 {
state MASTER
interface ens160
lvs_sync_daemon_interface ens192 ##心跳检测端口
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.10
}
}
virtual_server 172.25.254.10 80 {
delay_loop 6
lb_algo rr
lb_kind DR
#persistence_timeout 50
protocol TCP
real_server 172.25.254.201 80 {
weight 1
TCP_CHECK{
connect_timeout 3
retry 3
delay_before_retry 3
connetc_port 80
}
}
real_server 172.25.254.202 80 {
weight 1
TCP_CHECK{
connect_timeout 3
retry 3
delay_before_retry 3
connetc_port 80
}
}
}
## openEuler-2
[root@openEuler-2 ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id LVS_2
}
vrrp_instance VI_1 {
state BACKUP
interface ens160
lvs_sync_daemon_interface ens192
virtual_router_id 51
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.25.254.10
}
}
virtual_server 172.25.254.10 80 {
delay_loop 6
lb_algo rr
lb_kind DR
#persistence_timeout 50
protocol TCP
real_server 172.25.254.201 80 {
weight 1
TCP_CHECK{
connect_timeout 3
retry 3
delay_before_retry 3
connetc_port 80
}
}
real_server 172.25.254.202 80 {
weight 1
TCP_CHECK{
connect_timeout 3
retry 3
delay_before_retry 3
connetc_port 80
}
}
}
## 在openEuler-1和openEuler-2上分别开启路由转发功能
[root@openEuler-2 ~]# vim /etc/sysctl.conf
......
net.ipv4.ip_forward = 1 ##将0改为1
......
[root@openEuler-2 ~]# sysctl -p
LVS-DR模式配置不明白的,可以参考我的其他博客lvs负载均衡集群
在openEuler-3和openEuler-4上使用脚本进行ARP抑制
,可以参考我的其他博客LVS-DR模式配置脚本
## 配置nginx的默认发布页面
[root@openEuler-3 ~]# echo "web1 tset page,`hostname -I`." > /usr/share/nginx/html/index.html
[root@openEuler-4 ~]# echo "web2 tset page,`hostname -I`." > /usr/share/nginx/html/index.html
## 两台机器都启动ARP抑制脚本
[root@openEuler-4 ~]# /etc/init.d/lvs_rs start
Reloading systemd: [ OK ]
Starting lvs_rs (via systemctl): [ OK ]
[root@openEuler-4 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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
inet 172.25.254.10/32 brd 172.25.254.10 scope global lo:10 ##VIP绑定成功
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:a5:34:fe brd ff:ff:ff:ff:ff:ff
altname enp3s0
inet 172.25.254.202/24 brd 172.25.254.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet6 fe80::89dc:284:592a:5b75/64 scope link dadfailed tentative noprefixroute
valid_lft forever preferred_lft forever
inet6 fe80::14d:910a:4705:b203/64 scope link dadfailed tentative noprefixroute
valid_lft forever preferred_lft forever
inet6 fe80::bf01:39f:619d:7869/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@openEuler-4 ~]# /etc/init.d/lvs_rs start^C
[root@openEuler-4 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.25.254.2 0.0.0.0 UG 100 0 0 ens160
172.25.254.0 0.0.0.0 255.255.255.0 U 100 0 0 ens160
172.25.254.10 0.0.0.0 255.255.255.255 UH 0 0 0 lo ##VIP
测试
## 查看LVS-DR模式
[root@openEuler-1 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.25.254.10:80 rr
-> 172.25.254.201:80 Route 1 0 0
-> 172.25.254.202:80 Route 1 0 0
## 在客户端访问vip172.25.254.10
[root@Rocky ~]# for ((i=0;i<10;i++));do curl 172.25.254.10 ;done
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
## 在172.25.254.201上停止nginx服务,稍等片刻查看
[root@openEuler-1 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.25.254.10:80 rr
-> 172.25.254.202:80 Route 1 0 5
[root@Rocky ~]# for ((i=0;i<10;i++));do curl 172.25.254.10 ;done
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
## 在172.25.254.100上停止keepalived服务
[root@openEuler-1 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
## 此时自动切换到172.25.254.200 openEuler-2上,后端服务不影响
[root@openEuler-2 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.25.254.10:80 rr
-> 172.25.254.201:80 Route 1 0 0
-> 172.25.254.202:80 Route 1 0 10
[root@Rocky ~]# for ((i=0;i<10;i++));do curl 172.25.254.10 ;done
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
健康检查方式
Keepalived 的健康检查是其重要功能之一,通过多种检查方式来确保后端服务器的可用性,以下是对 Keepalived 健康检查的详细介绍:
-
检查方式
-
TCP_CHECK:工作在第 4 层,Keepalived 向后端服务器发起一个 TCP 连接请求,如果后端服务器没有响应或超时,那么这个后端将从服务器池中移除。例如,可通过设置
connect_timeout
(连接超时时间)、nb_get_retry
(重连次数)、delay_before_retry
(重连间隔时间)和connect_port
(健康检查的端口)等参数来配置 TCP 检查。 -
HTTP_GET/SSL_GET:工作在第 5 层。
HTTP_GET
向指定的 URL 执行 HTTP 请求,将得到的结果用 MD5 加密并与指定的 MD5 值比较是否匹配,不匹配则从服务器池中移除,还可指定 HTTP 返回码来判断检测是否成功,也能指定多个 URL 用于检测,适用于一台服务器有多个虚拟主机的情况。SSL_GET
与HTTP_GET
相似,只是使用 SSL 连接。它们都有基于返回码确认和基于确认后端页面内容 hash 值两种检测方式,可处理简单的 GET 请求,不适用基于 POST 返回值确认,POST 方式可通过MISC_CHECK
支持检测。 -
SMTP_CHECK:用于检测邮件服务的 SMTP。可配置
connect_ip
、connect_port
(默认检查端口 25)、connect_timeout
、retry
、delay_before_retry
以及helo_name
(请求命令参数,可选)等参数来进行 SMTP 健康检查。 -
MISC_CHECK:通过脚本来检测。脚本返回值为 0 表示检测成功;为 1 表示检测失败,将从服务器池中移除;为 2 - 255 表示检测成功,如果设置了
misc_dynamic
,权重自动调整为退出码 - 2。需指定misc_path
(外部程序或者脚本路径)、misc_timeout
(执行脚本的超时时间)等参数,若设置了misc_dynamic
,则健康检查程序的退出状态码会用来动态调整服务器的权重。
-
-
相关配置参数
-
delay_loop:指定每隔多长时间做一次健康检测,单位为秒。
-
connect_timeout:连接超时时间,单位为秒。
-
nb_get_retry:检测失败后的重试次数,如果达到重试次数仍然失败,将后端从服务器池中移除。
-
delay_before_retry:失败重试的间隔时间,单位为秒。
-
-
配置示例
-
以 TCP 健康检查为例,配置如下:
TCP_CHECK { connect_timeout 5 #连接超时时间 nb_get_retry 3 #重连次数 delay_before_retry 3 #重连间隔时间 connect_port 80 #健康检查的端口 }
-
以 HTTP_GET 健康检查为例,配置如下:
HTTP_GET | SSL_GET { url { path / # HTTP/SSL检查的URL,可配置多个 digest <STRING> # HTTP/SSL检查后的摘要信息,用工具genhash生成 status_code 200 # HTTP/SSL检查返回的状态码,期望返回200表示成功 } connect_port 80 # 连接端口 bindto <IPADD> # 绑定的IP地址(需替换为实际IP) connect_timeout 3 # 连接超时时间,3秒后若未成功连接则判定超时 nb_get_retry 3 # 重连次数,连接失败后尝试重连3次 delay_before_retry 2 # 连接间隔时间,每次重连间隔2秒 } ## 两种方式都有基于返回码和基于页面内容 hash 值两种检测方式; ## 都只能处理简单的 GET 请求,POST 请求可通过 MISC_CHECK 方式检测; ## 配置语法相似,区别仅在于协议(HTTP 与 HTTPS)。
-
SMTP 健康检查方式
SMTP_CHECK { host { connect_ip <IP ADDRESS> # 连接的IP地址(需替换为实际IP) connect_port <PORT> # 默认检查端口25,可按需修改 } connect_timeout <INTEGER> # 连接超时时间(需设置具体整数,单位秒) retry <INTEGER> # 重试次数(需设置具体整数) delay_before_retry <INTEGER> # 失败重试的间隔时间(需设置具体整数,单位秒) helo_name <STRING>|<QUOTED-STRING> # 请求命令参数,可选 }
-
MISC 健康检查方式
MISC_CHECK { misc_path <STRING>|<QUOTED-STRING> # 外部程序或脚本路径 misc_timeout <INT> # 执行脚本的超时时间(需设置具体整数,单位秒) user USERNAME [GROUPNAME] #指定运行脚本的用户和组,默认为当前用户;如果没有指定GROUPNAME,则GROUPNAME同USERNAME。 misc_dynamic # 如果设置,healthchecker程序的退出状态码会动态调整服务器权重 # 返回0:健康检查OK,权重不被修改 # 返回1:健康检查失败,权重设为0 # 返回2 - 255:健康检查OK,权重设置为:退出状态码 - 2,如果退出码为250,则权重调整为248 warmup <INT> #指定一个随机延迟,可防止网络阻塞,如果为0,则关闭该功能 }
-
genhash工具使用
## keepalived自带,无需另外下载 [root@openEuler-1 ~]# genhash Usage: genhash COMMAND [OPTIONS] Commands: -s server-address -p port -u url -S -s server-address -p port -u url -h Options: Either long or short options are allowed. --use-ssl -S Use SSL connection to remote server. --use-sni -I Use SNI during SSL handshake (uses virtualhost setting; see -V). --server -s Use the specified remote server address. --port -p Use the specified remote server port. --url -u Use the specified remote server url. --use-virtualhost -V Use the specified virtualhost in GET query. --verbose -v Use verbose mode output. --help -h Display this short inlined help screen. --fwmark -m Use the specified FW mark. --protocol -P Use the specified HTTP protocol - '1.0', 1.0c', '1.1'. 1.0c means 1.0 with 'Connection: close' --timeout -t Timeout in seconds 命令格式 genhash COMMAND [OPTIONS],说明genhash命令需要跟一个具体的子命令(如-s -p -u等组合)以及一些可选的选项来执行特定的操作。 子命令 -s server -address -p port -u url:这是最主要的子命令组合,用于指定远程服务器的地址、端口和要获取哈希值的 URL。通过这个组合,genhash会连接到指定的服务器和端口,并针对给定的 URL 生成哈希值。 -S -s server -address -p port -u url:与上面的子命令类似,但多了-S选项,表示使用 SSL 连接到远程服务器,增加了连接的安全性。 选项 --use - ssl 或 -S:指定使用 SSL 连接到远程服务器。 --use - sni 或 -I:在 SSL 握手期间使用 SNI(Server Name Indication),需要结合-V选项使用,用于指定虚拟主机设置。 --server 或 -s:指定远程服务器的地址。 --port 或 -p:指定远程服务器的端口。 --url 或 -u:指定远程服务器上要获取哈希值的 URL。 --use - virtualhost 或 -V:在 GET 查询中使用指定的虚拟主机。 --verbose 或 -v:使用详细模式输出,会提供更多关于操作执行过程的信息。 --help 或 -h:显示这个简短的内联帮助屏幕,就是你看到的输出内容。 --fwmark 或 -m:指定要使用的防火墙标记。 --protocol 或 -P:指定使用的 HTTP 协议版本,可以是'1.0'、'1.0c'、'1.1'。其中1.0c表示1.0版本且带有Connection: close头信息。 --timeout 或 -t:设置连接的超时时间,单位为秒。如果在指定时间内没有完成操作,命令将自动终止
-
示例
-
TCP_CHECK健康检查方式
[root@openEuler-1 ~]# vim /etc/keepalived/keepalived.conf real_server 172.25.254.201 80 { weight 1 TCP_CHECK{ connect_timeout 3 retry 3 delay_before_retry 3 connetc_port 80 } } real_server 172.25.254.202 80 { weight 1 TCP_CHECK{ connect_timeout 3 retry 3 delay_before_retry 3 connetc_port 80 } }
-
HTTP_GET/SSL_GET健康检查方式
[root@openEuler-1 ~]# genhash -s 172.25.254.201 -p 80 -u /index.html 307e37d3795b16258184fab0b8f2b8cf [root@openEuler-1 ~]# genhash -s 172.25.254.202 -p 80 -u /index.html 88d26bf251daebfed14eb46055303697 [root@openEuler-1 ~]# vim /etc/keepalived/keepalived.conf ## 将TCP_CHECK更换 real_server 172.25.254.201 80 { weight 1 HTTP_GET { url { path /index.html digest 307e37d3795b16258184fab0b8f2b8cf #基于genhash监测 status_code 200 #基于状态码监测 } connect_timeout 3 connect_port 80 nb_get_retry 3 delay_before_retry 3 } } real_server 172.25.254.202 80 { weight 1 HTTP_GET { url { path /index.html 88d26bf251daebfed14eb46055303697 status_code 200 } connect_timeout 3 connect_port 80 nb_get_retry 3 delay_before_retry 3 } }
-
MISC 健康检查方式
[root@openEuler-1 ~]# yum install nmap -y ## nginx正常启动 [root@openEuler-1 ~]# nmap 172.25.254.202 -p 80 Starting Nmap 7.92 ( https://nmap.org ) at 2025-04-09 15:33 CST Nmap scan report for 172.25.254.202 Host is up (0.00066s latency). PORT STATE SERVICE 80/tcp open http MAC Address: 00:0C:29:A5:34:FE (VMware) Nmap done: 1 IP address (1 host up) scanned in 13.18 seconds ## nginx关闭 [root@openEuler-1 ~]# nmap 172.25.254.202 -p 80 Starting Nmap 7.92 ( https://nmap.org ) at 2025-04-09 15:34 CST Nmap scan report for 172.25.254.202 Host is up (0.00077s latency). PORT STATE SERVICE 80/tcp closed http MAC Address: 00:0C:29:A5:34:FE (VMware) Nmap done: 1 IP address (1 host up) scanned in 13.14 seconds ## 当防火墙拦截时 [root@openEuler-1 ~]# nmap 172.25.254.202 -p 80 Starting Nmap 7.92 ( https://nmap.org ) at 2025-04-09 15:35 CST Nmap scan report for 172.25.254.202 Host is up (0.0013s latency). PORT STATE SERVICE 80/tcp filtered http MAC Address: 00:0C:29:A5:34:FE (VMware) Nmap done: 1 IP address (1 host up) scanned in 13.16 seconds ## open——正常,closed关闭,filtered——防火墙拦截 [root@openEuler-1 ~]# nmap 172.25.254.202 -p 80 | grep "^80\/tcp" | awk '{print $2}' open ## 编写脚本 [root@openEuler-1 ~]# vim chk_http.sh #!/bin/bash if [ $# -ne 2 ] then echo "Error,Parameter error" exit 1 else n=`nmap $1 -p $2 | grep "^$2\/tcp" | awk '{print $2}'` if [ "$n" == "open" ] then exit 0 else exit 1 fi fi [root@openEuler-1 ~]# chmod +x chk_http.sh [root@openEuler-1 ~]# ./chk_http.sh 172.25.254.201 80 [root@openEuler-1 ~]# echo $? 0 ## 在172.25.254.201上分别停止nginx和开启防火墙进行测试 [root@openEuler-3 ~]# systemctl stop nginx [root@openEuler-1 ~]# ./chk_http.sh 172.25.254.201 80 [root@openEuler-1 ~]# echo $? 1 [root@openEuler-3 ~]# systemctl start firewalld [root@openEuler-1 ~]# ./chk_http.sh 172.25.254.201 80 [root@openEuler-1 ~]# echo $? 1 ## 修改keepalived配置文件 [root@openEuler-1 ~]# vim /etc/keepalived/keepalived.conf real_server 172.25.254.201 80 { weight 1 MISC_CHECK { misc_path "/root/chk_http.sh 172.25.254.201 80" misc_timeout 3 } } real_server 172.25.254.202 80 { weight 1 MISC_CHECK { misc_path "/root/chk_http.sh 172.25.254.202 80" misc_timeout 3 } }
-
-
Nginx+Keepalived实现nginx集群配置案例
机器 | IP | 说明 |
---|---|---|
openEuler-1 | 172.25.254.100 | 主调度服务器 |
openEuler-2 | 172.25.254.200 | 副调度服务器 |
openEuler-3 | 172.25.254.201 | web1 |
openEuler-4 | 172.25.254.202 | web2 |
Rocky | 172.25.254.104 | 客户端 |
采用子配置文件的方式配置
##在openEuler-1和openEuler-2两台机器上配置
# yum install nginx -y
## 配置反向代理
# vim /etc/nginx/conf.d/web.conf
upstream websrvs {
server 172.25.254.201:80 weight=1;
server 172.25.254.202:80 weight=1;
}
server{
location / {
proxy_pass http://websrvs;
index index.html;
}
}
## 编写检测nginx存活的shell脚本
# vim /etc/keepalived/check_nginx.sh
#!/bin/bash
#代码一定注意空格,逻辑就是:如果nginx进程不存在则启动nginx,如果nginx无法启动则kill掉keepalived所有进程
A=`ps -C nginx --no-header |wc -l`
if [ $A -eq 0 ];then
systemctl start nginx
sleep 3
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
systemctl stop keepalived
fi
fi
## 配置keepalived
# mkdir /etc/keepalived/conf.d
# vim /etc/keepalived/keepalived.conf
......
include /etc/keepalived/conf.d/*.conf
[root@openEuler-1 ~]# vim /etc/keepalived/conf.d/server1.conf
vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -20
}
vrrp_instance VI_NGINX {
state MASTER
interface ens160
virtual_router_id 110
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
track_script {
chk_nginx
}
virtual_ipaddress {
172.25.254.10
}
}
[root@openEuler-2 ~]# vim /etc/keepalived/conf.d/server1.conf
vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -20
}
vrrp_instance VI_NGINX {
state BACKUP
interface ens160
virtual_router_id 110
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
track_script {
chk_nginx
}
virtual_ipaddress {
172.25.254.10
}
}
测试
## 在客户端测试
[root@Rocky ~]# for ((i=0;i<10;i++));do curl 172.25.254.10;done
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
web1 tset page,172.25.254.201 .
web2 tset page,172.25.254.202 .
## 停止172.25.254.201的nginx服务
[root@openEuler-3 ~]# systemctl stop nginx
[root@Rocky ~]# for ((i=0;i<10;i++));do curl 172.25.254.10;done
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
web2 tset page,172.25.254.202 .
[root@openEuler-3 ~]# systemctl start nginx
## 停止172.25.254.101的keepalived服务
[root@openEuler-1 ~]# systemctl stop keepalived
[root@openEuler-2 ~]# ip a | grep 172.25.254.10 ##此时vip漂移到172.25.254.200上
inet 172.25.254.10/32 scope global ens160
##开启keepalived服务,vip回归
[root@openEuler-1 ~]# systemctl start keepalived
[root@openEuler-1 ~]# ip a | grep 172.25.254.10
inet 172.25.254.10/32 scope global ens160
## 停止172.25.254.100上的nginx服务,可以发现nginx又自动启动
## 这是因为,当主调度服务器上的nginx异常时,check_nginx.sh脚本会先尝试重启nginx,如果启动失败,则切换到BACKUP
[root@openEuler-1 ~]# systemctl stop nginx
[root@openEuler-1 ~]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
Active: active (running) since Wed 2025-04-09 17:25:04 CST; 1s ago
Process: 11559 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Process: 11560 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 11562 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Main PID: 11564 (nginx)
Tasks: 2 (limit: 8950)
Memory: 3.1M
CGroup: /system.slice/nginx.service
├─11564 "nginx: master process /usr/sbin/nginx"
└─11566 "nginx: worker process"
Apr 09 17:25:04 openEuler-1 systemd[1]: Starting The nginx HTTP and reverse proxy server...
Apr 09 17:25:04 openEuler-1 nginx[11560]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Apr 09 17:25:04 openEuler-1 nginx[11560]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Apr 09 17:25:04 openEuler-1 systemd[1]: Started The nginx HTTP and reverse proxy server.
5.254.10/32 scope global ens160
## 停止172.25.254.100上的nginx服务,可以发现nginx又自动启动
## 这是因为,当主调度服务器上的nginx异常时,check_nginx.sh脚本会先尝试重启nginx,如果启动失败,则切换到BACKUP
[root@openEuler-1 ~]# systemctl stop nginx
[root@openEuler-1 ~]# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
Active: active (running) since Wed 2025-04-09 17:25:04 CST; 1s ago
Process: 11559 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Process: 11560 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 11562 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Main PID: 11564 (nginx)
Tasks: 2 (limit: 8950)
Memory: 3.1M
CGroup: /system.slice/nginx.service
├─11564 "nginx: master process /usr/sbin/nginx"
└─11566 "nginx: worker process"
Apr 09 17:25:04 openEuler-1 systemd[1]: Starting The nginx HTTP and reverse proxy server...
Apr 09 17:25:04 openEuler-1 nginx[11560]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Apr 09 17:25:04 openEuler-1 nginx[11560]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Apr 09 17:25:04 openEuler-1 systemd[1]: Started The nginx HTTP and reverse proxy server.