Keepalived——保持存活,在網絡里的含義就是保持在線。Keepalived提供高可用和熱備的功能,用來防止單點故障的發生。
1、VRRP協議基本原理介紹
Keepalived實現的基礎是VRRP協議,我們將會在這一節中簡要介紹VRRP協議的基本原理。
1.1 協議
VRRP協議是為消除在靜態缺省路由環境下的缺省路由器單點故障引起的網絡失效而設計的主備模式的協議,使得在發生故障而進行設備功能切換時可以不影響內外數據通信,不需要再修改內部網絡的網絡參數。VRRP協議具有IP地址備份,優先路由選擇,減少不必要的路由器間通信等功能。
VRRP協議將兩台或多台路由器設備虛擬成一個設備,對外提供虛擬路由器IP(一個或多個),而在路由器組內部,如果實際擁有這個對外IP的路由器能夠工作正常的話就是MASTER, MASTER實現針對虛擬路由器IP的各種網絡功能,如ARP請求,ICMP,以及數據的轉發等;其他設備不擁有該IP,狀態是BACKUP,除了接收MASTER的VRRP狀態通告信息外,不執行對外的網絡功能。當主機失效時,BACKUP將接管原先MASTER的網絡功能。
配置VRRP協議時需要配置每個路由器的虛擬路由器ID(VRID)和優先權值,使用VRID將路由器進行分組,具有相同VRID值的路由器為同一個組,VRID是一個0~255的正整數;同一組中的路由器通過使用優先權值來選舉MASTER,優先權大者為MASTER,優先權也是一個0~255的正整數。
VRRP協議使用多播數據來傳輸VRRP數據,VRRP數據使用特殊的虛擬源MAC地址發送數據而不是自身網卡的MAC地址,VRRP運行時只有MASTER路由器定時發送VRRP通告信息,表示MASTER工作正常以及虛擬路由器IP(組),BACKUP只接收VRRP數據,不發送數據,如果一定時間內沒有接收到MASTER的通告信息,各BACKUP將宣告自己成為MASTER,發送通告信息,重新進行MASTER選舉狀態。
1.2 MASTER選舉
如果對外的虛擬路由器IP就是路由器本身配置的IP地址的話,該路由器始終都是MASTER;否則如果不具備虛擬IP的話,將進行MASTER選舉,各路由器都宣告自己是MASTER,發送VRRP通告信息;如果收到其他機器的發來的通告信息的優先級比自己高,將轉回BACKUP狀態;如果優先級相等的話,將比較路由器的實際IP,IP值較大的優先權高;不過如果對外的虛擬路由器IP就是路由器本身的IP的話,該路由器始終將是MASTER,這時的優先級值為255。
2、Keepalived內部原理
2.1 Keepalived組件
keepalived是模塊化設計,不同模塊負責不同的功能。
core:keepalived的核心,負責主進程的啟動和維護,全局配置文件的加載解析等;
check:負責healthchecker(健康檢查),包括了各種健康檢查方式,以及對應的配置文件的解析;
vrrp:VRRPD子進程,用來實現VRRP協議;
libipfwc:iptables(ipchains)庫,配置LVS;
libipvs*:配置LVS;
2.2 Keepalived進程
keepalived啟動后會有三個進程:
父進程:內存管理,子進程管理等等
子進程:VRRP子進程
子進程:healthchecker子進程
兩個子進程都被系統WatchDog看管,兩個子進程各自負責自己的事,healthchecker子進程負責檢查各自服務器的健康程度,如果healthchecker子進程檢查到MASTER上服務不可用了,就會通知本機上的兄弟VRRP子進程,讓他刪除通告,並且去掉虛擬IP,轉換為BACKUP狀態。
3、Keepalived安裝
3.1安裝Keepalived
wget http://www.keepalived.org/software/keepalived-1.2.6.tar.gz
tar zxvf keepalived-1.2.6.tar.gz
cd keepalived-1.2.6
./configure
make
make install
3.2 添加Keepalived為系統服務
cp /usr/local/etc/rc.d/init.d/keepalived /etc/rc.d/init.d/
cp /usr/local/etc/sysconfig/keepalived /etc/sysconfig/
cp /usr/local/sbin/keepalived /usr/sbin/
mkdir /etc/keepalived
3.3添加keepalived的配置項
vi /etc/keepalived/keepalived.conf
我們將會在下一節對Keepalived配置文件——keepalived.conf進行詳細介紹。
3.4 啟動
service keepalived start
4、Keepalived配置詳解
一個功能比較完整的keepalived的配置文件,其配置文件keepalived.conf可以包含三個文本塊:全局定義塊、VRRP實例定義塊及虛擬服務器定義塊。
4.1 全局定義塊
4.1.1 email通知
有故障,發郵件報警。
4.1.2 Lvs負載均衡器標識
在一個網絡內,它應該是唯一的。
4.1.3 花括號“{}”
用來分隔定義塊,因此必須成對出現。如果寫漏了,keepalived運行時,不會得到預期的結果。由於定義塊內存在嵌套關系,因此很容易遺漏結尾處的花括號,這點要特別注意。
4.1.4 notification_email_from
指定發件人。
4.1.5 smtp_server
smtp服務器地址,可以配置為localhost。
4.1.6 smtp_connect_timeout
指定smtp連接超時時間。
4.1.7 router_id
運行keepalived機器的一個標識。
4.2 VRRP定義塊
4.2.1 同步vrrp組vrrp_sync_group
確定失敗切換(FailOver)包含的路由實例個數。即在有2個負載均衡器的場景,一旦某個負載均衡器失效,需要自動切換到另外一個負載均衡器的實例是哪些。
4.2.2 實例組group
至少包含一個vrrp實例。
4.2.3 Vrrp實例vrrp_instance
實例名出自實例組group所包含的那些名字。
(1)實例狀態state只有MASTER和BACKUP兩種狀態,並且需要大寫這些單詞。其中MASTER為工作狀態,BACKUP為備用狀態。當MASTER所在的服務器失效時,BACKUP所在的系統會自動把它的狀態有BACKUP變換成MASTER;當失效的MASTER所在的系統恢復時,BACKUP從MASTER恢復到BACKUP狀態。
(2)通信接口interface。對外提供服務的網絡接口,如eth0,eth1。當前主流的服務器都有2個或2個以上的接口,在選擇服務接口時,一定要核實清楚。
(3)lvs_sync_daemon_inteface。負載均衡器之間的監控接口,類似於HA HeartBeat的心跳線。但它的機制優於Heartbeat,因為它沒有“裂腦”這個問題,它是以優先級這個機制來規避這個麻煩的。【腦裂:在“雙機熱備”高可用(HA)系統中,當聯系2個節點的“心跳線”斷開時,本來為一整體、動作協調的HA系統,就分裂成為2個獨立的個體。由於相互失去了聯系,都以為是對方出了故障,2個節點上的HA軟件像“裂腦人”一樣,“本能”地爭搶“共享資源”、爭起“應用服務”,就會發生嚴重后果:或者共享資源被瓜分、2邊“服務”都起不來了;或者2邊“服務”都起來了,但同時讀寫“共享存儲”,導致數據損壞(常見如數據庫輪詢着的聯機日志出錯)。】
(4) 虛擬路由標識virtual_router_id。這個標識是一個數字,並且同一個vrrp實例使用唯一的標識。即同一個vrrp_stance,MASTER和BACKUP的virtual_router_id是一致的,同時在整個vrrp內是唯一的。
(5)優先級priority。這是一個數字,數值愈大,優先級越高。在同一個vrrp_instance里,MASTER 的優先級高於BACKUP。
(6) 同步通知間隔 advert_int。MASTER與BACKUP負載均衡器之間同步檢查的時間間隔,單位為秒。
(7) 驗證authentication。包含驗證類型和驗證密碼。類型主要有PASS、AH兩種,通常使用的類型為PASS。驗證密碼為明文,同一vrrp實例MASTER與BACKUP 使用相同的密碼才能正常通信。
4.2.4 虛擬ip地址virtual_ipaddress
可以有多個地址,每個地址占一行,不需要指定子網掩碼。注意:這個ip必須與我們在lvs客戶端設定的vip相一致。(開啟Keepalived服務后,可以通過命令:ip a 來查看虛擬IP是否綁定到本機)
4.3虛擬服務器virtual_server定義塊
4.3.1 虛擬服務器virtual_server
這個ip來自於vrrp定義塊的第“4”步,后面一個空格,然后加上端口號。定義一個vip,可以實現多個tcp端口的負載均衡功能。
(1)delay_loop:健康檢查時間間隔,單位是秒。
(2)lb_algo:負載均衡調度算法,互聯網應用常使用wlc或rr。
(3)lb_kind:負載均衡轉發規則。一般包括DR,NAT,TUN3種。
(4)persistence_timeout:會話保持時間,單位是秒。
(5)protocol:轉發協議,一般有tcp和udp兩種。
4.3.2 真實服務器real_server
Real_server的值包括ip地址和端口號。多個連續的真實ip,轉發的端口相同。
(1)權重weight。權重值是一個數字,數值越大,權重越高。使用不同的權重值的目的在於為不同性能的機器分配不同的負載,性能較好的機器,負載分擔大些;反之,性能差的機器,則分擔較少的負載,這樣就可以合理的利用不同性能的機器資源。
(2)Tcp檢查 tcp_check。
5、Keepalived、Redis高可用配置及腳本
5.1 Keepalived配置文件keepalived.conf
global_defs { router_id LVS_DEVEL } vrrp_script Monitor_Redis { script "/home/plat/laizy/redis/redis/script/redis_keepalive.sh" interval 1 #重復執行間隔1秒 weight -2 #當健康檢查腳本失敗后,主機權重將會-2 }
vrrp_instance VI_1 { state BACKUP #主備機狀態均設為BASKUP,這樣才可以做到在主機宕掉之后,其余#備機爭搶主機身份 interface em1 #綁定網卡名稱 virtual_router_id 52 priority 100 #優先級,其余備機應設置比100小的值 advert_int 1 nopreempt authentication { auth_type PASS auth_pass 1111 } notify_master /home/plat/laizy/redis/redis/script/redis_master.sh notify_backup /home/plat/laizy/redis/redis/script/redis_backup.sh track_script { Monitor_Redis #健康檢查腳本 } virtual_ipaddress { 10.0.63.251 #虛擬IP地址,可以設置多個 } } |
5.2 Redis服務健康檢查腳本redis_keepalive.sh
#!/bin/bash time=$(date '+%Y-%m-%d %H:%M:%S' ) redispath=/home/plat/laizy/redis/redis rediscli=$redispath/redis-cli logfile=$redispath/logs/redis-state.log oldfile=$logfile'.'$(date +%Y-%m-%d --date='30 days ago') yesterdayfile=$logfile'.'$(date +%Y-%m-%d --date='1 days ago') if [ -f $yesterdayfile ] then echo "OK" else mv $logfile $yesterdayfile >> $logfile 2>&1 echo "$time [$yesterdayfile] Move yesterdayfile Success!" >> $logfile fi if [ -f $oldfile ] then rm -f $oldfile >> $logfile 2>&1 echo "$time [$oldfile] Delete Old File Success!" >> $logfile else echo "no old file" fi status=`$rediscli -h 127.0.0.1 -p 6379 info|grep role|awk -F ":" '{print $2}'` $rediscli -h 127.0.0.1 -p 6379 info > /dev/null if [ $? -eq 0 ] then echo "$time redis server is OK" >>$logfile echo The status is:$status >>$logfile else echo "$time no redis service found!" >>$logfile sleep 1 # try to found it again $rediscli -h 127.0.0.1 -p 6379 info > /dev/null if [ $? -eq 0 ] then echo "$time redis server is OK" >>$logfile echo The status is:$status >>$logfile #exit 0 else echo "$time redis server error" >>$logfile #stop keepalived /etc/init.d/keepalived stop echo "$time stop keepalived" >>$logfile fi fi |
5.3 轉換為Master身份時觸發腳本redis_master.sh
#!/bin/sh localip=127.0.0.1 backip=10.0.63.246 port="6379"
time=$(date '+%Y-%m-%d %H:%M:%S' ) redispath=/home/plat/laizy/redis/redis rediscli=$redispath/redis-cli logfile=$redispath/logs/redis-state.log for p in $port do { echo "$time redis $p is the master port" >>$logfile #以主機身份配置Redis服務,注意,Redis支持熱配置,即在不重啟Redis的情況 #下完成主備機身份的轉換 $rediscli -h $localip -p $p slaveof no one >>$logfile 2>&1 } done |
5.4轉換為Backup身份時觸發腳本redis_backup.sh
#!/bin/sh localip=127.0.0.1 backip=10.0.63.246 port="6379"
time=$(date '+%Y-%m-%d %H:%M:%S' ) redispath=/home/plat/laizy/redis/redis rediscli=$redispath/redis-cli logfile=$redispath/logs/redis-state.log for p in $port do { echo "$time redis $p change to $backip port" >>$logfile $rediscli -h $localip -p $p slaveof $backip $p >>$logfile 2>&1 } done |