nginx(四) nginx+keepalived 實現主備+雙主熱備模型的高可用負載均衡代理服務
在前面《nginx配置:反向代理 負載均衡 後端健康檢查 緩存》等幾篇文章中,我們配置了nginx的反向代理負載均衡WEB集羣,而在《keepalived 及 keepalived配置LVS高可用集羣》進行keepalived配置LVS高可用集羣。下面將在前文的一些基礎上,用keepalived分別實現主備模型和雙主模型的nginx反向代理服務器的高可用。
1、配置環境準備
1-1、模擬環境
1、各服務器主機系統:CentOS 6.4 x86_64
2、反向代理服務器:
node1: IP:192.168.18.241 (host name:node1.tjiyu.com);
node2: IP:192.168.18.242 (host name:node2.tjiyu.com);
VIP1:192.168.18.240;(主備模型只使用VIP1)
VIP2:192.168.18.250;
service:nginx 1.10.2 提供反向代理、負載均衡服務;
keepalived 爲nginx(VIP)提供高可用服務;
3、後端兩臺realserver:
realserver1: IP:192.168.18.251 (host name:realserver1.tjiyu,com);
realserver2: IP:192.168.18.252 (host name:realserver2.tjiyu.com);
service:nginx 1.10.2 提供WEB服務
1-2、配置前所需要的準備
各主機需要做以下準備:
1、配置IP、關閉防火牆/SELINUX;
2、時間同步;
3、配置節點名稱(不是必須的,最好配置上,方便操作)
在前面《heartbeat v2 haresource 配置可用集羣》說到的高可用集羣已有詳細介紹,這裏就不再給出了。
2、nginx和keepalived相關準備說明
nginx可以參考《nginx配置:反向代理 負載均衡 後端健康檢查 緩存》文章,先在配置好兩臺代理服務器,使得它們都可以實現反向代理和負載均衡(注意。不用配置緩存,影響測試),分別訪問它們的IP測試正常,如下:
Nginx根據前文配置好後,下面就不會去配置nginx了,主要是對keepalived進行配置,以及相關測試。
Keepalived相關的原理、配置說明,可以參考《keepalived 及 keepalived配置LVS高可用集羣》;首先需要在兩臺代理服務器分別下載安裝,yum install -y keepalived就可以了。下面我們用到它裏面的一些配置,不過會重新給出並作出說明。
3、配置nginx+keepalived主備模型
我們先來說明配置的一些細節,後面再給出完整的配置文件。一個是對nignx狀態進行監測,一個是對nginx進行管理。
3-1、配置keepalived對nignx進行監測
配置/etc/keepalived/keepalived.conf文件使得keepalived可以對nignx進行監測,如下:
[root@node1 ~]# cd /etc/keepalived/ [root@node1 keepalived]# cp keepalived.conf keepalived.conf.bak [root@node1 keepalived]# vim keepalived.conf
在配置文中增加vrrp_script chk_nginx_health { script "killall -0 nginx"… }塊,定義nginx服務狀態跟蹤腳本,腳本中可以檢查nginx的狀態,如下:
這裏我們直接用"killall -0 nginx"命令,它不會殺死nginx,只會在nginx啓動正常時返回0,停止時返回1,如下:
然後在vrrp_instance VI_1 {track_script {… }}中調用上面定義的服務狀態跟蹤腳本,如下:
3-2、配置keepalived狀態轉換通知,以及轉換時對nignx進行管理
自定義keepalived狀態轉換狀態變化腳本notify.sh,放到/etc/keepalived目錄下,如下:
該腳本可以在keepalived狀態轉換時,發出郵件通知;還可以對nginx服務進行管理,如keepalived成功主節點時,啓動nginx,成爲備節點時停止nginx(主備時)或重啓nginx(雙主時),配置到vrrp_instance VI_1 {}塊中,如下:
注意,配置的發件人用戶得是系統用戶,不存在用戶發不出郵件,得先在兩節點上添加用戶,過程如下:
[root@node1 keepalived]# useradd root_keepalived
3-3、node1上的keepalived配置
配置node1成主節點,優先級較高(搶佔式),配置如下:
! Configuration File for keepalived global_defs { #全局配置,這裏額外的靜態路由並未添加因爲它是非必要的,除非我們在當前或特定的主機上生成特殊的靜態路由等 notification_email { #realserver故障時通知郵件的收件人地址,可以多個 root@localhost } notification_email_from root_keepalived #發件人信息(可以隨意僞裝,因爲郵件系統不會驗證處理髮件人信息) smtp_server 127.0.0.1 #發郵件的服務器(一定不可爲外部地址) smtp_connect_timeout 30 #連接超時時間 router_id LVS_DEVEL #路由器的標識(可以隨便改動) } vrrp_script chk_nginx_health { # 定義服務狀態跟蹤腳本,腳本中可以檢查高可用服務的狀態,返回狀態碼0表示服務正常;配置調用則在vrrp_instance中的track_script段;這裏chk_nginx是定義腳本的名稱,可隨意取 script "killall -0 nginx" #判斷命令/自己定義好的腳本路徑;#這裏killall -0 nginx不會殺死nginx,只會在nginx啓動正常時返回0,停止時返回1,返回1就會在vrrp實例定義的優先級減去下面的weight值,就表示期望這個節點爲備用狀態。 interval 1 #每隔1秒鐘執行一次 weight -2 #上面的命令腳本執行失敗,優先級降低2;這個值的絕對值必須大於MASTER減BACKUP定義的優先級 fall 2 #命令/腳本執行失敗多少次纔算真的失敗 rise 1 #命令/腳本執行成功多少次纔算真的成功 } vrrp_instance VI_1 { #配置虛擬路由器的實例,VI_1是自定義的實例名稱 state MASTER #初始狀態,MASTER|BACKUP,當state指定的instance的初始化狀態,在兩臺服務器都啓動以後,馬上發生競選,優先級高的成爲MASTER,所以這裏的MASTER並不是表示此臺服務器一直是MASTER interface eth0 #通告選舉所用端口 virtual_router_id 51 #虛擬路由的ID號(一般不可大於255) priority 101 #優先級信息 #備必須更低 advert_int 1 #VRRP通告間隔,秒 authentication { auth_type PASS #認證機制 auth_pass 5344 #密碼(儘量使用隨機) } virtual_ipaddress { #虛擬地址(VIP地址) 192.168.18.240 } track_script { #調用上面定義的服務狀態跟蹤腳本 chk_nginx_health } #nopreempt #設置不搶佔,這裏只能設置在state爲BACKUP的節點上,而且這個節點的優先級必須別另外的高 #preempt delay 300 #搶佔延遲,和nopreempt一樣只能用在BACKUP上,但不能和nopreempt同時使用 notify_master "/etc/keepalived/notify.sh -m mb -n master -s nginx -a 192.168.18.240" #轉換爲master狀態時使用此腳本通知 notify_backup "/etc/keepalived/notify.sh -m mb -n backup -s nginx -a 192.168.18.240" #轉換爲backup狀態時使用此腳本通知 notify_fault "/etc/keepalived/notify.sh -m mb -n fault -s nginx -a 192.168.18.240" #轉換爲fault狀態時使用此腳本通知,如果腳本帶有參數也就是有空格必須使用引號 }
3-4、node2上的keepalived配置
配置node2成爲備節點,和node1h配置主要差別有兩處,一是state BACKUP,二是priority 100優先級更低,這是在搶佔模式下的配置,後面我們再說非搶佔式配置,差別不大,本配置如下:
! Configuration File for keepalived global_defs { #全局配置,這裏額外的靜態路由並未添加因爲它是非必要的,除非我們在當前或特定的主機上生成特殊的靜態路由等 notification_email { #realserver故障時通知郵件的收件人地址,可以多個 root@localhost } notification_email_from root_keepalived #發件人信息(可以隨意僞裝,因爲郵件系統不會驗證處理髮件人信息) smtp_server 127.0.0.1 #發郵件的服務器(一定不可爲外部地址) smtp_connect_timeout 30 #連接超時時間 router_id LVS_DEVEL #路由器的標識(可以隨便改動) } vrrp_script chk_nginx_health { # 定義服務狀態跟蹤腳本,腳本中可以檢查高可用服務的狀態,返回狀態碼0表示服務正常;配置調用則在vrrp_instance中的track_script段;這裏chk_nginx是定義腳本的名稱,可隨意取 script "killall -0 nginx" #判斷命令/自己定義好的腳本路徑;#這裏killall -0 nginx不會殺死nginx,只會在nginx啓動正常時返回0,停止時返回1,返回1就會在vrrp實例定義的優先級減去下面的weight值,就表示期望這個節點爲備用狀態。 interval 1 #每隔1秒鐘執行一次 weight -2 #上面的命令腳本執行失敗,優先級降低2;這個值的絕對值必須大於MASTER減BACKUP定義的優先級 fall 2 #命令/腳本執行失敗多少次纔算真的失敗 rise 1 #命令/腳本執行成功多少次纔算真的成功 } vrrp_instance VI_1 { #配置虛擬路由器的實例,VI_1是自定義的實例名稱 state BACKUP #初始狀態,MASTER|BACKUP,當state指定的instance的初始化狀態,在兩臺服務器都啓動以後,馬上發生競選,優先級高的成爲MASTER,所以這裏的MASTER並不是表示此臺服務器一直是MASTER interface eth0 #通告選舉所用端口 virtual_router_id 51 #虛擬路由的ID號(一般不可大於255) priority 100 #優先級信息 #備必須更低 advert_int 1 #VRRP通告間隔,秒 authentication { auth_type PASS #認證機制 auth_pass 5344 #密碼(儘量使用隨機) } virtual_ipaddress { #虛擬地址(VIP地址) 192.168.18.240 } track_script { #調用上面定義的服務狀態跟蹤腳本 chk_nginx_health } #nopreempt #設置不搶佔,這裏只能設置在state爲BACKUP的節點上,而且這個節點的優先級必須別另外的高 #preempt delay 300 #搶佔延遲,和nopreempt一樣只能用在BACKUP上,但不能和nopreempt同時使用 notify_master "/etc/keepalived/notify.sh -m mb -n master -s nginx -a 192.168.18.240" #轉換爲master狀態時使用此腳本通知 notify_backup "/etc/keepalived/notify.sh -m mb -n backup -s nginx -a 192.168.18.240" #轉換爲backup狀態時使用此腳本通知 notify_fault "/etc/keepalived/notify.sh -m mb -n fault -s nginx -a 192.168.18.240" #轉換爲fault狀態時使用此腳本通知,如果腳本帶有參數也就是有空格必須使用引號 }
3-5、狀態轉換通知腳本notify.sh
前面我們說過,自定義keepalived狀態轉換狀態變化腳本notify.sh,放到/etc/keepalived目錄下,如下:
#!/bin/bash # description: An example of notify script # Usage: notify.sh -m|--mode {mm|mb} -s|--service SERVICE1,... -a|--address VIP -n|--notify {master|backup|falut} -h|--help contact='root@localhost' helpflag=0 serviceflag=0 modeflag=0 addressflag=0 notifyflag=0 Usage() { echo "Usage: notify.sh [-m|--mode {mm|mb}] [-s|--service SERVICE1,...] <-a|--address VIP> <-n|--notify {master|backup|falut}>" echo "Usage: notify.sh -h|--help" } ParseOptions() { local I=1; if [ $# -gt 0 ]; then while [ $I -le $# ]; do case $1 in -s|--service) [ $# -lt 2 ] && return 3 serviceflag=1 services=(`echo $2|awk -F"," '{for(i=1;i<=NF;i++) print $i}'`) shift 2 ;; -h|--help) helpflag=1 return 0 shift ;; -a|--address) [ $# -lt 2 ] && return 3 addressflag=1 vip=$2 shift 2 ;; -m|--mode) [ $# -lt 2 ] && return 3 mode=$2 shift 2 ;; -n|--notify) [ $# -lt 2 ] && return 3 notifyflag=1 notify=$2 shift 2 ;; *) echo "Wrong options..." Usage return 7 ;; esac done return 0 fi } #workspace=$(dirname $0) RestartService() { if [ ${#@} -gt 0 ]; then for I in $@; do if [ -x /etc/rc.d/init.d/$I ]; then /etc/rc.d/init.d/$I restart else echo "$I is not a valid service..." fi done fi } StopService() { if [ ${#@} -gt 0 ]; then for I in $@; do if [ -x /etc/rc.d/init.d/$I ]; then /etc/rc.d/init.d/$I stop else echo "$I is not a valid service..." fi done fi } Notify() { mailsubject="`hostname` to be $1: $vip floating" mailbody="`date '+%F %H:%M:%S'`, vrrp transition, `hostname` changed to be $1." echo $mailbody | mail -s "$mailsubject" $contact } # Main Function ParseOptions $@ [ $? -ne 0 ] && Usage && exit 5 [ $helpflag -eq 1 ] && Usage && exit 0 if [ $addressflag -ne 1 -o $notifyflag -ne 1 ]; then Usage exit 2 fi mode=${mode:-mb} case $notify in 'master') if [ $serviceflag -eq 1 ]; then RestartService ${services[*]} fi Notify master ;; 'backup') if [ $serviceflag -eq 1 ]; then if [ "$mode" == 'mb' ]; then StopService ${services[*]} else RestartService ${services[*]} fi fi Notify backup ;; 'fault') Notify fault ;; *) Usage exit 4 ;; esac exit 0
4、測試主備模型
1、在node1和node2上分別啓動keepalived,可以看到VIP配置到了node1上,成爲了主節點,而訪問測試也正常,如下:
2、當我們killall nginx停止node1上的nginx時,可以看到VIP流轉到node2上,即node2成爲主節點,而訪問正常,如下:
3、而接着當我們killall nginx停止node2的nginx時,可以看到VIP流轉回了node1,也即node1重新成爲主節點,而訪問也正常;注意,我們並沒有手動啓動node1上前面kil掉的nginx,這是由notify.sh在node1成功主節點時完成的,如下:
4、當我們killall keepalived停止node1上的keepalived時,可以VIP再次流轉到node2,也即node2再次成爲主節點,而訪問也正常;注意,我們查看node1上的日誌可以看到node1上的VIP被移除了,如下:
5、接着,我們重啓node1上的keepalived,發現VIP流轉回node1,即node1成爲了主節點,而之前node2作爲主節點在正常運行的,這就是搶佔式了,node1配置優先級高,恢復正常後搶佔了node2的主節點資源,如下:
6、配置非搶佔式:在配置BACKUP的node2上配置,nopreempt並且優先級比MASTER的node1高,而後我們重啓node2上的keepalived,然後停止node1上的keepalived,再次使node2成爲主節點,如下:
7、接着,如上面第5步,重啓node1上的keepalived,VIP依然在node2,即node2還作爲主節點在正常運行,這就是非搶佔式,如下:
8、接着,我們停止node2上的keepalived,可以看到node1成爲主節點,但VIP在node1、node2上都有,即node2沒有撤除VIP,keepalived就停止了,不過這也沒關,因爲node1配置VIP時會自己自動發出ARP,這樣報文就能轉到node1了,如下:
9、接着,我們重啓node2上的keepalived,可以看到node2成爲備節點,node1依然還是主節點,也沒有被搶佔,如下:
5、配置nginx+keepalived雙主模型
我們在《keepalived 及 keepalived配置LVS高可用集羣》中說過,Keepalived工作模型總是一主多備的,而這個雙主是指兩個VIP分別對應兩個VRRP實例(也就是兩個主備同時運行),如果兩個VIP對應同一個服務,可以在前面再加DNS輪循,對就兩條DNS的A記錄,這樣可以做到scale out 橫向擴展,並且充分利用資源。
注意,雙主最好不要配置非搶佔模式,因爲一臺故障時另一臺運行兩個VIP,當恢復時需要把一個VIP搶佔流轉回來,這樣就才能平分流量。
5-1、修改主備配置
我們就在上面主備模型的基礎上,增加一個VRRP實例對就VIP2(192.168.18.250),但需要稍微修改前面配置,如記錄得改回node2上的搶佔模式,還有狀態轉換通知的腳本配置改"-m mm",如下:
5-2、node1上增加的配置
直接在配置文件後面加上加一個VRRP實例配置,這個實例node1爲備節點,如下:
vrrp_instance VI_2 { #配置虛擬路由器的實例,VI_1是自定義的實例名稱 state BACKUP #初始狀態,MASTER|BACKUP,當state指定的instance的初始化狀態,在兩臺服務器都啓動以後>,馬上發生競選,優先級高的成爲MASTER,所以這裏的MASTER並不是表示此臺服務器一直是MASTER interface eth0 #通告選舉所用端口 virtual_router_id 55 #虛擬路由的ID號(一般不可大於255) priority 100 #優先級信息 #備必須更低 advert_int 1 #VRRP通告間隔,秒 authentication { auth_type PASS #認證機制 auth_pass 6675 #密碼(儘量使用隨機) } virtual_ipaddress { #虛擬地址(VIP地址) 192.168.18.250 } track_script { #調用上面定義的服務狀態跟蹤腳本 chk_nginx_health } #nopreempt #設置不搶佔,這裏只能設置在state爲BACKUP的節點上,而且這個節點的優先級必須別另外的高 #preempt delay 300 #搶佔延遲,和nopreempt一樣只能用在BACKUP上,但不能和nopreempt同時使用 notify_master "/etc/keepalived/notify.sh -m mm -n master -s nginx -a 192.168.18.250" #轉換爲master狀態時使用 此腳本通知 notify_backup "/etc/keepalived/notify.sh -m mm -n backup -s nginx -a 192.168.18.250" #轉換爲backup狀態時使用 此腳本通知 notify_fault "/etc/keepalived/notify.sh -m mm -n fault -s nginx -a 192.168.18.250" #轉換爲fault狀態時使用>此腳本通知,如果腳本帶有參數也就是有空格必須使用引號 }
5-3、node2上增加的配置
直接在配置文件後面加上加一個VRRP實例配置,這個實例node2爲主節點,如下:
vrrp_instance VI_2 { #配置虛擬路由器的實例,VI_1是自定義的實例名稱 state MASTER #初始狀態,MASTER|BACKUP,當state指定的instance的初始化狀態,在兩臺服務器都啓動以後,>馬上發生競選,優先級高的成爲MASTER,所以這裏的MASTER並不是表示此臺服務器一直是MASTER interface eth0 #通告選舉所用端口 virtual_router_id 55 #虛擬路由的ID號(一般不可大於255) priority 101 #優先級信息 #備必須更低 advert_int 1 #VRRP通告間隔,秒 authentication { auth_type PASS #認證機制 auth_pass 6675 #密碼(儘量使用隨機) } virtual_ipaddress { #虛擬地址(VIP地址) 192.168.18.250 } track_script { #調用上面定義的服務狀態跟蹤腳本 chk_nginx_health } #nopreempt #設置不搶佔,這裏只能設置在state爲BACKUP的節點上,而且這個節點的優先級必須別另外的高 #preempt delay 300 #搶佔延遲,和nopreempt一樣只能用在BACKUP上,但不能和nopreempt同時使用 notify_master "/etc/keepalived/notify.sh -m mm -n master -s nginx -a 192.168.18.240" #轉換爲master狀態時使用此 腳本通知 notify_backup "/etc/keepalived/notify.sh -m mm -n backup -s nginx -a 192.168.18.240" #轉換爲backup狀態時使用此 腳本通知 notify_fault "/etc/keepalived/notify.sh -m mm -n fault -s nginx -a 192.168.18.240" #轉換爲fault狀態時使用此>腳本通知,如果腳本帶有參數也就是有空格必須使用引號 }
6、測試nginx+keepalived雙主模型
我們分別重啓兩個節點上keepalived,可以看到VIP1(192.168.18.240)配置到node1上,而VIP2(192.168.18.250)配置到node2上,說明node1成爲VRRP實例1的主節點,node2成爲VRRP實例2的主節點;而訪問VIP1和VIP2都能正常,如下
到這裏,我們完成了用keepalived分別實現主備模型和雙主模型的nginx反向代理負載均衡服務器的高可用,後面有時間將會在本文件的基礎上進行nginx+tomcat的動靜分離配置……
【參考資料】
1、nginx官網文檔:http://nginx.org/en/docs/
2、keepalived官網文檔:http://www.keepalived.org/documentation.html
3、keepalived 及 keepalived配置LVS高可用集羣:http://blog.csdn.net/tjiyu/article/details/52891835
4、nginx詳解:http://blog.csdn.net/tjiyu/article/details/53027619
5、nginx配置:反向代理 負載均衡 後端健康檢查 緩存:http://blog.csdn.net/tjiyu/article/details/53028026