1. 程式人生 > >Keepalived 高可用服務

Keepalived 高可用服務

一、Keepalived 詳解配置

1、Keepalived 軟體介紹:
Keeplived 軟體起初就是專為 LVS 負載均衡軟體設計的,用來管理並監控 LVS 集群系統中各個伺服器節點的狀態,後來又加入了可以實現高可用的 VRRP 功能。因此 Keepalived 除了能夠管理 LVS 軟體外,還可以作為其他服務(Nginx、Haproxy、MySQL 等)的高可用解決方案軟體。
Keeplived 軟體主要是通過 VRRP 協議實現高可用功能的,VRRP 出現的目的就是為了解決靜態路由單點故障問題的,它能夠保證當個別節點宕機時,整個網路可以不間斷的執行,所以 Keepalived 一方面具有配置管理 LVS 的功能,同時還具有對 LVS 下面節點進行健康檢查的功能,另一方面也可實現系統網路服務的高可用性。
Keeplived 軟體的官方網站是

http://www.keepalived.org
2、Keeplived 高可用故障切換轉移原理:
Keeplived 高可用服務對之間的故障切換轉移,是通過 VRRP 協議(Virtual Router Redundancy Protocol,中文意思:虛擬路由器冗餘協議)來實現的。
在 Keepailved 服務正常工作時,主 Master 節點會不斷地向備節點發送(多播的方式)心跳訊息,用以告訴備 Backup 節點自己還活著,當主 Master 節點發生故障時,就無法傳送心跳資訊了,備節點也就因此無法繼續監測到來自主 Master 節點的心跳了,進而呼叫自身的接管程式,接管主 Master 節點的 IP 資源及服務。而當主 Master 節點恢復時,備 Bacckup 節點又會釋放主節點故障時自身接管的 IP 資源及服務,恢復到原來的備用角色。
3、企業面試題:簡要回答 Keeplived 的工作原理:

Keeplived 軟體高可用對之間是通過 VRRP 協議通訊的,因此,我從 VRRP 協議介紹開始:
① VRRP 協議全稱 Virtual Router Redundancy Protocol,中文意思:虛擬路由器冗餘協議。它的出現是為了解決靜態路由的單點故障;
② VRRP 協議是通過一種競選協議機制來將路由任務交給某臺 VRRP 路由器的;
③ VRRP 協議是通過 IP 多播方式(預設多播地址 224.0.0.18)實現高可用對之間通訊的;
④ 工作主節點發包,備節點接包,當備節點接收不到主節點發的資料包的時候,就啟動接管程式接管主節點的資源,備節點可以有多個,通過優先順序競選,但一般 Keepalived 系統運維工作中都是用一對。
⑤ VRRP 使用了加密協議加密資料,但 Keepalived 官方目前還是推薦用明文的方式配置認證型別和密碼。
介紹完了 VRRP 協議,接下來介紹 Keepalived 服務的工作原理:
Keepalived 高可用對之間是通過 VRRP 協議進行通訊的,VRRP 協議是通過競選機制來確定主備的,主優先順序高於備,因此工作時主會優先獲得所有的資源,備節點處於等待狀態,當主掛了的時候,備節點就會接管主節點的資源,然後頂替主節點對外提供服務。
在 Keepalived 服務對之間,只有作為主的伺服器會一直髮送 VRRP 廣播包,告訴備它還活著,此時備不會搶佔主,當主不可用時,即備監聽不到主傳送的廣播包時就會啟動相關服務接管資源,保證業務的連續性,接管速度最快可以小於 1 秒。
4、keepalived 高可用服務搭建:

1)、搭建環境準備:
Keepalived 高可用服務
2)、Keepalived 軟體安裝:
a、在兩臺負載均衡伺服器安裝 Keepalived 軟體:

[[email protected] ~]# yum install keepalived -y
[[email protected] ~]# rpm -qa keepalived
keepalived-1.2.13-5.el6_6.x86_64

b、在兩臺負載均衡伺服器啟動 Keepalived 軟體:

[[email protected] ~]# /etc/init.d/keepalived start
Starting keepalived:         [  OK  ]
[[email protected] ~]# ps -ef|grep keep|grep -v grep        # 有三個程序表示正常
root      1186     1  0 Jul26 ?        00:00:03 /usr/sbin/keepalived -D
root      1187  1186  0 Jul26 ?        00:00:03 /usr/sbin/keepalived -D
root      1188  1186  0 Jul26 ?        00:00:12 /usr/sbin/keepalived -D

c、新增虛擬 IP 的兩種方式:

        ① ifconfig eth0:0 192.168.153.100/24 up
        ② ip addr add 192.168.153.100/24 dev eth0 label eth0:1  #  這種給新增的 IP 加標籤的方式可以用 ifconfig 命令查到新增的 IP,否則只能用 ip add 檢視新增的 IP。
        提示:Keepalived 預設使用第二種方式新增的虛擬 IP 。早期的 Heartbeat 使用第一種方式新增虛擬 IP,在 Heartbeat 3.0 版本以後也使用第二種方式新增虛擬 IP 了。
[[email protected] ~]# ip addr add 192.168.153.100/24 dev eth0 label eth0:1
[[email protected] ~]# ip add|grep 153.100         
    inet 192.168.153.100/24 scope global secondary eth0:1

d、編輯 Keepalived 配置檔案:

[[email protected] ~]# man keepalived.conf   # Keepalived 配置檔案有三個部分。
TOP HIERACHY
       GLOBAL CONFIGURATION # 全域性配置

       VRRPD CONFIGURATION  # VRRP 的配置

       LVS CONFIGURATION        # 結合 LVS 的配置
[[email protected] ~]# vim /etc/keepalived/keepalived.conf 
  1 ! Configuration File for keepalived    #  這裡井號歎號都為註釋。
  2 
  3 global_defs {       #  全域性配置。
  4    notification_email {
  5      [email protected]          ##############
  6      [email protected]            # 這三行是接收郵件的收件人(沒什麼用)。
  7      [email protected]        ##############
  8    }
  9    notification_email_from [email protected]    #  發件人。
 10    smtp_server 192.168.200.1        #  郵件伺服器。
 11    smtp_connect_timeout 30           #  郵件伺服器。
 12    router_id LVS_DEVEL    #  路由 ID,不同機器之間不能重複。
 13 }
 14 
 15 vrrp_instance VI_1 {    #  VRRP 例項【VI_1 是例項名字,可以配多個(VI_2等)】。
 16     state MASTER        #  角色(主),傀儡、不決定主備。
 17     interface eth0          #  通訊的介面。
18     virtual_router_id 51  #  該例項的 ID,不同的例項 ID 要不同。
19     priority 150               #  優先順序,競選看優先順序(決定主備的引數)。
 20     advert_int 1             #  通訊檢查間隔時間為 1 s,發廣播的間隔時間內從 Backup 伺服器沒有接收到廣播就接替工作。
 21     authentication {       #  主備通訊方式。
 22         auth_type PASS  #  認證機制,明文的密碼方式。
 23         auth_pass 1111   #  認證的密碼。
 24     }
 25     virtual_ipaddress {   #  VIP 虛擬 IP,可以是一組也可以是一個。  
 26         192.168.153.100/24 dev eth0 label eth0:1
 27     }
 28 }
  上面為主伺服器的配置檔案,綠色的部分都是備伺服器需要修改的:
12    router_id LVS_DEVEL1
16     state BACKUP
19     priority 100

e、Master 節點和 Backup 節點特殊引數的不同:
Keepalived 高可用服務
3)、此時檢視兩臺伺服器上面的虛擬 IP:

      在主節點檢視虛擬 IP 的存在:
[[email protected] ~]# ip add|grep 153.100                 #  主 Master 節點有新增的虛擬 IP(優先順序高)。
    inet 192.168.153.100/24 scope global secondary eth0:1
      在備節點檢視虛擬 IP 的存在:
[[email protected] ~]# ip add |grep 153.100         #  備 Backup 節點沒有(主正常,備等待)。

4)、以 Windows為客戶端測試主備節點的高可用:
① 通過 Windows 客戶端連續 ping 虛擬 IP:
Keepalived 高可用服務
② 此時在主節點可以看到虛擬 IP :

[[email protected] ~]# ip add|grep 192.168.136.100
    inet 192.168.136.100/24 scope global secondary eth0:1

③ 關掉主節點的 Keepalived 服務:

[[email protected] ~]# /etc/init.d/keepalived stop
Stopping keepalived:          [  OK  ] 

④ 檢視備節點的虛擬 IP(備接管主的工作):

[[email protected] ~]# ip add|grep 192.168.136.100
    inet 192.168.136.100/24 scope global secondary eth0:1

⑤ 啟動主節點的 Keepalived 服務並檢視虛擬 IP :

[[email protected] ~]# /etc/init.d/keepalived start
Starting keepalived:           [  OK  ]
[[email protected] ~]# ip add|grep 192.168.136.100      #  略有延遲,編譯安裝快?
    inet 192.168.136.100/24 scope global secondary eth0:1

5)、Keepalived 多例項的配置及實現:
首先新增另一個虛擬 IP :
[[email protected] ~]# ip addr add 192.168.153.200/24 dev eth0 label eth0:2
修改兩臺負載均衡器的 keepalived.conf 配置檔案:
① 在 lb 01 的 keepalived.conf 配置檔案新增如下內容:

vrrp_instance VI_2 {    # 表示第二個例項名字。(與第一個例項不同)
    state BACKUP        #  第二個例項的備 Backup 節點。
    interface eth0
    virtual_router_id 52    #  虛擬路由 id,不同例項要不同,同一例項主備相同。
    priority 100            #  優先順序。
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1112  #  主備通訊的密碼,同一例項主備相同(不同例項最好區分,非必須)。
    }
    virtual_ipaddress {
        192.168.153.200/24 dev eth0 label eth0:2    #  新增的虛擬 IP 不同例項不同,網絡卡標籤不同。
    }
}

② 在 lb 02 的 keepalived.conf 配置檔案新增如下內容:

vrrp_instance VI_2 {    # 表示第二個例項名字。(與第一個例項不同)
    state MASTER        #  第二個例項的主 MASTER 節點。
    interface eth0
    virtual_router_id 52    #  虛擬路由 id,不同例項要不同,同一例項主備相同。
    priority 150            #  優先順序。
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1112  #  主備通訊的密碼,同一例項主備相同(不同例項最好區分,非必須)。
    }
    virtual_ipaddress {
        192.168.153.200/24 dev eth0 label eth0:2·   #  新增的虛擬 IP 不同例項不同,網絡卡標籤不同。
    }
}

③ 重啟兩臺伺服器使配置生效:

[[email protected] ~]# /etc/init.d/keepalived restart 
Stopping keepalived:              [  OK  ]
Starting keepalived:                [  OK  ]   
[[email protected] ~]# /etc/init.d/keepalived restart 
Stopping keepalived:              [  OK  ]
Starting keepalived:                [  OK  ]

④ 通過檢視虛擬 IP 測試多例項的生效:

[[email protected] ~]# ip add|egrep "153.100|153.200"   # 例項一優先順序高的是 lb01,所以 VIP 100存在。
    inet 192.168.153.100/24 scope global secondary eth0:1
[[email protected] ~]# ip add |egrep "153.100|153.200"     # 例項二優先順序高的是 lb02,所以 VIP 200存在。
    inet 192.168.153.200/24 scope global secondary eth0:2

關閉 lb01 伺服器的 Keepalived 服務:

[[email protected] ~]# /etc/init.d/keepalived stop
Stopping keepalived:              [  OK  ]
[[email protected] ~]# ip add |egrep "153.100|153.200"  #  此時該伺服器沒有 VIP 在工作了。
[[email protected] ~]# ip add|egrep "153.100|153.200"   #  lb02 伺服器接管了兩個 VIP 的工作。
    inet 192.168.153.100/24 scope global secondary eth0:1
    inet 192.168.153.200/24 scope global secondary eth0:2

啟動 lb01 伺服器的 Keepalived 服務:

[[email protected] ~]# /etc/init.d/keepalived start
Starting keepalived:               [  OK  ]
[[email protected] ~]# ip add|egrep "153.100|153.200"   # 例項一優先順序高的是 lb01,所以 VIP 100存在。
    inet 192.168.153.100/24 scope global secondary eth0:1
[[email protected] ~]# ip add |egrep "153.100|153.200"  # 例項二優先順序高的是 lb02,所以 VIP 200存在。
    inet 192.168.153.200/24 scope global secondary eth0:2

關閉 lb02 伺服器的 Keepalived 服務:

[[email protected] ~]# /etc/init.d/keepalived stop
Stopping keepalived:                                       [  OK  ]
[[email protected] ~]# ip add |egrep "153.100|153.200"  #  此時該伺服器沒有 VIP 在工作了。
[[email protected] ~]# ip add|egrep "153.100|153.200"   #  lb01 伺服器接管了兩個 VIP 的工作。
    inet 192.168.153.100/24 scope global secondary eth0:1
    inet 192.168.153.200/24 scope global secondary eth0:2

5、Keepalived 配合 Nginx 負載均衡實現高可用:
Keepalived 高可用服務
方案一:兩臺負載同時啟動 Nginx 代理,Keepalived 負責 VIP 漂移,VIP 漂移到哪個機器哪個就提供訪問:
① 檢查環境:
兩臺 Nginx 負載均衡器的 Keepalived 服務和 Nginx 服務都是開啟狀態:

[[email protected] ~]# /etc/init.d/keepalived status  
keepalived (pid  2622) is running...
[[email protected] ~]# /etc/init.d/keepalived status
keepalived (pid  2622) is running...
[[email protected] conf]# ps -ef|grep nginx|grep -v grep
root       2045      1  0 Jun22 ?        00:00:00 nginx: master process /application/nginx/sbin/nginx
nginx      2137   2045  0 Jun22 ?        00:00:00 nginx: worker process
[[email protected] conf]# ps -ef|grep nginx|grep -v grep
root       2045      1  0 Jun22 ?        00:00:00 nginx: master process /application/nginx/sbin/nginx
nginx      2137   2045  0 Jun22 ?        00:00:00 nginx: worker process    

② 備份並編輯 Web 伺服器的配置檔案:

[[email protected] conf]# pwd
/application/nginx/conf
[[email protected] conf]# vim nginx.conf
[[email protected] conf]# cat 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{
   # ip_hash;
   server 192.168.136.150:80  weight=1;
   server 192.168.136.151:80  weight=1;
}
server {
        listen       80;
        server_name  www.etiantian.org;
        location / {
          proxy_pass http://www_server_pools;  
 }
   }    
}

③ 檢查 Web01 和 Web02 伺服器 www 站點首頁檔案:

[[email protected] ~]# cat /application/nginx/html/www/index.html
www.etiantian.org 150
[[email protected] ~]# cat /application/nginx/html/www/index.html
www.etiantian.org 151

④ 修改負載均衡伺服器 hosts 並 curl 訪問 Web 伺服器:

[[email protected] conf]# vim /etc/hosts
[[email protected] conf]# cat /etc/hosts
192.168.153.100 www.etiantian.org    #  將域名解析到虛擬 IP。
[[email protected] conf]# for n in `seq 10`;do curl www.etiantian.org;done   # 實現。
www.etiantian.org 150
www.etiantian.org 151
www.etiantian.org 150
www.etiantian.org 151
www.etiantian.org 150
www.etiantian.org 151
www.etiantian.org 150
www.etiantian.org 151
www.etiantian.org 150
www.etiantian.org 151

⑤ 實現兩臺負載均衡器的高可用,要讓它們的 Nginx 配置檔案一致:

[[email protected] conf]# cd /application/nginx/conf/
[[email protected] conf]# vim nginx.conf   # 跟以上配置一致。
[[email protected] conf]# ../sbin/nginx -t
nginx: the configuration file /application/nginx-1.6.3/conf/nginx.conf syntax is ok
nginx: configuration file /application/nginx-1.6.3/conf/nginx.conf test is successful
[[email protected] conf]# ../sbin/nginx -s reload

測試 lb02 負載均衡器的工作是否正常:

[[email protected] conf]# tail -1 /etc/hosts
192.168.136.162 www.etiantian.org   #  備節點沒有 VIP,所以解析到自己的 IP 測試。
[[email protected] conf]# for n in `seq 10`;do curl www.etiantian.org;done                  
www.etiantian.org 150
www.etiantian.org 151
www.etiantian.org 150
www.etiantian.org 151
www.etiantian.org 150
www.etiantian.org 151
www.etiantian.org 150
www.etiantian.org 151
www.etiantian.org 150
www.etiantian.org 151

⑥ 在 Windows 做域名對應 VIP 的解析並通過瀏覽器訪問:
徽標鍵 + R 執行視窗 drivers 命令修改 hosts如下:
192.168.136.100 www.etiantian.org
通過瀏覽器訪問域名 www.etiantian.org:
訪問到 Web 01 的首頁檔案:
Keepalived 高可用服務
重新整理後訪問到 Web 02 的首頁檔案:
Keepalived 高可用服務
⑦ 此時讓 LB01 宕機,再訪問,業務不受影響:
原因:VIP 飄到 LB 02 伺服器了,lb 02 接管工作,如下:

[[email protected] conf]# ip add|egrep 136.100
    inet 192.168.136.100/24 scope global secondary eth0:1

⑧ 開啟 LB01 伺服器,再訪問,業務不受影響,VIP 重新飄回LB01:

[[email protected] conf]# ip add|egrep 136.100
    inet 192.168.136.100/24 scope global secondary eth0:1
[[email protected] conf]# ip add|egrep 136.100    #  lb02 沒有 VIP 100 了。

方案二:通過 Keepalived 多例項配合 Nginx 實現雙主:
www.etiantian.org 的 VIP 為 192.168.136.100 ,在 lb01 上是主。
blog.etiantian.org 的 VIP 為 192.168.136.200 ,在 lb02 上是主。
① 編輯 lb01 的 Nginx 配置檔案:

[[email protected] conf]# vim nginx.conf          
[[email protected] conf]# cat 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{
   # ip_hash;
   server 192.168.136.150:80  weight=1;
   server 192.168.136.151:80  weight=1;
}
server {
        listen      192.168.136.100:80;
        server_name  www.etiantian.org;
        location / {
          proxy_pass http://www_server_pools;  
     }
}
server {
        listen      192.168.136.200:80;
        server_name  blog.etiantian.org;
        location / {
          proxy_pass http://www_server_pools;
   }
  }    
}

② Nginx 無法啟動的問題:

[[email protected] conf]# pkill nginx
[[email protected] conf]# /application/nginx/sbin/nginx
nginx: [emerg] bind() to 192.168.136.200:80 failed (99: Cannot assign requested address)
[[email protected] conf]# lsof -i :80   #  Nginx 無法啟動。
[[email protected] conf]# ifconfig|egrep 136.200    #  原因:配置檔案監聽了網絡卡上不存在的 IP。
[[email protected] conf]# echo 'net.ipv4.ip_nonlocal_bind = 1' >>/etc/sysctl.conf   # 新增核心引數。
[[email protected] conf]# sysctl -p|grep net.ipv4.ip_nonlocal_bind
net.ipv4.ip_nonlocal_bind = 1   # 啟動 Nginx 時忽略配置中監聽的 VIP 是否存在。
[[email protected] conf]# /application/nginx/sbin/nginx   #  啟動成功。
[[email protected] conf]# lsof -i :80
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   3040  root    6u  IPv4  15768      0t0  TCP www.etiantian.org:http (LISTEN)
nginx   3040  root    7u  IPv4  15769      0t0  TCP 192.168.136.200:http (LISTEN)
nginx   3041 nginx    6u  IPv4  15768      0t0  TCP www.etiantian.org:http (LISTEN)
nginx   3041 nginx    7u  IPv4  15769      0t0  TCP 192.168.136.200:http (LISTEN)     

③ 讓 lb02 伺服器的 Nginx 配置檔案和 lb01 相同:

[[email protected] conf]# vim nginx.conf
[[email protected] conf]# echo 'net.ipv4.ip_nonlocal_bind = 1' >>/etc/sysctl.conf
[[email protected] conf]# sysctl -p|grep net.ipv4.ip_nonlocal_bind
net.ipv4.ip_nonlocal_bind = 1
[[email protected] conf]# pkill nginx
[[email protected] conf]# ../sbin/nginx -t
[[email protected] conf]# ../sbin/nginx

④ 檢視 Keepalilved 配置檔案(多例項):
說明:192.168.136.100 這個 VIP 在 lb01 上是 MASTER,在 lb02 上是 BACKUP;
192.168.136.200 這個 VIP 在 lb02 上是 MASTER,在 lb01 上是 BACKUP;

[[email protected] conf]# cat /etc/keepalived/keepalived.conf   #  lb01 配置。(lb02 略)
   router_id LVS_DEVEL_1
}
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.136.100/24 dev eth0 label eth0:1
    }
}
vrrp_instance VI_2 {
    state BACKUP
    interface eth0
    virtual_router_id 5
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1112
    }
    virtual_ipaddress {
        192.168.136.200/24 dev eth0 label eth0:2
    }
}

⑤ 檢視兩邊執行的 VIP 及Web 伺服器 blog 站點首頁檔案:

[[email protected] conf]# ip add|egrep "136.100|136.200"   #  lb01 提供服務的 VIP 是 100。
    inet 192.168.136.100/24 scope global secondary eth0:1
[[email protected] conf]# ip add|egrep "136.100|136.200"   #  lb02 提供服務的 VIP 是 200。
    inet 192.168.136.200/24 scope global secondary eth0:2
[[email protected] ~]# cat /application/nginx/html/blog/index.html
blog.etiantian.org 150
[[email protected] ~]# cat /application/nginx/html/blog/index.html
blog.etiantian.org 151

⑥ 在負載均衡器測試訪問 blog 站點:

[[email protected] conf]# vim /etc/hosts    # lb02 上面提供服務的 VIP 為 200。
192.168.136.200 blog.etiantian.org
[[email protected] conf]# for n in `seq 10`;do curl blog.etiantian.org;done
blog.etiantian.org 150
blog.etiantian.org 151
blog.etiantian.org 150
blog.etiantian.org 151
blog.etiantian.org 150
blog.etiantian.org 151
blog.etiantian.org 150
blog.etiantian.org 151
blog.etiantian.org 150
blog.etiantian.org 151     

⑦ 在 WINDOWS 上做 hosts 解析並通過瀏覽器測試:
Windows 上的 hosts 解析:

192.168.136.100 www.etiantian.org
192.168.136.200 blog.etiantian.org

通過 ping 域名確保配置可用:

C:\Users\admin>ping blog.etiantian.org -t
正在 Ping blog.etiantian.org [192.168.136.200] 具有 32 位元組的資料
來自 192.168.136.200 的回覆: 位元組=32 時間<1ms TTL=64
來自 192.168.136.200 的回覆: 位元組=32 時間<1ms TTL=64
來自 192.168.136.200 的回覆: 位元組=32 時間<1ms TTL=64
C:\Users\admin>ping www.etiantian.org -t
正在 Ping www.etiantian.org [192.168.136.100] 具有 32 位元組的資料:
來自 192.168.136.100 的回覆: 位元組=32 時間=38ms TTL=64
來自 192.168.136.100 的回覆: 位元組=32 時間<1ms TTL=64
來自 192.168.136.100 的回覆: 位元組=32 時間<1ms TTL=64

通過瀏覽器訪問域名測試:
首先訪問 www.etiantian.org 結果如下:
Keepalived 高可用服務
重新整理後實現負載均衡:
Keepalived 高可用服務
通過訪問 blog.etiantian.org 結果如下:
Keepalived 高可用服務
重新整理後實現負載均衡:
Keepalived 高可用服務
⑧ 把 lb01 停掉,檢視業務執行情況:
關掉後 ping 兩個域名都是能通的:

 C:\Users\admin>ping blog.etiantian.org -t
正在 Ping blog.etiantian.org [192.168.136.200] 具有 32 位元組的資料
來自 192.168.136.200 的回覆: 位元組=32 時間<1ms TTL=64
來自 192.168.136.200 的回覆: 位元組=32 時間<1ms TTL=64
來自 192.168.136.200 的回覆: 位元組=32 時間<1ms TTL=64
C:\Users\admin>ping www.etiantian.org -t
正在 Ping www.etiantian.org [192.168.136.100] 具有 32 位元組的資料:
來自 192.168.136.100 的回覆: 位元組=32 時間=38ms TTL=64
來自 192.168.136.100 的回覆: 位元組=32 時間<1ms TTL=64
來自 192.168.136.100 的回覆: 位元組=32 時間<1ms TTL=64

檢視 lb02 負載均衡器提供服務的 VIP:

[[email protected] conf]# ifconfig|egrep "136.100|36.200"
inet addr:192.168.136.100  Bcast:0.0.0.0  Mask:255.255.255.0  # 該 VIP 飄到 lb02 了。
inet addr:192.168.136.200  Bcast:0.0.0.0  Mask:255.255.255.0

此時通過瀏覽器訪問兩個域名,業務是正常的(結果略)。
⑨ 重新把負載均衡器 lb01 啟動,檢查業務情況:
通過 ping 兩個域名都能 ping 通:

C:\Users\admin>ping blog.etiantian.org -t
正在 Ping blog.etiantian.org [192.168.136.200] 具有 32 位元組的資料
來自 192.168.136.200 的回覆: 位元組=32 時間<1ms TTL=64
來自 192.168.136.200 的回覆: 位元組=32 時間<1ms TTL=64
來自 192.168.136.200 的回覆: 位元組=32 時間<1ms TTL=64
C:\Users\admin>ping www.etiantian.org -t
正在 Ping www.etiantian.org [192.168.136.100] 具有 32 位元組的資料:
來自 192.168.136.100 的回覆: 位元組=32 時間=38ms TTL=64
來自 192.168.136.100 的回覆: 位元組=32 時間<1ms TTL=64
來自 192.168.136.100 的回覆: 位元組=32 時間<1ms TTL=64

此時通過瀏覽器訪問兩個域名,業務是正常的(結果略)。
檢視兩個負載均衡器 VIP 的工作情況:

[[email protected] conf]# ifconfig|egrep "136.100|36.200"  # VIP 100 重新飄回。
inet addr:192.168.136.100  Bcast:0.0.0.0  Mask:255.255.255.0
[[email protected] conf]# ifconfig|egrep "136.100|36.200"   # VIP 200 正常。
inet addr:192.168.136.200  Bcast:0.0.0.0  Mask:255.255.255.0

⑩ 把 lb02 停掉,檢視業務執行情況(同上,略)。
注意:Web 服務可以來回切換,但是資料庫千萬不能用該方式切換,因為把資料庫從主切到備,使用者在備上寫資料,再切回主會導致主從資料庫資料不一致的情況(一般資料庫通過手動切換)。

二、Keepalived 常見故障解決:

伺服器網線鬆動等網路故障;
伺服器硬體故障發生損壞現象而崩潰;
Nginx 服務死掉。
提示:keepalived 是伺服器級別的切換(基於系統的,不是基於軟體的)。

1、問題描述:負載均衡伺服器沒宕機,但 Nginx 服務宕了,如何保證高可用正常切換?
思路:監控 Nginx 服務狀態,如果不正常就停掉 Keepalived 或 halt 關機。
模擬問題場景如下:

[[email protected] conf]# pkill nginx
[[email protected] conf]# lsof -i :80
[[email protected] conf]# ifconfig|egrep "136.100|136.200"
inet addr:192.168.136.100  Bcast:0.0.0.0  Mask:255.255.255.0

此時 www.etiantian.org 域名無法訪問:
Keepalived 高可用服務
方法一:通過守護程序指令碼實現:

[[email protected] scripts]# ps -C nginx
   PID TTY          TIME CMD
  3436 ?        00:00:00 nginx
  3437 ?        00:00:00 nginx
[[email protected] scripts]# ps -C nginx --no-header
  3482 ?        00:00:00 nginx
  3483 ?        00:00:00 nginx
[[email protected] scripts]# ps -C nginx --no-header|wc -l
2
[[email protected] scripts]# pkill nginx
[[email protected] scripts]# ps -C nginx --no-header
[[email protected] scripts]# ps -C nginx --no-header|wc -l
0
[[email protected] scripts]# /application/nginx/sbin/nginx
[[email protected] conf]# mkdir -p /server/scripts/
[[email protected] conf]# cd /server/scripts/      
[[email protected] scripts]# vim check_w_proxy.sh
[[email protected] scripts]# cat check_w_proxy.sh
#!/bin/sh
while true
do
nginxpid=`ps -C nginx --no-header|wc -l`
if [ $nginxpid -eq 0 ];then
   /application/nginx/sbin/nginx
   sleep 5
nginxpid=`ps -C nginx --no-header|wc -l`
if [ $nginxpid -eq 0 ];then
   /etc/init.d/keepalived stop
   exit 1
   fi
fi
   sleep 5
done
[[email protected] scripts]# yum install dos2unix -y
[[email protected] scripts]# dos2unix check_w_proxy.sh
[[email protected] scripts]# sh check_w_proxy.sh &   #  讓指令碼後臺執行。
[1] 3510

測試過程:

[[email protected] scripts]# ps -ef|grep nginx   #  Nginx 服務正常。
root     3482   1  0 23:54 ?    00:00:00 nginx: master process /application/nginx/sbin/nginx
nginx   3483   3482  0 23:54 ?        00:00:00 nginx: worker process
[[email protected] scripts]# ps -ef|grep keepalived  #  Keepalived 服務正常。
root       2622      1  0 18:16 ?        00:00:01 /usr/sbin/keepalived -D
root       2624   2622  0 18:16 ?        00:00:01 /usr/sbin/keepalived -D
root       2625   2622  0 18:16 ?        00:00:12 /usr/sbin/keepalived -D
root       3618   3087  0 23:59 pts/1    00:00:00 grep keepalived
[[email protected] scripts]# ifconfig|egrep "136.100|136.200"   #  VIP 100 工作正常。
inet addr:192.168.136.100  Bcast:0.0.0.0  Mask:255.255.255.0
[[email protected] scripts]# pkill nginx   #  殺掉 Nginx 服務程序。
[[email protected] scripts]# ifconfig|egrep "136.100|136.200"   #  VIP 沒有飄移。
inet addr:192.168.136.100  Bcast:0.0.0.0  Mask:255.255.255.0
[[email protected] scripts]# ps -ef|grep nginx  #  檢視 Nginx 服務程序(腳本里啟動了 Nginx)。              
root       3772      1  0 00:02 ?        00:00:00 nginx: master process /application/nginx/sbin/nginx
nginx      3774   3772  0 00:02 ?        00:00:00 nginx: worker process        
root       3786   3087  0 00:02 pts/1    00:00:00 grep nginx

編輯上面的指令碼讓 Nginx 不嘗試啟動:

[[email protected] scripts]# vim check_w_proxy.sh
[[email protected] scripts]# cat check_w_proxy.sh    #  註釋掉啟動 Nginx 的內容。
#!/bin/sh
while true
do
nginxpid=`ps -C nginx --no-header|wc -l`
if [ $nginxpid -eq 0 ];then
#   /application/nginx/sbin/nginx
#   sleep 5
# nginxpid=`ps -C nginx --no-header|wc -l`
# if [ $nginxpid -eq 0 ];then
   /etc/init.d/keepalived stop
   exit 1
   fi
# fi
   sleep 5
done

重新執行該指令碼:

[[email protected] scripts]# ps -ef|grep check  #  檢視該守護程序。
root       3510   3087  0 Jun23 pts/1    00:00:00 sh check_w_proxy.sh
[[email protected] scripts]# jobs   #  檢視後臺執行的程式。
[1]+  Running      sh check_w_proxy.sh &
[[email protected] scripts]# fg   #  拿到前臺執行。
sh check_w_proxy.sh   
^C    #  通過 Ctrl + c 停止該程式的執行。
[[email protected] scripts]# sh check_w_proxy.sh &  # 再讓指令碼後臺執行。
[1] 4178
[[email protected] scripts]# ps -ef|grep nginx|grep -v grep  #  Nginx 是執行狀態。
root       3772      1  0 00:02 ?        00:00:00 nginx: master process /application/nginx/sbin/nginx
nginx      3774   3772  0 00:02 ?        00:00:00 nginx: worker process  
[[email protected] scripts]# ifconfig|egrep "136.100|136.200"   #  VIP 工作正常。
inet addr:192.168.136.100  Bcast:0.0.0.0  Mask:255.255.255.0
[[email protected] scripts]# pkill nginx   #  殺掉 Nginx 程序。
[[email protected] scripts]# Stopping keepalived:     [  OK  ]   #  守護程序自動關閉 Keepalived。
[1]+  Exit 1                  sh check_w_proxy.sh
[[email protected] scripts]# ps -ef|grep nginx   #  檢視 Nginx 程序(沒有了)。
root       4374   3087  0 00:16 pts/1    00:00:00 grep nginx
[[email protected] scripts]# ps -ef|grep nginx|grep -v grep
[[email protected] scripts]# ifconfig|egrep "136.100|136.200"   #  VIP 沒有了。

到 lb02 檢視 VIP 漂移的情況:

[[email protected] conf]# ifconfig|egrep "136.100|136.200"  #  VIP 飄到了 lb02 上提供服務。
inet addr:192.168.136.100  Bcast:0.0.0.0  Mask:255.255.255.0
inet addr:192.168.136.200  Bcast:0.0.0.0  Mask:255.255.255.0

此時業務也迴歸正常了:
Keepalived 高可用服務
Keepalived 高可用服務
方法二:Keepalived 配置觸發:
① 修改 Keepalived 配置檔案:

[[email protected] scripts]# cat /etc/keepalived/keepalived.conf    
! Configuration File for keepalived
global_defs {
   notification_email {
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL_1
}

vrrp_script check_w_proxy {   # 定義 VRRP 指令碼檢查 Nginx 程序號。
script "/server/scripts/check_w_proxy.sh"   #  當 Nginx 有問題就執行指令碼停掉 Keepailved。
interval 2   #  間隔時間 2s 。
weight 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.136.100/24 dev eth0 label eth0:1
    }
    track_script {    #  放到哪個例項哪個例項就進行觸發。
     check_w_proxy  #  觸發檢查。
       }
  }

vrrp_instance VI_2 {
    state BACKUP
    interface eth0
    virtual_router_id 5
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1112
    }
    virtual_ipaddress {
        192.168.136.200/24 dev eth0 label eth0:2
    }
}

② 重啟並測試配置結果:

[[email protected] scripts]# /application/nginx/sbin/nginx    #  啟動 Nginx。
[[email protected] scripts]# /etc/init.d/keepalived stop   # 關閉 Keepalived 服務。
Stopping keepalived:           [  OK  ]
[[email protected] scripts]# /etc/init.d/keepalived start   # 啟動 Keepalived 服務。
Starting keepalived:             [  OK  ]
[[email protected] scripts]# chmod +x check_w_proxy.sh   #  給指令碼加執行許可權。
[[email protected] scripts]# ps -ef|grep nginx|grep -v grep  #  Nginx 服務正常。
root       4485      1  0 00:40 ?        00:00:00 nginx: master process /application/nginx/sbin/nginx
nginx      4486   4485  0 00:40 ?        00:00:00 nginx: worker process  
[[email protected] scripts]# ifconfig|egrep "136.100|136.200"  #  VIP 工作正常。
inet addr:192.168.136.100  Bcast:0.0.0.0  Mask:255.255.255.0

③ 正常情況下殺掉 Nginx 後 Keepalived 會停掉,VIP 飄移到 lb02上面:

[[email protected] ~]# ip add|grep 136.100    #  lb01 上的 VIP 正常工作。       
    inet 192.168.136.100/24 scope global secondary eth0:1
[[email protected] ~]# pkill nginx     #  殺掉 Nginx 程序。                 
[[email protected] ~]# ps -ef|grep keepalived|grep -v grep   #  觸發指令碼關掉了 Keepalived 服務。    
[[email protected] ~]# ip add|grep 136.100    #  lb01 上的 VIP 沒有了(漂移到 lb02 了)。       
[[email protected] scripts]# ip add|egrep "136.100|136.200"   #  LB02 接替 lb01 的工作,VIP 飄過來。                               
inet 192.168.136.200/24 scope global secondary eth0:2
inet 192.168.136.100/24 scope global secondary eth0:1
[[email protected] ~]# /application/nginx/sbin/nginx   #  重新啟動 Nginx 服務。
[[email protected] ~]# /etc/init.d/keepalived start       #  重新啟動 Keepalived 服務。
Starting keepalived:                     [  OK  ]
[[email protected] ~]# ip add|grep 136.100      #  lb01 上的 VIP 恢復了正常工作。        
    inet 192.168.136.100/24 scope global secondary eth0:1
[[email protected] scripts]# ip add|egrep "136.100|136.200"  #  lb02 恢復正常工作狀態。   
    inet 192.168.136.200/24 scope global secondary eth0:2

2、多組 Keepalived 伺服器在一個區域網的衝突問題:
當在同一個區域網內部署了多組 Keepalived 伺服器對,而又未使用專門的心跳線通訊時,可能會發生高可用接管的嚴重故障問題。Keepalived 高可用功能是通過 VRRP 協議實現的,VRRP 協議預設通過 IP 多播的形式實現高可用對之間的通訊,如果同一個區域網記憶體在多組 Keepalived 伺服器對,就會造成 IP 多播地址衝突問題,導致接管錯亂,不同組的 Keepalived 都會使用預設的 224.0.0.
18 作為多播地址。此時的解決辦法是在同組的 Keepalived 伺服器所有的配置檔案裡指定獨一無二的多播地址,配置如下:

global_defs  {
   route_id LVS_19
   vrrp_mcast_group4 224.0.0.19      #  這個就是指定多播地址的配置。
}

3、配置指定檔案接收 Keepalived 服務日誌:
預設情況下 Keepalived 服務日誌會輸出到系統日誌 /var/log/message,和其他日誌資訊混合在一起很不方便,可以將其調整成獨立的檔案記錄 Keepalived 服務日誌。

[[email protected] scripts]# tailf /var/log/messages
Jun 24 01:01:32 lb01 Keepalived[5896]: Stopping Keepalived v1.2.13 (03/19,2015)
Jun 24 01:01:32 lb01 Keepalived_vrrp[5899]: VRRP_Instance(VI_1) sending 0 priority
Jun 24 01:01:32 lb01 Keepalived_vrrp[5899]: VRRP_Instance(VI_1) removing protocol VIPs.
Jun 24 01:01:32 lb01 Keepalived_healthcheckers[5898]: Netlink reflector reports IP 192.168.136.100 removed

配置指定檔案記錄 Keepalived 服務日誌操作步驟:
① 編輯檔案 /etc/sysconfig/keepalived 如下:

KEEPALIVED_OPTIONS="-D -d -S 0"
[[email protected] scripts]# less /etc/sysconfig/keepalived   #  檢視配置引數的詳細資訊。
# --vrrp               -P    Only run with VRRP subsystem.
# --check              -C    Only run with Health-checker subsystem.
# --dont-release-vrrp  -V    Dont remove VRRP VIPs & VROUTEs on daemon stop.
# --dont-release-ipvs  -I    Dont remove IPVS topology on daemon stop.
# --dump-conf          -d    Dump the configuration data.   #  匯出資料。
# --log-detail         -D    Detailed log messages.    #  詳細日誌。
# --log-facility       -S    0-7 Set local syslog facility (default=LOG_DAEMON)   #  指定裝置。
KEEPALIVED_OPTIONS="-D -d -S 0"
[[email protected] scripts]# sed -i '14 s#KEEPALIVED_OPTIONS="-D"#KEEPALIVED_OPTIONS="-D -d -S 0"#g' /etc/sysconfig/keepalived   #  修改內容。
[[email protected] scripts]# sed -n '14p' /etc/sysconfig/keepalived
KEEPALIVED_OPTIONS="-D -d -S 0"

② 修改 /etc/rsyslog.conf 檔案新增如下內容:

[[email protected] scripts]# tail -3  /etc/rsyslog.conf
# keepalived
local0.*          /var/log/keepalived.log
# ### end of the forwarding rule ###
[[email protected] scripts]# /etc/init.d/rsyslog restart   # 重啟 rsyslog。
Shutting down system logger:                [  OK  ]
Starting system logger:                          [  OK  ]
[[email protected] scripts]# cat /var/log/keepalived.log
[[email protected] scripts]# /etc/init.d/keepalived restart
Stopping keepalived:                             [FAILED]
Starting keepalived:                               [  OK  ]
[[email protected] scripts]# cat /var/log/keepalived.log   #  生成 Keepalived 日誌內容。
Jun 24 01:49:27 lb01 Keepalived[6057]: Starting Keepalived v1.2.13 (03/19,2015)
Jun 24 01:49:27 lb01 Keepalived[6058]: Starting Healthcheck child process, pid=6060
Jun 24 01:49:27 lb01 Keepalived[6058]: Starting VRRP child process, pid=6061
 。。。。。。。。。。。。省略若干內容。。。。。。。。。。。。。

③ 讓 /var/log/message 不記錄 Keepalived 日誌:【local0.none】

[[email protected] scripts]# vim /etc/rsyslog.conf
[[email protected] scripts]# sed -n '42p' /etc/rsyslog.conf
*.info;mail.none;authpriv.none;cron.none;local0.none       /var/log/messages
[[email protected] scripts]# /etc/init.d/rsyslog restart   
Shutting down system logger:              [  OK  ]
Starting system logger:                        [  OK  ]
[[email protected] scripts]# > /var/log/messages   #  清空系統日誌。
[[email protected] scripts]# > /var/log/keepalived.log    #  清空 Keepalived 日誌。
[[email protected] scripts]# /etc/init.d/keepalived restart
Stopping keepalived:                           [  OK  ]
Starting keepalived:                             [  OK  ]
[[email protected] scripts]# cat /var/log/messages   #  系統日誌為空(不再記錄 Keepalived 日誌)。
[[email protected] scripts]# cat /var/log/keepalived.log    
# 只有配置的 Keepalived 日誌檔案記錄 Keepalived 的日誌。
Jun 24 02:00:47 lb01 Keepalived[6058]: Stopping Keepalived v1.2.13 (03/19,2015)
Jun 24 02:00:47 lb01 Keepalived_vrrp[6061]: VRRP_Instance(VI_1) sending 0 priority
Jun 24 02:00:47 lb01 Keepalived_vrrp[6061]: VRRP_Instance(VI_1) removing protocol VIPs
```.
**4、Keepalived 高可用伺服器對裂腦問題:**      
**什麼是裂腦:**
        由於某些原因,導致兩臺高可用伺服器對在指定時間內,無法檢測到對方的心跳資訊,各自取得資源及服務的所有權,而此時的兩臺高可用伺服器對都還活著並在正常執行,這樣就會導致同一個 IP 或服務在兩端同時存在而發生衝突,最嚴重的是兩臺主機佔用同一個 VIP 地址,每當使用者寫入資料時可能會分別寫入到兩端,這可能會導致伺服器兩端的資料不一致或資料丟失,這種情況被稱為裂腦。
**列腦發生的原因:**
① 高可用伺服器對之間心跳線鏈路故障,導致無法正常通訊:
        心跳線壞了(斷掉、老化);
        網絡卡及相關驅動壞了,IP 配置及衝突問題(網絡卡直連);
        心跳間連線的裝置故障(網絡卡及交換機);
        仲裁的機器出問題(採用仲裁的方案)。
② 高可用伺服器對上開啟了 iptables 防火牆阻擋了心跳訊息傳輸:
③  高可用伺服器對上心跳網絡卡地址等資訊配置不正確,導致傳送心跳失敗:
④ 其他服務配置不當等原因,如心跳方式不同,心跳廣播衝突、軟體 Bug 等。
提示:Keepalived 配置統一 VRRP 例項,如果 virtual_route_id 引數兩端配置不一致也會導致裂腦。 
**避免裂腦問題的常見方法:**
① 同時使用序列電纜和乙太網電纜連線,同時用兩條心跳線路,這樣一條線路壞了,另一個還是好的,依然能傳送心跳資訊;
② 當檢測到裂腦時強行關閉一個心跳節點(這個功能需要特殊裝置,如 Stonith、Fence)。相當於裝置節點接收不到心跳資訊,傳送關機命令通過單獨的線路關閉主節點的電源;【Stonith:Shoot the other node in the head(爆頭,關掉另一個節點)】。
③ 做好對裂腦的監控報警(如郵件及手機簡訊等或值班),在問題發生時人為第一時間介入仲裁,降低損失。例如:百度的監控報警簡訊就有上行和下行的區別。報警資訊報到管理員手機上,管理員可以通過手機回覆對應數字或簡單的字串操作返回給伺服器,讓伺服器根據指令自動處理相應故障,這樣解決故障的時間更短。
        當然,在實施高可用方案時,要根據實際業務確定是否能容忍這樣的損失,根據不同的需求選擇不同的解決方案(一般網站的常規業務,這個損失是可容忍的)。
**常見的解決裂腦的方案:**
        作為網際網路應用伺服器的高可用,特別是前端 Web 負載均衡器的高可用,裂腦的問題對普通業務的影響是可以忍受的,如果是資料庫或者儲存的業務,一般出現裂腦問題就非常嚴重了。因此可以通過增加冗餘心跳線路來避免裂腦問題的發生,同時加強對系統的監控,以便裂腦發生時人為快速介入解決問題。
① 如果開啟 iptables 防火牆,一定要讓心跳訊息通過,一般通過允許 IP 段的方式解決;
② 可以拉一條乙太網網線或者串列埠線作為主備節點心跳線路的冗餘;
③ 開發檢測程式通過監控軟體(例如 Nagios)監控裂腦。
生產場景檢測裂腦的思路:
① 簡單判斷的思想:只要備節點出現 VIP 就報警,這個報警有兩種情況,一是主機宕機備機接管了;二十主機沒宕,裂腦了,無論哪種情況,都進行報警,然後由人工檢視判斷及解決。
② 比較嚴禁的判斷:備節點出現對應 VIP,並且主節點及對應服務(如果遠端連線主節點看是否有 VIP 就更好了)還活著,就說明裂腦了。
在備節點開發指令碼測試是否發生裂腦問題:

[[email protected] conf]# cd /server/scripts/
[[email protected] scripts]# vim check_split_brain.sh
[[email protected] scripts]# cat check_split_brain.sh
#!/bin/sh
lb01_vip=192.168.136.100
lb01_ip=192.168.136.161
while true
do
ping -c 2 -W 3 $lb01_ip &>/dev/null
if [ $? -e