1.1 Keepalived高可用軟件
1.1.1 Keepalived介紹
- Keepalived軟件起初是專門為LVS負載均衡軟件設計的,用來管理並監控LVS集群系統中各個服務節點的狀態,后來又加入了可以實現高可用的VRRP功能。因此,Keepalived除了能夠管理LVS軟件外,還可以作為其他服務(例如:Nginx,Haproxy,MySQL等)的高可用解決方案軟件。
- Keepalived軟件主要是通過VRRP協議實現高可用功能的。VRRP是Virtual Router Redundancy Protocol(虛擬路由器冗余協議)的縮寫,VRRP出現的目的就是為了解決靜態路由單點故障問題的,他能夠保證當個別節點宕機時,整個網絡可以不間斷地運行。所以,Keepalived一方面具有配置管理LVS的功能,同時還具有對LVS下面節點進行健康檢查的功能,另一方面也可實現系統網絡服務的高可用功能。
- Keepalived軟件的官方站點是http://www.keepalived.org
1.1.2 Keepalived服務的三個重要功能
(1)管理LVS負載均衡軟件
早期的LVS軟件,需要通過命令行或腳本實現管理,並且沒有針對LVS節點的健康檢查功能。為了解決LVS的這些使用不便問題,Keepalived誕生了,可以說,Keepalived軟件起初是專為解決LVS的問題而誕生的。因此,Keepalived和LVS的感情很深,他們的關系如同夫妻一樣,可以緊密地結合,愉快地工作。Keepalived可以通過讀取自身的配置文件,實現通過更底層的接口直接管理LVS的配置以及控制服務的啟動,停止功能,這使得LVS的應用更加簡單方便了。
(2)實現對LVS集群節點健康檢查功能(healthcheck)
前文已講過,Keepalived可以通過在自身的Keepalived.conf文件里配置LVS的節點IP和相關參數實現對LVS的直接管理;除此之外,當LVS集群中的某一個甚至是幾個節點服務器同時發生故障無法提供服務時,Keepalived服務會自動將失效的節點服務器從LVS的正常轉發隊列中清除出去,並將請求調度到別的正常節點服務器上,從而保證最終用戶的訪問不受影響;當故障的節點服務器被修復以后,Keepalived服務又會自動地把它們加入到正常轉發隊列中,對客戶提供服務。
(3)作為系統網絡服務的高可用功能(failover)
- Keepalived可以實現任意兩台主機之間,例如Master和Backup主機之間的故障轉移和自動切換,這個主機可以是普通的不能停機的業務服務器,也可以是LVS負載均衡,Nginx反向代理這樣的服務器。
- Keepalived高可用功能實現的簡單原理為,兩台主機同時安裝好Keepalived軟件並啟動服務,開始正常工作時,由角色為Master的主機獲得所有資源並對用戶提供服務,角色為Backup的主機作為Master主機的熱備;當角色為Master的主機失效或出現故障時,角色為Backup的主機將自動接管Master主機的所有工作,包括接管VIP資源及相應資源服務;而當角色為Master的主機故障修復后,又會自動接管回它原來處理的工作,角色為Backup的主機則同時釋放Master主機失效時它接管的工作,此時,兩台主機將恢復到最初啟動時各自的原始角色及工作狀態。
說明: Keepalived的高可用功能是本章的重點,后面除了講解Keepalived高可用的功能外,還會講解Keepalived配合Nginx反向代理負載均衡的高可用的實戰案例。
1.1.3 Keepalived高可用故障切換轉移原理
- Keepalived高可用服務之間的故障切換轉移,是通過VRRP(Virtual Router Redundancy Protocol,虛擬路由器冗余協議)來實現的。
- 在Keepalived服務正常工作時,主Master節點會不斷地向備節點發送(多播的方式)心跳消息,用以告訴備Backup節點自己還活着,當主Master節點發生故障時,就無法發送心跳消息,備節點也就因此無法繼續檢測到來自主Master節點的心跳了,於是調用自身的接管程序,接管主Master節點的IP資源及服務。而當主Master節點恢復時,備Backup節點又會釋放主節點故障時自身接管的IP資源及服務,恢復到原來的備用角色。
- 那么,什么是VRRP呢?
VRRP,全稱Virtual Router Redundancy Protocol,中文名為虛擬路由冗余協議,VRRP的出現就是為了解決靜態路由的單點故障問題,VRRP是通過一種競選機制來將路由的任務交給某台VRRP路由器的。- VRRP早期是用來解決交換機,路由器等設備單點故障的,下面是交換,路由的Master和Backup切換原理描述,同樣適用於Keepalived的工作原理。
- 在一組VRRP路由器集群中,有多台物理VRRP路由器,但是這多台物理的機器並不是同時工作的,而是由一台稱為Master的機器負責路由工作,其他的機器都是Backup。Master角色並非一成不變的,VRRP會讓每個VRRP路由參與競選,最終獲勝的就是Master。獲勝的Master有一些特權,比如擁有虛擬路由器的IP地址等,擁有系統資源的Master負責轉發發送給網關地址的包和響應ARP請求。
- VRRP通過競選機制來實現虛擬路由器的功能,所有的協議報文都是通過IP多播(Multicast)包(默認的多播地址224.0.0.18)形式發送的。虛擬路由器由VRID(范圍0-225)和一組IP地址組成,對外表現為一個周知的MAC地址:00-00-5E-00-01-{VRID}。所以,在一個虛擬路由器中,不管誰是Master,對外都是相同的MAC和IP(稱之為VIP)。客戶端主機並不需要因Master的改變而修改自己的路由配置。對他們來說,這種切換是透明的。
- 在一組虛擬路由器中,只有作為Master的VRRP路由器會一直發送VRRP廣播包(VRRP Advertisement messages),此時Backup不會搶占Master。當Master不可用時,Backup就收不到來自Master的廣播包了,此時多台Backup中優先級最高的路由器會搶占為Master。這種搶占是非常快速的(可能只有1秒甚至更少),以保證服務的連續性。出於安全性考慮,VRRP數據包使用了加密協議進行了加密。
注意:如果同學們在面試時,要你解答Keepalived的工作原理,建議用自己的話回答如下內容,以下為對面試官的表述:
Keepalived高可用之間是通過VRRP通信的,因此,我從VRRP開始給您講起:
- VRRP也就是虛擬路由冗余協議,它的出現就是為了解決靜態路由的單點故障。
- VRRP是通過一種競選協議機制來將路由任務交給某台VRRP路由器的。
- VRRP用IP多播的方式(默認多播地址(224.0.0.18))實現高可用之間通信。
- 工作時主節點發包,備節點接包,當備節點接收不到主節點發的數據包的時候,就啟動接管程序接管主節點的資源。備節點可以有多個,通過優先級競選,但一般Keepalived系統運維工作中都是一對。
- VRRP使用了加密協議加密數據,但Keepalived官方目前還是推薦用明文的方式配置認證類型和密碼。
介紹完了VRRP,接下來我再介紹一下Keepalived服務的工作原理:
- Keepalived高可用之間是通過VRRP進行通信的,VRRP是通過競選機制來確定主備的,主的優先級高於備,因此,工作時主會優先獲得所有的資源,備節點處於等待狀態,當主掛了的時候,備節點就會接管主節點的資源,然后頂替主節點對外提供服務。
- 在Keepalived服務之間,只有作為主的服務器會一直發送VRRP廣播包,告訴備它還活着,此時備不會搶占主,當主不可用時,即備監聽不到主發送的廣播包時,就會啟動相關服務接管資源,保證業務的連續性。接管速度最快可以小於1秒。
1.2 Keepalived高可用服務搭建准備
1.2.1 安裝Keepalived環境說明
這里建議大家使用《閱讀材料18》介紹的Nginx負載均衡的系統環境來安裝Keepalived服務,因為本章后面的實戰案例是實現Nginx負載均衡的高可用案例。安裝Keepalived的基礎准備環境如下。
(1)硬件環境准備
准備4台物理服務器或4台VM虛擬機,兩台用來做Keepalived服務,兩台做測試的Web節點如下表所示:
HOSTNAME | IP | 說明 |
---|---|---|
lb01 | 192.168.0.221 | Keepalived主服務器(Nginx主負載均衡器) |
lb02 | 192.168.0.222 | Keepalived備服務器(Nginx備負載均衡器) |
web01 | 192.168.0.223 | web01服務器 |
web02 | 192.168.0.224 | web02服務器 |
(2)CentOS系統及Nginx代理環境
下面是CentOS系統及Nginx代理環境:
[root@lb01 ~]# cat /etc/redhat-release
CentOS release 6.5 (Final)
[root@lb01 ~]# uname -r
2.6.32-431.el6.x86_64
[root@lb01 ~]# uname -m
x86_64
[root@lb01 ~]# ls -l /usr/local/nginx/
total 36
drwx------. 2 nginx root 4096 Jul 27 09:00 client_body_temp
drwxr-xr-x. 2 root root 4096 Jul 27 09:30 conf
drwx------. 2 nginx root 4096 Jul 27 09:00 fastcgi_temp
drwxr-xr-x. 2 root root 4096 Jul 27 08:58 html
drwxr-xr-x. 2 root root 4096 Jul 27 09:00 logs
drwx------. 2 nginx root 4096 Jul 27 09:00 proxy_temp
drwxr-xr-x. 2 root root 4096 Jul 27 08:58 sbin
drwx------. 2 nginx root 4096 Jul 27 09:00 scgi_temp
drwx------. 2 nginx root 4096 Jul 27 09:00 uwsgi_temp
1.2.2 開始安裝Keepalived軟件
說明:下面有關Keepalived安裝,啟動服務的操作都是同時處理lb01,lb02兩台機器。
可通過官方地址獲取Keepalived源碼軟件包編譯安裝,也可以使用yum的安裝方式直接安裝,這里選擇更為簡便額后者--yum安裝方式,下面以lb01為例,介紹整個安裝步驟,如下:
[root@lb01 ~]# yum -y install keepalived
[root@lb01 ~]# rpm -qa keepalived
keepalived-1.2.7-3.el6.x86_64
提示:
1)上述安裝過程需要在lb01和lb02兩台服務器上同時安裝。
2)Keepalived版本為2.7版
1.2.3 啟動Keepalived服務並檢查
啟動及檢查Keepalived服務的命令如下:
[root@lb01 ~]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
[root@lb01 ~]# ps -ef | grep keep | grep -v grep
root 7111 1 0 11:18 ? 00:00:00 /usr/sbin/keepalived -D
root 7114 7111 0 11:18 ? 00:00:00 /usr/sbin/keepalived -D
root 7117 7111 0 11:18 ? 00:00:00 /usr/sbin/keepalived -D
#提示:啟動后有3個Keepalived進程表示安裝正確
[root@lb01 ~]# ip add | grep 192.168
inet 192.168.0.221/24 brd 192.168.0.255 scope global eth0
inet 192.168.200.16/32 scope global eth0
inet 192.168.200.17/32 scope global eth0
inet 192.168.200.18/32 scope global eth0
#提示:默認情況會啟動三個VIP地址
[root@lb01 ~]# /etc/init.d/keepalived stop
Stopping keepalived: [ OK ]
#提示:測試完畢后關閉服務,上述測試需要同時在lb01和lb02兩台服務器上進行
1.2.4 Keepalived配置文件說明
和其他使用yum安裝的軟件一樣,Keepalived軟件的配置文件默認路徑及配置文件名為:
[root@lb02 ~]# ls -l /etc/keepalived/keepalived.conf
-rw-r--r--. 1 root root 3562 Feb 21 2013 /etc/keepalived/keepalived.conf
前面已經說過,Keepalived軟件有3個主要功能,而這里僅講解其高可用部分的功能。
這里的具備高可用功能的Keepalived.conf配置文件包含了兩個重要區塊,下面會分別說明
(1)全局定義(Global Definitions)部分
這部分主要用來設置Keepalived的故障通知機制和Router ID標識。示例代碼如下:
[root@lb02 ~]# head -13 /etc/keepalived/keepalived.conf | cat -n
1 ! Configuration File for keepalived
2
3 global_defs {
4 notification_email {
5 acassen@firewall.loc
6 failover@firewall.loc
7 sysadmin@firewall.loc
8 }
9 notification_email_from Alexandre.Cassen@firewall.loc
10 smtp_server 192.168.200.1
11 smtp_connect_timeout 30
12 router_id LVS_DEVEL
13 }
基礎參數說明:
第1行是注釋,!開頭和#號開發一樣,都是注釋。
第2行是空行。
第3~8行是定義服務故障報警的Email地址。作用是當服務發生切換或RS節點等有故障時,發報警郵件。這幾行是可選配置,notification_email指定在Keepalived發生事件時,需要發送的Email地址,可以有多個,每行一個。
第9行是指定發送郵件的發送人,即發件人地址,也是可選的配置。
第10行smtp_server指定發送郵件的smtp服務器,如果本機開啟了sendmail或postfix,就可以使用上面默認配置實現郵件發送,也是可選配置。
第11行smtp_connect_timeout是連接smtp的超時時間,也是可選配置。
注意:
第4~11行所有和郵件報警相關的參數均可以不配,在實際工作中會將監控的任務交給更加擅長監控報警的Nagios或Zabbix軟件。
第12行是Keepalived服務器的路由標識(router_id).在一個局域網內,這個標識(router_id)應該是唯一的。
大括號“{}”。用來分隔區塊,要成對出現。如果漏寫了半個大括號,Keepalived運行時,不會報錯,但也不會得到預期的結果。另外,由於區塊間存在多層嵌套關系,因此很容易遺漏區塊結尾處的大括號,要特別注意。
(2)VRRP實例定義區塊(VRRP instance(s))部分
[root@lb02 ~]# sed -n '15,30{=;p}' /etc/keepalived/keepalived.conf | xargs -L2
15 vrrp_instance VI_1 {
16 state MASTER
17 interface eth0
18 virtual_router_id 51
19 priority 100
20 advert_int 1
21 authentication {
22 auth_type PASS
23 auth_pass 1111
24 }
25 virtual_ipaddress {
26 192.168.200.16
27 192.168.200.17
28 192.168.200.18
29 }
30 }
參數說明:
第15行表示定義一個vrrp_instance實例,名字是VI_1,每個vrrp_instance實例可以認為是Keepalived服務的一個實例或者作為一個業務服務,在Keepalived服務配置中,這樣的vrrp_instance實例可以有多個。注意,存在於主節點中的vrrp_instance實例在備節點中也要存在,這樣才能實現故障切換接管。
第16行state MASTER表示當前實例VI_1的角色狀態,當前角色為MASTER,這個狀態只能有MASTER和BACKUP兩種狀態,並且需要大寫這些字符。其中MASTER為正式工作的狀態,BACKUP為備用的狀態。當MASTER所在的服務器故障或失效時,BACKUP所在的服務器會接管故障的MASTER繼續提供服務。
第17行interface為網絡通信接口。為對外提供服務的網絡接口,如eth0,eth1。當前主流的服務器都有2~4個網絡接口,在選擇服務接口時,要搞清楚了。
第18行virtual_router_id為虛擬路由ID標識,這個標識最好是一個數字,並且要在一個keepalived.conf配置中是唯一的。但是MASTER和BACKUP配置中相同實例的virtual_router_id又必須是一致的,否則將出現腦裂問題。
第19行priority為優先級,其后面的數值也是一個數字,數字越大,表示實例優先級越高。在同一個vrrp_instance實例里,MASTER的優先級配置要高於BACKUP的。若MASTER的priority值為150,那么BACKUP的priority必須小於150,一般建議間隔50以上為佳,例如:設置BACKUP的priority為100或更小的數值。
第20行advert_int為同步通知間隔。MASTER與BACKUP之間通信檢查的時間間隔,單位為秒,默認為1.
第21~24行authentication為權限認證配置。包含認證類型(auth_type)和認證密碼(auth_pass)。認證類型有PASS(Simple Passwd(suggested)),AH(IPSEC(not recommended))兩種,官方推薦使用的類型為PASS。驗證密碼為明文方式,最好長度不要超過8個字符,建議用4位數字,同一vrrp實例的MASTER與BACKUP使用相同的密碼才能正常通信。
第25 ~ 29 行virtual_ipaddress為虛擬IP地址。可以配置多個IP地址,每個地址占一行,配置時最好明確指定子網掩碼以及虛擬IP綁定的網絡接口。否則,子網掩碼默認是32位,綁定的接口和前面的interface參數配置的一致。注意,這里的虛擬IP就是在工作中需要和域名綁定的IP,即和配置的高可用服務監聽的IP要保持一致!
1.3 Keepalived高可用服務單實例實戰
1.3.1 配置Keepalived實現單實例單IP自動漂移接管
- 事實上,網絡服務的高可用功能基本原理都很簡單,就是把手動的操作自動化運行而已。當沒有配置高可用服務時,如果服務器宕機了怎么解決呢?無非就是找一個新服務器,配好域名解析的那個原IP,然后搭好相應的網絡服務罷了,只不過手工去實現這個過程會比較漫長,相比而言,自動化切換效率更高,效果更好,而且還可以有更多的功能,例如:發送ARP廣播,觸發執行相關腳本動作等。
- 實際上也可以將高可用對的兩台機器應用服務同時開啟,但是只讓有VIP一端的服務器提供服務,若主的服務器宕機,VIP會自動漂移到備用服務器上,此時用戶的請求直接發送到備用服務器上,而無需臨時啟動對應服務(事先開啟應用服務)。下面就來學習VIP自動漂移的實戰案例。
(1)實戰配置Keepalived主服務器lb01 MASTER
首先,配置lb01 MASTER的keepalived.conf配置文件,操作步驟如下:
[root@lb01 ~]# cd /etc/keepalived/
[root@lb01 keepalived]# vim keepalived.conf
#刪掉已有的所有默認配置,加入經過修改好的如下配置:
[root@lb01 keepalived]# cat keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
215379068@qq.com #郵箱隨便寫
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1 #郵件服務器IP
smtp_connect_timeout 30
router_id lb01 #id為lb1,不能和其他Keepalived節點相同(全局唯一)
}
vrrp_instance VI_1 { #實例名字為VI_1,相同實例的備節點名字要和這個相同
state MASTER #狀態為MASTER,備節點狀態需要為BACKUP
interface eth1 #通信(心跳)接口為eth1,此參數備節點設置和主節點相同
virtual_router_id 55 #實例ID為55,要和備節點相同
priority 150 #優先級為150,備節點的優先級必須比此數字低
advert_int 1 #通信檢查間隔時間1秒
authentication {
auth_type PASS #PASS認證類型,此參數備節點設置和主節點相同
auth_pass 1111 #密碼1111,此參數備節點設置和主節點相同
}
virtual_ipaddress {
192.168.0.240/24 dev eth0 label eth0:1
#虛擬IP,即VIP為192.168.0.240,子網掩碼為24位,綁定接口為eth0,別名為eth0:1,此參數備節點設置和主節點相同
}
}
配置完畢后,啟動Keepalived服務,如下:
[root@lb01 keepalived]# /etc/init.d/keepalived start
然后檢查配置結果,查看是否有虛擬IP 192.168.0.240
[root@lb01 keepalived]# ip a | grep 192.168.0.240
inet 192.168.0.240/24 scope global secondary eth0:1
出現上述帶有vip:192.168.0.240行的結果表示lb01的Keepalived服務單實例配置成功
(2)實戰配置Keepalived備服務器lb02 BACKUP
首先,配置lb02 BACKUP的keepalived.conf配置文件,操作步驟如下:
[root@lb02 ~]# cd /etc/keepalived/
[root@lb02 keepalived]# vim keepalived.conf
#刪掉已有的默認配置,加入經過修改的如下配置(注意和lb01的不同):
[root@lb02 keepalived]# cat keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
215379068@qq.com
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id lb02 #此參數和lb01 MASTER不同
}
vrrp_instance VI_1 { #和lb01 MASTER相同
state BACKUP #此參數和lb01 MASTER不同
interface eth1 #和lb01 MASTER相同
virtual_router_id 55 #和lb01 MASTER相同
priority 100 #此參數和lb01 MASTER不同
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.240/24 dev eth0 label eth0:1
}
}
配置完成后,啟動Keepalived服務,如下:
[root@lb02 keepalived]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
#然后檢查配置結果,查看是否有虛擬IP 192.168.0.240
[root@lb02 keepalived]# ip a | grep 192.168.0.240
[root@lb02 keepalived]#
#這里沒有返回任何結果就對了,因為lb02為BACKUP,當主節點活着的時候,它不會接管VIP 192.168.0.240
- 出現上述無任何結果的現象,表示lb02的Keepalived服務單實例配置成功。如果同學們的配置過濾后有192.168.0.240的IP,則表示Keepalived工作不正常,同一個IP地址同一時刻應該只能出現一台服務器。
- 如果查看BACKUP備節點VIP有如下信息,說明高可用裂腦了,裂腦是兩台服務器爭搶同一資源導致的,例如:兩邊都配置了同一個VIP地址。
- 出現上述兩台服務器爭搶同一IP資源問題,一般要先考慮排查兩個地方:
1)主備兩台服務器對應的Keepalived.conf配置文件是否有錯誤?例如,是否同一實例的virtual_router_id配置不一致。
(3)進行高可用主備服務器切換實驗
root@lb01 keepalived]# ip a | grep 192.168.0.240 #虛擬VIP在lb01服務器上
inet 192.168.0.240/24 scope global secondary eth0:1
[root@lb01 keepalived]# /etc/init.d/keepalived stop #停掉服務
Stopping keepalived: [ OK ]
[root@lb01 keepalived]# /etc/init.d/keepalived stop
[root@lb01 keepalived]# ip a | grep 192.168.0.240 #虛擬VIP消失了
[root@lb01 keepalived]#
#再檢查lb02服務器
[root@lb02 keepalived]# ip a | grep 192.168.0.240 #虛擬VIP出現在了lb02上
inet 192.168.0.240/24 scope global secondary eth0:1
[root@lb02 keepalived]#
- 我們可以發現,備節點lb02已經接管綁定了192.168.0.240這個VIP,這期間備節點還會發送ARP廣播,讓所有的客戶端更新本地的ARP表,以便客戶端訪問新接管VIP服務的節點。
- 此時如果再啟動主服務器的Keepalived服務,主服務器就會接管回VIP 192.168.0.240,啟動后可以觀察下主備的IP漂移情況,備服務器是否釋放了IP?主服務器是否又接管了IP?
主節點啟動Keepalived服務后,發現很快就又接管了VIP 192.168.0.240,操作及檢查步驟如下:
[root@lb01 keepalived]# ip a | grep 192.168.0.240
[root@lb01 keepalived]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
[root@lb01 keepalived]# ip a | grep 192.168.0.240
inet 192.168.0.240/24 scope global secondary eth0:1
#與此同時,備節點上的VIP 192.168.0.240則被釋放了,如下:
[root@lb02 keepalived]# ip a | grep 192.168.0.240
[root@lb02 keepalived]#
#這樣就實現了單實例Keepalived服務IP自動漂移接管了,VIP飄逸到了新機器新服務上,用戶的訪問請求自然就會找新機器新服務了。
說明:
這里僅實現了VIP的自動漂移切換,因此,僅適合兩台服務器提供的服務均保持開啟的應用場景,這也是工作中常用的高可用解決方案。
1.3.2 單實例主備模式Keepalived配置文件對比
上述Keepalived單實例MASTER和BACKUP節點的配置差別項,只有3項是不同的。
Keepalived配置參數 | MASTER節點特殊參數 | BACKUP節點特殊參數 |
---|---|---|
router_id(唯一標識) | router_id lb01 | router_id lb02 |
state(角色狀態) | state MASTER | state BACKUP |
priority(競選優先級) | priority 150 | priority 100 |
1.4 Keepalived高可用服務器的“裂腦”問題
1.4.1 什么是裂腦
由於某些原因,導致兩台高可用服務器對在指定時間內,無法檢測到對方的心跳消息,各自取得資源及服務的所有權,而此時的兩台高可用服務器對都還活着並在正常運行,這樣就會導致同一個IP或服務在兩端同時存在而發生沖突,最嚴重的是兩台主機占用同一個VIP地址,當用戶寫入數據時可能會分別寫入到兩端,這可能會導致服務器兩端的數據不一致或造成數據丟失,這種情況就被稱為裂腦。
1.4.2 導致裂腦發生的原因
一般來說,裂腦的發生,有以下幾種原因:
- 高可用服務器對之間心跳線鏈路發生故障,導致無法正常通信。
- 心跳線壞了(包括斷了,老化)
- 網卡及相關驅動壞了,IP配置及沖突問題(網卡直連)。
- 心跳線間連接的設備故障(網卡及交換機)
- 仲裁的機器出問題(采用仲裁的方案)
- 高可用服務器上開啟了iptables防火牆阻擋了心跳消息傳輸
- 高可用服務器上心跳網卡地址等信息配置不正確,導致發送心跳失敗。
- 其他服務配置不當等原因,如心跳方式不同,心跳廣播沖突,軟件BUG等
提示:
Keepalived配置里同一VRRP實例如果virtual_router_id兩端參數配置不一致,也會導致裂腦問題發生。
1.4.3 解決裂腦的常見方案
在實際生產環境中,我們可以從以下幾個方面來防止裂腦問題的發生:
- 同時使用串行電纜和以太網電纜連接,同時用兩條心跳線路,這樣一條線路壞了,另一個還是好的,依然能傳送心跳消息。
- 當檢測到裂腦時強行關閉一個心跳節點(這個功能需特殊設備支持,如Stonith,fence)。相當於備節點接收不到心跳消息,通過單獨的線路發送關機命令關閉主節點的電源。
- 做好對裂腦的監控報警(如郵件及手機短信等或值班),在問題發生時人為第一時間介入仲裁,降低損失。例如,百度的監控報警短信就有上行和下行的區別。報警信息發送到管理員手機上,管理員可以通過手機回復對應數字或簡單的字符串操作返回給服務器,讓服務器根據指令自動處理相應故障,這樣解決故障的時間更短。
- 當然,在實施高可用方案時,要根據業務實際需求確定是否能容忍這樣的損失。對於一般的網站常規業務,這個損失是可容忍的。
1.4.4 解決Keepalived裂腦的常見方案
作為互聯網應用服務器的高可用,特別是前端Web負載均衡器的高可用,裂腦的問題對普通業務的影響是可以忍受的,如果是數據庫或者存儲的業務,一般出現裂腦問題就非常嚴重了。因此,可以通過增加冗余心跳線路來避免裂腦問題的發生,同時加強對系統的監控,以便裂腦發生時人為快速介入解決問題。
- 如果開啟防火牆,一定要讓心跳消息通過,一般通過允許IP段的形式解決。
- 可以拉一條以太網網線或者串口線作為主被節點心跳線路的冗余。
- 開發檢測程序通過監控軟件(例如Nagios)檢測裂腦。
下面是生產場景檢測裂腦故障的一些思路:
1)簡單判斷的思想:只要備節點出現VIP就報警,這個報警有兩種情況,一是主機宕機了備機接管了;二是主機沒宕,裂腦了。不管屬於哪個情況,都進行報警,然后由人工查看判斷及解決。
2)比較嚴謹的判斷:備節點出現對應VIP,並且主節點及對應服務(如果能遠程連接主節點看是否有VIP就更好了)還活着,就說明發生裂腦了。
具體檢測系統裂腦的腳本見本節附錄
1.5 Keepalived雙實例雙主模式配置
1.5.1 Keepalived雙實例雙主模式配置實戰
前面給出的是Keepalived單實例主備模式的高可用演示,Keepalived還支持多實例多業務雙向主備模式,即A業務在lb01上是主模式,在lb02上是備模式,而B業務在lb01上是備模式,在lb02上是主模式,下面就以雙實例為例講解不同業務實現雙主的配置。
下圖為Keepalived雙實例雙主模式IP及VIP規划表
HOSTNAME | IP | 說明 |
---|---|---|
lb01 | 192.168.0.221 | VIP:192.168.0.240(用於綁定A服務www.yunjisuan.com域名) |
lb02 | 192.168.0.222 | VIP:192.168.0.250(用於綁定B服務bbs.yunjisuan.com域名) |
首先,配置lb01 192.168.0.221的Keepalived.conf,在單實例的基礎上增加一個vrrp_instance VI_2實例,步驟及內容如下:
[root@lb01 keepalived]# cat keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
215379068@qq.com
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id lb01
}
vrrp_instance VI_1 {
state MASTER
interface eth1
virtual_router_id 55
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.240/24 dev eth0 label eth0:1
}
}
vrrp_instance VI_2 {
state BACKUP
interface eth1
virtual_router_id 56
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.250/24 dev eth0 label eth0:2
}
}
#提示:
以vrrp_instance VI_1在lb01 192.168.0.221服務器上的角色為主,vrrp_instance VI_2在lb01 192.168.0.221服務器上的角色為備。
然后配置lb02 192.168.0.222的Keepalived.conf,在單實例的基礎上增加vrrp_instance VI_2實例,步驟及內容如下:
root@lb02 keepalived]# cat keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
215379068@qq.com
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id lb02
}
vrrp_instance VI_1 {
state BACKUP
interface eth1
virtual_router_id 55
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.240/24 dev eth0 label eth0:1
}
}
vrrp_instance VI_2 {
state MASTER
interface eth1
virtual_router_id 56
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.250/24 dev eth0 label eth0:2
}
}
#提示:
以vrrp_instance VI_1在lb02 192.168.0.222服務器上的角色為備,vrrp_instance VI_2在lb02 192.168.0.222服務器上的角色為主。
接着,在lb01,lb02上分別重啟Keepalived服務,觀察初始VIP設置情況。
首先要關閉lb01和lb02的Keepalived服務,然后再進行如下操作:
#在lb01上進行如下操作:
[root@lb01 keepalived]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
[root@lb01 keepalived]# ip a | egrep "192.168.0.240|192.168.0.250"
inet 192.168.0.240/24 scope global secondary eth0:1 #由於lb02還沒開服務
inet 192.168.0.250/24 scope global secondary eth0:2 #主備VIP都顯示在lb01上
#在lb02上進行如下操作:
[root@lb02 keepalived]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
[root@lb02 keepalived]# ip a | egrep "192.168.0.240|192.168.0.250"
inet 192.168.0.250/24 scope global secondary eth0:2 #lb01開啟的情況下,lb02開啟服務后,只顯示了vrrp_instance VI_2實例lb02作為主模式的VIP 192.168.0.250
#再次在lb01上進行如下操作:
[root@lb01 ~]# ip a | egrep "240|250"
inet 192.168.0.240/24 scope global secondary eth0:1
#lb01上只有192.168.0.240了。
特別提示:
如果測試結果不符,請查看是否沒有關閉iptables
到此為止,我們發現lb01,lb02主備節點已經實現了初始配置的VIP服務狀態,當任意一端宕機,VIP可以實現互相切換接管。在實際工作中,可以把www.yunjisuan.com解析到192.168.0.240提供服務,把bbs.yunjisuan.com解析到192.168.0.250提供服務,當然了,lb01,lb02也要配置相應服務,例如:Nginx反向代理服務等。
1.5.2 雙實例雙主模式的配置文件對比
Keepalived雙實例雙主模式在企業工作場景也是比較常用的,下圖為大家展示了這種情況下主備配置文件的差別。
可以看出主備節點在增加實例方面就兩項區別:
- state(狀態)
- priority(精選優先級)
其中優先級決定VIP在哪個機器上初始運行
1.6 Nginx負載均衡配合Keepalived服務案例實戰
1.6.1 在lb01和lb02上配置Nginx負載均衡
結合上節介紹的Nginx負載均衡的環境,調整好主負載均衡器lb01,備用負載均衡器lb02服務器上Nginx負載均衡環境,兩台服務器的安裝基礎環境一模一樣。
這里使用的Nginx負載均衡的配置如下:
[root@lb01 ~]# cat /usr/local/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream www_server_pools {
server 192.168.0.223:80 weight=1;
server 192.168.0.224:80 weight=1;
}
server {
listen 80;
server_name www.yunjisuan.com;
location / {
proxy_pass http://www_server_pools;
proxy_set_header host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
}
#提示:此配置僅代理了www.yunjisuan.com域名
1.6.2 在lb01和lb02上配置Keepalived服務
Keepalived的配置與本節之前的實驗配置一致。
1.6.3 用戶訪問准備
准備工作如下:
(1)在客戶端hosts文件里把www.yunjisuan.com域名解析到VIP 192.168.0.240上,正式場景需通過DNS解析。
(2)兩台服務器配好Nginx負載均衡服務,並且確保后面代理的Web節點可以測試訪問。
#Web01上測試如下:
[root@web01 ~]# curl www.yunjisuan.com
192.168.0.223 www
[root@web01 ~]# curl www.yunjisuan.com
192.168.0.223 www
[root@web01 ~]# curl www.yunjisuan.com
192.168.0.223 www
#Web02上測試如下:
[root@web02 ~]# curl www.yunjisuan.com
192.168.0.224 www
[root@web02 ~]# curl www.yunjisuan.com
192.168.0.224 www
[root@web02 ~]# curl www.yunjisuan.com
192.168.0.224 www
(3)下面模擬實際的訪問過程
通過客戶端瀏覽器輸入www.yunjisuan.com測試訪問,正常應該顯示下圖。
此時停止lb01服務器或停掉Keepalived服務,觀察業務是否正常:
```
[root@lb01 ~]# /etc/init.d/keepalived stop
Stopping keepalived: [ OK ]
[root@lb01 ~]# ip a | grep 192.168.0.240
```
觀察lb02備節點是否接管了VIP 192.168.0.240
[root@lb02 ~]# ip a | grep 192.168.0.240
inet 192.168.0.240/24 scope global secondary eth0:1
再次在客戶端瀏覽器輸入www.yunjisuan.com測試訪問,正常應該出現和切換lb02前相同的訪問結果
(4)開啟lb01的Keepalived服務
[root@lb01 ~]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
[root@lb01 ~]# ip a | grep 192.168.0.240
inet 192.168.0.240/24 scope global secondary eth0:1
#可以看到,VIP很快就接管回來了,此時瀏覽器訪問結果依然正常
1.7 解決高可用服務只針對物理服務器的問題
默認情況下Keepalived軟件僅僅在對方機器宕機或Keepalived停掉的時候才會接管業務。但在實際工作中,有業務服務停止而Keepalived服務還在工作的情況,這就會導致用戶訪問的VIP無法找到對應的服務,那么,如何解決業務服務宕機可以將IP漂移到備節點使之接管提供服務呢?
第一個方法:可以寫守護進程腳本來處理。當Nginx業務有問題時,就停掉本地的Keepalived服務,實現IP漂移到對端繼續提供服務。實際工作中部署及開發的示例腳本如下:
[root@lb01 scripts]# cat check_nginx.sh
#!/bin/sh
while true
do
if [ `netstat -antup | grep nginx | wc -l` -ne 1 ];then
/etc/init.d/keepalived stop
fi
sleep 5
done
#此腳本的基本思想是若沒有80端口存在,就停掉Keepalived服務實現釋放本地的VIP。在后台執行上述腳本並檢查:
[root@lb01 scripts]# sh check_nginx.sh &
[1] 1521
[root@lb01 scripts]# ps -ef | grep check | grep -v grep
root 1521 1195 0 10:49 pts/0 00:00:00 sh check_nginx.sh
#確認Nginx以及Keepalived服務是正常的
[root@lb01 scripts]# netstat -antup | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1492/nginx
[root@lb01 scripts]# /etc/init.d/keepalived status
keepalived (pid 1512) is running...
#然后模擬Nginx服務掛掉,看IP是否發生切換。
[root@lb01 scripts]# /usr/local/nginx/sbin/nginx -s stop
[root@lb01 scripts]# Stopping keepalived: [ OK ]
[root@lb01 scripts]# /etc/init.d/keepalived status
keepalived is stopped
[root@lb01 scripts]# netstat -antup | grep nginx
#此時,備節點已接管:
[root@lb02 ~]# ip a | grep 192.168.0.240
inet 192.168.0.240/24 scope global secondary eth0:1
第二個方法:可以使用Keepalived的配置文件參數觸發寫好的監測服務腳本。首先要開發檢測服務腳本,注意這個腳本與上一個腳本的不同。
[root@lb01 scripts]# cat chk_nginx_proxy.sh
#!/bin/bash
if [ `netstat -antup | grep nginx | wc -l` -ne 1 ];then
/etc/init.d/keepalived stop
fi
[root@lb01 scripts]# chmod +x chk_nginx_proxy.sh
[root@lb01 scripts]# ls -l chk_nginx_proxy.sh
-rwxr-xr-x. 1 root root 102 Jul 31 10:59 chk_nginx_proxy.sh
此時,Keepalived服務的完整配置為:
[root@lb01 scripts]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
215379068@qq.com
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id lb01
}
vrrp_script chk_nginx_proxy { #定義vrrp腳本,檢測HTTP端口
script "/server/scripts/chk_nginx_proxy.sh" #執行腳本,當Nginx服務有問題,就停掉Keepalived服務
interval 2 #間隔2秒
weight 2
}
vrrp_instance VI_1 {
state MASTER
interface eth1
virtual_router_id 55
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.240/24 dev eth0 label eth0:1
}
track_script {
chk_nginx_proxy #觸發檢查
}
}
下面測試接管結果
#先殺掉之前的后台進程腳本的運行,之后進行如下操作
[root@lb01 scripts]# /usr/local/nginx/sbin/nginx
[root@lb01 scripts]# netstat -antup | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3937/nginx
[root@lb01 scripts]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
[root@lb01 scripts]# /etc/init.d/keepalived status
keepalived (pid 3949) is running...
[root@lb01 scripts]# ip a | grep 192.168.0.240
inet 192.168.0.240/24 scope global secondary eth0:1
[root@lb01 scripts]# /usr/local/nginx/sbin/nginx -s stop
[root@lb01 scripts]# ip a | grep 192.168.0.240
[root@lb01 scripts]# /etc/init.d/keepalived status
keepalived is stopped
#當停掉Nginx的時候,Keepalived 2秒鍾內會被自動停掉,VIP被釋放,由對端接管,這樣就實現了即使服務宕機也會進行IP漂移,業務切換。
1.8 解決多組Keepalived服務器在一個局域網的沖突問題
當在同一個局域網內部署了多組Keepalived服務器對,而又未使用專門的心跳線通信時,可能會發生高可用接管的嚴重故障問題。之前已經講解過Keepalived高可用功能是通過VRRP協議實現的,VRRP協議默認通過IP多播的形式實現高可用對之間的通信,如果同一個局域網內存在多組Keepalived服務器對,就會造成IP多播地址沖突問題,導致接管錯亂,不同組的Keepalived都會使用默認的224.0.0.18作為多播地址。此時的解決辦法是,在同組的Keepalived服務器所有的配置文件里指定獨一無二的多播地址,配置如下:
global_defs {
router_id LVS_19
vrrp_mcast_group4 224.0.0.19 #這個就是指定多播地址的配置
}
#提示:
1)不同實例的通信認證密碼也最好不同,以確保接管正常。
2)另一款高可用軟件Heartbeat,如果采用多播方式實現主備通信,同樣會有多播地址沖突問題。
1.9 開發檢測Keepalived裂腦的腳本
檢測思路:在備節點上執行腳本,如果可以ping通主節點並且備節點有VIP就報警,讓人員介入檢查是否裂腦。
1)在lb02備節點開發腳本並執行
[root@lb02 scripts]# cat check_split_brain.sh
#!/bin/bash
lb01_vip=192.168.0.240
lb01_ip=192.168.0.221
while true
do
ping -c 2 -W 3 $lb01_ip &>/dev/null
if [ $? -eq 0 -a `ip a | grep "$lb01_vip" | wc -l` -eq 1 ];then
echo "ha is split brain.warning."
else
echo "ha is OK"
fi
sleep 5
done
[root@lb02 scripts]# sh check_split_brain.sh
ha is OK
ha is OK
ha is OK
#正常情況下,主節點活着,VIP 192.168.0.221在主節點,因此不會報警,提示“ha is OK”
2)停止Keepalived服務看lb02腳本執行情況。
lb01上:
[root@lb01 scripts]# /etc/init.d/keepalived stop
Stopping keepalived: [ OK ]
[root@lb01 scripts]# ip a | grep 192.168.0.240
[root@lb01 scripts]#
#在lb02上觀察即可,此前腳本已經執行。
[root@lb02 scripts]# sh check_split_brain.sh
ha is OK
ha is OK
ha is OK
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
3)關掉lb01服務器,然后再觀察lb02腳本的輸出。
[root@lb02 scripts]# sh check_split_brain.sh
ha is OK
ha is OK
ha is OK
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
ha is OK
ha is OK
ha is OK
#裂腦報警恢復了。
4)可以將此腳本整合到Nagios或Zabbix監控服務里,進行監控報警。