OpenResty(nginx) + keepliaved 實現站點高可用

前言

利用 Nginx 的負載均衡和反向代理,我們可以實現後臺應用的高可用。這時候的用戶請求是先通過 nginx, 然後在訪問我們的應用,如果 nginx 掛掉了,那我們所有的應用都無法訪問了。所以我們必須實現 Nginx 的高可用,達到一臺 Nginx 宕機,另一臺備機自動接管服務的效果。

本文沒有直接使用 nginx ,而是使用了 OpenResty 。其實效果是一樣的。 OpenResty 是一個基於 Nginx 與 Lua 的高性能 Web 平臺。

Keepalived 介紹

Keepalived是一個基於VRRP協議來實現的服務高可用方案,可以利用其來避免IP單點故障,類似的工具還有heartbeat、corosync、pacemaker。但是它一般不會單獨出現,而是與其它負載均衡技術(如lvs、haproxy、nginx)一起工作來達到集羣的高可用。

VRRP協議

VRRP全稱 Virtual Router Redundancy Protocol,即 虛擬路由冗餘協議。可以認爲它是實現路由器高可用的容錯協議,即將N臺提供相同功能的路由器組成一個路由器組(Router Group),這個組裏面有一個master和多個backup,但在外界看來就像一臺一樣,構成虛擬路由器,擁有一個虛擬IP(vip,也就是路由器所在局域網內其他機器的默認路由),佔有這個IP的master實際負責ARP相應和轉發IP數據包,組中的其它路由器作爲備份的角色處於待命狀態。master會發組播消息,當backup在超時時間內收不到vrrp包時就認爲master宕掉了,這時就需要根據VRRP的優先級來選舉一個backup當master,保證路由器的高可用。

在VRRP協議實現裏,虛擬路由器使用 00-00-5E-00-01-XX 作爲虛擬MAC地址,XX就是唯一的 VRID (Virtual Router IDentifier),這個地址同一時間只有一個物理路由器佔用。在虛擬路由器裏面的物理路由器組裏面通過多播IP地址 224.0.0.18 來定時發送通告消息。每個Router都有一個 1-255 之間的優先級別,級別最高的(highest priority)將成爲主控(master)路由器。通過降低master的優先權可以讓處於backup狀態的路由器搶佔(pro-empt)主路由器的狀態,兩個backup優先級相同的IP地址較大者爲master,接管虛擬IP。

VRRP協議 + nginx

keepalived可以認爲是VRRP協議在Linux上的實現,主要有三個模塊,分別是core、check和vrrp。core模塊爲keepalived的核心,負責主進程的啓動、維護以及全局配置文件的加載和解析。check負責健康檢查,包括常見的各種檢查方式。vrrp模塊是來實現VRRP協議的。

Keepalived 實現 OpenResty 的高可用

準備

筆者準備了二臺服務器,其 ip 地址爲:

192.168.56.101 worker-01 worker-01.joyxj.com
192.168.56.102 worker-02 worker-02.joyxj.com

系統爲 Centos 7。
我們需要在這二臺服務器上 安裝 OpenResty 和 Keepalived 。其中 192.168.56.101 爲 主機,192.168.56.102 爲備機。

OpenResty 安裝

可以參考 OpenResty 快速入門

其安裝後的目錄在 /usr/local/openresty, nginx 目錄在 /usr/local/openresty/nginx

Keepliaved 安裝

直接使用 yum 進行安裝

yum -y install kernel kernel-devel*  popt popt-devel libssl-dev libnl libnl-devel openssl openssl-* ipvsadm libnfnetlink-devel
yum install -y keepalived

安裝後使用 keepalived -v 查看版本,會輸出以下信息則表示安裝成功。

Keepalived v1.3.5 (03/19,2017), git commit v1.3.5-6-g6fa32f2
Copyright(C) 2001-2017 Alexandre Cassen, <[email protected]>

監控腳本

需要一個腳本,用於監測 Nginx 是否運行,如果 nginx 已經宕機,需要把相應機器的 Keepalived 已關掉,才能實現虛 IP 的飄移。如果不關掉 Keepalived,是不會進行虛 IP 的飄移。


vim /etc/keepalived/check_nginx.sh


#!/bin/bash
# curl -IL http://localhost/member/login.htm
# curl --data "memberName=fengkan&password=22" http://localhost/member/login.htm

count=0
for (( k=0; k<2; k++ ))
do
    # 通過 curl 的方式看可否可以訪問 Nginx 的首頁
    check_code=$( curl --connect-timeout 3 -sL -w "%{http_code}\\n" http://localhost/index.html -o /dev/null )
    if [ "$check_code" != "200" ]; then
        count=$(expr $count + 1)
        sleep 3
        continue
    else
        count=0
        break
    fi
done
if [ "$count" != "0" ]; then
   /etc/init.d/keepalived stop
    exit 1
else
    exit 0
fi

Keepalived 配置文件 keepalived.conf

我們需要對 /etc/keepalived/keepalived.conf 做一些修改。

vim /etc/keepalived/keepalived.conf

! Configuration File for keepalived

global_defs {
   notification_email {
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
   # vrrp_strict 需要註釋掉,否則會無法 ping 通虛 IP。
   # vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}
vrrp_script chk_nginx {
#    script "killall -0 nginx"
    script "/etc/keepalived/check_nginx.sh"
    interval 2
    weight -5
    fall 3  
    rise 2
}
vrrp_instance VI_1 {
    state MASTER
    interface enp0s8 #使用的網卡,這個要和 IP 相對應的網卡一致
    virtual_router_id 51
    priority 101
    advert_int 1
    mcast_src_ip 192.168.56.101 # ip
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.56.106 # 虛擬出來的 IP
    }
    track_script {
       chk_nginx
    }
}
... 省略其它默認的配置 ...

在另外一臺備機上,只需要改變 state MASTER -> state BACKUP,priority 101 -> priority 100,mcast_src_ip 192.168.56.101 -> mcast_src_ip 192.168.56.102 即可。

啓動

分別在二臺機器上啓動 Nginx 和 Keepalived。

/usr/local/openresty/nginx/sbin/nginx
systemctrl start keepalived

可以通過 /var/log/message 查看日誌。

或者通過 ps 命令查看進程查看 nginx 和 keepalived 是否已經啓動。


ps -ef | grep nginx
ps -ef | grep keepalived

root      6973     1  0 15:22 ?        00:00:00 /usr/sbin/keepalived -D
root      6974  6973  0 15:22 ?        00:00:01 /usr/sbin/keepalived -D
root      6975  6973  0 15:22 ?        00:00:01 /usr/sbin/keepalived -D
root     23980  6975  0 16:22 ?        00:00:00 /usr/sbin/keepalived -D
root     23981 23980  0 16:22 ?        00:00:00 /bin/bash /etc/keepalived/check_nginx.sh
root     23987  3587  0 16:22 pts/0    00:00:00 grep --color=auto keepalived

使用 ip a 命令可以查看 ip 情況。

ip a

3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:71:46:c1 brd ff:ff:ff:ff:ff:ff
    inet 192.168.56.101/24 brd 192.168.56.255 scope global noprefixroute enp0s8
       valid_lft forever preferred_lft forever
    inet 192.168.56.106/32 scope global enp0s8
       valid_lft forever preferred_lft forever
    inet6 fe80::23e9:cd08:cf12:aa6c/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::3725:99a9:e2e2:b667/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

從中,可以看到已經多了一個 IP 192.168.56.106 。這個 IP 就是 keepalived 虛擬出來的,通過在 keepalived.conf 文件中配置。

高可用測試

爲了方面測試,我們對 nginx 的首頁進行一些修改,增加一些標識。

直接通過服務器的 IP 進行訪問。


curl http://192.168.56.101

... 省略 ...
<h1>Welcome to OpenResty! worker-01</h1>
... 省略 ...

curl http://192.168.56.102

... 省略 ...
<h1>Welcome to OpenResty! worker-02</h1>
... 省略 ...

其中 worker-01 和 worker-02 是筆者加的標識,分別標識這二臺服務器。其它的輸出內容省略。

下面我們通過虛擬出來的 IP 192.168.56.106 進行訪問。


curl http://192.168.56.106

... 省略 ...
<h1>Welcome to OpenResty! worker-01</h1>
... 省略 ...

我們可以看到,由於 192.168.56.101 這臺服務器被我們設置爲 master ,所以 192.168.56.106 這個虛擬 IP 會漂移到 192.168.56.101 這臺機器上。現在我們把 192.168.56.101 這臺機器的 nginx 停掉,由於我們有一個監控腳本,Nginx 停掉後, Keepalived 也會被停掉。

# 停掉 nginx
/usr/local/openresty/nginx/sbin/nginx -s stop

重新訪問 虛擬 IP。


curl http://192.168.56.106

... 省略 ...
<h1>Welcome to OpenResty! worker-02</h1>
... 省略 ...

此時,已經訪問 192.168.56.102 這臺服務器,實現了切換。

可以通過 ip a 命令查看 ip 信息,發現 192.168.56.106 這個 IP 已經在 192.168.56.102 這臺服務器上了。

ip a


3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:72:75:f8 brd ff:ff:ff:ff:ff:ff
    inet 192.168.56.102/24 brd 192.168.56.255 scope global noprefixroute enp0s8
       valid_lft forever preferred_lft forever
    inet 192.168.56.106/32 scope global enp0s8
       valid_lft forever preferred_lft forever
    inet6 fe80::23e9:cd08:cf12:aa6c/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

這樣,我們就實現了 OpenResty 的高可用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章