公司内部 oa 系統要做線上高可用,避免單點故障,是以計劃使用2台虛拟機通過 keepalived 工具來實作 nginx 的高可用(high avaiability),達到一台nginx入口伺服器當機,另一台備機自動接管服務的效果。(nginx做反向代理,實作後端應用伺服器的負載均衡)快速搭建請直接跳至 第2節。
keepalived是一個基于vrrp協定來實作的服務高可用方案,可以利用其來避免ip單點故障,類似的工具還有heartbeat、corosync、pacemaker。但是它一般不會單獨出現,而是與其它負載均衡技術(如lvs、haproxy、nginx)一起工作來達到叢集的高可用。
在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。
heartbeat、corosync、keepalived這三個叢集元件我們到底選哪個好,首先我想說明的是,heartbeat、corosync是屬于同一類型,keepalived與heartbeat、corosync,根本不是同一類型的。keepalived使用的vrrp協定方式,虛拟路由備援協定 (virtual router redundancy protocol,簡稱vrrp);heartbeat或corosync是基于主機或網絡服務的高可用方式;簡單的說就是,keepalived的目的是模拟路由器的高可用,heartbeat或corosync的目的是實作service的高可用。 是以一般keepalived是實作前端高可用,常用的前端高可用的組合有,就是我們常見的lvs+keepalived、nginx+keepalived、haproxy+keepalived。而heartbeat或corosync是實作服務的高可用,常見的組合有heartbeat v3(corosync)+pacemaker+nfs+httpd 實作web伺服器的高可用、heartbeat v3(corosync)+pacemaker+nfs+mysql 實作mysql伺服器的高可用。總結一下,keepalived中實作輕量級的高可用,一般用于前端高可用,且不需要共享存儲,一般常用于兩個節點的高可用。而heartbeat(或corosync)一般用于服務的高可用,且需要共享存儲,一般用于多節點的高可用。這個問題我們說明白了。 又有博友會問了,那heartbaet與corosync我們又應該選擇哪個好啊,我想說我們一般用corosync,因為corosync的運作機制更優于heartbeat,就連從heartbeat分離出來的pacemaker都說在以後的開發當中更傾向于corosync,是以現在corosync+pacemaker是最佳組合。
keepalived可以認為是vrrp協定在linux上的實作,主要有三個子產品,分别是core、check和vrrp。core子產品為keepalived的核心,負責主程序的啟動、維護以及全局配置檔案的加載和解析。check負責健康檢查,包括常見的各種檢查方式。vrrp子產品是來實作vrrp協定的。本文基于如下的拓撲圖:
我的環境是centos 6.2 x86_64,直接通過yum方式安裝最簡單:
該腳本檢測ngnix的運作狀态,并在nginx程序不存在時嘗試重新啟動ngnix,如果啟動失敗則停止keepalived,準備讓其它機器接管。
<code>/etc/keepalived/check_nginx.sh</code> :
你也可以根據自己的業務需求,總結出在什麼情形下關閉keepalived,如 curl 首頁連續2個5s沒有響應則切換:
在其它備機backup上,隻需要改變 <code>state master</code> -> <code>state backup</code>,<code>priority 101</code> -> <code>priority 100</code>,<code>mcast_src_ip 172.29.88.224</code> -> <code>mcast_src_ip 172.29.88.225</code>即可。
global_defs
<code>notification_email</code> : keepalived在發生諸如切換操作時需要發送email通知位址,後面的 smtp_server 相比也都知道是郵件伺服器位址。也可以通過其它方式報警,畢竟郵件不是實時通知的。
<code>router_id</code> : 機器辨別,通常可設為hostname。故障發生時,郵件通知會用到
vrrp_instance
<code>state</code> : 指定instance(initial)的初始狀态,就是說在配置好後,這台伺服器的初始狀态就是這裡指定的,但這裡指定的不算,還是得要通過競選通過優先級來确定。如果這裡設定為master,但如若他的優先級不及另外一台,那麼這台在發送通告時,會發送自己的優先級,另外一台發現優先級不如自己的高,那麼他會就回搶占為master
<code>interface</code> : 執行個體綁定的網卡,因為在配置虛拟ip的時候必須是在已有的網卡上添加的
<code>mcast_src_ip</code> : 發送多點傳播資料包時的源ip位址,這裡注意了,這裡實際上就是在那個位址上發送vrrp通告,這個非常重要,一定要選擇穩定的網卡端口來發送,這裡相當于heartbeat的心跳端口,如果沒有設定那麼就用預設的綁定的網卡的ip,也就是interface指定的ip位址
<code>virtual_router_id</code> : 這裡設定vrid,這裡非常重要,相同的vrid為一個組,他将決定多點傳播的mac位址
<code>priority</code> : 設定本節點的優先級,優先級高的為master
<code>advert_int</code> : 檢查間隔,預設為1秒。這就是vrrp的定時器,master每隔這樣一個時間間隔,就會發送一個advertisement封包以通知組内其他路由器自己工作正常
<code>authentication</code> : 定義認證方式和密碼,主從必須一樣
<code>virtual_ipaddress</code> : 這裡設定的就是vip,也就是虛拟ip位址,他随着state的變化而增加删除,當state為master的時候就添加,當state為backup的時候删除,這裡主要是有優先級來決定的,和state設定的值沒有多大關系,這裡可以設定多個ip位址
<code>track_script</code> : 引用vrrp腳本,即在 vrrp_script 部分指定的名字。定期運作它們來改變優先級,并最終引發主備切換。
vrrp_script
告訴 keepalived 在什麼情況下切換,是以尤為重要。可以有多個 vrrp_script
<code>script</code> : 自己寫的檢測腳本。也可以是一行指令如<code>killall -0 nginx</code>
<code>interval 2</code> : 每2s檢測一次
<code>weight -5</code> : 檢測失敗(腳本傳回非0)則優先級 -5
<code>fall 2</code> : 檢測連續 2 次失敗才算确定是真失敗。會用weight減少優先級(1-255之間)
<code>rise 1</code> : 檢測 1 次成功就算成功。但不修改優先級
這裡要提示一下script一般有2種寫法:
通過腳本執行的傳回結果,改變優先級,keepalived繼續發送通告消息,backup比較優先級再決定
腳本裡面檢測到異常,直接關閉keepalived程序,backup機器接收不到advertisement會搶占ip
上文 vrrp_script 配置部分,<code>killall -0 nginx</code>屬于第1種情況,<code>/etc/keepalived/check_nginx.sh</code>屬于第2種情況(腳本中關閉keepalived)。個人更傾向于通過shell腳本判斷,但有異常時exit 1,正常退出exit 0,然後keepalived根據動态調整的 vrrp_instance 優先級選舉決定是否搶占vip:
如果腳本執行結果為0,并且weight配置的值大于0,則優先級相應的增加
如果腳本執行結果非0,并且weight配置的值小于0,則優先級相應的減少
其他情況,原本配置的優先級不變,即配置檔案中priority對應的值。
提示:
優先級不會不斷的提高或者降低
可以編寫多個檢測腳本并為每個檢測腳本設定不同的weight(在配置中列出就行)
不管提高優先級還是降低優先級,最終優先級的範圍是在[1,254],不會出現優先級小于等于0或者優先級大于等于255的情況
在master節點的 vrrp_instance 中 配置 <code>nopreempt</code> ,當它異常恢複後,即使它 prio 更高也不會搶占,這樣可以避免正常情況下做無謂的切換
以上可以做到利用腳本檢測業務程序的狀态,并動态調整優先級進而實作主備切換。
配置結束
在預設的keepalive.conf裡面還有 virtual_server,real_server 這樣的配置,我們這用不到,它是為lvs準備的。 <code>notify</code> 可以定義在切換成master或backup時執行的腳本,如有需求請自行google。
notify
當然nginx沒有什麼可配置的,因為它與keepalived并沒有聯系。但記住,2台nginx伺服器上的配置應該是完全一樣的(rsync同步),這樣才能做到對使用者透明,nginx.conf 裡面的 <code>server_name</code> 盡量使用域名來代替,然後dns解析這個域名到虛拟ip 172.29.88.222。
根據上面的配置,初始化狀态:172.29.88.224 (itoatest1,master,101),172.29.88.222(itoatest2,backup,100),nginx和keepalived都啟動,虛拟ip 172.29.88.222 在 itoatest1 上:
浏覽器通路 172.29.88.222 或域名,ok。
直接關閉 itoatest1 上的nginx:<code>/usr/local/nginx-1.6/sbin/nginx -s stop</code>:
vip消失,漂移到 itoatest2:
同時可以看到兩台伺服器上 <code>/var/log/messages</code>:
你也可以通過在兩台伺服器上抓包來檢視 優先級priority 的變化: