当我们只有一台服务器上部署了应用服务时,如果使用规模慢慢扩大,一台服务器的复杂能力肯定会达到极限,这时候如果我们有多台服务器部署着同样的服务,用户访问时可以被较为合理的分发到各个服务器上,提升了系统的负载能力和稳定性;
上面也说了,当使用多节点的时候,N多用户的访问请求如何合理的平均分配到不同应用服务器上,这时候Nginx就是中间的那个协调者,它负责统一入口并进行服务转发。
起初我们应为担心单应用挂掉,使用了多应用多节点,多节点的出现涉及流量请求转发的问题,这时候Nginx上前去做了负载均衡器。
既然Nginx是一台负载均衡服务器的服务,这台服务器是否稳定或者服务是否会异常停止,这个还真说不来,比如流量过大主机宕了,或者蓝翔挖掘机挖断了电缆(LOL)。
单一Nginx节点可能会出现一些不可预测的问题,所以我们模拟多节点应用服务器,就出现了多Nginx服务器的行为;
但是不可能给用户一堆域名和端口说你访问不了第一个的话访问第二个,所以就需要使用到了虚拟IP的技术VIP;
有了VIP,用户统一访问虚拟IP地址,再由Keepalived进行Nginx主备服务的检测,确保请求流量能够稳定的分发到对应的Nginx服务器上;
一旦Keepalived发现Nginx主服务挂了,就会通过一些机制尝试检测与恢复,当确认无法恢复时将立刻把请求服务转发给Nginx备用机,做到高可用不断线;
当然,两个Nginx服务器最好采用两点中心的策略,不然挖掘机可能一把挖断两台Nginx服务器的电缆。(LOL)
↓↓↓废话少说,接下来我们看看如何实操↓↓↓
Nginx + Keepalived 是一种常见的服务器高可用和负载均衡解决方案。
Nginx 是一款轻量级的高性能 Web 服务器、反向代理服务器以及电子邮件(IMAP/POP3)代理服务器。它具有高性能、高并发处理能力和低资源消耗等优点,常用于实现网站的负载均衡、动静分离等功能。
Keepalived 则是一个用于实现服务器高可用性(High Availability)的软件。它通过虚拟 IP 地址(VIP)的方式,监控服务器的状态,当主服务器出现故障时,能够自动将服务切换到备份服务器上,保证服务的连续性和稳定性。
例如,在一个网站架构中,有多台服务器运行 Nginx 来处理用户的请求。通过 Keepalived 配置一个虚拟 IP 地址,用户访问这个虚拟 IP 时,实际上会被动态地分配到正常工作的 Nginx 服务器上。如果某台 Nginx 服务器出现故障,Keepalived 会迅速将虚拟 IP 切换到其他正常的服务器上,用户的访问不会受到影响。
总之,Nginx + Keepalived 的组合可以有效地提高服务器的可靠性和服务的可用性,保障业务的稳定运行。
(附:NG+KL的这种架构可以换成任意的 X + KL的架构做到高可用,X可以是Mysql、Redis、Web服务等等)
【4】台Linux服务器,【2】台部署Nginx+Keepalived服务器,【2】台部署http服务;
Server1: Nginx+Keepalived主服务 IP:172.16.249.101
Server2: Nginx+Keepalived从服务 IP:172.16.249.102
Server3: HTTP双活A服务 IP:172.16.249.201
Server4: HTTP双活B服务 IP:172.16.249.202
推荐使用VMware Fusion虚拟机,并采用CentOS7 Mini镜像进行搭建(Server1、2、3、4均需要按此前置,若使用虚拟机,配置好一个直接完整复制虚拟机即可)
安装CentOS7操作系统
CentOS-7-x86_64-Minimal-2009.iso
安装必要包
yum install -y psmisc net-tools vim wget traceroute
cd /etc/yum.repos.d/ && mv CentOS-Base.repo CentOS-Base.repo.bak
wget http://mirrors.aliyun.com/repo/Centos-7.repo
mv Centos-7.repo CentOS-Base.repo
yum clean all
yum makecache
yum update -y
yum upgrade -y
注意这里可能出现403网络问题,如果出现简单的办法就是宿主机直接下载http://mirrors.aliyun.com/repo/Centos-7.repo
文件,并通过sftp上传到服务器上进行操作;
同步时间服务器
# 安装 ntp
yum install ntp -y
# 同步时间,这里以阿里云3号服务器为例,可以根据需要选择其他服务器
ntpdate ntp3.aliyun.com
# 默认EDT时间 需要切换
mv /etc/localtime /etc/localtime.bak
# 切换CST中国上海时间
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 测试时间是否同步
date
关闭防火墙
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
cat /etc/selinux/config
systemctl status firewalld.service
systemctl stop firewalld.service
systemctl disable firewalld.service
systemctl stop NetworkManager
systemctl disable NetworkManager
检查DNS和网关Gateway(参考)
1. cat /etc/resolv.conf # DNS 查看
2. traceroute www.baidu.com # 第一行就是自己的网关
3. route -n
4. ip route show
5. cat /etc/sysconfig/network-scripts/ifcfg-ens33
6. cat /etc/sysconfig/network
7. netstat –r
设置固定IP
vim /etc/sysconfig/network-scripts/ifcfg-ens33
# 将BOOTPROTO从dhcp调整为static(静态)
dhcp => static
# 文件末尾添加如下
IPADDR=172.16.249.101 # 固定IP
GATEWAY=172.16.249.2 # 网关
NETMASK=255.255.255.0 # 子网掩码
DNS1=172.16.249.2 # 默认DNS
DNS2=223.5.5.5 # 公共DNS
# 刷新网络服务
service network restart
安装Nginx
# 添加Nginx到Yum源
rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
# 安装Nginx
yum install -y nginx
# 启动Nginx服务
systemctl start nginx.service
配置Nginx
vim /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
#include /etc/nginx/conf.d/*.conf;
upstream ProxyServer {
server 172.16.249.201:80 weight=1;
server 172.16.249.202:80 weight=1;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# root /usr/share/nginx/html;
# include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://ProxyServer;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
# 重启启Nginx服务
systemctl start nginx.service
安装Keepalived
yum install -y keepalived
配置Keepalived
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id NginxNode001 # 唯一标识不可重复
vrrp_skip_check_adv_addr
#vrrp_strict # 不注释无法访问VIP
vrrp_garp_interval 0
vrrp_gna_interval 0
}
# 检测配置
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh" # 心跳检测脚本,用于检测Nginx服务,如果发现Nginx服务挂了,就立刻重启,如果重启多次后依旧发现起不来,则直接将当期服务器Keepalived节点服务关闭;
interval 5 # 心跳检测周期(秒)
weight -20 # 脚本检测失败的话 将减少priority优先级 每脚本检测失败后进行权重变更的单位
fall 2 # 检测脚本2次均失败的话,则认为脚本检测失败,进行服务优先级权重值变更
rise 1 # 检测脚本1次成功的话,就认为脚本检测成功,不会变更优先级权重值
}
vrrp_instance VI_1 {
state MASTER # 节点名称 MASTER/BACKUP 一般不关注,主要做个标识,主备依旧通过priority来控制
interface ens33 # 网卡名称
virtual_router_id 51 # Keepalived服务集群编号 同号同集群
priority 150 # 主备权重优先级 越大优先级越高 默认100 最大的是主
advert_int 1 # 主备通讯时间间隔(秒)
# 验证类型与密码 主备服务必须使用相同的验证方式与密码才可以正常通讯
authentication {
auth_type PASS
auth_pass 1111
}
# 添加检测脚本
track_script {
check_nginx
}
# 虚拟IP地址,可以设置1个或多个,只要没被使用过的同域IP均可
virtual_ipaddress {
172.16.249.80
172.16.249.90
172.16.249.100
}
}
配置心跳检测脚本
touch /etc/keepalived/check_nginx.sh
touch /etc/keepalived/check_nginx.log
chmod 777 /etc/keepalived/check_nginx.sh
vim /etc/keepalived/check_nginx.sh
#!/bin/bash
nginxpid=`ps -C nginx --no-header | wc -l`
if [ $nginxpid -eq 0 ];then
systemctl restart nginx
sleep 2
echo "$(date): systemctl restart nginx" >> /etc/keepalived/check_nginx.log
nginxpid=`ps -C nginx --no-header | wc -l`
if [ $nginxpid -eq 0 ];then
killall keepalived
echo "$(date): killall keepalived" >> /etc/keepalived/check_nginx.log
fi
fi
说明一下,脚本的意思是检测有没有nginx相关的进程,如果没有那么启动nginx服务,启动后等待2秒后再次检测,如果发现依旧没启动起来,那就说明nginx的配置或者服务有问题了,这个时候就需要杀掉keepalived服务进程,将服务转交给其它Keepalived服务节点;
# 重启keepalived服务
systemctl restart keepalived.service
与Server1 NG+KL服务器配置基本相同,只有2、6部分需要做调整,已标注。
检查DNS和网关Gateway(参考)
1. cat /etc/resolv.conf # DNS 查看
2. traceroute www.baidu.com # 第一行就是自己的网关
3. route -n
4. ip route show
5. cat /etc/sysconfig/network-scripts/ifcfg-ens33
6. cat /etc/sysconfig/network
7. netstat –r
设置固定IP
vim /etc/sysconfig/network-scripts/ifcfg-ens33
# 将BOOTPROTO从dhcp调整为static(静态)
dhcp => static
# 文件末尾添加如下
IPADDR=172.16.249.102 # 固定IP(这里与Server1不同)
GATEWAY=172.16.249.2 # 网关
NETMASK=255.255.255.0 # 子网掩码
DNS1=172.16.249.2 # 默认DNS
DNS2=223.5.5.5 # 公共DNS
# 刷新网络服务
service network restart
安装Nginx
# 添加Nginx到Yum源
rpm -Uvh
http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
# 安装Nginx
yum install -y nginx
# 启动Nginx服务
systemctl start nginx.service
配置Nginx
vim /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
#include /etc/nginx/conf.d/*.conf;
upstream ProxyServer {
server 172.16.249.201:80 weight=1;
server 172.16.249.202:80 weight=1;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# root /usr/share/nginx/html;
# include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://ProxyServer;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
# 重启启Nginx服务
systemctl restart nginx.service
安装Keepalived
yum install -y keepalived
配置Keepalived
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id NginxNode002 # 唯一标识不可重复(这里与Server1不同)
vrrp_skip_check_adv_addr
#vrrp_strict # 不注释无法访问VIP
vrrp_garp_interval 0
vrrp_gna_interval 0
}
# 检测配置
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh" # 心跳检测脚本,用于检测Nginx服务,如果发现Nginx服务挂了,就立刻重启,如果重启多次后依旧发现起不来,则直接将当期服务器Keepalived节点服务关闭;
interval 5 # 心跳检测周期(秒)
weight -20 # 脚本检测失败的话 将减少priority优先级 每脚本检测失败后进行权重变更的单位
fall 2 # 检测脚本2次均失败的话,则认为脚本检测失败,进行服务优先级权重值变更
rise 1 # 检测脚本1次成功的话,就认为脚本检测成功,不会变更优先级权重值
}
vrrp_instance VI_1 {
state MASTER # 节点名称 MASTER/BACKUP 一般不关注,主要做个标识,主备依旧通过priority来控制
interface ens33 # 网卡名称
virtual_router_id 51 # Keepalived服务集群编号 同号同集群
priority 100 # 主备权重优先级 越大优先级越高 默认100 这里是备(这里与Server1不同)
advert_int 1 # 主备通讯时间间隔(秒)
# 验证类型与密码 主备服务必须使用相同的验证方式与密码才可以正常通讯
authentication {
auth_type PASS
auth_pass 1111
}
# 添加检测脚本
track_script {
check_nginx
}
# 虚拟IP地址,可以设置1个或多个,只要没被使用过的同域IP均可
virtual_ipaddress {
172.16.249.80
172.16.249.90
172.16.249.100
}
}
配置心跳检测脚本
touch /etc/keepalived/check_nginx.sh
touch /etc/keepalived/check_nginx.log
chmod 777 /etc/keepalived/check_nginx.sh
vim /etc/keepalived/check_nginx.sh
#!/bin/bash
nginxpid=`ps -C nginx --no-header | wc -l`
if [ $nginxpid -eq 0 ];then
systemctl restart nginx
sleep 2
echo "$(date): systemctl restart nginx" >> /etc/keepalived/check_nginx.log
nginxpid=`ps -C nginx --no-header | wc -l`
if [ $nginxpid -eq 0 ];then
killall keepalived
echo "$(date): killall keepalived" >> /etc/keepalived/check_nginx.log
fi
fi
说明一下,脚本的意思是检测有没有nginx相关的进程,如果没有那么启动nginx服务,启动后等待2秒后再次检测,如果发现依旧没启动起来,那就说明nginx的配置或者服务有问题了,这个时候就需要杀掉keepalived服务进程,将服务转交给其它Keepalived服务节点;
# 重启keepalived服务
systemctl restart keepalived.service
检查DNS和网关Gateway(参考)
1. cat /etc/resolv.conf # DNS 查看
2. traceroute www.baidu.com # 第一行就是自己的网关
3. route -n
4. ip route show
5. cat /etc/sysconfig/network-scripts/ifcfg-ens33
6. cat /etc/sysconfig/network
7. netstat –r
设置固定IP
vim /etc/sysconfig/network-scripts/ifcfg-ens33
# 将BOOTPROTO从dhcp调整为static(静态)
dhcp => static
# 文件末尾添加如下
IPADDR=172.16.249.201 # 固定IP
GATEWAY=172.16.249.2 # 网关
NETMASK=255.255.255.0 # 子网掩码
DNS1=172.16.249.2 # 默认DNS
DNS2=223.5.5.5 # 公共DNS
# 刷新网络服务
service network restart
安装http web服务
yum -y install httpd
调整显示页面信息
echo 'HTTP WEB NODE 01' > /usr/share/httpd/noindex/index.html
启动服务
systemctl start httpd.service
检查DNS和网关Gateway(参考)
1. cat /etc/resolv.conf # DNS 查看
2. traceroute www.baidu.com # 第一行就是自己的网关
3. route -n
4. ip route show
5. cat /etc/sysconfig/network-scripts/ifcfg-ens33
6. cat /etc/sysconfig/network
7. netstat –r
设置固定IP
vim /etc/sysconfig/network-scripts/ifcfg-ens33
# 将BOOTPROTO从dhcp调整为static(静态)
dhcp => static
# 文件末尾添加如下
IPADDR=172.16.249.202 # 固定IP(这里与Server3不同)
GATEWAY=172.16.249.2 # 网关
NETMASK=255.255.255.0 # 子网掩码
DNS1=172.16.249.2 # 默认DNS
DNS2=223.5.5.5 # 公共DNS
# 刷新网络服务
service network restart
安装http web服务
yum -y install httpd
调整显示页面信息
echo 'HTTP WEB NODE 02' > /usr/share/httpd/noindex/index.html # (这里与Server3不同)
启动服务
systemctl start httpd.service
在同网段其它机器/宿主机,检查server1、server2、server3、server4服务是否均OK
# NG 检测
curl 172.16.249.101:80
curl 172.16.249.102:80
# Web 服务器检测
curl 172.16.249.201:80
curl 172.16.249.201:80
高可用测试
开5个终端进行测试
# VIP
watch -d -n 1 "curl 172.16.249.80:80"
# NG+KL
watch -d -n 1 "curl 172.16.249.101:80"
watch -d -n 1 "curl 172.16.249.102:80"
# HTTPWEB
watch -d -n 1 "curl 172.16.249.201:80"
watch -d -n 1 "curl 172.16.249.202:80"
Server1(NG+KL)、Server2(NG+KL)、Server3(HTTPWEB)、Server4(HTTPWEB)服务均正常运行时,我们可以看到:
# VIP(176.16.249.80/90/100)正常通过Server1的Nginx在进行分发请求;
# S1(176.16.249.101):正常(主)
# S2(176.16.249.102):正常(备)
# S3(176.16.249.201):正常
# S4(176.16.249.202):正常
HTTP WEB NODE01
HTTP WEB NODE02
HTTP WEB NODE01
HTTP WEB NODE02
...
Server1(NG+KL) 关闭Nginx与Keepalived服务
Server2(NG+KL)、Server3(HTTPWEB)、Server4(HTTPWEB)正常,我们可以看到:
# VIP(176.16.249.80/90/100)正常通过Server2的Nginx在进行分发请求;
# S1(176.16.249.101):NG\KL服务关闭(主)
# S2(176.16.249.102):正常(备)
# S3(176.16.249.201):正常
# S4(176.16.249.202):正常
HTTP WEB NODE01
HTTP WEB NODE02
HTTP WEB NODE01
HTTP WEB NODE02
...
Server1(NG+KL) 、Server2(NG+KL)关闭Nginx与Keepalived服务
Server3(HTTPWEB)、Server4(HTTPWEB)正常,我们可以看到:
# VIP(176.16.249.80/90/100)请求阻塞(不刷新了)
# S1(176.16.249.101):NG\KL服务关闭(主)
# S2(176.16.249.102):NG\KL服务关闭(备)
# S3(176.16.249.201):正常
# S4(176.16.249.202):正常
# 卡住
Server1(NG+KL) 关闭Nginx与Keepalived服务
Server3(HTTPWEB)、Server4(HTTPWEB)正常,
重启Server2(NG+KL)的Keepalived服务,我们可以看到:
# VIP(176.16.249.80/90/100)正常通过Server2的Nginx在进行分发请求;
# S1(176.16.249.101):NG\KL服务关闭(主)
# S2(176.16.249.102):重启NG\KL服务(备)
# S3(176.16.249.201):正常
# S4(176.16.249.202):正常
HTTP WEB NODE01
HTTP WEB NODE02
HTTP WEB NODE01
HTTP WEB NODE02
...
Server1(NG+KL) 、Server3(HTTPWEB)、Server4(HTTPWEB)正常,
重启Server1(NG+KL)的Keepalived服务,我们可以看到:
# VIP(176.16.249.80/90/100)立刻自动切换到Server1上进行转发(会有一个跳动点)
# S1(176.16.249.101):重启NG\KL服务(备)
# S2(176.16.249.102):正常(备)
# S3(176.16.249.201):正常
# S4(176.16.249.202):正常
HTTP WEB NODE01
HTTP WEB NODE02
HTTP WEB NODE01
HTTP WEB NODE02
...
🎉如果对你有所帮助,可以点赞、关注、收藏起来,不然下次就找不到了🎉
【点赞】⭐️⭐️⭐️⭐️⭐️
【关注】⭐️⭐️⭐️⭐️⭐️
【收藏】⭐️⭐️⭐️⭐️⭐️
Thanks for watching.
–Kenny