【keepalived、nginx】CentOS7使用keepalived实现nginx高可用架构

专题:Linux应用服务配置

各类Linux软件安装配置

更多内容请点击 我的博客 查看,欢迎来访。

系统架构

【keepalived、nginx】CentOS7使用keepalived实现nginx高可用架构_第1张图片

  • Nginx实现后端多台业务服务器的负载均衡,当一台Web宕机后,并不影响访问;
  • 多台Nginx实现高可用,配置VIP,当一台Nginx宕机后,虚拟IP自动转移到备用主机;

CentOS7配置网络

不能使用ifconfig,使用ip xxx查询IP相关的信息

# ip address

可以查看到网卡名为ens33

配置动态IP

先使用动态获取IP,前提要开启DHCP,由于测试环境是VMWare,使用NAT模式即可

修改网卡配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33 (最后一个为网卡名称)

动态获取IP地址需要修改两处地方即可

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp  # 修改
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=c6020abe-d007-4ca7-8f0c-c705f6792b09
DEVICE=ens33
ONBOOT=yes  # 修改

修改后重启一下网络服务即可 systemctl restart network

接下来可以使用ssh远程连接了,查看获取到的IP

[root@centos7 ~]# ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:37:71:33 brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.128/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1598sec preferred_lft 1598sec
    inet6 fe80::9d52:3661:696b:8573/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

配置静态IP

实际环境中,需要固定IP地址

设置静态IP地址与动态iIP差不多,也是要修改网卡配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33 (最后一个为网卡名称)

BOOTPROTO=static
# ...
ONBOOT=yes
# 在最后加上几行,IP地址、子网掩码、网关、dns服务器
IPADDR=192.168.1.2
NETMASK=255.255.255.0
GATEWAY=192.168.1.1
DNS1=xxx.xxx.xxx.xxx
DNS2=8.8.8.8

如果习惯使用vim,使用下面的命令安装即可

[root@centos7 ~]# yum install vim

下面来创建测试环境,克隆当前的系统

使用python运行简单的Web服务

业务服WebSvr1【88.129】

查看ip

[root@centos7 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:79:ad:91 brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.129/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1536sec preferred_lft 1536sec
    inet6 fe80::9d52:3661:696b:8573/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

创建html页面用于模拟web服务器

[root@centos7 ~]# vim index.html

<html>
<body>
<h1>Web Svr 1</h1>
</body>
</html>

启动web服务

[root@centos7 ~]# python -m SimpleHTTPServer 8080
Serving HTTP on 0.0.0.0 port 8080 ...

在本地可以访问

[root@centos7 ~]# curl 192.168.88.129:8080
<html>
<body>
<h1>Web Svr 1</h1>
</body>
</html>

但其他同一网段的浏览器无法访问 http://192.168.88.129:8080/ ,检查防火墙且关闭

# 查看防火墙状态
[root@centos7 ~]# firewall-cmd --state
running
# 停止firewall
[root@centos7 ~]# systemctl stop firewalld.service
[root@centos7 ~]# firewall-cmd --state
not running
# 禁止firewall开机启动
[root@centos7 ~]# systemctl disable firewalld.service
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.

现在浏览器访问 http://192.168.88.129:8080/ 就正常了,页面显示Web Svr 1

业务服WebSvr2【88.130】

查看ip

[root@centos7 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:41:d5:ed brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.130/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1390sec preferred_lft 1390sec
    inet6 fe80::9d52:3661:696b:8573/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::7b58:fa7c:8526:dd29/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

和1号配置类似,只需要把html模板改为2,方便后面测试观察

[root@centos7 ~]# vim index.html

# 添加下面内容
<html>
<body>
<h1>Web Svr 2</h1>
</body>
</html>

关闭防火墙,启动web服务,测试同网段浏览器访问

[root@centos7 ~]# systemctl stop firewalld.service
[root@centos7 ~]# systemctl disable firewalld.service
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@centos7 ~]# python -m SimpleHTTP

浏览器访问 http://192.168.88.130:8080/ ,页面显示Web Svr 2

这两台服务器都可以访问了,实际业务中,显示的内容应该是一样的,查询的是同一个数据库。

Nginx实现多个Web服务器负载均衡

Nginx是一个高性能Web服务器,通过upstream模块可以实现多个Web服务器的负载均衡。

在克隆一台虚拟机,可以查看到它的IP

[root@centos7 ~]# ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:9f:da:d2 brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.131/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1715sec preferred_lft 1715sec
    inet6 fe80::9d52:3661:696b:8573/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::7b58:fa7c:8526:dd29/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::9cb3:ef45:2493:99cb/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

安装nginx依赖包

[root@centos7 nginx-1.17.3]# yum install gcc gcc-c++  pcre pcre-devel zlib zlib-devel openssl-devel -y

下载nginx源码

访问 http://nginx.org/en/download.html 获取下载链接

复制下载链接,使用下面命令下载

[root@centos7 ~]# yum install wget -y
# 如果没安装wget,首先需要安装

[root@centos7 ~]# wget http://nginx.org/download/nginx-1.17.3.tar.gz

下载最新版的nginx,解压

[root@centos7 ~]# ls
index.html  nginx-1.17.3.tar.gz

[root@centos7 ~]# tar -xzf nginx-1.17.3.tar.gz 
[root@centos7 ~]# ls
index.html  nginx-1.17.3  nginx-1.17.3.tar.gz

编译配置nginx

[root@centos7 nginx-1.17.3]# ./configure \
--prefix=/etc/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_dav_module \
--with-http_stub_status_module \
--with-threads \
--with-file-aio


# 执行完成后会看到下面回显
Configuration summary
  + using threads
  + using system PCRE library
  + using system OpenSSL library
  + using system zlib library

  nginx path prefix: "/etc/nginx"
  nginx binary file: "/etc/nginx/sbin/nginx"
  nginx modules path: "/etc/nginx/modules"
  nginx configuration prefix: "/etc/nginx"
  nginx configuration file: "/etc/nginx/nginx.conf"
  nginx pid file: "/var/run/nginx.pid"
  nginx error log file: "/var/log/nginx/error.log"
  nginx http access log file: "/var/log/nginx/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

编译参数说明

--prefix=  指向安装目录。
--sbin-path=  指定执行程序文件存放位置。
--modules-path=  指定第三方模块的存放路径。
--conf-path= 指定配置文件存放位置。
--error-log-path=  指定错误日志存放位置。
--pid-path=  指定pid文件存放位置。
--lock-path=  指定lock文件存放位置。
--user=  指定程序运行时的非特权用户。
--group=  指定程序运行时的非特权用户组。
--builddir=  指向编译目录。
--with-rtsig_module  启用rtsig模块支持。
--with-select_module  启用select模块支持,一种轮询处理方式,不推荐在高并发环境中使用,禁用:--without-select_module。
--with-poll_module  启用poll模块支持,功能与select相同,不推荐在高并发环境中使用。
--with-threads 启用thread pool支持。
--with-file-aio  启用file aio支持。
--with-http_ssl_module 启用https支持。
--with-http_v2_module    启用ngx_http_v2_module支持。
--with-ipv6    启用ipv6支持。
--with-http_realip_module    允许从请求报文头中更改客户端的ip地址,默认为关。
--with-http_addition_module    启用ngix_http_additon_mdoule支持(作为一个输出过滤器,分部分响应请求)。
--with -http_xslt_module    启用ngx_http_xslt_module支持,过滤转换XML请求 。
--with-http_image_filter_mdoule  启用ngx_http_image_filter_module支持,传输JPEG\GIF\PNG图片的一个过滤器,默认不启用,需要安装gd库。
--with-http_geoip_module  启用ngx_http_geoip_module支持,用于创建基于MaxMind GeoIP二进制文件相配的客户端IP地址的ngx_http_geoip_module变量。
--with-http_sub_module  启用ngx_http_sub_module支持,允许用一些其他文本替换nginx响应中的一些文本。
--with-http_dav_module  启用ngx_http_dav_module支持,增加PUT、DELETE、MKCOL创建集合,COPY和MOVE方法,默认为关闭,需要编译开启。
--with-http_flv_module  启用ngx_http_flv_module支持,提供寻求内存使用基于时间的偏移量文件。
--with-http_mp4_module  启用ngx_http_mp4_module支持,启用对mp4类视频文件的支持。
--with-http_gzip_static_module  启用ngx_http_gzip_static_module支持,支持在线实时压缩输出数据流。
--with-http_random_index_module  启用ngx_http_random_index_module支持,从目录中随机挑选一个目录索引。
--with-http_secure_link_module  启用ngx_http_secure_link_module支持,计算和检查要求所需的安全链接网址。
--with-http_degradation_module  启用ngx_http_degradation_module 支持允许在内存不足的情况下返回204或444代码。
--with-http_stub_status_module  启用ngx_http_stub_status_module 支持查看nginx的状态页。
--without-http_charset_module  禁用ngx_http_charset_module这一模块,可以进行字符集间的转换,从其它字符转换成UTF-8或者从UTF8转换成其它字符。它只能从服务器到客户端方向,只有一个字节的字符可以转换。
--without-http_gzip_module  禁用ngx_http_gzip_module支持,同--with-http_gzip_static_module功能一样。
--without-http_ssi_module  禁用ngx_http_ssi_module支持,提供了一个在输入端处理服务器包含文件(SSI)的过滤器。
--without-http_userid_module  禁用ngx_http_userid_module支持,该模块用来确定客户端后续请求的cookies。
--without-http_access_module  禁用ngx_http_access_module支持,提供了基于主机ip地址的访问控制功能。
--without-http_auth_basic_module  禁用ngx_http_auth_basic_module支持,可以使用用户名和密码认证的方式来对站点或部分内容进行认证。
--without-http_autoindex_module  禁用ngx_http_authindex_module,该模块用于在ngx_http_index_module模块没有找到索引文件时发出请求,用于自动生成目录列表。
--without-http_geo_module  禁用ngx_http_geo_module支持,这个模块用于创建依赖于客户端ip的变量。
--without-http_map_module  禁用ngx_http_map_module支持,使用任意的键、值 对设置配置变量。
--without-http_split_clients_module 禁用ngx_http_split_clients_module支持,该模块用于基于用户ip地址、报头、cookies划分用户。
--without-http_referer_module  禁用ngx_http_referer_modlue支持,该模块用来过滤请求,报头中Referer值不正确的请求。
--without-http_rewrite_module  禁用ngx_http_rewrite_module支持。该模块允许使用正则表达式改变URI,并且根据变量来转向以及选择配置。如果在server级别设置该选项,那么将在location之前生效,但如果location中还有更进一步的重写规则,location部分的规则依然会被执行。如果这个URI重写是因为location部分的规则造成的,那么location部分会再次被执行作为新的URI,这个循环会被执行10次,最后返回一个500错误。
--without-http_proxy_module  禁用ngx_http_proxy_module支持,http代理功能。
--without-http_fastcgi_module  禁用ngx_http_fastcgi_module支持,该模块允许nginx与fastcgi进程交互,并通过传递参数来控制fastcgi进程工作。
--without-http_uwsgi_module  禁用ngx_http_uwsgi_module支持,该模块用来使用uwsgi协议,uwsgi服务器相关。
--without-http_scgi_module  禁用ngx_http_scgi_module支持,类似于fastcgi,也是应用程序与http服务的接口标准。
--without-http_memcached_module  禁用ngx_http_memcached支持,用来提供简单的缓存,提高系统效率。
--without-http_limit_conn_module  禁用ngx_http_limit_conn_module支持,该模块可以根据条件进行会话的并发连接数进行限制。
--without-http_limit_req_module  禁用ngx_limit_req_module支持,该模块可以实现对于一个地址进行请求数量的限制。
--without-http_empty_gif_module  禁用ngx_http_empty_gif_module支持,该模块在内存中常驻了一个1*1的透明gif图像,可以被非常快速的调用。
--without-http_browser_module  禁用ngx_http_browser_mdoule支持,创建依赖于请求报头的值 。如果浏览器为modern,则$modern_browser等于modern_browser_value的值;如果浏览器为old,则$ancient_browser等于$ancient_browser_value指令分配的值;如果浏览器为MSIE,则$msie等于1。
--without-http_upstream_ip_hash_module 禁用ngx_http_upstream_ip_hash_module支持,该模块用于简单的负载均衡。
--with-http_perl_module  启用ngx_http_perl_module支持,它使nginx可以直接使用perl或通过ssi调用perl。
--with-perl_modules_path=  设定perl模块路径
--with-perl=  设定perl库文件路径
--http-log-path=  设定access log路径
--http-client-body-temp-path=  设定http客户端请求临时文件路径
--http-proxy-temp-path=  设定http代理临时文件路径
--http-fastcgi-temp-path=  设定http fastcgi临时文件路径
--http-uwsgi-temp-path=  设定http scgi临时文件路径
--http-scgi-temp-path=  设定http scgi临时文件路径
--without-http  禁用http server功能
--without-http-cache  禁用http cache功能
--with-mail  启用POP3、IMAP4、SMTP代理模块
--with-mail_ssl_module  启用ngx_mail_ssl_module支持
--without-mail_pop3_module  禁用pop3协议。
--without-mail_iamp_module  禁用iamp协议。
--without-mail_smtp_module  禁用smtp协议。
--with-google_perftools_module  启用ngx_google_perftools_mdoule支持,调试用,可以用来分析程序性能瓶颈。
--with-cpp_test_module 启用ngx_cpp_test_module支持。
--add-module=  指定外部模块路径,启用对外部模块的支持。
--with-cc=  指向C编译器路径。
--with-cpp=  指向C预处理路径。
--with-cc-opt=  设置C编译器参数,指定--with-cc-opt="-I /usr/lcal/include",如果使用select()函数,还需要同时指定文件描述符数量--with-cc-opt="-D FD_SETSIZE=2048"(PCRE库)
--with-ld-opt=  设置连接文件参数,需要指定--with-ld-opt="-L /usr/local/lib"。(PCRE库)
--with-cpu-opt=  指定编译的CPU类型,如pentium,pentiumpro,...amd64,ppc64...
--without-pcre  禁用pcre库。
--with-pcre  启用pcre库。
--with-pcre=  指向pcre库文件目录。
--with-pcre-opt=  在编译时为pcre库设置附加参数 。
--with-md5=  指向md5库文件目录。
--with-md5-opt=  编译时为md5库设置附加参数。
--with-md5-asm  使用md5汇编源。
--with-sha1=  指向sha1库文件目录。
--with-sha1-opt=  编译时为sha1库设置附加参数。
--with-sha1-asm  使用sha1汇编源。
--with-zlib=  指向zlib库文件目录。
--with-zlib-opt=  在编译时为zlib设置附加参数。
--with-zlib-asm=  为指定的CPU使用汇编源进行优化。
--with-libatomic  为原子内存的更新操作的实现提供一个架构。
--with-libatomic=  指向libatomic_ops的安装目录。
--with-openssl=  指向openssl安装目录。
--with-openssl-opt=  在编译时为openssl设置附加参数。
--with-debug  启用debug日志。

执行编译后安装

[root@centos7 nginx-1.17.3]# make && make install

手动启动nginx

[root@centos7 nginx-1.17.3]# /etc/nginx/sbin/nginx
nginx: [emerg] getpwnam("nginx") failed  # 没有nginx用户

启动失败,创建nginx用户

# 创建nginx用户
[root@centos7 nginx-1.17.3]# useradd -r nginx
# 启动nginx
[root@centos7 nginx-1.17.3]# /etc/nginx/sbin/nginx

现在访问 http://192.168.88.131/ 可以看到nginx页面

【keepalived、nginx】CentOS7使用keepalived实现nginx高可用架构_第2张图片

创建nginx启动文件

需要在init.d文件夹中创建nginx启动文件。 这样每次服务器重新启动init进程都会自动启动Nginx。

[root@centos7 nginx]# cd /etc/init.d/
[root@centos7 init.d]# vim nginx

# 写入下面的内容
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemin
#
# chkconfig:   - 85 15
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /etc/nginx/nginx.conf
# pidfile:     /var/run/nginx.pid
# user:        nginx

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

nginx="/etc/nginx/sbin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/etc/nginx/nginx.conf"

lockfile=/var/run/nginx.lock

start() {
    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    configtest || return $?
    stop
    start
}

reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
esac

校验配置文件依次输入下列命令

[root@centos7 init.d]# chkconfig --add nginx 
[root@centos7 init.d]# chkconfig --level 345 nginx on

给这个文件添加执行权限

[root@centos7 init.d]# chmod +x nginx 

[root@centos7 init.d]# ls
functions  netconsole  network  nginx  README

启动Nginx服务

[root@centos7 init.d]# service nginx start
Reloading systemd:  [  确定  ]
Starting nginx (via systemctl):  [  确定  ]

# 查看启动状态
[root@centos7 init.d]# service nginx status

# 如果可以通过系统日志检查发生错误的原因

# 如果修改了nginx.conf配置文件,使用reload重启
[root@centos7 nginx]# service nginx reload
Reloading nginx configuration (via systemctl):  Warning: nginx.service changed on disk. Run 'systemctl daemon-reload' to reload units.
[  确定  ]

防火墙允许80端口

Linux 服务器上防火墙会端口拦截,所以需要在防火墙中开放80 端口,也可以直接关闭防火墙,这儿提供允许80端口方法,但之前已经关闭防火墙了

# 允许80端口
firewall-cmd --permanent --add-port=80/tcp --zone=public

# 重新加载防火墙配置
firewall-cmd --reload

代理服Nginx1【88.131】

修改nginx.conf配置文件

[root@centos7 nginx-1.17.3]# cd /etc/nginx/
[root@centos7 nginx]# mv nginx.conf nginx.conf.bak

# 首个字符以#开头
[root@centos7 nginx]# egrep -v '^#' nginx.conf.bak
# 首个字符已#开头,# 前面有空格
[root@centos7 nginx]# egrep -v '^#|^[ ]*#' nginx.conf.bak
# 再去掉空行
[root@centos7 nginx]# egrep -v '^#|^[ ]*#|^$' nginx.conf.bak 

查看无注释的配置文件,使用>>将其写入新的文件

[root@centos7 nginx]# egrep -v '^#|^[ ]*#|^$' nginx.conf.bak >> nginx.conf
[root@centos7 nginx]# cat nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

重新加载nginx配置

# 测试配置文件是否正常
[root@centos7 nginx]# /etc/nginx/sbin/nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

# 重新加载配置文件
[root@centos7 nginx]# /etc/nginx/sbin/nginx -s reload

如果是通过service nginx start启动的nginx,建议通过service nginx reload来重新加载。

接下来浏览器访问 http://192.168.88.129/ 也是正常的

配置Nginx负载均衡

可以通过访问 http://192.168.88.129/ 代理显示 http://192.168.88.129:8080/ 和 http://192.168.88.130:8080/ 的页面

修改 nginx.conf 文件

[root@centos7 init.d]# cd /etc/nginx/
[root@centos7 nginx]# vim nginx.conf

# 修改为以下配置
worker_processes  1;
events {
    # 并发连接数
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    # websvr 服务器集群(也可以叫负载均衡池)
    upstream websvr {
        server 192.168.88.129:8080  weight=1;
        server 192.168.88.130:8080  weight=2;
    }

    server {
        # 监听80端口
        listen       80;
        # 用来指定ip地址或者域名,多个配置之间用空格分隔
        server_name  192.168.88.131;
        location / {
            # 将所有请求交给websvr集群去处理
            proxy_pass http://websvr;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

现在重启nginx

[root@centos7 nginx]# /etc/nginx/sbin/nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

# 测试没问题后进行reload
[root@centos7 nginx]# /etc/nginx/sbin/nginx -s reload

# 也可以使用下面的命令重新加载
[root@centos7 nginx]# service nginx reload
Reloading nginx configuration (via systemctl):  [  确定  ]

websvr名称可自定义,可以指明这些服务器的含义。

也就是只需要添加upstream websvrproxy_pass就可以实现负载均衡。

Nginx转发原理

访问 http://192.168.88.131/ ,页面上就会出现Web Svr 1Web Svr 2切换,会根据权重选择服务器,weight值越大,权重越高,也就是重复刷新该页面,平均Web Svr 2出现2次,Web Svr 1出现1次。

【keepalived、nginx】CentOS7使用keepalived实现nginx高可用架构_第3张图片

Nginx收到请求后,将所有请求交给websvr集群处理,假如此刻【88.129】的websvr挂掉了,也不会影响Web访问,因为Nginx会自动将请求发给【88.130】,此时刷新 http://192.168.88.129/ 页面上始终只会显示Web Svr 2。重新启动【88.129】的web服务[root@centos7 ~]# python -m SimpleHTTPServer 8080,刷新页面,又会访问 http://192.168.88.131/ ,页面上就会出现Web Svr 1Web Svr 2切换了。

到目前为止,仍然不能实现高可用,虽然web服务可以这样做,单点故障可以通过这种方式处理,但是如果nginx服务故障了,整个系统基本就无法访问了,那么就需要使用多台Nginx来保障。

多个Nginx协同工作,Nginx高可用【双机主从模式】

先查看新增的IP

[root@centos7 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:7e:35:d1 brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.132/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1776sec preferred_lft 1776sec
    inet6 fe80::9d52:3661:696b:8573/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::7b58:fa7c:8526:dd29/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::9cb3:ef45:2493:99cb/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever

可以看到增加的一台用于Nginx的服务器IP为 192.168.88.132

代理服Nginx2【88.132】

【keepalived、nginx】CentOS7使用keepalived实现nginx高可用架构_第4张图片

新增一台nginx服务,和之前的配置一样,只需要修改 nginx.conf 即可

[root@centos7 ~]# vim /etc/nginx/nginx.conf
events {
    # 并发连接数
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    # websvr 服务器集群
    upstream websvr {
        server 192.168.88.129:8080  weight=1;
        server 192.168.88.130:8080  weight=2;
    }

    server {
        # 监听80端口
        listen       80;
        # 用来指定ip地址或者域名,多个配置之间用空格分隔
        server_name  192.168.88.132;
        location / {
            # 将所有请求交给websvr集群去处理
            proxy_pass http://websvr;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

# 修改完成后重新加载nginx配置
[root@centos7 ~]# service nginx reload
Reloading nginx configuration (via systemctl):  [  确定  ]

现在访问 http://192.168.88.132/ 也可以得到和 http://192.168.88.131/ 类似的结果。

这两台Nginx服务器的IP是不同的,那怎么做才能将这两台nginx服务器一起工作呢?

了解keepalived

  1. 基于VRRP协议:路由器和操作系统层面的协议,虚拟路由器动态转移IP;
  2. 需要安装keepalived软件;
  3. 需要配置:有主备(master/backup)两个角色,可以配置多重定期监控来实现应用的高可用性;
  4. keepalived命令直接指定配置文件启动,生产环境需要配置自启动。

不仅可以做Nginx的高可用,也可以做其他的例如Mysql高可用。

一个机器可以绑定多个IP,可以在Nginx上使用keepalived绑定一个虚拟IP,当某一台Nginx出现问题,这个虚拟IP就会自动转移到另一台。

高可用故障切换转移原理

Keepalived高可用故障切换,是通过VRRP虚拟路由器冗余协议来实现的。

在Keepalived服务正常工作时,主Master节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备Backup节点自己还活着,当主Master节点发生故障时,就无法发送心跳消息,备节点无法检测到来自主Master节点心跳了,于是调用自身的接管程序,接管主Master节点的IP资源及服务。而当主Master节点恢复时,备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。

VRRP协议

虚拟路由冗余协议,可以认为是实现路由器高可用的协议,即将N台提供相同功能的路由器组成一个路由器组,这个组里面有一个master和多个backup,master上面有一个对外提供服务的vip(该路由器所在局域网内其他机器的默认路由/网关为该vip),master会发组播,当backup收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级来选举一个backup当master。这样的话就可以保证路由器的高可用了。

keepalived主要有三个模块

分别是core、check和vrrp。
core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。
check负责健康检查,包括常见的各种检查方式。
vrrp模块是来实现VRRP协议的。

代理服Nginx1【88.131】安装keepalived主虚拟IP88.133

下载keepalived源码

访问 https://www.keepalived.org/download.html 获取下载地址

[root@centos7 ~]# wget https://www.keepalived.org/software/keepalived-2.0.18.tar.gz

2019-09-17 09:28:21 (178 KB/s) - 已保存 “keepalived-2.0.18.tar.gz” [1015958/1015958])

[root@centos7 ~]# tar xzf keepalived-2.0.18.tar.gz

[root@centos7 ~]# ls
keepalived-2.0.18         nginx-1.17.3     index.html       keepalived-2.0.18.tar.gz  nginx-1.17.3.tar.gz

配置keepalived,编译安装

[root@centos7 ~]# cd keepalived-2.0.18

# 配置
[root@centos7 keepalived-2.0.18]# ./configure --prefix=/etc/keepalived

# 如果出现下面错误,安装依赖包
*** WARNING - this build will not support IPVS with IPv6. Please install libnl/libnl-3 dev libraries to support IPv6 with IPVS.
[root@centos7 keepalived-2.0.18]# yum -y install libnl libnl-devel

# 编译安装
[root@centos7 keepalived-2.0.18]# make && make install

keepalived将安装到 /etc/keepalived 目录,当然,很多教程是安装在/usr/local/keepalived,影响不大,也可以自定义安装路径,将所有软件都安装到一个目录,如果没有该目录会自动创建

运行前配置

[root@centos7 keepalived-2.0.18]# ls
aclocal.m4   ChangeLog      CONTRIBUTORS  install-sh          Makefile.am  TODO
ar-lib       compile        COPYING       keepalived          Makefile.in
AUTHOR       config.log     depcomp       keepalived.spec     missing
bin          config.status  doc           keepalived.spec.in  README
bin_install  configure      genhash       lib                 README.md
build_setup  configure.ac   INSTALL       Makefile            snap

# 从源码包中复制 keepalived 服务启动脚本到默认的目录
[root@centos7 keepalived-2.0.18]# cp keepalived/etc/init.d/keepalived /etc/init.d/
[root@centos7 keepalived-2.0.18]# chmod +x /etc/init.d/keepalived

# 从安装目录复制自启动文件到系统环境中
[root@centos7 keepalived-2.0.18]# cd /etc/keepalived/
[root@centos7 keepalived]# ls
bin  etc  sbin  share

[root@centos7 keepalived]# cp etc/sysconfig/keepalived /etc/sysconfig/  

# 复制配置文件到指定目录,也可以不复制,直接创建新的
[root@centos7 keepalived]# cp etc/keepalived/keepalived.conf /etc/keepalived/

可以在安装目录 /etc/keepalived/etc/keepalived/samples 下查看官方示例

[root@centos7 samples]# pwd
/etc/keepalived/etc/keepalived/samples
[root@centos7 samples]# ls
client.pem                        keepalived.conf.track_interface
dh1024.pem                        keepalived.conf.virtualhost
keepalived.conf.conditional_conf  keepalived.conf.virtual_server_group
keepalived.conf.fwmark            keepalived.conf.vrrp
keepalived.conf.HTTP_GET.port     keepalived.conf.vrrp.localcheck
keepalived.conf.inhibit           keepalived.conf.vrrp.lvs_syncd
keepalived.conf.IPv6              keepalived.conf.vrrp.routes
keepalived.conf.misc_check        keepalived.conf.vrrp.rules
keepalived.conf.misc_check_arg    keepalived.conf.vrrp.scripts
keepalived.conf.quorum            keepalived.conf.vrrp.static_ipaddress
keepalived.conf.sample            keepalived.conf.vrrp.sync
keepalived.conf.SMTP_CHECK        root.pem
keepalived.conf.SSL_GET           sample.misccheck.smbcheck.sh
keepalived.conf.status_code       sample_notify_fifo.sh

主keepalived配置keepalived.conf

修改 keepalived.conf 配置文件,默认是 /etc/keepalived/keepalived.conf ,如果是其他名字,启动keepalived就需要指定配置文件 keepalived -f keepalived_xxx.conf

[root@centos7 keepalived]# pwd
/etc/keepalived

# 删除原来的配置文件后再新增创建
[root@centos7 keepalived]# rm keepalived.conf -y

[root@centos7 keepalived]# vim keepalived.conf

# 添加下面的内容

global_defs {
    # (VI_1) the virtual router id must be set,运行keepalived的机器的一个标识,通常可设为hostname。故障发生时,发邮件时显示在邮件主题中的信息
    router_id chk_niginx_133
    # default user 'keepalived_script' for script execution does not exist - please create.需添加下面配置
    script_user root
    enable_script_security
}
vrrp_script chk_nginx {
	# 指定监控脚本,检测nginx服务是否正常运行
	script "/etc/keepalived/chk_nginx.sh"
	# 指定监控时间,每10s执行一次
	interval 10
	# 脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
	# weight -5
	# # 检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
    # fall 2
    # 检测1次成功就算成功。但不修改优先级
    # rise 1
}

# keepalived在同一virtual_router_id中priority(0-255)最大的会成为master,也就是接管VIP,当priority最大的主机发生故障后,priority较小将会接管。
vrrp_instance VI_1 {
	# 指定keepalived的角色,主机设置为MASTER,备用机设置为BACKUP,注意这里的state指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,那么他会就回抢占为MASTER。
	state MASTER
	# 指定HA监测网络的接口。centos7使用 ip addr 获取
	interface ens33
	# 发送多播数据包时的源IP地址,这里实际上就是在哪个地址上发送VRRP通告,这个非常重要,一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址
	# mcast_src_ip 192.168.88.xx
    # 主备的virtual_router_id必须一样,可以设置为IP后一组:must be between 1 & 255
	virtual_router_id 133
	# 优先级值,在同一个vrrp_instance下, MASTRE 一定要高于 BAUCKUP,MASTER恢复后,BACKUP自动交接
	priority 100
	# VRRP 广播周期秒数,如果没检测到该广播,就被认为服务挂了,将切换主备
	advert_int 1
	# 设置验证类型和密码。主从必须一样
	authentication {
		# 设置vrrp验证类型,主要有PASS和AH两种
		auth_type PASS
		# 加密的密码,两台服务器一定要一样,才能正常通信
		auth_pass passwd
	}
	track_script {
		# 执行监控的服务,引用VRRP脚本,即在 vrrp_script 部分指定的名字。定期运行它们来改变优先级
		chk_nginx
	}
	virtual_ipaddress {
		# VRRP HA 虚拟地址 如果有多个VIP,继续换行填写
		192.168.88.133
	}
}

指定虚拟IP: 192.168.88.133 需要为未使用,配置完成后可通过 http://192.168.88.133/ 访问后端服务。

主keepalived配置监控脚本chk_nginx.sh

创建一个脚本,用于在keepalived中执行

[root@centos7 keepalived]# pwd
/etc/keepalived
[root@centos7 keepalived]# vim chk_nginx.sh

# 添加下面脚本

#!/bin/bash
# 查看是否有 nginx进程 把值赋给变量counter
counter=`ps -C nginx --no-header |wc -l`
# 如果没有进程值得为 0
if [ $counter -eq 0 ];then
	# 尝试启动nginx
	echo "Keepalived Info: Try to start nginx" >> /var/log/messages
	/etc/nginx/sbin/nginx
	sleep 3
	if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
		# 输出日至道系统消息
		echo "Keepalived Info: Unable to start nginx" >> /var/log/messages
		# 如果还没没启动,则结束 keepalived 进程
		# killall keepalived
		# 或者停止
		/etc/init.d/keepalived stop
		exit 1
	else
		echo "Keepalived Info: Nginx service has been restored" >> /var/log/messages
		exit 0
	fi
else
	# 状态正常
	echo "Keepalived Info: Nginx detection is normal" >> /var/log/messages;
	exit 0
fi

# 接下来授予执行权限
[root@centos7 keepalived]# chmod +x chk_nginx.sh

# 测试脚本是否正常使用
[root@centos7 keepalived]# ./chk_nginx.sh

执行前可以通过下面命令实时查看 messages 中的输出日志

[root@centos7 keepalived]# tail -f /var/log/messages 

# 如果nginx关闭
Keepalived Info: Try to start nginx
Keepalived Info: Nginx service has been restored
# nginx正常打开
Keepalived Info: Nginx detection is normal

当nginx检测正常,就会返回0;检测没有了,返回1,但是keepalived似乎不是检测这个返回值来实现转移,而是检测keepalived服务是否存在,来释放本地VIP后,最终转移虚拟IP,到另一台服务器。

启动keepalived服务及开机启动

启动keepalived

启动服务,查看服务启动情况

# 启动keepalived
[root@centos7 keepalived]# service keepalived start
Starting keepalived (via systemctl):  [  确定  ]

# 查看进程不存在,说明没有启动成功
[root@centos7 keepalived]# ps -aux |grep keepalived
root      30574  0.0  0.1 112724  1000 pts/0    R+   13:31   0:00 grep --color=auto keepalived

但是查看日志

[root@centos7 keepalived]# tail -f /var/log/messages


Sep 17 13:28:00 centos7 Keepalived_vrrp[30570]: WARNING - default user 'keepalived_script' for script execution does not exist - please create.

global_defs 中添加

   script_user root
   enable_script_security

继续处理

# 解决这个后又有下面的提示

Sep 17 13:47:48 centos7 Keepalived_vrrp[30675]: (Line 18) number '88133' outside range [1, 255]
Sep 17 13:47:48 centos7 Keepalived_vrrp[30675]: (Line 18) (VI_1): VRID '88133' not valid - must be between 1 & 255
Sep 17 13:47:48 centos7 Keepalived_vrrp[30675]: (VI_1) the virtual router id must be set

global_defs 中添加

    router_id chk_niginx_133

解决日志中的错误提示后,通过service keepalived start命令可以启动 keepalived,并且在 messages中可以查看shell中显示的日志

Keepalived Info: Nginx detection is normal
Keepalived Info: Nginx detection is normal
Keepalived Info: Nginx detection is normal
Keepalived Info: Nginx detection is normal

每10s检测1次。

测试关闭nginx

关闭后查看日志中的输出内容

[root@centos7 keepalived]# /etc/nginx/sbin/nginx -s stop

# 正在尝试重启nginx成功
Keepalived Info: Try to start nginx
Keepalived Info: Nginx service has been restored
Keepalived Info: Nginx detection is normal

切记在脚本中如果通过 /etc/nginx/sbin/nginx 命令启动的nginx,也需要使用 /etc/nginx/sbin/nginx -s stop 管理,如果使用的``

访问 http://192.168.88.133/ 也是可以正常显示的,也就是绑定的IP成功了

设置keepalived开机启动

[root@centos7 keepalived]# chkconfig keepalived on
注意:正在将请求转发到“systemctl enable keepalived.service”。
Created symlink from /etc/systemd/system/multi-user.target.wants/keepalived.service to /usr/lib/systemd/system/keepalived.service

# 或者是这两命令配置开机自启动
[root@centos7 keepalived]# systemctl enable keepalived

代理服Nginx2【88.132】安装keepalived备虚拟IP88.133

下载配置编译安装

# 下载安装
[root@centos7 ~]# wget https://www.keepalived.org/software/keepalived-2.0.18.tar.gz

[root@centos7 ~]# tar xzf keepalived-2.0.18.tar.gz
[root@centos7 ~]# cd keepalived-2.0.18
[root@centos7 keepalived-2.0.18]# yum -y install libnl libnl-devel
[root@centos7 keepalived-2.0.18]# ./configure --prefix=/etc/keepalived
[root@centos7 keepalived-2.0.18]# make && make install

# 复制配置文件
[root@centos7 keepalived-2.0.18]# cp keepalived/etc/init.d/keepalived /etc/init.d/
[root@centos7 keepalived-2.0.18]# chmod +x /etc/init.d/keepalived
[root@centos7 keepalived-2.0.18]# cd /etc/keepalived/
[root@centos7 keepalived]# cp etc/sysconfig/keepalived /etc/sysconfig/

备keepalived配置keepalived.conf

注意需要改变的内容:state BACKUPpriority 90备优先级一定小于主,其他基本一致

[root@centos7 keepalived]# pwd
/etc/keepalived
[root@centos7 keepalived]# vim keepalived.conf


global_defs {
    # (VI_1) the virtual router id must be set
    router_id chk_niginx_133
    # default user 'keepalived_script' for script execution does not exist - please create.需添加下面配置
    script_user root
    enable_script_security
}
vrrp_script chk_nginx {
	# 指定监控脚本
	script "/etc/keepalived/chk_nginx.sh"
	# 指定监控时间,每10s执行一次
	interval 10
}
vrrp_instance VI_1 {
	# 主机设置为MASTER,备用机设置为BACKUP
	state BACKUP
	# 监测网卡名称,centos7使用 ip addr 获取
	interface ens33
    # 主备的virtual_router_id必须一样,可以设置为IP后一组:must be between 1 & 255
	virtual_router_id 133
	# 权重值 MASTRE 一定要高于 BAUCKUP
	priority 90
	# VRRP 广播周期秒数,如果没检测到该广播,就呗认为服务挂了,将切换主备
	advert_int 1
	authentication {
		# 加密
		auth_type PASS
		# 加密的密码,两台服务器一定要一样,不然会出错
		auth_pass passwd
	}
	track_script {
		# 执行监控的服务
		chk_nginx
	}
	virtual_ipaddress {
		#  VIP 虚拟IP地址
		192.168.88.133
	}
}

备keepalived配置监控脚本chk_nginx.sh

脚本和主keepalived的 chk_nginx.sh 一样即可。

[root@centos7 keepalived]# vim chk_nginx.sh

#!/bin/bash
# 查看是否有 nginx进程 把值赋给变量counter
counter=`ps -C nginx --no-header |wc -l`
# 如果没有进程值得为 0
if [ $counter -eq 0 ];then
	# 尝试启动nginx
	echo "Keepalived Info: Try to start nginx" >> /var/log/messages
	/etc/nginx/sbin/nginx
	sleep 3
	if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
		# 输出日至道系统消息
		echo "Keepalived Info: Unable to start nginx" >> /var/log/messages
		# 如果还没没启动,则结束 keepalived 进程
		# killall keepalived
		# 或者停止
		/etc/init.d/keepalived stop
		exit 1
	else
		echo "Keepalived Info: Nginx service has been restored" >> /var/log/messages
		exit 0
	fi
else
	# 状态正常
	echo "Keepalived Info: Nginx detection is normal" >> /var/log/messages;
	exit 0
fi

[root@centos7 keepalived]# chmod +x chk_nginx.sh
[root@centos7 keepalived]# ./chk_nginx.sh

# 在系统消息中显示:Keepalived Info: Nginx detection is normal

启动keepalived服务及开机启动

[root@centos7 keepalived]# service keepalived start
Starting keepalived (via systemctl):  [  确定  ]

# 查看日志
Sep 17 14:34:31 centos7 Keepalived_vrrp[24328]: VRRP_Script(chk_nginx) succeeded
Sep 17 14:34:31 centos7 Keepalived_vrrp[24328]: (VI_1) Entering BACKUP STATE
Keepalived Info: Nginx detection is normal
Keepalived Info: Nginx detection is normal

# 设置开机启动
[root@centos7 keepalived]# systemctl enable keepalived
Created symlink from /etc/systemd/system/multi-user.target.wants/keepalived.service to /usr/lib/systemd/system/keepalived.service.

keepalived如果有防火墙配置

# 指定keepalived配置的网卡:ens33,固定的VRRP广播地址:224.0.0.18
firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface ens33 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface ens33 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
firewall-cmd --reload

# 查看配置的规则
firewall-cmd --direct --get-rules ipv4 filter INPUT
firewall-cmd --direct --get-rules ipv4 filter OUTPUT

解决多组Keepalived服务器在一个局域网的冲突问题

当在同一个局域网内部署了多组Keepalived服务器对,而又未使用专门的心跳线通信时,可能会发生高可用接管的严重故障问题。之前已经讲解过Keepalived高可用功能是通过VRRP协议实现的,VRRP协议默认通过IP多播的形式实现高可用对之间的通信,如果同一个局域网内存在多组Keepalived服务器对,就会造成IP多播地址冲突问题,导致接管错乱,不同组的Keepalived都会使用默认的224.0.0.18作为多播地址。此时的解决办法是,在同组的Keepalived服务器所有的配置文件里指定独一无二的多播地址,配置如下:

global_defs {                                    #全局配置
    router_id LVS_19                              #服务标识
    vrrp_mcast_group4 224.0.0.19    #这个就是指定多播地址的配置
}
  1. 不同实例的通信认证密码也最好不同,以确保接管正常。
  2. 另一款高可用软件Heartbeat,如果采用多播方式实现主备通信,同样会有多播地址冲突问题。

测试主备Nginx自动切换

keepalived监控Nginx的状态

经过前面的配置,如果master主服务器的keepalived停止服务,backup从服务器会自动接管VIP对外服务;一旦主服务器的keepalived恢复,会重新接管VIP。
keepalived支持配置监控脚本,可以通过脚本监控Nginx的状态,如果状态不正常则进行一系列的操作,最终仍不能恢复Nginx则杀掉keepalived,使得从服务器能够接管服务。

如何监控Nginx的状态

最简单的做法是监控Nginx进程,更靠谱的做法是检查NginX端口,最靠谱的做法是检查多个url能否获取到页面。

keepalived.conf 中vrrp_script配置区的script一般有2种写法:

  1. 通过脚本执行的返回结果,所以脚本就需要返回exit 0,或exit 1,keepalived收到这个返回值之后,如果配置了weight -5这种方式,则改变优先级,keepalived继续发送通告消息,backup比较优先级再决定。这是直接监控Nginx进程的方式。
  2. 脚本里面检测到异常,直接关闭keepalived进程,backup机器接收不到advertisement会抢占IP。这是检查NginX端口的方式。

对于改变keepalived优先级方式:
通过shell脚本判断,但有异常时exit 1,正常退出exit 0,然后keepalived根据动态调整的 vrrp_instance 优先级选举决定是否抢占VIP:

  • 如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加,例如weight -5,则priority 100变为priority 105
  • 如果脚本执行结果为1,并且weight配置的值小于0,则优先级相应的减少,例如weight -5,则priority 100变为priority 95
  • 其他情况,原本配置的优先级不变,即配置文件中priority对应的值。

提示:

  • 优先级不会不断的提高或者降低,可以编写多个检测脚本并为每个检测脚本设置不同的weight(在配置中列出就行)
  • 不管提高优先级还是降低优先级,最终优先级的范围在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况

在MASTER节点的 vrrp_instance 中 配置 nopreempt ,当它异常恢复后,即使它 priority 更高也不会抢占,这样可以避免正常情况下做无谓的切换,以上可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。

测试虚拟IP转移

在转移过程中可以通过ap addr查看到指定的网卡会出现2个IP,即一个为原本的IP,另一个为转移后的虚拟IP。

关闭主Nginx1

# 主机
# 注释启动nginx的代码,也就是把 chk_nginx.sh脚本中的/etc/nginx/sbin/nginx注释掉,不让其发生异常时自动启动
# 然后停止nginx
[root@centos7 keepalived]# /etc/nginx/sbin/nginx -s stop

# 可以看到主机停掉keepalived
Keepalived Info: Nginx detection is normal
Keepalived Info: Nginx detection is normal
Keepalived Info: Nginx detection is normal
Keepalived Info: Try to start nginx
Keepalived Info: Unable to start nginx
Sep 17 14:46:04 centos7 Keepalived[32308]: Stopping
Sep 17 14:46:04 centos7 systemd: Stopping LVS and VRRP High Availability Monitor...
Sep 17 14:46:04 centos7 Keepalived_vrrp[32309]: (VI_1) sent 0 priority
Sep 17 14:46:04 centos7 Keepalived_vrrp[32309]: (VI_1) removing VIPs.
Sep 17 14:46:05 centos7 Keepalived_vrrp[32309]: Stopped - used 0.002880 user time, 0.030797 system time
Sep 17 14:46:05 centos7 Keepalived[32308]: Stopped Keepalived v2.0.18 (07/26,2019)
Sep 17 14:46:05 centos7 systemd: Stopped LVS and VRRP High Availability Monitor.

# IP信息变化
[root@centos7 ~]# ip add
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:9f:da:d2 brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.131/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1047sec preferred_lft 1047sec


# 备机继续提供服务,已经变为MASTER
Keepalived Info: Nginx detection is normal
Keepalived Info: Nginx detection is normal
Keepalived Info: Nginx detection is normal
Sep 17 14:46:04 centos7 Keepalived_vrrp[24328]: (VI_1) Backup received priority 0 advertisement
Sep 17 14:46:05 centos7 Keepalived_vrrp[24328]: (VI_1) Receive advertisement timeout
Sep 17 14:46:05 centos7 Keepalived_vrrp[24328]: (VI_1) Entering MASTER STATE
Sep 17 14:46:05 centos7 Keepalived_vrrp[24328]: (VI_1) setting VIPs.
Sep 17 14:46:05 centos7 Keepalived_vrrp[24328]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:46:05 centos7 Keepalived_vrrp[24328]: (VI_1) Sending/queueing gratuitous ARPs on ens33 for 192.168.88.133
Sep 17 14:46:05 centos7 Keepalived_vrrp[24328]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:46:05 centos7 Keepalived_vrrp[24328]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:46:05 centos7 Keepalived_vrrp[24328]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:46:05 centos7 Keepalived_vrrp[24328]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:46:10 centos7 Keepalived_vrrp[24328]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:46:10 centos7 Keepalived_vrrp[24328]: (VI_1) Sending/queueing gratuitous ARPs on ens33 for 192.168.88.133
Sep 17 14:46:10 centos7 Keepalived_vrrp[24328]: Sending gratuitous ARP on ens33 for 192.168.88.133

# IP信息变化
[root@centos7 ~]# ip add
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:7e:35:d1 brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.132/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1790sec preferred_lft 1790sec
    inet 192.168.88.133/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::9d52:3661:696b:8573/64 scope link tentative noprefixroute dadfailed 

也就是主Nginx1停了后,虚拟IP 88.133 自动从 Nginx1(主) 转移到Nginx2(备)

重启主Nginx1

# 现在启动主Nginx
[root@centos7 keepalived]# /etc/nginx/sbin/nginx
[root@centos7 keepalived]# service keepalived start
Starting keepalived (via systemctl):  [  确定  ]

# 主机
Sep 17 14:47:31 centos7 Keepalived[32435]: Command line: '/etc/keepalived/sbin/keepalived' '-D'
Sep 17 14:47:31 centos7 Keepalived[32435]: Opening file '/etc/keepalived/keepalived.conf'.
Sep 17 14:47:31 centos7 systemd: PID file /run/keepalived.pid not readable (yet?) after start.
Sep 17 14:47:31 centos7 Keepalived[32436]: Starting VRRP child process, pid=32437
Sep 17 14:47:31 centos7 systemd: Started LVS and VRRP High Availability Monitor.
Sep 17 14:47:31 centos7 Keepalived_vrrp[32437]: Registering Kernel netlink reflector
Sep 17 14:47:31 centos7 Keepalived_vrrp[32437]: Registering Kernel netlink command channel
Sep 17 14:47:31 centos7 Keepalived_vrrp[32437]: Opening file '/etc/keepalived/keepalived.conf'.
Sep 17 14:47:31 centos7 Keepalived_vrrp[32437]: Assigned address 192.168.88.131 for interface ens33
Sep 17 14:47:31 centos7 Keepalived_vrrp[32437]: Assigned address fe80::9d52:3661:696b:8573 for interface ens33
Sep 17 14:47:31 centos7 Keepalived_vrrp[32437]: Registering gratuitous ARP shared channel
Sep 17 14:47:31 centos7 Keepalived_vrrp[32437]: (VI_1) removing VIPs.
Sep 17 14:47:31 centos7 Keepalived_vrrp[32437]: VRRP sockpool: [ifindex(2), family(IPv4), proto(112), unicast(0), fd(11,12)]
Keepalived Info: Nginx detection is normal
Sep 17 14:47:31 centos7 Keepalived_vrrp[32437]: VRRP_Script(chk_nginx) succeeded
Sep 17 14:47:31 centos7 Keepalived_vrrp[32437]: (VI_1) Entering BACKUP STATE
Sep 17 14:47:32 centos7 Keepalived_vrrp[32437]: (VI_1) received lower priority (90) advert from 192.168.88.132 - discarding
Sep 17 14:47:33 centos7 Keepalived_vrrp[32437]: (VI_1) received lower priority (90) advert from 192.168.88.132 - discarding
Sep 17 14:47:34 centos7 Keepalived_vrrp[32437]: (VI_1) received lower priority (90) advert from 192.168.88.132 - discarding
Sep 17 14:47:34 centos7 Keepalived_vrrp[32437]: (VI_1) Receive advertisement timeout
Sep 17 14:47:34 centos7 Keepalived_vrrp[32437]: (VI_1) Entering MASTER STATE
Sep 17 14:47:34 centos7 Keepalived_vrrp[32437]: (VI_1) setting VIPs.
Sep 17 14:47:34 centos7 Keepalived_vrrp[32437]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:47:34 centos7 Keepalived_vrrp[32437]: (VI_1) Sending/queueing gratuitous ARPs on ens33 for 192.168.88.133
Sep 17 14:47:34 centos7 Keepalived_vrrp[32437]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:47:34 centos7 Keepalived_vrrp[32437]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:47:34 centos7 Keepalived_vrrp[32437]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:47:35 centos7 Keepalived_vrrp[32437]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:47:39 centos7 Keepalived_vrrp[32437]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:47:39 centos7 Keepalived_vrrp[32437]: (VI_1) Sending/queueing gratuitous ARPs on ens33 for 192.168.88.133
Sep 17 14:47:39 centos7 Keepalived_vrrp[32437]: Sending gratuitous ARP on ens33 for 192.168.88.133
Sep 17 14:47:39 centos7 Keepalived_vrrp[32437]: Sending gratuitous ARP on ens33 for 192.168.88.133

# IP信息变化
[root@centos7 ~]# ip add
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:9f:da:d2 brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.131/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1725sec preferred_lft 1725sec
    inet 192.168.88.133/32 scope global ens33
       valid_lft forever preferred_lft forever


# 备机,自动变为BACKUP
Keepalived Info: Nginx detection is normal
Keepalived Info: Nginx detection is normal
Keepalived Info: Nginx detection is normal
Sep 17 14:47:34 centos7 Keepalived_vrrp[24328]: (VI_1) Master received advert from 192.168.88.131 with higher priority 100, ours 90
Sep 17 14:47:34 centos7 Keepalived_vrrp[24328]: (VI_1) Entering BACKUP STATE
Sep 17 14:47:34 centos7 Keepalived_vrrp[24328]: (VI_1) removing VIPs.

# IP信息变化
[root@centos7 ~]# ip add
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:7e:35:d1 brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.132/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1637sec preferred_lft 1637sec

也就是主Nginx1重新开启后,虚拟IP 88.133 自动从 Nginx2(备) 转移到 Nginx1(主),让主机提供服务。

另外假如Nginx1服务器死机了,或者断电关机,虚拟IP也会自动转移到Nginx2服务器上,业务服务依然不会受影响。

这样就实现了Nginx的高可用。

双机高可用方案主从、双主对比

  1. Nginx+keepalived 双机主从模式:即前端使用两台服务器,一台主服务器和一台热备服务器,正常情况下,主服务器绑定一个公网虚拟IP,提供负载均衡服务,热备服务器处于空闲状态;当主服务器发生故障时,热备服务器接管主服务器的公网虚拟IP,提供负载均衡服务;但是热备服务器在主机器不出现故障的时候,永远处于浪费状态,对于服务器不多的网站,该方案不经济实惠。上面实验的就是该方案。
  2. Nginx+keepalived 双机主主模式:即前端使用两台负载均衡服务器,互为主备,且都处于活动状态,同时各自绑定一个公网虚拟IP,提供负载均衡服务;当其中一台发生故障时,另一台接管发生故障服务器的公网虚拟IP(这时由非故障机器一台负担所有的请求)。这种方案,不会造成资源的空闲,经济实惠。

Nginx1【88.131】配置备虚拟IP88.134

#虚拟IP2, 本机作为Backup
vrrp_instance VI_2 {
    state BACKUP
    interface ens33
    virtual_router_id 134
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass passwd2
    }
    # track_script {  # 执行上面检测nginx进程脚本
    #    chk_nginx
    # }
    virtual_ipaddress {  #虚拟ip
        192.168.88.134
    }
}

配置好后进行reload,观察IP变化

# Nginx1
[root@centos7 keepalived]# service keepalived reload
Reloading keepalived configuration (via systemctl):  [  确定  ]
[root@centos7 keepalived]# ip addr
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:9f:da:d2 brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.131/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1204sec preferred_lft 1204sec
    inet 192.168.88.133/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet 192.168.88.134/32 scope global ens33
       valid_lft forever preferred_lft forever

Nginx2【88.132】配置主虚拟IP88.134

#虚拟IP2, 本机作为Master
vrrp_instance VI_2 {
    state MASTER
    interface ens33
    virtual_router_id 134
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass passwd2
    }
    # track_script {  # 执行上面检测nginx进程脚本
    #    chk_nginx
    # }
    virtual_ipaddress {  #虚拟ip
        192.168.88.134
    }
}

配置好后观察IP变化,由于Nginx2为虚拟IP2 88.134 的主机,那么Nginx2配置成功后,88.134就会自动从Nginx1转移到Ngixn2了。

# Nginx2
[root@centos7 keepalived]# service keepalived reload
Reloading keepalived configuration (via systemctl):  [  确定  ]
[root@centos7 keepalived]# ip add
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:7e:35:d1 brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.132/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1792sec preferred_lft 1792sec
    inet 192.168.88.134/32 scope global ens33
       valid_lft forever preferred_lft forever

看Nginx1的IP

[root@centos7 keepalived]# ip addr
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:9f:da:d2 brd ff:ff:ff:ff:ff:ff
    inet 192.168.88.131/24 brd 192.168.88.255 scope global noprefixroute dynamic ens33
       valid_lft 1055sec preferred_lft 1055sec
    inet 192.168.88.133/32 scope global ens33
       valid_lft forever preferred_lft forever

此时 http://192.168.88.133/ 和 http://192.168.88.134/ 都可以访问到。

这种配置下有两个Virtual IP,两个机器互为主备,最后DNS服务器把域名解析至两个Virtual IP即可。

【keepalived、nginx】CentOS7使用keepalived实现nginx高可用架构_第5张图片

你可能感兴趣的:(Linux)