原理
nginx 可以实现负载均衡,但 nginx 自身存在单点故障的问题,这时候最先想到的就是 keepalived,可以解决单点故障的问题
由于没有使用 lvs,所以这里 nginx 之间不存在负载均衡
同时,如果 keepalived 的 master 节点 nginx 服务宕了以后,如果 keepalived 还在运行,则用户就访问不到 nginx 服务了,所以需要添加监控脚本,当 nginx 宕机时,杀死本机的 keepalived 服务
这样,keepalived 的 master 就会切换,同时用户访问的 nginx 服务也会切换到原来的 backup 节点
测试节点
RIP | VIP | |
MASTER | 192.168.132.136 | 192.168.132.200 |
SLAVE | 192.168.132.140 | 192.168.132.200 |
配置nginx
安装 nginx 不是重点,这里就是用 yum 简单安装
yum -y install nginx systemctl start nginx
配置keepalived
安装 keepalived 使用 yum 安装即可
keepalived 配置如下:
global_defs { notification_email { chen@test.com } notification_email_from chen@test.com smtp_server smtp.exmail.qq.com smtp_connect_timeout 30 router_id my-slave } vrrp_script chk_nginx { script "/etc/keepalived/nginx_check.sh" interval 5 } vrrp_instance my_nginx { state MASTER # BACKUP 节点这里配置成 BACKUP interface ens37 virtual_router_id 51 priority 200 # BACKUP 节点配置要比该值小 advert_int 1 # vrrp_script定义的chk_nginx需要放到vrrp_instance里,用track_script指定,才能执行 track_script { chk_nginx } authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.132.200/24 dev ens37 label ens37:200 } }
以上配置中,重点在脚本 /etc/keepalived/nginx_check.sh
该脚本会被每 5s 执行一次,用来检测 nginx 是否存活,如果不存活,则尝试重启 nginx,启动失败的话,会将本机的 keepalived 服务也杀死,保证切换主节点,不影响 nginx 访问
脚本 /etc/keepalived/nginx_check.sh 内容如下:
#!/bin/bash # 注意,整个脚本的执行时间必须小于keepalived中定义的时间间隔,即interval定义的时间,否则下次执行脚本时,会杀死上次正在执行的脚本 systemctl status nginx &> /dev/null # 检查nginx状态,nginx正常运行,$?为0,否则为非零数 if [ $? -ne 0 ];then systemctl start nginx # 启动nginx后等待2s,保证nginx已经正常启动运行,如果nginx还未正常运行,则关闭keepalived服务,使用备用keepalived sleep 2 systemctl status nginx &> /dev/null if [ $? -ne 0 ];then systemctl stop keepalived fi fi
keepalived 配置公网虚拟IP
因为内网IP我们可以随意支配,随意容易配置,但配置公网虚拟IP时,还是有很大不同的,这里以云厂商提供的云主机为例
首先,需要主备keepalived机器都包含两个网卡,其中一个网卡为绑定内网,另一个绑定公网
事实上,两台云主机只需要有一个绑定了公网即可,但网卡数量不能少
大部分云厂商提供的云主机中,都包含公网网卡,但是也有只有内网网卡的
之所以可以使用公网IP访问,应该是通过路由器设置的,如金山云的云主机就只有内网网卡,这种机器暂时不知道怎么配置keepalived 的虚拟公网IP
这里服务器ip如下:
服务器 | 内网 | 外网 |
A | 192.168.10.30 | 118.110.20.14 |
B | 192.168.10.40 |
外网IP的默认路由为118.110.20.11
内网网卡名为 ens224
外网网卡名为 ens160
方法一:
这里需要将两个服务器外网网卡都配置成不包含IP的配置并启动:
[admin@test ~]$ cat /etc/sysconfig/network-scripts/ifcfg-ens160 # 其中大部分配置都不是必须的,只需要能保证网卡能正常启动且不包含IP即可 HWADDR=00:50:56:8b:72:14 NAME=ens160 # GATEWAY=118.110.20.12 # NETMASK=255.255.255.240 # IPADDR=118.110.20.14 DNS1=8.8.4.4 DNS2=8.8.8.8 DOMAIN=example DEVICE=ens160 ONBOOT=yes USERCTL=no BOOTPROTO=static PEERDNS=no check_link_down() { return 1; }
keepalived配置如下:
# 这里只列出了主要部分,其他部分按照前面的例子来即可 vrrp_instance my_nginx { state MASTER interface ens224 # 这里必须写成内网网卡名,不能写成外网网卡名 virtual_router_id 51 priority 100 advert_int 1 track_script { chk_nginx } authentication { auth_type PASS auth_pass 111111 } virtual_ipaddress { 118.110.20.14/28 dev ens160 # 这里配置和上面的例子不一样,相当于直接配置ens160网卡,没用到label } virtual_routes { default via 118.110.20.12 # 这里配置默认路由 } }
注意,我们前面的例子中,interface 和虚拟网卡指定的网卡名都是一样,但事实上,这两个是没有联系的
interface 指定的网卡是用来发送arrp包的源地址,而虚拟网卡指定的网卡是为了做虚拟IP的
因为,如果我们这里interface 指定的网卡名为ens160,由于这个网卡没有IP,则由于发送arrp包时找不到源地址,而导致启动keepalived失败,报错如下,在/var/log/message中能找到报错信息:
Cannot find an IP address to use for interface
方法二:
主要思路是,两台机器都配置好公网网卡,IP都配置成118.193.20.4,然后让主的公网网卡启动,从的公网网卡关闭
具体步骤如下:
网卡配置如下:
[root@test sites]# cat /etc/sysconfig/network-scripts/ifcfg-ens160 HWADDR=00:50:56:8b:0e:60 NAME=ens160 GATEWAY=118.110.20.12 DNS1=8.8.4.4 DNS2=8.8.8.8 DOMAIN=example DEVICE=ens160 ONBOOT=yes USERCTL=no BOOTPROTO=static NETMASK=255.255.255.240 IPADDR=118.110.20.14 PEERDNS=no check_link_down() { return 1; }
keepalived配置如下:
vrrp_instance my_nginx { state BACKUP interface ens224 # 这里必须写成内网网卡名,不能写成外网网卡名 virtual_router_id 51 priority 100 advert_int 1 track_script { chk_nginx } authentication { auth_type PASS auth_pass 111111 } notify_master /etc/keepalived/script/master.sh notify_backup /etc/keepalived/script/backup.sh }
这里master.sh内容如下,主要功能是保证公网网卡启动:
#!/bin/bash ifconfig | grep 118.110.20.14 if [ $? -ne 0 ];then ifconfig ens160 up fi
backup.sh内容如下,主要功能就是关闭公网网卡:
#!/bin/bash # 即使已经关闭了,再执行该命令也不会有报错,所以不用做判定 ifconfig ens160 down