簡介
Keepalived是一個基於VRRP協議來實現的服務高可用方案,可以利用其來避免IP單點故障,類似的工具還有heartbeat、corosync、pacemaker。
但是它一般不會單獨出現,而是與其它負載均衡技術(如lvs、haproxy、nginx)一起工作來達到集群的高可用。
Keepalived的作用是檢測服務器的狀態,如果有一台web服務器死機,或工作出現故障,Keepalived將檢測到,並將有故障的服務器從系統中剔除,同時使用其他服務器代替該服務器的工作;
當服務器工作正常后Keepalived自動將服務器加入到服務器群中,這些工作全部自動完成,不需要人工干涉,需要人工做的只是修復故障的服務器。
安裝
#下載 wget http://www.keepalived.org/software/keepalived-1.2.23.tar.gz #解壓 tar -zxvf keepalived-1.2.23.tar.gz cd keepalived-1.2.23 #安裝 ./configure --prefix=/usr/local/keepalived #prefix指定安裝目錄 make make install
配置
【/usr/local/keepalived/etc/keepalived/keepalived.conf】
global_defs { notification_email { #指定keepalived在發生事情的時候,發送郵件告知,可以有多個地址,每行一個。 acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc #指定發件人 smtp_server 127.0.0.1 #發送email的smtp地址 smtp_connect_timeout 30 #超時時間 router_id LVS_DEVEL #運行keepalived的機器的一個標識,多個節點標識可以相同,也可以不同 vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state MASTER #指定當前節點為主節點 備用節點上設置為BACKUP即可 interface eth0 #綁定虛擬IP的網絡接口 virtual_router_id 51 #VRRP組名,兩個節點的設置必須一樣,以指明各個節點屬於同一VRRP組 priority 100 #主節點的優先級(1-254之間),備用節點必須比主節點優先級低 advert_int 1 authentication { #設置驗證信息,兩個節點必須一致 auth_type PASS auth_pass 1111 } virtual_ipaddress { #指定虛擬IP, 兩個節點設置必須一樣 192.168.1.21/24 } }
【/usr/local/keepalived/etc/sysconfig/keepalived】
KEEPALIVED_OPTIONS="-D -f /usr/local/keepalived/etc/keepalived/keepalived.conf" #指定keepalived配置文件路徑
因為我們使用非默認路徑(/usr/local)安裝keepalived,需要設置一些軟鏈接以保證keepalived能正常啟動
ln -s /usr/local/keepalived/sbin/keepalived /usr/bin #將keepalived主程序加入到環境變量 ln -s /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/ #keepalived啟動腳本,放到/etc/init.d/目錄下就可以使用service命令便捷調用 ln -s /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/ #keepalived啟動腳本變量引用文件,默認文件路徑是/etc/sysconfig/,也可以不做軟鏈接,直接修改啟動腳本中文件路徑即可
啟動
service keepalived start|stop|restart
chkconfig keepalived on
默認的配置文件中,指定了虛擬IP :192.168.1.21,可使用ip addr(或ip a)命令驗證之。
應用
keepalived兩種模式:主-備、主-主
主-備
虛擬IP:192.168.1.21 主節點:192.168.1.23 備用節點:192.168.1.24
主配置文件
【/usr/local/keepalived/etc/keepalived/keepalived.conf】
global_defs { notification_email { #指定keepalived在發生事情的時候,發送郵件告知,可以有多個地址,每行一個。 acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc #指定發件人 smtp_server 127.0.0.1 #發送email的smtp地址 smtp_connect_timeout 30 #超時時間 router_id LVS_DEVEL #運行keepalived的機器的一個標識,多個節點標識可以相同,也可以不同 vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state MASTER #指定當前節點為主節點 備用節點上設置為BACKUP即可 interface eth0 #綁定虛擬IP的網絡接口 virtual_router_id 51 #VRRP組名,兩個節點的設置必須一樣,以指明各個節點屬於同一VRRP組 priority 100 #主節點的優先級(1-254之間),備用節點必須比主節點優先級低 advert_int 1 authentication { #設置驗證信息,兩個節點必須一致 auth_type PASS auth_pass 1111 } virtual_ipaddress { #指定虛擬IP, 兩個節點設置必須一樣 192.168.1.21/24 } }
備配置文件
【/usr/local/keepalived/etc/keepalived/keepalived.conf】
global_defs { notification_email { #指定keepalived在發生事情的時候,發送郵件告知,可以有多個地址,每行一個。 acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc #指定發件人 smtp_server 127.0.0.1 #發送email的smtp地址 smtp_connect_timeout 30 #超時時間 router_id LVS_DEVEL #運行keepalived的機器的一個標識,多個節點標識可以相同,也可以不同 vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state BACKUP #指定當前節點為主節點 備用節點上設置為BACKUP即可 interface eth0 #綁定虛擬IP的網絡接口 virtual_router_id 51 #VRRP組名,兩個節點的設置必須一樣,以指明各個節點屬於同一VRRP組 priority 99 #主節點的優先級(1-254之間),備用節點必須比主節點優先級低 advert_int 1 authentication { #設置驗證信息,兩個節點必須一致 auth_type PASS auth_pass 1111 } virtual_ipaddress { #指定虛擬IP, 兩個節點設置必須一樣 192.168.1.21/24 } }
主-主
虛擬IP:192.168.1.21、192.168.1.22 A節點:192.168.1.23 B節點:192.168.1.24
主備模式的缺點就是始終只有一台機器位於工作狀態,另外一台機器永遠是備用狀態,存在資源浪費之問題。
雙主模式允許兩台機器均處於工作狀態並互相作為備份。搭建keepalived雙方模式的要素:
1.必須有兩個虛擬IP, 分別綁定至兩個節點上 2.每個節點作為某個虛擬IP的主節點,並同時作為另外一個虛擬IP的備用節點。 3.當某個節點產生故障時,兩個虛擬IP自動綁定至正常節點上
也就是說,兩個節點的配置應該是交叉的,對同個虛擬IP,交叉互為主備。
節點A配置文件
【/usr/local/keepalived/etc/keepalived/keepalived.conf】
global_defs { notification_email { #指定keepalived在發生事情的時候,發送郵件告知,可以有多個地址,每行一個。 acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc #指定發件人 smtp_server 127.0.0.1 #發送email的smtp地址 smtp_connect_timeout 30 #超時時間 router_id LVS_DEVEL #運行keepalived的機器的一個標識,多個節點標識可以相同,也可以不同 vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 #本機兩個vrrp_instance組的此值不能相同,但對應備用節點的此值必須相同 priority 100 #對應備用節點值應該比此值小 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.21/24 } } vrrp_instance VI_2 { state BACKUP interface eth0 virtual_router_id 52 #本機兩個vrrp_instance組的此值不能相同,但對應備用節點的此值必須相同 priority 99 #主節點的值應該比此值大 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.22/24 } }
節點B配置文件
【/usr/local/keepalived/etc/keepalived/keepalived.conf】
global_defs { notification_email { #指定keepalived在發生事情的時候,發送郵件告知,可以有多個地址,每行一個。 acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc #指定發件人 smtp_server 127.0.0.1 #發送email的smtp地址 smtp_connect_timeout 30 #超時時間 router_id LVS_DEVEL #運行keepalived的機器的一個標識,多個節點標識可以相同,也可以不同 vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 #本機兩個vrrp_instance組的此值不能相同,但對應備用節點的此值必須相同 priority 99 #對應主節點值應該比此值大 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.21/24 } } vrrp_instance VI_2 { state MASTER interface eth0 virtual_router_id 52 #本機兩個vrrp_instance組的此值不能相同,但對應備用節點的此值必須相同 priority 100 #對應備用節點的值應該比此值小 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.22/24 } }
腦裂問題
兩個節點實際都處於正常工作狀態,但是無法接收到彼此的組播通知,這時兩個節點均強行綁定虛擬IP,導致不可預料的后果。
這時就需要設置仲裁,即每個節點必須判斷自身的狀態(應用服務狀態及自身網絡狀態),要實現這兩點可使用自定義shell腳本實現,通過周期性地檢查自身應用服務狀態,並不斷ping網關(或其它可靠的參考IP)均可。當自身服務異常、或無法ping通網關,則認為自身出現故障,就應該移除掉虛擬IP(停止keepalived服務即可)。
主要借助keepalived提供的vrrp_script及track_script實現:
在keepalived的配置文件最前面加入以下代碼,定義一個跟蹤腳本:
vrrp_script check_local { #定義一個名稱為check_local的檢查腳本 script "/usr/local/keepalived/bin/check_local.sh" #shell腳本的路徑 interval 5 #運行間隔 }
再在vrrp_instance配置中加入以下代碼使用上面定義的檢測腳本:
track_script {
check_local
}
我們在/usr/local/keepalived/bin/check_local.sh定義的檢測規則是:
1. 自身web服務故障(超時,http返回狀態不是200)
2. 無法ping通網關
3. 產生以上任何一個問題,均應該移除本機的虛擬IP(停止keepalived實例即可)
但這里有個小問題,如果本機或是網關偶爾出現一次故障,那么我們不能認為是服務故障。更好的做法是如果連續N次檢測本機服務不正常或連接N次無法ping通網關,才認為是故障產生,才需要進行故障轉移。
但這么做的缺點是,如果腳本檢測到故障產生,並停止掉了keepalived服務,那么當故障恢復后,keepalived是無法自動恢復的。
還可以利用獨立的腳本以秒級的間隔檢查自身服務及網關連接性,再根據故障情況控制keepalived的運行或是停止。
在每個節點運行shell腳本(check_service.sh)檢測本機的服務是否正常,一旦檢測到服務異常時,停止掉本機的keepalived, 如此虛擬IP自動轉移到備用機器之上,如每隔3秒檢測一次本機服務狀態,如果連接3次檢測失敗,則停止掉keepalived實例。同時如果本機服務是正常的,但是keepalived沒有啟動(故障恢復之后),則啟動keepalived,以達到故障恢復之目的。
check_service.sh文件的內容
#!/bin/bash pidfile=/var/lock/subsys/`basename $0`.pid if [ -f $pidfile ] && [ -e /proc/`cat $pidfile` ] ; then exit 1 fi trap "rm -fr $pidfile ; exit 0" 1 2 3 15 echo $$ > $pidfile maxfails=3 fails=0 success=0 while [ 1 ] do /usr/bin/wget --timeout=3 --tries=1 http://127.0.0.1/ -q -O /dev/null if [ $? -ne 0 ] ; then let fails=$[$fails+1] success=0 else fails=0 let success=$[$success+1] fi if [ $fails -ge $maxfails ] ; then fails=0 success=0 #check keepalived is running ? try to stop it service keepalived status | grep running if [ $? -eq 0 ] ; then logger -is "local service fails $maxfails times ... try to stop keepalived." service keepalived stop 2>&1 | logger fi fi if [ $success -gt $maxfails ] ; then #check keepalived is stopped ? try to start it service keepalived status | grep stopped if [ $? -eq 0 ] ; then logger -is "service changes normal, try to start keepalived ." service keepalived start fi success=0 fi sleep 3 done
兩個節點上均應運行此腳本,請將此腳本加入到cron任務中(此程序已經作了單實例運行機制,加入計划任務的作用就是防止腳本意外中斷后檢測功能失效),可實現的功能:
如果本地服務連續三次檢測失敗,就嘗試停止keepalived服務(如果keepalived處於運行狀態)
如果本地服務連接三次檢測成功,但keepalived沒有啟動,則啟動之
關鍵的執行點,均已經記錄到系統日志中(/var/log/messages)
執行crontab -e , 加入以下內容:
*/1 * * * * /root/check_service.sh
停止掉本機的keepalived, 稍過一會,就會keepalived服務被自動啟動了(這是因為本地服務檢測正常)
停止掉本機的nginx, 稍過一會,就會發現keepalived服務也被停止掉了
再啟動nginx, 稍過一會,發現keepalived也被正常啟動,並綁定了正確的虛擬IP
參考資料:
http://zhangxugg-163-com.iteye.com/blog/1665419