Linux学习124 keepalived和nginx实现高可用故障转移

一、回顾

  1、keepalived:HA Cluster

    a、vrrp:vrrp_instance

      虚拟路由器:物理路由器;

        VRID:Virutal Router ID;

        Master/Backup

          一主一备或一主多备;

          priority

        抢占模式/非抢占模式

    b、ipvs wrapper:通过ipvs wrapper去完成调用内核中的ioctl桶系统调用,从而实现向ipvs上添加或管理规则。ipvs wrapper的变动将取决于各种各样的checkers所获取的结果

      checkers:对各vs的各RS做健康状态检测;

        应用层检测:HTTP_GET,SSL_GET,SMTP_CHECK

        传输层检测:TCP_CHECK

        自定义检测:MISC_CHECK

二、使用keepalived + nginx

  1、架构图

  2、配置

    a、主机规划:

      (1)、nginx1(node1):外网网卡:172.16.10.41   内网网卡:192.168.10.41

      (2)、nginx2(node2):外网网卡:172.16.10.42   内网网卡:192.168.10.42

      (3)、后端主机1(node3,此处我们只是使用一个后端主机配置多个IP,我们的服务配置多个虚拟主机即可):192.168.10.43,192.168.10.44,192.168.10.45

    b、首先后端主机node3上的http服务

      (1)、网卡配置如下

[root@node3 ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens33 
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
NAME=ens33
#UUID=ce6a520c-95ca-4224-a123-f2d2d8592166
DEVICE=ens33
ONBOOT=yes
IPADDR0=192.168.10.43
NETMASK=255.255.255.0
GATEWAY=192.168.10.254
IPADDR1=192.168.10.44
IPADDR2=192.168.10.45
DNS1=8.8.8.8
DNS2=114.114.114.114

[root@node3 ~]# ip a
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:64:52:46 brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.43/24 brd 192.168.10.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.10.44/24 brd 192.168.10.255 scope global secondary noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.10.45/24 brd 192.168.10.255 scope global secondary noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe64:5246/64 scope link 
       valid_lft forever preferred_lft forever

      (2)、web配置如下

[root@node3 ~]# cat /etc/httpd/conf.d/vhosts.conf 
<VirtualHost 192.168.10.43:80>
    ServerName 192.168.10.43
    DocumentRoot "/data/web/vhost1"
    <Directory "/data/web/vhost1">
        Options FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>
<VirtualHost 192.168.10.44:80>
    ServerName 192.168.10.44
    DocumentRoot "/data/web/vhost2"
    <Directory "/data/web/vhost2">
        Options FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>
<VirtualHost 192.168.10.45:80>
    ServerName 192.168.10.45
    DocumentRoot "/data/web/vhost3"
    <Directory "/data/web/vhost3">
        Options FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>
[root@node3 ~]# curl 192.168.10.43
<h1>Vhost1</h1>
[root@node3 ~]# curl 192.168.10.44
<h1>Vhost2</h1>
[root@node3 ~]# curl 192.168.10.45
<h1>Vhost3</h1>

    c、接下来配置keepalived高可用nginx,keepalived要想高可用nginx这种服务其内建是没有这种功能的,因此他需要调用外部的服务脚本进行资源监控,我们只需要确保nginx在对应节点始终处于运行状态即可。万一nginx没有运行我们可以想办法把他启动起来,所以这个外部脚本只有一个作用,当地址转移到这个节点上的时候,我们想办法把nginx给启动起来或重启一下。所以keepalived我们就需要去定义这样一个脚本,即一旦地址转移过来或转移走的时候我们都能执行这个脚本,转移过来就启动nginx转移走的话将nginx服务停止即可。我们还可以用这个脚本来做一些外部资源监控,比如看这台主机上nginx进程是否还在运行着,如果在运行着我们就认为这台主机上的nginx服务是正常的,地址不需要转移,如果当前节点nginx进程运行不了了,例如有人把nginx关掉再启动了httpd,再次启动nginx时就启动不了了,因为他的端口被征用了。如果启动不了我们就不能将当前节点作为主节点了,我们就需要降低优先级,本来A主机是100,B主机是96,我们将A主机优先级减去10就变成90了,B主机就变成主节点了。

      (1)、keepalived调用外部的辅助脚本进行资源监控,并根据监控的结果状态能实现优先动态调整;

        分两步:

        1)、先定义一个脚本;

          vrrp_script <SCRIPT_NAME> {

            script ""  #脚本命令,一般而言脚本很简单的话可以直接写到这儿

            interval INT  #每隔多少时间监控脚本就执行一次

            weight -INT  #万一失败了当前节点的权重就减去多少,我们一般需要确保减去这个数后当前节点的权重要小于备节点。

          }

        2)、调用此脚本。(1)中我们是定义的在某个vrrp实例中打算基于这个脚本来决定我们地址是如何转移的,我们调用此脚本的方式如下:

          track_script {

            SCRIPT_NAME_1

            SCRIPT_NAME_2

            ...

          }

      (2)、示例

        1)、定义一个检查nginx进程的脚本

        vrrp_script chk_nginx {

          script "killall -0 nginx && exit 0 || exit 1"  #killall -0 的意思是查询这个进程是否存在但是不真正杀死他,意思是看我的killall命令能否执行,如果这个进程存在表示能执行即测试成功,如果不存在就表示不能执行即测试失败。此处我们的意思是测试成功就返回0,测试失败就返回1。

          interval 1 #每隔1s监控脚本就执行一次

          weight -5  #如果监测失败了就将优先级降低为5

          fall 2  #如果检测不在,至少需要检测两次才能定义检测真失败了

          rise 1 #如果此前是失败的然后再次检测他又成功了,只要检测成功了1次就立即把检测失败的权重再加回来。

        }

        2)、定义一个升降权的脚本,我们可以定义检测/etc/keepalived/down这个文件是否存在,如果存在则降权,虚IP就切换为备,如果不存在则升权,虚IP又被切换回来。如果想手动降权touch /etc/keepalived/down即可,如果想升权将down文件删除即可。

        vrrp_script chk_down {

          script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0"

          interval 1

          weight -5

        }

      (3)、脚本定义和调用截图

    d、配置node1和node2的keepalived服务

      (1)、配置虚IP检测,当/etc/keepalived/down文件存在时虚IP浮动到备节点,不存在时虚IP浮动到主节点。

        node1中的配置信息如下

[root@node1 keepalived]# cat keepalived.conf 
global_defs {
   notification_email {
    root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id node1
   vrrp_mcast_group4 224.1.101.33
}

vrrp_script chk_down {
    script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0" #检测/etc/keepalived/down文件是否存在,存在则正常退出,不存在则错误退出。此处最好写成脚本执行而不要直接写成命令。
    weight -10 #如果脚本不存在则权重减去10
    interval 1 #每隔1s监控脚本就执行一次
    fall 1 ##如果检测不在,至少需要检测1次才能定义检测真失败了
    rise 1  #如果此前是失败的然后再次检测他又成功了,只要检测成功了1次就立即把检测失败的权重再加回来。
}

vrrp_instance VI_1 {
    state MASTER
    priority 100
    interface ens33
    virtual_router_id 51
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass w0KE4b81
    }
    virtual_ipaddress {
        192.168.10.100/24 dev ens33 label ens33:0
    }

    track_script {
    chk_down #根据上述定义的chk_down这个脚本来判定状态是否ok。
    }    

    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
}

        node2中的配置信息如下

[root@node2 keepalived]# cat keepalived.conf 
global_defs {
   notification_email {
    root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id node2
   vrrp_mcast_group4 224.1.101.33
}

vrrp_script chk_down {
        script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0" #检测/etc/keepalived/down文件是否存在,存在则正常退出,不存在则错误退出,此处最好写成脚本执行而不是命令。
        weight -10 #如果脚本不存在则权重减去10
        interval 1 #每隔1s监控脚本就执行一次
        fall 1 ##如果检测不在,至少需要检测1次才能定义检测真失败了
        rise 1  #如果此前是失败的然后再次检测他又成功了,只要检测成功了1次就立即把检测失败的权重再加回来。
}

vrrp_instance VI_1 {
    state BACKUP
    priority 96
    interface ens33
    virtual_router_id 51
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass w0KE4b81
    }
    virtual_ipaddress {
        192.168.10.100/24 dev ens33 label ens33:0
    }

    track_script {
        chk_down #根据上述定义的chk_down这个脚本来判定状态是否ok。
    }

    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"

}

      (2)、我们通过上述配置启动keepalived服务后发现,当创建/etc/keepalived/down文件后我们的vip会从master飘逸到bakup,将该文件删除后vip会从backup飘逸到master。

    e、接下来我们来配置keepalived + nginx

      (1)、首先我们在node1和node2两个节点安装nginx用作为反向代服务

[root@node1 yum.repos.d]# yum install -y nginx

      (2)、接下来我们进行node1和node2中的nginx的配置(两节点配置一致)

[root@node1 nginx]# cat nginx.conf |grep -Ev " *#"

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;
    upstream websrvs {
    server 192.168.10.43:80;
    server 192.168.10.44:80;
    server 192.168.10.45:80;
    }
    include /etc/nginx/conf.d/*.conf;

    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://websrvs;
        }

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }


}

      我们可以看到nginx可以正常代理到后端

[root@node1 nginx]# curl 192.168.10.41
<h1>Vhost1</h1>
[root@node1 nginx]# curl 192.168.10.41
<h1>Vhost2</h1>
[root@node1 nginx]# curl 192.168.10.41
<h1>Vhost3</h1>
[root@node1 nginx]# curl 192.168.10.100
<h1>Vhost1</h1>
[root@node1 nginx]# curl 192.168.10.100
<h1>Vhost2</h1>
[root@node1 nginx]# curl 192.168.10.100
<h1>Vhost3</h1>

      (3)、接下来我们来配置脚本监控nginx服务是否正常,我们可以配置监控脚本来决定地址转移时nginx服务是否启动,一旦当前节点变为备节点我们就将nginx服务给停止,如果当前节点变成主节点我们又需要将nginx服务给启动起来。

        1)、我们可以在notify.sh脚本中添加两个命令,在当前节点为主节点的时候将nginx服务启动,在当前节点为备节点的时候将nginx服务停止。(node1和node2节点都添加)

[root@node1 nginx]# cat /etc/keepalived/notify.sh
#!/bin/bash
#
contact='root@localhost'
notify(){
    mailsubject="$(hostname) to be $1,vip floating"
    mailbody="$(date +'%F%T'):vrrp transltion,$(hostname) changed to be $1"
    echo "$mailbody" |mail -s "$mailsubject" $contact
}
case $1 in
    master)
        systemctl start nginx.service
        notify master
        ;;
    backup)
        systemctl stop nginx.service
        notify backup
        ;;
    fault)
        systemctl stop nginx.service
        notify fault
        ;;
    *)
        echo "Usage: $(basename $0) {master|backup|fault}"
        exit 1
        ;;
esac

        2)、开始我们的vip在node1中,node1和node2中的nginx都停止服务。我们可以在node1中创建/etc/keepalived/down 文件,可以看到vip转移到了node2,并且node2中的nginx服务也启动起来了,然后我们将node1中的down文件删除会发现vip又会漂移至node1,并且node1中的nginx服务自动启动了,node2中的nginx服务也自动停止了。

        3)、不过一般而言,为了把nginx自身服务用作进程运行检查脚本的话无论主备节点都不应该把nginx进程停掉,因为停止的话一检查nginx进程没有,那么他就会降权,就算是备节点也会降权的,如果主节点nginx服务挂了,那么主节点就会降权降了10,备节点因为nginx默认是停止的所以一开始降权也是降了10,这样的话主备节点都降权降了10,这样的话主节点的优先级还是要高于备节点,那么地址就转移不出去了。因此我们备节点原则上是不应该停止nginx服务的,而是应该备节点也启动nginx的,他如果停止了我们就启动,他如果出现了故障我们就重启。因此此处我们需要将主备就都配置启动nginx,相应的notify.sh配置应该如下:

[root@node1 keepalived]# cat /etc/keepalived/notify.sh
#!/bin/bash
#
contact='root@localhost'
notify(){
    mailsubject="$(hostname) to be $1,vip floating"
    mailbody="$(date +'%F%T'):vrrp transltion,$(hostname) changed to be $1"
    echo "$mailbody" |mail -s "$mailsubject" $contact
}
case $1 in
    master)
        systemctl start nginx.service
        notify master
        ;;
    backup)
        systemctl start nginx.service
        notify backup
        ;;
    fault)
        systemctl stop nginx.service
        notify fault
        ;;
    *)
        echo "Usage: $(basename $0) {master|backup|fault}"
        exit 1
        ;;
esac

        此时我们无论哪个node是主备nginx服务就都不会停止了。

    f、那么我们如果要在前端主机上对nginx做出监控动作需要怎么办?接下来我们来编辑脚本来监控nginx进程。

      (1)、我们配置监控脚本(在两个节点上都需要配置)

[root@node1 /]# cat /etc/keepalived/keepalived.conf 
global_defs {
   notification_email {
    root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id node1
   vrrp_mcast_group4 224.1.101.33
   script_user root
   enable_script_security
}

vrrp_script chk_down {
       # script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0"
        script "/application/test.sh"
        weight -10
        interval 2
        fall 2
        rise 2
}

vrrp_script chk_ngx {
    script "/application/chk_ngx.sh"
        weight -10
        interval 2
        fall 2
        rise 2
}

vrrp_instance VI_1 {
    state MASTER
    priority 100
    interface ens33
    virtual_router_id 51
    advert_int 2
    authentication {
        auth_type PASS
        auth_pass w0KE4b81
    }
    virtual_ipaddress {
        192.168.10.100/24 dev ens33 label ens33:0
    }

    track_script {
        chk_down
    chk_ngx
    }

    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
}
[root@node1 /]# cat /application/chk_ngx.sh 
#!/bin/bash
#
#查看nginx是否存在,如果存在则正常退出如果不存在则异常退出
killall -0 nginx && exit 0 || exit 1
[root@node1 /]# chmod +x /application/chk_ngx.sh

      (2)、接下来我们重启keepalived服务。此时我们的vip在node1中。然后我们在node1中安装一个httpd后将nginx停止然后启动httpd,这样我们node1中nginx服务就启动不起来了,我们可以看到vip就从node1中漂移到node2中了。然后我们将node1中的httpd服务停掉然后将nginx服务启动起来,然后发现我们的vip又漂移到了node1。

 

posted @ 2021-02-19 11:22  Presley  阅读(582)  评论(0编辑  收藏  举报