Keepalive + VIP 配置 nginx 主备集群

发布时间: 更新时间: 总字数:1935 阅读时间:4m 作者: IP上海 分享 网址

Keepalived 是一个用 C 语言编写的路由软件,它通过维护 VIP(Virtual IP) 实现为 Linux 系统提供简单而健壮的负载均衡和高可用性设施。

介绍

  • 架构

keepalive vip arch

说明:

  • 图中的 VIP 由 keepalive 维护
  • 使用场景
    • 双活主备
    • 冷备(注意是否切换成功)
        • 主 priority > 备 priority && 主 priority + 主 vrrp_script.weight < 备 priority + 备 vrrp_script.weight
      • 备的 notify_master 脚本中有启动服务的命令,备中服务最初处于关闭状态

重要概念

  • 虚拟 IP 地址(VIP 或 VIPA)是指与实际物理网口不对应的 IP 地址。对 vip 的使用包括网络地址转换(特别是一对多 NAT)、容错和移动性
    • A virtual IP address (VIP or VIPA) is an IP address that doesn’t correspond to an actual physical network interface. Uses for VIPs include network address translation (especially, one-to-many NAT), fault-tolerance, and mobility.
  • LVS(Linux virtual server) Linux 虚拟服务器,是一个虚拟的服务器集群系统。工作原理:用户请求 LVS VIP,LVS 根据转发方式和算法,将请求转发给后端服务器,后端服务器接收到请求,返回给用户。
  • ARP(Address Resolution Protocol) 协议属于 TCP/IP 协议族里面一种用户将 IP 地址解析为 MAC 地址的协议。该协议是用户局域网内解析 IP 地址对应的物理地址。
  • 虚拟路由冗余协议 VRRP(Virtual Router Redundancy Protocol) 通过把几台路由设备联合组成一台虚拟的路由设备,将虚拟路由设备的 IP 地址作为用户的默认网关实现与外部网络通信。

安装部署

环境说明

VMware Fusion pro,自定义网络已经打开混杂模式(VMware Fusion -> 偏好设置 -> 网络 -> 勾选 允许通过鉴定才能进入混杂模式):

  • host1: 172.20.0.21
  • host2: 172.20.0.22
  • vip: 172.20.0.20

所有机器均配置 ip_nonlocal_bind 绑定(实现没有 vip 时,可以启动 haproxy 等服务):

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

CentOS 安装

host1host2 安装软件

  • rpm 安装
yum install -y nginx keepalived
  • 修改 nginx 主页
sed -i "s#Welcome to CentOS#Welcome to CentOS`ip a | grep "172.20" | awk '{print $2}'`#g" /usr/share/nginx/html/index.html

通过 ip 地址区分访问的是哪个 nginx

  • 启动服务
systemctl start nginx.service
systemctl enable nginx.service

systemctl start keepalived.service
systemctl enable keepalived.service

配置 nginx

  • nginx 存活检测脚本 /usr/local/bin/check_nginx_alive.sh
#!/bin/bash

nginx_count=`ps -C nginx --no-header |wc -l`
if [ $nginx_count -eq 0 ]; then
    echo 'nginx server is died'
    exit 1
fi

exit 0

或使用 systemctl is-active nginx 命令检测。

  • 添加执行权限
chmod +x /usr/local/bin/check_nginx_alive.sh

配置 host1 keepalive

host1 为 MASTER,priority 优先级为 100

  • 如果 rise 次脚本执行都是成功的(返回 0),则增加 weight 数量的优先级

  • 如果是 fall 次脚本执行都是失败的(返回 1),则减少|weight|数量的优先级

  • /etc/keepalived/keepalived.conf

    • 配置文件示例 /etc/keepalived/keepalived.conf.sample/usr/share/.../keepalived.conf.vrrp.localcheck(不同版本略有不同)
! Configuration File for keepalived

global_defs {
    router_id LVS_DEVEL
    vrrp_skip_check_adv_addr
    # vrrp_strict
    vrrp_garp_interval 0
    vrrp_gna_interval 0
}

vrrp_script check_nginx_alive {
    script "/usr/local/bin/check_nginx_alive.sh"
    interval 3
		rise 2
		fall 3
    weight -15
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.20.0.20 dev ens33
    }
    track_script {
        check_nginx_alive
    }
    # notify_master xxx
    # notify_backup xxx
		# notify_f.. xxx
}

virtual_server 172.20.0.20 80 {
    delay_loop 6
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
		# preempt

    real_server 172.20.0.21 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port 80
        }
    }
}
  • advert_int: 心跳间隔

  • interface eth0 监听的网卡名称

  • virtual_router_id 51 必须与主节点一致

  • priority 50 优先级低于主节点

  • 工作模式

    • preempt 抢占模式(默认)当 master 出现异常后,backup 自动切换为 master;当 master 恢复正常后会再次抢占成为 master
    • nopreempt 非抢占模式
  • 重启

systemctl restart keepalived

配置 host2 keepalive

host2 为 BACKUP,priority 优先级为 90(比 host1 底)

  • /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
    router_id LVS_DEVEL
    vrrp_skip_check_adv_addr
    # vrrp_strict
    vrrp_garp_interval 0
    vrrp_gna_interval 0
}

vrrp_script check_nginx_alive {
    script "/usr/local/bin/check_nginx_alive.sh"
    interval 3
    weight -15
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.20.0.20 dev ens33
    }
    track_script {
        check_nginx_alive
    }
}

virtual_server 172.20.0.20 80 {
    delay_loop 6
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    real_server 172.20.0.22 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port 80
        }
    }
}
  • 重启
systemctl restart keepalived

检测

  • host1 中存在 vip
$ ip a show ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:33:42:98 brd ff:ff:ff:ff:ff:ff
    inet 172.20.0.21/24 brd 172.20.0.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet 172.20.0.20/32 scope global ens33
       valid_lft forever preferred_lft forever
  • 访问 http://172.20.0.20 可以看到为 host1 的 nginx

  • 停止 host1 的 nginx

systemctl stop nginx

可以观察到 vip 漂移到 host2,并且 访问 http://172.20.0.20 可以看到为 host2 的 nginx

  • 启动 host1 的 nginx
systemctl start nginx

可以观察到 vip 漂移到 host1,并且 访问 http://172.20.0.20 可以看到为 host1 的 nginx

运维

问题是排查命令

  • tcpdump proto 112
  • tcpdump -i ens33 vrrp -n
  • arp -n
  • ip -br a 查看 ip 地址

haproxy 存活检测脚本

  • check_haproxy
vrrp_script check_haproxy {
    script "/usr/local/bin/check_keepalive.sh"
    interval 1
    weight -15
    fall 3
    rise 2
    timeout 2
}
  • /usr/local/bin/check_haproxy_alive.sh
#!/bin/bash

# This will return 0 when it successfully talks to the haproxy daemon via the socket
# Failures return 1

echo "show info" | socat unix-connect:/var/lib/haproxy/stats stdio > /dev/null

chmod a+x /usr/local/bin/check_haproxy_alive.sh

  • /usr/local/bin/check_haproxy_alive2.sh 另一种实现方式?
#!/bin/bash

/usr/bin/killall -0 haproxy || systemctl restart haproxy

nginx

vrrp_script chk_nginx {
 script "/etc/keepalived/nginx_check.sh"
 interval 2   # 指定脚本执行的间隔,单位是秒,默认为1s
 weight -20   # 调整优先级。默认为2。如果脚本执行失败(退出状态码为非0),weight小于0,则priority减少
 fall 3     # 执行失败多少次才认为失败
 rise 2     # 执行成功多少次才认为是成功
 user root      # 加上用户名,使用root用户登录的话
}
  • nginx_check.sh
#!/bin/bash
A=`ps -ef | grep nginx | grep -v grep | wc -l`
if [ $A -eq 0 ];then
    nginx
    sleep 2
    if [ `ps -ef | grep nginx | grep -v grep | wc -l` -eq 0 ];then
        # killall keepalived
        ps -ef|grep keepalived|grep -v grep|awk '{print $2}'|xargs kill -9
    fi
fi  

Tracking files

  • Keepalived 支持根据文件内容来决定优先级,如运行的应用程序能向该文件(/var/run/my_app/vrrp_track_file)写入值
    • echo 5 > /var/run/my_app/vrrp_track_file,则 prio 249 = 244 + 5
vrrp_track_file track_app_file {
      file /var/run/my_app/vrrp_track_file
}

vrrp_instance VI_1 {
      state MASTER
      interface eth0
      virtual_router_id 51
      priority 244
      advert_int 1
      authentication {
         auth_type PASS
         auth_pass 12345
      }
      virtual_ipaddress {
         192.168.122.200/24
      }
      track_file {
         track_app_file weight 1
   }
}

Track interface

  • 对于有多个接口的服务器,根据接口的状态调整 Keepalived 实例的优先级
    • 若接口 ens5 是 up 的状态,prio 249 = 244 + 5
vrrp_instance VI_1 {
      state MASTER
      interface eth0
      virtual_router_id 51
      priority 244
      advert_int 1
      authentication {
         auth_type PASS
         auth_pass 12345
      }
      virtual_ipaddress {
         192.168.122.200/24
      }
      track_interface {
         ens9 weight 5
      }
}

F&Q

Error exec-ing command ‘’, error 8: Exec format error

脚本开头加 #!bin/bash

Disabling track script xxx since not found/accessible

脚本需要写绝对路径

Keepalived_vrrp[]: WARNING - default user ‘keepalived_script’ for script execution does not exist

keepalived.conf 中添加:

global_defs {
   script_user root
}

scripts are being executed but script_security not enabled

keepalived.conf 中添加:

global_defs {
   enable_script_security
}

vip ping 不通

删除如下配置中的 vrrp_strict,严格遵守 VRRP 协议,不允许状况:

  • 没有 VIP 地址
  • 单播
  • 在 VRRP 版本 2 中使用 IPv6 地址
global_defs {
   vrrp_strict
}

参考

  1. https://www.keepalived.org
  2. https://www.redhat.com/en/blog/advanced-keepalived
  3. https://en.wikipedia.org/wiki/Virtual_IP_address
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数