当前位置: 首页 > news >正文

高可用集群-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 也可以根据配置,决定是否将服务切回原主服务器,或者让新主服务器继续承担服务任务,直到下次故障发生
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 具有以下主要特点:

    1. 与 LVS 兼容性好:作为 LVS 的扩展项目,Keepalived 与 LVS 之间有着良好的兼容性,能在 LVS 相关场景中稳定高效运行,为基于 LVS 的负载均衡系统提供有力支持。
    2. 配置相对简单:相较于 Heartbeat 等 HA 软件,Keepalived 的部署更为简洁。Heartbeat 复杂的配置流程让不少人望而却步,而 Keepalived 在这方面具有明显优势,降低了运维成本和技术门槛。
    3. 健康检查与故障隔离:通过对服务器池对象进行健康检查,Keepalived 能够及时发现失效的机器或服务,并将其隔离,确保整个系统的稳定性和可靠性,避免因单点故障影响业务的正常运行。
    4. 基于 VRRP 的故障切换:负载均衡器之间的失败切换是通过 VRRPv2 stack 实现的。VRRP 最初就是为解决静态路由器的单点故障问题而设计,Keepalived 借助这一成熟的协议,实现了高效、快速的故障切换,保障网络服务的连续性。
    5. 与 iptables 兼容性佳:在实际线上项目中可知,iptables 的启用不会影响 Keepalived 的运行。不过,为了追求更好的性能,通常会将整套系统内所有主机的 iptables 停用,以减少系统开销,提升整体性能。
    6. VIP 设置与灵活组网:Keepalived 产生的 VIP 作为整个系统对外的 IP,方便进行统一的网络配置和管理。如果最外端的防火墙采用路由模式,还可将此内网 IP 映射为公网 IP,实现内外网的灵活组网和通信,适应不同的网络环境和应用需求。

keepalive配置文件说明

整体结构

Keepalived 配置文件主要由 3 个部分构成:

  1. 全局配置(Global Configuration):这部分定义了与 Keepalived 进程相关的全局参数。
  2. VRRP 实例配置(VRRP Instance Configuration):用于配置 VRRP 实例,实现虚拟路由冗余。
  3. 虚拟服务器配置(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_masternotify_backupnotify_fault:分别为切换到主、备用、故障状态时执行的脚本路径。

    • smtp_serversmtp_connect_timeoutemail_fromemail_to:邮件通知相关配置。

  • VRRP 实例配置(vrrp_instance

    • state:实例的初始状态,有 MASTERBACKUP 两种。

    • 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.100openEuler-1MASTER(主路由器)
    172.25.254.200openEuler-2BACKUP(备份路由器)
  • 安装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值之和,主节点不变,不发生切换。
    • weight 为负数
      • 脚本检测失败:当 Master 节点的vrrp_script脚本检测失败,若其priority值与weight值之差小于 Backup 节点的priority值,会发生主备切换。
      • 脚本检测成功:当 Master 节点的vrrp_script脚本检测成功,若其priority值大于 Backup 节点的priority值,主节点不变,不发生切换。
  • 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-1ens160:172.25.254.100/24
ens192:10.10.10.1/24
ens192用于心跳检测
openEuler-2ens160:172.25.254.200/24
ens192:10.10.10.2/24
openEuler-3172.25.254.201web1
openEuler-4172.25.254.202web2
## 在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_GETHTTP_GET相似,只是使用 SSL 连接。它们都有基于返回码确认和基于确认后端页面内容 hash 值两种检测方式,可处理简单的 GET 请求,不适用基于 POST 返回值确认,POST 方式可通过MISC_CHECK支持检测。

    • SMTP_CHECK:用于检测邮件服务的 SMTP。可配置connect_ipconnect_port(默认检查端口 25)、connect_timeoutretrydelay_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-1172.25.254.100主调度服务器
openEuler-2172.25.254.200副调度服务器
openEuler-3172.25.254.201web1
openEuler-4172.25.254.202web2
Rocky172.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.

相关文章:

  • 学习笔记八——内存管理相关
  • 丝杆升降机各部件材质深度剖析:解锁高效稳定运行的技术密码
  • Spring Security 中 PasswordEncoder(密码编码器) 及其实现类对比与示例
  • 【深度学习】【目标检测】【Ultralytics-YOLO系列】YOLOV3工程整体结构解析
  • 自动化运行后BeautifulReport内容为空
  • 【第三十一周】ViT 论文阅读笔记
  • 【Redis】redis事物与管道
  • (四)深入理解AVFoundation-播放:高度自定义视频播放器 UI
  • react从零开始的基础课1
  • LeetCode:链表
  • 如何使用DeepSeek制作数学动态可视化课件?
  • MyBatis 中 Mapper 传递参数的多种方法
  • STM32自学进阶指南:从入门到精通的成长路径 | 零基础入门STM32第九十九步
  • 2. Scala 高阶语法之集合与元组
  • 【HarmonyOS 5】鸿蒙实现手写板
  • Linux找不到virtualenvwrapper.sh(已解决)
  • 提示词工程学习笔记
  • FreertosHAL库笔记
  • 什么是供应链金融
  • 监控docker中的java应用
  • 中国空间站多项太空实验已取得成果,未来将陆续开展千余项研究
  • 中国代表:美“对等关税”和歧视性补贴政策严重破坏世贸规则
  • 应急管理部派出工作组赴山西太原小区爆炸现场指导救援处置
  • 4月译著联合书单|心爱之物:热爱如何联结并塑造我们
  • 十四届全国人大常委会举行第四十三次委员长会议 ,听取有关草案和议案审议情况汇报
  • 安阳一村支书微信群骂村民被警方行拘,辩称对方先“污蔑造谣”