Docker 搭建 Keepalived 实现 Nginx 双机热备

keepalived Nginx HA

docker 搭建 keepalived 实现 nginx 双机热备

❯ docker run --privileged -d --name node1 debian:11 top -b
❯ docker run --privileged -d --name node2 debian:11 top -b

–-privileged 是指以特权模式启动容器,否则 keepalived 无法成功生成虚拟 IP

分别进入 node1、node2 容器节点(docker exec -it node1 /bin/bashdocker exec -it node2 /bin/bash

安装以下软件 apt update && apt install curl vim iproute2 inetutils-ping psmisc net-tools systemctl nginx keepalived -y

创建以下两个文件:

vi /etc/keepalived/chk_nginx.sh

#!/bin/bash
echo $(date) "start check nginx..." >> /etc/keepalived/check_nginx.log

counter=$(systemctl status nginx | grep running | wc -l)
if [ "${counter}" = "0"  ]; then
   echo $(date)  "nginx is not running, restarting..." >> /etc/keepalived/check_nginx.log
   systemctl start nginx
   sleep 2
   counter=$(systemctl status nginx | grep running | wc -l)
   if [ "${counter}" =  "0" ]; then
      echo $(date) "nginx is down, kill all keepalived..." >> /etc/keepalived/check_nginx.log
      killall keepalived
   fi
fi

脚本作用是查看是否存在 nginx 进程,不存在就重启 nginx,然后再查看一次,还不存在就杀掉 keepalived 进程(这样备既就会自动上线) 脚本权限需设置为 755(chmod 755 /etc/keepalived/chk_nginx.sh),否则 keepalived 会认为它不安全 注意首行一定是 #!/bin/bash,而不是 #/bin/bash,否则脚本不会被 keepalived 执行

node1 容器节点为虚拟 IP 172.17.0.201 的主节点、虚拟IP 172.17.0.202 的备用节点, keepalived 配置文件如下:

vi /etc/keepalived/keepalived.conf

! Configuration File for keepalived

global_defs {
    router_id localhost
    script_user root
    enable_script_security
}

vrrp_script chk_http_port {
    script /etc/keepalived/chk_nginx.sh
    interval 10 # 间隔几秒执行脚本(注意最好大于脚本的执行时间)
    weight -20
}

vrrp_instance VI_1 {
    state MASTER # 1、备机改为:BACKUP
    interface eth0 # 2、替换为实际网卡名称,可使用 ifconfig 或 ip addr 查看
    virtual_router_id 51
    priority 100 # 3、备机优先级设置小一点,例如:90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    track_script {
       chk_http_port
    }
    virtual_ipaddress {
        172.17.0.201 # 虚拟 IP(和 node1、node2 容器节点在同一网段的任意闲置 IP 即可)
    }
}

vrrp_instance VI_2 {
    state BACKUP
    interface eth0 #
    virtual_router_id 52
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    track_script {
       chk_http_port
    }
    virtual_ipaddress {
        172.17.0.202
    }
}

node2 容器节点为虚拟 IP 172.17.0.202 的主节点、虚拟IP 172.17.0.201 的备用节点, keepalived 配置文件如下:

vi /etc/keepalived/keepalived.conf

! Configuration File for keepalived

global_defs {
    router_id localhost
    script_user root
    enable_script_security
}

vrrp_script chk_http_port {
    script /etc/keepalived/chk_nginx.sh
    interval 10
    weight -20
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    track_script {
       chk_http_port
    }
    virtual_ipaddress {
        172.17.0.201
    }
}

vrrp_instance VI_2 {
    state MASTER
    interface eth0
    virtual_router_id 52
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    track_script {
       chk_http_port
    }
    virtual_ipaddress {
        172.17.0.202
    }
}

node1 和 node2 容器节点互为主备, keepalived 配置文件除过注释标注的 3 处不同外,其余配置项保持一致即可 可使用 keepalived -t 检测配置文件是否有误

为了验证主备切换效果,可分别在主备 nginx 默认界面添加不同信息加以区分(vi /var/www/html/index.nginx-debian.html

1、分别启动 node1 和 node2 容器节点的 keepalived(systemctl start keepalived

2、在 node1 节点容器使用 ifconfig 或 ip addr 命令可看到绑定的虚拟 IP 172.17.0.201,此时通过访问虚拟 IP:curl http://172.17.0.201 展示的是 node1 节点的 nginx 信息

3、在 node2 节点容器使用 ifconfig 或 ip addr 命令可看到绑定的虚拟 IP 172.17.0.202,此时通过访问虚拟 IP:curl http://172.17.0.202 展示的是 node2 节点的 nginx 信息

4、故意改错 node1 上的 nginx 配置文件让其无法启动,并且停止 nginx(systemctl stop nginx)(模拟宕机情况),node1 节点的 keepalived 检测到 nginx 进程不存在,然后尝试启动 nginx,发现启动失败,所以会杀掉 keepalived 进程,释放虚拟 IP 172.17.0.201

5、node2 节点 keepalived 感知到 node1 节点下线后会绑定虚拟 IP 172.17.0.201 接管请求,完成主备切换。此时在 node2 节点容器使用 ifconfig 或 ip addr 命令可看到绑定的虚拟 IP 172.17.0.201172.17.0.202,此时通过访问 curl http://172.17.0.201curl http://172.17.0.201 展示的都是 node2 节点的 nginx 信息

6、当恢复 node1 节点 nginx 配置文件并重新加载,然后启动 keepalived,在 node1 容器节点使用 ifconfig 或 ip addr 命令可再次看到绑定的虚拟 IP 172.17.0.201,此时通过访问 curl http://172.17.0.201 展示的又是 node1 节点的 nginx 信息,访问 curl http://172.17.0.201 展示的是 node2 节点的 nginx 信息