Keepalived + nginx實現高可用性和負載均衡

前幾天使用了Heartbeat作爲高可用服務架構的解決方案,今天有試驗了一種全新的解決方案,即採用Keepalived來實現這個功能。

Keepalived 是一種高性能的服務器高可用或熱備解決方案,Keepalived可以用來防止服務器單點故障(單點故障是指一旦某一點出現故障就會導致整個系統架構的不可用)的發生,通過配合Nginx可以實現web前端服務的高可用。

Keepalived實現的基礎是VRRP協議,Keepalived就是巧用VRRP協議來實現高可用性(HA)的.

VRRP(Virtual Router Redundancy Protocol)協議是用於實現路由器冗餘的協議,VRRP協議將兩臺或多臺路由器設備虛擬成一個設備,對外提供虛擬路由器IP(一個或多個),而在路由器組內部,如果實際擁有這個對外IP的路由器如果工作正常的話就是MASTER,或者是通過算法選舉產生,MASTER實現針對虛擬路由器IP的各種網絡功能,如ARP請求,ICMP,以及數據的轉發等;其他設備不擁有該IP,狀態是BACKUP,除了接收MASTER的VRRP狀態通告信息外,不執行對外的網絡功能。當主機失效時,BACKUP將接管原先MASTER的網絡功能。

VRRP協議使用多播數據來傳輸VRRP數據,VRRP數據使用特殊的虛擬源MAC地址發送數據而不是自身網卡的MAC地址,VRRP運行時只有MASTER路由器定時發送VRRP通告信息,表示MASTER工作正常以及虛擬路由器IP(組),BACKUP只接收VRRP數據,不發送數據,如果一定時間內沒有接收到MASTER的通告信息,各BACKUP將宣告自己成爲MASTER,發送通告信息,重新進行MASTER選舉狀態。

1. 安裝Keeplived依賴

安裝keepalived之前,也要安裝一些依賴庫

安裝 openssl

yum install openssl*

安裝popt

yum install popt*

安裝ipvsadm

yum isntall ipvsadm

安裝libnl-dev

yum install libnl-dev*

2. 安裝Keepalived

keepalived安裝包地址:

http://www.keepalived.org/software/keepalived-1.2.7.tar.gz

下載解壓後編譯配置

./configure --prefix=/usr/local/keepalived

編譯配置需要確保一下幾項爲Yes狀態:

Use IPVS Framework : Yes IPVS sync daemon support : Yes IPVS use libnl : Yes Use VRRP Framework : Yes

然後就可以編譯安裝了:

make && make install

因爲沒有使用keepalived的默認路徑安裝(默認是/usr/local),安裝完成之後,需要做一些工作

cp /usr/local/keepalived/sbin/keepalived /usr/sbin/
#複製keepalived啓動文件到默認路徑,也可以通過設置環境變量的path實現

cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
#複製服務啓動腳本到,以便可以通過service控制keepalived服務

cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
#複製keepalived服務腳本到默認的地址,也通過修改init.d/keepalived文件中的相應配置實現

mkdir -p /etc/etc/keepalived/
cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
vi /etc/keepalived/keepalived.conf
#複製默認配置文件到默認路徑,其實也可以在/etc/init.d/keepalived中設置路徑

chkconfig keepalived on
#開機啓動服務

3. 配置Keepalived

接下來就是配置了,很簡單,直接上配置文件

先是主服務器:

global_defs
{
notification_email    #通知email,根據實際情況配置
{
[email protected]
}
notification_email_from [email protected]
smtp_server 127.0.0.1
stmp_connect_timeout 30
router_id node1         #節點名標識,主要用於通知中
}

vrrp_instance VI_NODE {
  state MASTER          #配置爲主服務器
  interface eth0        #通訊網卡
  virtual_router_id 100 #路由標識
  priority 200          #優先級,0-254
  advert_int 5          #通知間隔,實際部署時可以設置小一點,減少延時
  
  authentication {
    auth_type PASS
    auth_pass 123456    #驗證密碼,用於通訊主機間驗證
  }

  virtual_ipaddress {
    192.168.1.206       #虛擬ip,可以定義多個
  }
}
接下是從服務器設置:
global_defs {
  notification_email {
    [email protected]
  }
  notification_email_from [email protected]
  smtp_server 127.0.0.1
  stmp_connect_timeout 30
  router_id node2
}

vrrp_instance VI_NODE {
  state BACKUP           #與主服務器對應
  interface eth0         #從服務器的通信網卡
  virtual_router_id 100  #路由標識,和主服務器相同
  priority 100           #優先級,小於主服務器即可
  advert_int 5           #這裏是接受通知間隔,與主服務器要設置相同
  
  authentication {
   auth_type PASS
    auth_pass 123456     #驗證密碼,與主服務器相同
  }
  
  virtual_ipaddress {
    192.168.1.206        #虛擬IP,也要和主服務器相同
  }
}

上面的設置是最基礎的設置,實現的功能是如果主服務器的Keepalived停止服務(一般情況下服務器宕機),則將虛擬IP切換至從服務器,主服務器恢復後從新切換回主服務器。

但是很多情況下我們面臨的處境是nginx掛掉了,而這個時候Keepalived就不能發揮作用,這時候就需要我們來改良下Keepalived了。通過向Keepalived添加一個自定義腳本來監控neginx的運行狀態,如果nginx進程結束,則kill Keepalived進程,以此來達到主從服務器的切換功能。

我們在修改上面配置的主服務器的配置文件,在中間添加腳本實現

global_defs {
   notification_email {
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id nginx_master
}
vrrp_script chk_http_port {
   script "/usr/local/keepalived/nginx.sh"  #在這裏添加腳本鏈接
   interval 3       #腳本執行間隔
   weight 2         #腳本結果導致的優先級變更
}
vrrp_instance VI_NODE {
    state MASTER
    interface eth0
    virtual_router_id 100
    priority 200
    advert_int 5
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    track_script {
        chk_http_port     #添加腳本執行
    }
    virtual_ipaddress {
        192.168.1.206
    }
}

具體的配置可以參考另一篇文章Keepalived配置詳解

如果我們使用了LVS+Keepalived集成,那麼keepalived可以代替ipvsadm來配置LVS,可以方便的通過配置就可以搞定,這在另一篇文章Keepalived+LVS配置詳解

修改完配置文件我們寫我們的上面配置的nginx.sh,當然我們假定Nginx已經安裝完成

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

上面的腳本簡單的查看nginx進程是否存在,不存在就kill keepalived進程。

接下來我們對上面的哦腳本修改一下,當腳本檢測到nginx沒有運行的時候會嘗試去啓動nginx以此,如果失敗則停掉keepalived進程

#!/bin/bash
A=`ps -C nginx –no-header |wc -l`
if [ $A -eq 0 ];then
  /usr/local/nginx/sbin/nginx #nginx命令的路徑
  sleep 3
  if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
    killall keepalived
  fi
fi

把腳本保存到上面配置的具體路徑(我這裏是/usr/local/keepalived),然後很重要的一步是修改腳本的執行權限

chmod +x nginx.sh

4. 運行Keepalived

配置完成後就可以運行看下效果了,分別在主從服務器上啓動nginx和keepalived

service keepalived start

啓動之後通過·ip a·命令查看主服務器的網絡信息,可以看到在eth0網卡下生成了192.168.1.206這個虛擬ip,並可通過這個ip訪問到nginx

然後我們關閉nginx的進程(如果配置了一次嘗試重啓那要注意下),然後我們可以通過ps -e查看keepalived進程是否關閉,正常情況下查看網絡信息中,可以看到eth0網卡下的虛擬ip已經解除,然後在從服務器的網絡信息中可以看到從服務器的eth0網卡綁定了虛擬ip,通過這個ip就訪問到了從服務器的nginx去了,這是我們重新啓動主服務器的nginx和keepalieved,我們可以發現虛擬ip就綁回到了主服務器。

這樣就實現了基本雙擊主從熱備功能了。

這裏注意下防火牆的問題,就是這問題困擾了我很久。找了一些資料纔將問題解決

因爲Keepalived之間是通過組播來通知對方的是否存活,以及發送優先級的,並且通過組播來選舉MASTER的,而224.0.0.18就是常用的組播地址,防火牆開啓允許這個組播地址通信就可以了:

1.如果用的是默認防火牆,只需要添加:

iptables -I RH-Firewall-1-INPUT -d 224.0.0.18 -j ACCEPT

2.如果是自己用腳本設置的防火牆,需要添加如下規則

iptables -A OUTPUT -o eth0 -d 224.0.0.18 -j ACCEPT iptables -A OUTPUT -o eth0 -s 224.0.0.18 -j ACCEPT iptables -A INPUT -i eth0 -d 224.0.0.18 -j ACCEPT iptables -A INPUT -i eth0 -s 224.0.0.18 -j ACCEPT

5. 總結

  • keepalived通過虛擬路由實現雙機熱備,相比其他方案具有一定的優越性
  • 因爲是固定主從熱備,該方案比較適合兩個互備服務器性能有差異的情況
  • Keepalived同樣可以實現雙主互備,通過設置互爲主備,然後通過DNS負載均衡到不同vip就可以實現
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章