Docker+Nginx+KeepaLived 简单实现Nginx高可用+负载均衡
我们知道 Nginx反向代理可以简单的实现负载均衡(不知道的话可以先去百度了解下,这里就当你知道了,haha...)
如果服务器节点(Service节点)挂了,可以使用其他组件去做心跳检测(Consul、k8s等等),今天先不说这些。
今天主要说说:如果Nginx代理所在服务器挂了该怎么办?如何实现Nginx的高可用?
先看下图:
解释:
1,两台Nginx服务器,一主一备,也可以一主N备,每台Nginx服务器上负载有两台Service节点
2,客户端发起一个请求 ,请求没有到Nginx的实际IP上,而是请求的虚拟IP(会和实际IP通过配置文件进行绑定)
3,这时候如果有一台Nginx服务器挂了,Keepalived会自动在备Nginx服务器上选一台当主服务器
接下来落地实操
1,准备2台服务器(Linux),这里示例IP分别为:192.168.1.104、192.168.1.105
2,设置发送邮件的功能,后边使用:参考另一篇博文: Linux系统下用mail(mailx)发送邮件
3,两台服务器上分别安装 Docker (参考另一篇博文:https://www.cnblogs.com/peterzhang123/p/13858345.html)
4,在两台机器的Docker上分别安装Nginx,对外访问端口为:4001 (参考另一篇博文:https://www.cnblogs.com/peterzhang123/p/13864381.html)
5,在两台机器上分别安装 keepalived (注意:keepalived安装在实体机上,不是安装到Docker上)
6,准备一个虚拟IP,说人话就是弄个假IP,当前网段内没人用该IP 例如:192.168.1.110
7,准备两个Service服务(ApI应用),为了演示,这里提供两个不同端口IP地址作为负载(192.168.1.102:5001,192.168.1.102:5002)
1,配置Nginx内容
upstream group1 { server 192.168.1.102:5001; server 192.168.1.102:5002; } server { listen 80; server_name localhost; location / { proxy_pass http://group1/; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
2,在Linux主机上安装 Keepalived
#切换到 /usr目录下 cd /usr #安装keepalived环境依赖 yum install -y gcc openssl-devel popt-deve #安装keepalived yum install keepalived -y
#验证是否安装成功
rpm -q -a keepalived
#移除
yum remove keepalived
安装之后,在 /etc/keepalived目录下有个 keepalived.conf 配置文件
修改 keepalived.conf 配置文件,配置内容参考如下 (注意区分 主/备的配置不一样)
! Configuration File for keepalived global_defs { # 通知邮件服务器的配置 # 当master失去VIP或则VIP的时候,会发一封通知邮件到your-email@qq.com notification_email { 131xxxxx@qq.com # 收件人 } notification_email_from xxxxx@163.com # 邮件发送方地址 smtp_server smtp.163.com # 163邮件服务器 smtp_connect_timeout 30 # 邮件服务器超时时间 router_id LVS_DEVEL # 唯一ID,设置成IP也行 vrrp_mcast_group4 192.168.1.104 # 当前服务器的IP } # 检查nginx状态的脚本,健康监测脚本 vrrp_script chk_http_port { script "/etc/keepalived/nginx_check.sh" # 脚本路径 interval 2 # 脚本执行间隔时间 weight 3 } vrrp_instance VI_1 { state MASTER # 主机使用: MASTER 备机使用: BACKUP interface ens33 # 实例绑定的网卡, 用ip a命令查看网卡编号 virtual_router_id 51 # 虚拟路由标识,主、备服务器ID必须一样 priority 100 # 优先级,备份服务上将100改为小于100,可配置成90 advert_int 1 # 主备之间同步检查的时间间隔单位秒 authentication { # 验证类型和密码 auth_type PASS # 验证类型有两种 PASS和HA auth_pass 1111 # 验证密码,在一个实例中主备密码保持一样 } virtual_ipaddress { # 虚拟IP地址,可以有多个,每行一个,不需要指定端口,端口使用的是Nginx容器的端口(Port:4001) 192.168.1.110 } track_script { # 调用上边的脚本 chk_http_port }
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
健康监测脚本内容,如下:
#!/bin/bash #version 0.0.1 A=`ps -C nginx --no-header |wc -l` if [ $A -eq 0 ];then systemctl restart docker #判断docker是否能启动 sleep 2 if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then systemctl stop keepalived fi fi
脚本说明:
当nginx进程不存在时,会自动重启docker服务;
docker服务启动时会自动启动nginx容器;再次检查nginx进程,如果不存在,就停止keepalived服务,然后NGINX_BACKUP主机会自动接替NGINX_MASTER的工作;
将健康监测脚本文件:nginx_check.sh 放到配置文件中的路径下
有2个地方需要注意:
a,将Docker中的Nginx容器设置成开机自动启动,在每台nginx服务器上执行如下命令
docker update --restart=always nginx
b,给 keepalived 监控脚本添加执行权限,在每台机器上执行如下命令
chmod +x /etc/keepalived/nginx_check.sh
3,notify.sh 通知脚本
#!/bin/bash # contact='131xxxxx@qq.com' notify() { mailsubject="$(hostname) to be $1, vip floating" mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1" echo "$mailbody" | mailx -v -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
通知文件:notify.sh 同样放到路径 /etc/keepalived 下。
4,启动 keepalived 服务,两台都要启动
systemctl enable keepalived #将 keepalived 设置开机启动
systemctl start keepalived #启动服务
systemctl status keepalived #查看服务状态
systemctl restart keepalived #重启服务
systemctl stop keepalived #停止服务
4,最后测试,使用虚拟Ip测试,(截图仅作参考 )
第一次访问:http://192.168.2.110:4001/weatherforecast
刷新地址之后,返回另一个Service服务节点
这时候把主Nginx代理所在的服务停掉,继续访问以上地址,发现还是可以正常访问!
在主Nginx所在服务器使用命令 ip a 也能查看到 你设置的虚拟IP已经绑定到网卡上(查看备Nginx服务上是未绑定的)
最后测试收到的邮件
遗留问题:
1,当Master的Nginx访问某个服务时,在请求还未返回时就宕机了,这时候备Nginx会接着上一个请求继续访问吗?有待验证!下次分解!