Keepalived 軟件起初是專爲LVS負載均衡軟件設計的,用來管理並監控LVS集羣系統中各個服務節點的狀態,後來又加入了能夠實現高可用的VRRP功能。所以,Keepalived除了可以管理LVS軟件外,還能夠做爲其餘服務(例如:Nginx、Haproxy、MySQL等)的高可用解決方案軟件。html
Keepalived軟件主要是經過VRRP協議實現高可用功能的。VRRP是Virtual Router RedundancyProtocol(虛擬路由器冗餘協議)的縮寫,VRRP出現的目的就是爲了解決靜態路由單點故障問題的,它可以保證當個別節點宕機時,整個網絡能夠不間斷地運行。linux
因此,Keepalived 一方面具備配置管理LVS的功能,同時還具備對LVS下面節點進行健康檢查的功能,另外一方面也可實現系統網絡服務的高可用功能。nginx
連接: https://www.keepalived.org/c++
keepalived有三個重要的功能:算法
Keepalived 高可用服務之間的故障切換轉移,是經過 VRRP (Virtual Router Redundancy Protocol ,虛擬路由器冗餘協議)來實現的。數據庫
在 Keepalived 服務正常工做時,主 Master 節點會不斷地向備節點發送(多播的方式)心跳消息,用以告訴備 Backup 節點本身還活看,當主 Master 節點發生故障時,就沒法發送心跳消息,備節點也就所以沒法繼續檢測到來自主 Master 節點的心跳了,因而調用自身的接管程序,接管主 Master 節點的 IP 資源及服務。而當主 Master 節點恢復時,備 Backup 節點又會釋放主節點故障時自身接管的IP資源及服務,恢復到原來的備用角色。vim
那麼,什麼是VRRP呢?
VRRP ,全 稱 Virtual Router Redundancy Protocol ,中文名爲虛擬路由冗餘協議 ,VRRP的出現就是爲了解決靜態踣甶的單點故障問題,VRRP是經過一種競選機制來將路由的任務交給某臺VRRP路由器的。瀏覽器
Keepalived高可用對之間是經過VRRP通訊的,所以,咱們從 VRRP開始瞭解起:bash
介紹完 VRRP,接下來我再介紹一下 Keepalived服務的工做原理:服務器
Keepalived高可用是經過 VRRP 進行通訊的, VRRP是經過競選機制來肯定主備的,主的優先級高於備,所以,工做時主會優先得到全部的資源,備節點處於等待狀態,當主掛了的時候,備節點就會接管主節點的資源,而後頂替主節點對外提供服務。
在 Keepalived 服務之間,只有做爲主的服務器會一直髮送 VRRP 廣播包,告訴備它還活着,此時備不會槍佔主,當主不可用時,即備監聽不到主發送的廣播包時,就會啓動相關服務接管資源,保證業務的連續性.接管速度最快能夠小於1秒。
keepalived 的主配置文件是/etc/keepalived/keepalived.conf。其內容以下:
[root@master ~]# cat /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { //全局配置 notification_email { //定義報警收件人郵件地址 acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc //定義報警發件人郵箱 smtp_server 192.168.200.1 //郵箱服務器地址 smtp_connect_timeout 30 //定義郵箱超時時間 router_id LVS_DEVEL //定義路由標識信息,同局域網內惟一 vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { //定義實例 state MASTER //指定keepalived節點的初始狀態,可選值爲MASTER|BACKUP interface eth0 //VRRP實例綁定的網卡接口,用戶發送VRRP包 virtual_router_id 51 //虛擬路由的ID,同一集羣要一致 priority 100 //定義優先級,按優先級來決定主備角色,優先級越大越優先 nopreempt //設置不搶佔 advert_int 1 //主備通信時間間隔 authentication { //配置認證 auth_type PASS //認證方式,此處爲密碼 auth_pass 1111 //同一集羣中的keepalived配置裏的此處必須一致,推薦使用8位隨機數 } virtual_ipaddress { //配置要使用的VIP地址 192.168.200.16 } } virtual_server 10.10.10.2 1358 { //配置虛擬服務器 delay_loop 6 //健康檢查的時間間隔 lb_algo rr //lvs調度算法 lb_kind NAT //lvs模式 persistence_timeout 50 //持久化超時時間,單位是秒 protocol TCP //4層協議 sorry_server 192.168.200.200 1358 //定義備用服務器,當全部RS都故障時用sorry_server來響應客戶端 real_server 192.168.200.2 1358 { //定義真實處理請求的服務器 weight 1 //給服務器指定權重,默認爲1 HTTP_GET { url { path /testurl/test.jsp //指定要檢查的URL路徑 digest 640205b7b0fc66c1ea91c463fac6334d //摘要信息 } url { path /testurl2/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl3/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } connect_timeout 3 //鏈接超時時間 nb_get_retry 3 //get嘗試次數 delay_before_retry 3 //在嘗試以前延遲多長時間 } } real_server 192.168.200.3 1358 { weight 1 HTTP_GET { url { path /testurl/test.jsp digest 640205b7b0fc66c1ea91c463fac6334c } url { path /testurl2/test.jsp digest 640205b7b0fc66c1ea91c463fac6334c } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }
vrrp_instance段配置
nopreempt //設置爲不搶佔。默認是搶佔的,當高優先級的機器恢復後,會搶佔低優先 \ 級的機器成爲MASTER,而不搶佔,則容許低優先級的機器繼續成爲MASTER,即便高優先級 \ 的機器已經上線。若是要使用這個功能,則初始化狀態必須爲BACKUP。 preempt_delay //設置搶佔延遲。單位是秒,範圍是0---1000,默認是0.發現低優先 \ 級的MASTER後多少秒開始搶佔。
vrrp_script段配置
// 做用:添加一個週期性執行的腳本。腳本的退出狀態碼會被調用它的全部的VRRP Instance記錄。 // 注意:至少有一個VRRP實例調用它而且優先級不能爲0.優先級範圍是1-254. vrrp_script <SCRIPT_NAME> { ... } // 選項說明: script "/path/to/somewhere" //指定要執行的腳本的路徑。 interval <INTEGER> //指定腳本執行的間隔。單位是秒。默認爲1s。 timeout <INTEGER> //指定在多少秒後,腳本被認爲執行失敗。 weight <-254 --- 254> //調整優先級。默認爲2. rise <INTEGER> //執行成功多少次才認爲是成功。 fall <INTEGER> //執行失敗多少次才認爲失敗。 user <USERNAME> [GROUPNAME] //運行腳本的用戶和組。 init_fail //假設腳本初始狀態是失敗狀態。 //weight說明: 1. 若是腳本執行成功(退出狀態碼爲0),weight大於0,則priority增長。 2. 若是腳本執行失敗(退出狀態碼爲非0),weight小於0,則priority減小。 3. 其餘狀況下,priority不變。
real_server段配置
weight <INT> //給服務器指定權重。默認是1 inhibit_on_failure //當服務器健康檢查失敗時,將其weight設置爲0, \ 而不是從Virtual Server中移除 notify_up <STRING> //當服務器健康檢查成功時,執行的腳本 notify_down <STRING> //當服務器健康檢查失敗時,執行的腳本 uthreshold <INT> //到這臺服務器的最大鏈接數 lthreshold <INT> //到這臺服務器的最小鏈接數
tcp_check段配置
connect_ip <IP ADDRESS> //鏈接的IP地址。默認是real server的ip地址 connect_port <PORT> //鏈接的端口。默認是real server的端口 bindto <IP ADDRESS> //發起鏈接的接口的地址。 bind_port <PORT> //發起鏈接的源端口。 connect_timeout <INT> //鏈接超時時間。默認是5s。 fwmark <INTEGER> //使用fwmark對全部出去的檢查數據包進行標記。 warmup <INT> //指定一個隨機延遲,最大爲N秒。可防止網絡阻塞。若是爲0,則關閉該功能。 retry <INIT> //重試次數。默認是1次。 delay_before_retry <INT> //默認是1秒。在重試以前延遲多少秒。
環境說明:
系統 | 主機名 | IP |
---|---|---|
rhel7.4 | master | 192.168.206.129 |
rhel7.4 | slave | 192.168.206.129 |
本次高可用虛擬IP(VIP)地址暫定爲 192.168.100.250
主服務器上配置keepalived
//關閉防火牆與SELINUX [root@master ~]# systemctl stop firewalld [root@master ~]# systemctl disable firewalld Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service. Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service. [root@master ~]# setenforce 0 [root@master ~]# sed -ri 's/^(SELINUX=).*/\1disabled/g' /etc/selinux/config //配置網絡源 [root@master ~]# curl -o /etc/yum.repos.d/CentOS7-Base-163.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo [root@master ~]# sed -i 's/\$releasever/7/g' /etc/yum.repos.d/CentOS7-Base-163.repo [root@master ~]# sed -i 's/^enabled=.*/enabled=1/g' /etc/yum.repos.d/CentOS7-Base-163.repo [root@master ~]# yum -y install epel-release vim wget gcc gcc-c++ ……下載過程略 //安裝keepalived [root@master ~]# yum -y install keepalived ……下載過程略 //查看安裝生成的文件 [root@master ~]# rpm -ql keepalived /etc/keepalived //配置目錄 /etc/keepalived/keepalived.conf //此爲主配置文件 /etc/sysconfig/keepalived /usr/bin/genhash /usr/lib/systemd/system/keepalived.service //此爲服務控制文件 /usr/libexec/keepalived /usr/sbin/keepalived ........ ........ ........
備服務器上配置keepalived
//關閉防火牆與SELINUX [root@slave ~]# systemctl stop firewalld [root@slave ~]# systemctl disable firewalld Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service. Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service. [root@slave ~]# setenforce 0 [root@slave ~]# sed -ri 's/^(SELINUX=).*/\1disabled/g' /etc/selinux/config //配置網絡源 [root@slave ~]# curl -o /etc/yum.repos.d/CentOS7-Base-163.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo [root@slave ~]# sed -i 's/\$releasever/7/g' /etc/yum.repos.d/CentOS7-Base-163.repo [root@slave ~]# sed -i 's/^enabled=.*/enabled=1/g' /etc/yum.repos.d/CentOS7-Base-163.repo [root@slave ~]# yum -y install epel-release vim wget gcc gcc-c++ 安裝過程略..... //安裝keepalived [root@slave ~]# yum -y install keepalived ……下載過程略
主服務器上安裝nginx
[root@master ~]# yum -y install nginx [root@master ~]# cd /usr/share/nginx/html/ [root@master html]# ls 404.html 50x.html index.html nginx-logo.png poweredby.png [root@master html]# echo 'master' > index.html [root@master html]# ls 404.html 50x.html index.html nginx-logo.png poweredby.png [root@master html]# systemctl start nginx [root@master html]# systemctl enable nginx [root@master html]# ss -antl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 *:80 *:* LISTEN 0 128 *:22 *:* LISTEN 0 100 127.0.0.1:25 *:* LISTEN 0 128 :::80 :::* LISTEN 0 128 :::22 :::* LISTEN 0 100 ::1:25 :::*
備服務器上安裝nginx
[root@slave ~]# yum -y install nginx [root@slave ~]# cd /usr/share/nginx/html/ [root@slave html]# ls 404.html 50x.html index.html nginx-logo.png poweredby.png [root@slave html]# echo 'slave' > index.html [root@slave html]# ls 404.html 50x.html index.html nginx-logo.png poweredby.png [root@slave html]# systemctl start nginx 6632489/article/details/106626516
安裝完成後能夠在瀏覽器上用ip訪問,試一下是否能夠訪問!!!
[root@master ~]# cd /etc/keepalived/ [root@master keepalived]# mv keepalived.conf{,.bak} [root@master keepalived]# vim keepalived.conf ! Configuration File for keepalived global_defs { router_id lb01 } vrrp_instance VI_1 { state MASTER interface ens33 //此住要與你的網卡名一致 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 12345 } virtual_ipaddress { 192.168.206.250 } } virtual_server 192.168.206.250 80 { delay_loop 6 lb_algo rr lb_kind DR persistence_timeout 50 protocol TCP real_server 192.168.206.129 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.206.130 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } } [root@master ~]# systemctl start keepalived [root@master ~]# systemctl enable keepalived
[root@slave ~]# cd /etc/keepalived/ [root@slave keepalived]# mv keepalived.conf{,.bak} [root@slave keepalived]# vim keepalived.conf ! Configuration File for keepalived global_defs { router_id lb02 } vrrp_instance VI_1 { state BACKUP interface ens33 //此處要與你的網卡名一致 virtual_router_id 51 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 12345 } virtual_ipaddress { 192.168.206.250 } } virtual_server 192.168.206.250 80 { delay_loop 6 lb_algo rr lb_kind DR persistence_timeout 50 protocol TCP real_server 192.168.206.129 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.206.130 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } } [root@slave ~]# systemctl start keepalived [root@slave ~]# systemctl enable keepalived
配置完成後在主服務器上:
[root@master ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:0f:a6:60 brd ff:ff:ff:ff:ff:ff inet 192.168.206.129/24 brd 192.168.100.255 scope global ens33 valid_lft forever preferred_lft forever inet 192.168.206.250/32 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::92d4:d1c1:856a:e885/64 scope link valid_lft forever preferred_lft forever
在備服務器上:
[root@slave ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:ad:5e:54 brd ff:ff:ff:ff:ff:ff inet 192.168.206.130/24 brd 192.168.100.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fead:5e54/64 scope link valid_lft forever preferred_lft forever
測試:
//將master上的keepalived停掉 [root@master ~]# systemctl stop keepalived [root@master ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:0f:a6:60 brd ff:ff:ff:ff:ff:ff inet 192.168.206.129/24 brd 192.168.100.255 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::92d4:d1c1:856a:e885/64 scope link valid_lft forever preferred_lft forever //虛擬ip192.168.206.250沒了 // slave上查看(須要手動啓動nginx) [root@slave ~]# systemctl start nginx [root@slave ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:ad:5e:54 brd ff:ff:ff:ff:ff:ff inet 192.168.206.130/24 brd 192.168.100.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet 192.168.206.250/32 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fead:5e54/64 scope link valid_lft forever preferred_lft forever
keepalived經過腳原本監控nginx負載均衡機的狀態
在master上編寫腳本:
[root@master ~]# mkdir /scripts [root@master ~]# cd /scripts/ [root@master scripts]# vim check_n.sh #!/bin/bash nginx_status=$(ps -ef|grep -Ev "grep|$0"|grep '\bnginx\b'|wc -l) if [ $nginx_status -lt 1 ];then systemctl stop keepalived fi [root@master scripts]# chmod +x check_n.sh [root@master scripts]# ll total 4 -rwxr-xr-x 1 root root 168 Oct 19 23:38 check_n.sh [root@master scripts]# vim notify.sh #!/bin/bash VIP=$2 sendmail (){ subject="${VIP}'s server keepalived state is translate" content="`date +'%F %T'`: `hostname`'s state change to master" echo $content | mail -s "$subject" 1223901946@qq.com } case "$1" in master) nginx_status=$(ps -ef|grep -Ev "grep|$0"|grep '\bnginx\b'|wc -l) if [ $nginx_status -lt 1 ];then systemctl start nginx fi sendmail ;; backup) nginx_status=$(ps -ef|grep -Ev "grep|$0"|grep '\bnginx\b'|wc -l) if [ $nginx_status -gt 0 ];then systemctl stop nginx fi ;; *) echo "Usage:$0 master|backup VIP" ;; esac [root@master scripts]# chmod +x notify.sh [root@master scripts]# ll total 8 -rwxr-xr-x 1 root root 168 Oct 19 23:38 check_n.sh -rwxr-xr-x 1 root root 594 Oct 20 03:24 notify.sh
在slave上編寫腳本:
[root@slave ~]# mkdir /scripts [root@slave ~]# cd /scripts/ [root@slave scripts]# vim notify.sh #!/bin/bash VIP=$2 sendmail (){ subject="${VIP}'s server keepalived state is translate" content="`date +'%F %T'`: `hostname`'s state change to master" echo $content | mail -s "$subject" 1221901946@qq.com } case "$1" in master) nginx_status=$(ps -ef|grep -Ev "grep|$0"|grep '\bnginx\b'|wc -l) if [ $nginx_status -lt 1 ];then systemctl start nginx fi sendmail ;; backup) nginx_status=$(ps -ef|grep -Ev "grep|$0"|grep '\bnginx\b'|wc -l) if [ $nginx_status -gt 0 ];then systemctl stop nginx fi ;; *) echo "Usage:$0 master|backup VIP" ;; esac [root@slave scripts]# chmod +x notify.sh [root@slave scripts]# ll total 8 -rwxr-xr-x 1 root root 168 Oct 19 23:38 check_n.sh -rwxr-xr-x 1 root root 594 Oct 20 03:24 notify.sh
此處的腳本名稱應避免與服務名相同,推薦用服務名的首字母代替,如check_n,不要給腳本起名check_nginx
配置主keepalived
[root@master keepalived]# vim keepalived.conf ! Configuration File for keepalived global_defs { router_id lb01 } //加入下面四行 vrrp_script nginx_check { script "/scripts/check_n.sh" interval 1 weight -20 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 12345 } virtual_ipaddress { 192.168.206.250 } //加入下面四行 track_script { nginx_check } notify_master "/scripts/notify.sh master 192.168.206.250" notify_backup "/scripts/notify.sh backup 192.168.206.250" } virtual_server 192.168.206.250 80 { delay_loop 6 lb_algo rr lb_kind DR persistence_timeout 50 protocol TCP real_server 192.168.206.129 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.206.130 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } } [root@master ~]# systemctl restart keepalived
配置備keepalived
backup無需檢測nginx是否正常,當升級爲MASTER時啓動nginx,當降級爲BACKUP時關閉
[root@slave keepalived]# vim keepalived.conf ! Configuration File for keepalived
global_defs {
router_id lb02
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 12345
}
virtual_ipaddress {
192.168.206.250
}
//加入下面兩行
notify_master "/scripts/notify.sh master 192.168.206.250"
notify_backup "/scripts/notify.sh backup 192.168.206.250"
}
virtual_server 192.168.206.250 80 {
delay_loop 6
lb_algo rr
lb_kind DR
persistence_timeout 50
protocol TCP
real_server 192.168.206.129 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.206.130 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } }
}
[root@slave ~]# systemctl restart keepalived
**測試: 中止master的nginx服務,slave會自動搶佔成爲master**
//在master上關閉nginx服務
[root@master ~]# systemctl stop nginx
//在slave查看
[root@slave ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:ad:5e:54 brd ff:ff:ff:ff:ff:ff
inet 192.168.206.130/24 brd 192.168.100.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet 192.168.206.250/32 scope global ens33
valid_lft forever preferred_lft forever
//而後再在master上重啓nginx服務與keepalived服務,master又會從新奪回VIP
[root@master ~]# systemctl start nginx
[root@master ~]# systemctl restart keepalived
[root@master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:0f:a6:60 brd ff:ff:ff:ff:ff:ff
inet 192.168.206.129/24 brd 192.168.100.255 scope global ens33
valid_lft forever preferred_lft forever
inet 192.168.206.250/32 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::92d4:d1c1:856a:e885/64 scope link
valid_lft forever preferred_lft forever
----- # 7.腦裂 在高可用(HA)系統中,當聯繫2個節點的「心跳線」斷開時,原本爲一總體、動做協調的HA系統,就分裂成爲2個獨立的個體。因爲相互失去了聯繫,都覺得是對方出了故障。兩個節點上的HA軟件像「裂腦人」同樣,爭搶「共享資源」、爭起「應用服務」,就會發生嚴重後果——或者共享資源被瓜分、2邊「服務」都起不來了;或者2邊「服務」都起來了,但同時讀寫「共享存儲」,致使數據損壞(常見如數據庫輪詢着的聯機日誌出錯)。 對付HA系統「裂腦」的對策,目前達成共識的的大概有如下幾條: * 添加冗餘的心跳線,例如:雙線條線(心跳線也HA),儘可能減小「裂腦」發生概率。 * 啓用磁盤鎖。正在服務一方鎖住共享磁盤,「裂腦」發生時,讓對方徹底「搶不走」共享磁盤資源。但使用鎖磁盤也會有一個不小的問題,若是佔用共享盤的一方不主動「解鎖」,另外一方就永遠得不到共享磁盤。現實中假如服務節點忽然死機或崩潰,就不可能執行解鎖命令。後備節點也就接管不了共享資源和應用服務。因而有人在HA中設計了「智能」鎖。即:正在服務的一方只在發現心跳線所有斷開(察覺不到對端)時才啓用磁盤鎖。平時就不上鎖了。 * 設置仲裁機制。例如設置參考IP(如網關IP),小心跳線徹底斷開時,2個節點都各自ping一下參考IP,不通則代表斷點就出在本端。不只「心跳」、還兼對外「服務」的本端網絡鏈路斷了,即便啓動(或繼續)應用服務也沒有用了,那就主動放棄競爭,讓可以ping通參考IP的一端去起服務。更保險一些,ping不通參考IP的一方乾脆就自我重啓,以完全釋放有可能還佔用着的那些共享資源。 # 7.1 腦裂產生的緣由 通常來講,腦裂的發生,有如下幾種緣由: * 高可用服務器對之間心跳線鏈路發生故障,致使沒法正常通訊 > 因心跳線壞了(包括斷了,老化) > 因網卡及相關驅動壞了,ip配置及衝突問題(網卡直連) > 因心跳線間鏈接的設備故障(網卡及交換機) > 因仲裁的機器出問題(採用仲裁的方案) * 高可用服務器上開啓了 iptables防火牆阻擋了心跳消息傳輸 * 高可用服務器上心跳網卡地址等信息配置不正確,致使發送心跳失敗 * 其餘服務配置不當等緣由,如心跳方式不一樣,心跳廣插衝突、軟件Bug等 **注意:** > Keepalived配置裏同一 VRRP實例若是 virtual_router_id兩端參數配置不一致也會致使裂腦問題發生。 # 7.2 腦裂的常看法決方案 **在實際生產環境中,咱們能夠從如下幾個方面來防止裂腦問題的發生:** * 同時使用串行電纜和以太網電纜鏈接,同時用兩條心跳線路,這樣一條線路壞了,另外一個仍是好的,依然能傳送心跳消息 * 當檢測到裂腦時強行關閉一個心跳節點(這個功能需特殊設備支持,如Stonith、feyce)。至關於備節點接收不到心跳消患,經過單獨的線路發送關機命令關閉主節點的電源 * 作好對裂腦的監控報警(如郵件及手機短信等或值班).在問題發生時人爲第一時間介入仲裁,下降損失。例如,百度的監控報警短倍就有上行和下行的區別。報警消息發送到管理員手機上,管理員能夠經過手機回覆對應數字或簡單的字符串操做返回給服務器.讓服務器根據指令自動處理相應故障,這樣解決故障的時間更短. 固然,在實施高可用方案時,要根據業務實際需求肯定是否能容忍這樣的損失。對於通常的網站常規業務.這個損失是可容忍的 # 7.3 對腦裂進行監控 對腦裂的監控應在備用服務器上進行,經過添加zabbix自定義監控進行。 監控什麼信息呢?監控備上有無VIP地址 備機上出現VIP有兩種狀況: * 發生了腦裂 * 正常的主備切換 監控只是監控發生腦裂的可能性,不能保證必定是發生了腦裂,由於正常的主備切換VIP也是會到備上的。 **監控腳本以下:** > [root@slave ~]# mkdir -p /scripts && cd /scripts > [root@slave scripts]# vim check_keepalived.sh > #!/bin/bash > > while true;do > if [ `ip a show ens33 |grep 192.168.100.250|wc -l` -ne 0 ] > then > echo "keepalived is error!" > else > echo "keepalived is OK !" > fi > done **編寫腳本時要注意,網卡要改爲你本身的網卡名稱,VIP也要改爲你本身的VIP,最後不要忘了給腳本賦予執行權限,且要修改/scripts目錄的屬主屬組爲zabbix**