Nginx+Keepalived高可用

Keepalived 是一種高性能的服務器高可用或熱備解決方案, Keepalived 可以用來防止服務器單點故障的發(fā)生,通過配合 Nginx 可以實現(xiàn) web 前端服務的高可用。

Keepalived 以 VRRP 協(xié)議為實現(xiàn)基礎。 VRRP(Virtual RouterRedundancy Protocol)協(xié)議是用于實現(xiàn)路由器冗余的協(xié)議, 它將兩臺或多臺路由器設備虛擬成一個設備,對外提供虛擬路由器 IP(一個或多個),而在路由器組內部,如果實際擁有這個對外 IP 的路由器如果工作正常就是 MASTER,或者是通過算法選舉產生, MASTER 實現(xiàn)針對虛擬路由器 IP 的各種網(wǎng)絡功能,其他設備不擁有該虛擬 IP,狀態(tài)是 BACKUP,除了接收 MASTER 的VRRP 狀態(tài)通告信息外,不執(zhí)行對外的網(wǎng)絡功能。

當主機失效時, BACKUP 將接管原先 MASTER 的網(wǎng)絡功能。VRRP 協(xié)議使用多播數(shù)據(jù)來傳輸 VRRP 數(shù)據(jù), VRRP 數(shù)據(jù)使用特殊的虛擬源 MAC 地址發(fā)送數(shù)據(jù)而不是自身網(wǎng)卡的 MAC 地址, VRRP 運行時只有 MASTER 路由器定時發(fā)送 VRRP 通告信息,表示 MASTER 工作正常以及虛擬路由器 IP(組), BACKUP 只接收 VRRP 數(shù)據(jù),不發(fā)送數(shù)據(jù),如果一定時間內沒有接收到 MASTER 的通告信息,各 BACKUP 將宣告自己成為 MASTER,發(fā)送通告信息,重新進行 MASTER 選舉狀態(tài)。

安裝nginx

$ cd /usr/local/src/
$ wget http://nginx.org/download/nginx-1.13.0.tar.gz
$ tar -zxvf nginx-1.13.0.tar.gz
$ cd nginx-1.13.0
$ ./configure --prefix=/usr/local/nginx
$ make && make install

安裝完成后,檢查并連接nginx

# /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.13.0
# ln /usr/local/nginx/sbin/nginx /usr/local/bin/

連接完成后就可以直接使用命令nginx。

配置nginx.conf,模擬簡單的負載均衡,這里采用baidu和360兩個地址做測試。
修改/usr/local/nginx/conf/nginx.conf文件,參照下面的內容。

worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    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;

    keepalive_timeout  65;

    gzip  on;
   
    upstream  api  {
        server   61.135.169.121:80 max_fails=1; #baidu.com
        server   42.236.9.70:80 max_fails=1;  #so.com
    }

    server {
        listen  80;
        location / {
        proxy_next_upstream error timeout http_500 http_502 http_504;
                proxy_read_timeout 10s;
                proxy_pass        http://api;
                proxy_set_header   Host             $host;
                proxy_set_header   X-Real-IP        $remote_addr;
                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
    }
}

修改完了,重啟nginx,nginx -s reload
然后在瀏覽器上輸入對應機器的IP,此時應該看到地址切換效果。

防火墻開放端口
若不能訪問此機器,則可能是防火墻沒有開放80端口,可以打開端口或關閉防火墻
下面我們打開80端口

firewall-cmd --list-all #檢查 80 端口
firewall-cmd --zone=public --add-port=80/tcp  #開放80端口
firewall-cmd --reload

安裝keepalived

$ yum -y install keepalived

這樣安裝版本較低,下載最新版http://www.keepalived.org/download.html

設置 keepalived 服務開機啟動

$ chkconfig keepalived on

配置/etc/keepalived/keepalived.conf,加上以下內容:

global_defs {
    #這里發(fā)郵件只對內網(wǎng)
    notification_email {
      xxx@qq.com #郵件報警
    }
    notification_email_from xxx@163.com #指定發(fā)件人
    smtp_server smtp.163.com   #指定smtp服務器地址
    smtp_connect_timeout 30    #指定smtp連接超時時間
    router_id LVS_DEVEL  #負載均衡標識,在局域網(wǎng)內應該是唯一的。
}

vrrp_script chk_nginx {
    script "/etc/keepalived/nginx_check.sh"
    #每2秒檢測一次nginx的運行狀態(tài)
    interval 2
    #失敗一次,將自己的優(yōu)先級調整為-20
    weight  -20
}

# virtual_ipaddress vip
# vrrp-虛擬路由冗余協(xié)議
# vrrp_instance 用來定義對外提供服務的VIP區(qū)域及其相關屬性
vrrp_instance VI_1 {
    state BACKUP #指定該keepalived節(jié)點的初始狀態(tài)
    interface enp0s3 #@@vrrp實例綁定的接口,用于發(fā)送VRRP包
    virtual_router_id 51 #取值在0-255之間,用來區(qū)分多個instance的VRRP組播, 同一網(wǎng)段中該值不能重復,并且同一個vrrp實例使用唯一的標識
    priority 150 #@@指定優(yōu)先級,優(yōu)先級高的將成為MASTER
    nopreempt #設置為不搶占。默認是搶占的
    authentication {
        auth_type PASS
        auth_pass 11111
    }
    ###采用單播通信,避免同一個局域網(wǎng)中多個keepalived組之間的相互影響
    unicast_src_ip 172.19.165.254  ##@@本機ip
    unicast_peer { #@@采用單播的方式發(fā)送VRRP通告,指定單播鄰居的IP地址
        172.19.165.222
    }
    virtual_ipaddress { #@@指定VIP地址
        172.19.165.251
    }
    #nginx存活狀態(tài)檢測腳本
    track_script {
        chk_nginx
    }
    #提示如:I'm the MASTER! Whup whup
    notify "/container/service/keepalived/assets/notify.sh"
    #節(jié)點變?yōu)閙aster時執(zhí)行
    notify_master "/etc/keepalived/send_mail.sh"
}
vrrp_instance VI_2 {
    state BACKUP
    interface enp0s3
    virtual_router_id 52
    priority 99
    nopreempt
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    ###采用單播通信,避免同一個局域網(wǎng)中多個keepalived組之間的相互影響
    unicast_src_ip 172.19.165.254  ##本機ip
    unicast_peer { #采用單播的方式發(fā)送VRRP通告,指定單播鄰居的IP地址
        172.19.165.222
    }
    virtual_ipaddress {
         172.19.165.252
    }
    #nginx存活狀態(tài)檢測腳本
    track_script {
        chk_nginx
    }
    notify "/container/service/keepalived/assets/notify.sh"
    #節(jié)點變?yōu)閙aster時執(zhí)行
    notify_master "/etc/keepalived/send_mail.sh"
}

注意,標@@的地方是要修改的。

同時,我們還需要2個腳本,一個用來監(jiān)視nginx,另一個用來發(fā)送報警郵件。
nginx_check.sh

#!/bin/bash  
A=`ps -C nginx -no-header |wc -l`
if [ $A -eq 1 ];then
        pkill keepalived
fi

send_mail.sh

#!/usr/bin/perl -w  
use Net::SMTP_auth;
use strict;
#smtp服務器
my $mailhost = 'smtp.163.com';
#發(fā)送郵件的郵箱
my $mailfrom = 'xxx@163.com';
#接收郵件的郵箱
my @mailto   = ('xxx@qq.com');
#郵件主題
my $subject  = 'keepalived up on backup';
#郵件正文
my $text = "正文\n nginx-1服務器宕機??!nginx-2變?yōu)閙aster?。?!";
#發(fā)送郵件的用戶名
my $user   = 'xxx@163.com';
#發(fā)送郵件的郵箱--163授權碼
my $passwd = 'xxx';
&SendMail();
##############################
# Send notice mail
##############################
sub SendMail() {
    my $smtp = Net::SMTP_auth->new( $mailhost, Timeout => 120, Debug => 1 )
      or die "Error.\n";
    $smtp->auth( 'LOGIN', $user, $passwd );
    foreach my $mailto (@mailto) {
        $smtp->mail($mailfrom);
        $smtp->to($mailto);
        $smtp->data();
        $smtp->datasend("To: $mailto\n");
        $smtp->datasend("From:$mailfrom\n");
        $smtp->datasend("Subject: $subject\n");
        $smtp->datasend("\n");
        $smtp->datasend("$text\n\n");
        $smtp->dataend();
    }
    $smtp->quit;
}

給這2個腳本添加執(zhí)行權限

# chmod +x send_mail.sh  nginx_check.sh

注意,調用的send_mail.sh腳本為使用Perl編寫的,需要安裝環(huán)境:

$ yum -y install perl-CPAN
$ cpan Net::SMTP_auth

寫完腳本,可以直接測試發(fā)郵件,執(zhí)行./send_mail.sh。

重啟keepalived服務,則可發(fā)現(xiàn)接收到相關郵件提醒,因為state發(fā)生改變。

$ service keepalived restart

同樣的方式,再部署另一臺,依次修改的地方為:

  • interface
  • priority(減1)
  • unicast_src_ip
  • unicast_peer
    修改完成后,重啟服務。

驗證keepalived高可用
在瀏覽器上輸入虛擬IP,如輸入http://172.19.165.251會自動切換到MASTER的機器上,可以查看虛擬IP綁定在哪臺機器上,輸入 命令ip addr

image.png

可以看到MASTER真實IP下面綁定了2個虛擬IP
再看下SLAVE有沒有綁定虛擬IP
image.png

從圖上看到SLAVE上并沒有綁定虛擬IP

當關掉MASTER,可以收到相關郵件

[root@localhost ~]# nginx -s stop

然后,也看到虛擬IP綁定也發(fā)生了改變。


image.png

image.png

當MASTER再次啟動,由于是非搶占模式,所以它仍然是BACKUP狀態(tài)。
keepalived也要啟動

systemctl start keepalived
#service keepalived start

注意,上面的nginx_check.sh會關閉keepalived,當nginx停止時keepalived也會停止,所以啟動nginx也要一起啟動keepalived.

keepalived不能自動切換原因

  1. 查看keepalived是否啟動
    ps -ef|grep keepalived
  2. 防火墻放行keepalived
    centos7是firewall,之前的是iptables
# firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 \
  --in-interface enp0s8 --destination 172.19.165.222 --protocol vrrp -j ACCEPT
success
# firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 \
  --out-interface enp0s8 --destination 172.19.165.222 --protocol vrrp -j ACCEPT
success
# firewall-cmd --reload
success
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容