一、Keepalived 軟件介紹:
Keeplived 軟件起初就是專爲 LVS 負載均衡軟件設計的,用來管理並監控 LVS 集羣系統中各個服務器節點的狀態,後來又加入了能夠實現高可用的 VRRP 功能。所以 Keepalived 除了可以管理 LVS 軟件外,還能夠做爲其餘服務(Nginx、Haproxy、MySQL 等)的高可用解決方案軟件。
Keeplived 軟件主要是經過 VRRP 協議實現高可用功能的,VRRP 出現的目的就是爲了解決靜態路由單點故障問題的,它可以保證當個別節點宕機時,整個網絡能夠不間斷的運行,因此 Keepalived 一方面具備配置管理 LVS 的功能,同時還具備對 LVS 下面節點進行健康檢查的功能,另外一方面也可實現系統網絡服務的高可用性。
Keeplived 軟件的官方網站是 http://www.keepalived.org。
二、Keeplived 高可用故障切換轉移原理:
Keeplived 高可用服務對之間的故障切換轉移,是經過 VRRP 協議(Virtual Router Redundancy Protocol,中文意思:虛擬路由器冗餘協議)來實現的。
在 Keepailved 服務正常工做時,主 Master 節點會不斷地向備節點發送(多播的方式)心跳消息,用以告訴備 Backup 節點本身還活着,當主 Master 節點發生故障時,就沒法發送心跳信息了,備節點也就所以沒法繼續監測到來自主 Master 節點的心跳了,進而調用自身的接管程序,接管主 Master 節點的 IP 資源及服務。而當主 Master 節點恢復時,備 Bacckup 節點又會釋放主節點故障時自身接管的 IP 資源及服務,恢復到原來的備用角色。
三、企業面試題:簡要回答 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 秒。
四、keepalived 高可用服務搭建:
1)、搭建環境準備:
2)、Keepalived 軟件安裝:
a、在兩臺負載均衡服務器安裝 Keepalived 軟件:html
[root@lb01 ~]# yum install keepalived -y [root@lb01 ~]# rpm -qa keepalived keepalived-1.2.13-5.el6_6.x86_64
b、在兩臺負載均衡服務器啓動 Keepalived 軟件:前端
[root@lb01 ~]# /etc/init.d/keepalived start Starting keepalived: [ OK ] [root@lb01 ~]# 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 的兩種方式:node
① 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 了。 [root@lb01 ~]# ip addr add 192.168.153.100/24 dev eth0 label eth0:1 [root@lb01 ~]# ip add|grep 153.100 inet 192.168.153.100/24 scope global secondary eth0:1
d、編輯 Keepalived 配置文件:ios
[root@lb01 ~]# man keepalived.conf # Keepalived 配置文件有三個部分。 TOP HIERACHY GLOBAL CONFIGURATION # 全局配置 VRRPD CONFIGURATION # VRRP 的配置 LVS CONFIGURATION # 結合 LVS 的配置
[root@lb01 ~]# vim /etc/keepalived/keepalived.conf 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 # 路由 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 節點特殊參數的不一樣:
3)、此時查看兩臺服務器上面的虛擬 IP:nginx
在主節點查看虛擬 IP 的存在: [root@lb01 ~]# ip add|grep 153.100 # 主 Master 節點有添加的虛擬 IP(優先級高)。 inet 192.168.153.100/24 scope global secondary eth0:1 在備節點查看虛擬 IP 的存在: [root@lb02 ~]# ip add |grep 153.100 # 備 Backup 節點沒有(主正常,備等待)。
4)、以 Windows爲客戶端測試主備節點的高可用:
① 經過 Windows 客戶端連續 ping 虛擬 IP:
② 此時在主節點能夠看到虛擬 IP :面試
[root@lb01 ~]# ip add|grep 192.168.136.100 inet 192.168.136.100/24 scope global secondary eth0:1
③ 關掉主節點的 Keepalived 服務:數據庫
[root@lb01 ~]# /etc/init.d/keepalived stop Stopping keepalived: [ OK ]
④ 查看備節點的虛擬 IP(備接管主的工做):vim
[root@lb02 ~]# ip add|grep 192.168.136.100 inet 192.168.136.100/24 scope global secondary eth0:1
⑤ 啓動主節點的 Keepalived 服務並查看虛擬 IP :瀏覽器
[root@lb01 ~]# /etc/init.d/keepalived start Starting keepalived: [ OK ] [root@lb01 ~]# ip add|grep 192.168.136.100 # 略有延遲,編譯安裝快? inet 192.168.136.100/24 scope global secondary eth0:1
5)、Keepalived 多實例的配置及實現:
首先添加另外一個虛擬 IP :[root@lb01 ~]# 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 不一樣實例不一樣,網卡標籤不一樣。 } }
③ 重啓兩臺服務器使配置生效:
[root@lb01 ~]# /etc/init.d/keepalived restart Stopping keepalived: [ OK ] Starting keepalived: [ OK ] [root@lb02 ~]# /etc/init.d/keepalived restart Stopping keepalived: [ OK ] Starting keepalived: [ OK ]
④ 經過查看虛擬 IP 測試多實例的生效:
[root@lb01 ~]# ip add|egrep "153.100|153.200" # 實例一優先級高的是 lb01,因此 VIP 100存在。 inet 192.168.153.100/24 scope global secondary eth0:1 [root@lb02 ~]# ip add |egrep "153.100|153.200" # 實例二優先級高的是 lb02,因此 VIP 200存在。 inet 192.168.153.200/24 scope global secondary eth0:2
關閉 lb01 服務器的 Keepalived 服務:
[root@lb01 ~]# /etc/init.d/keepalived stop Stopping keepalived: [ OK ] [root@lb01 ~]# ip add |egrep "153.100|153.200" # 此時該服務器沒有 VIP 在工做了。 [root@lb02 ~]# 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 服務:
[root@lb01 ~]# /etc/init.d/keepalived start Starting keepalived: [ OK ] [root@lb01 ~]# ip add|egrep "153.100|153.200" # 實例一優先級高的是 lb01,因此 VIP 100存在。 inet 192.168.153.100/24 scope global secondary eth0:1 [root@lb02 ~]# ip add |egrep "153.100|153.200" # 實例二優先級高的是 lb02,因此 VIP 200存在。 inet 192.168.153.200/24 scope global secondary eth0:2
關閉 lb02 服務器的 Keepalived 服務:
[root@lb02 ~]# /etc/init.d/keepalived stop Stopping keepalived: [ OK ] [root@lb02 ~]# ip add |egrep "153.100|153.200" # 此時該服務器沒有 VIP 在工做了。 [root@lb01 ~]# 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
五、Keepalived 配合 Nginx 負載均衡實現高可用:
方案一:兩臺負載同時啓動 Nginx 代理,Keepalived 負責 VIP 漂移,VIP 漂移到哪一個機器哪一個就提供訪問:
① 檢查環境:
兩臺 Nginx 負載均衡器的 Keepalived 服務和 Nginx 服務都是開啓狀態:
[root@lb01 ~]# /etc/init.d/keepalived status keepalived (pid 2622) is running... [root@lb02 ~]# /etc/init.d/keepalived status keepalived (pid 2622) is running... [root@lnmp01 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 [root@lnmp02 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 服務器的配置文件:
[root@lb01 conf]# pwd /application/nginx/conf [root@lb01 conf]# vim nginx.conf [root@lb01 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 站點首頁文件:
[root@lnmp01 ~]# cat /application/nginx/html/www/index.html www.etiantian.org 150 [root@lnmp02 ~]# cat /application/nginx/html/www/index.html www.etiantian.org 151
④ 修改負載均衡服務器 hosts 並 curl 訪問 Web 服務器:
[root@lb01 conf]# vim /etc/hosts [root@lb01 conf]# cat /etc/hosts 192.168.153.100 www.etiantian.org # 將域名解析到虛擬 IP。
[root@lb01 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 配置文件一致:
[root@lb02 conf]# cd /application/nginx/conf/ [root@lb02 conf]# vim nginx.conf # 跟以上配置一致。 [root@lb02 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 [root@lb02 conf]# ../sbin/nginx -s reload
測試 lb02 負載均衡器的工做是否正常:
[root@lb02 conf]# tail -1 /etc/hosts 192.168.136.162 www.etiantian.org # 備節點沒有 VIP,因此解析到本身的 IP 測試。
[root@lb02 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 的首頁文件:
刷新後訪問到 Web 02 的首頁文件:
⑦ 此時讓 LB01 宕機,再訪問,業務不受影響:
緣由:VIP 飄到 LB 02 服務器了,lb 02 接管工做,以下:
[root@lb02 conf]# ip add|egrep 136.100 inet 192.168.136.100/24 scope global secondary eth0:1
⑧ 開啓 LB01 服務器,再訪問,業務不受影響,VIP 從新飄回LB01:
[root@lb01 conf]# ip add|egrep 136.100 inet 192.168.136.100/24 scope global secondary eth0:1 [root@lb02 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 配置文件:
[root@lb01 conf]# vim nginx.conf [root@lb01 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 沒法啓動的問題:
[root@lb01 conf]# pkill nginx [root@lb01 conf]# /application/nginx/sbin/nginx nginx: [emerg] bind() to 192.168.136.200:80 failed (99: Cannot assign requested address) [root@lb01 conf]# lsof -i :80 # Nginx 沒法啓動。 [root@lb01 conf]# ifconfig|egrep 136.200 # 緣由:配置文件監聽了網卡上不存在的 IP。 [root@lb01 conf]# echo 'net.ipv4.ip_nonlocal_bind = 1' >>/etc/sysctl.conf # 添加內核參數。 [root@lb01 conf]# sysctl -p|grep net.ipv4.ip_nonlocal_bind net.ipv4.ip_nonlocal_bind = 1 # 啓動 Nginx 時忽略配置中監聽的 VIP 是否存在。 [root@lb01 conf]# /application/nginx/sbin/nginx # 啓動成功。 [root@lb01 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 相同:
[root@lb02 conf]# vim nginx.conf [root@lb02 conf]# echo 'net.ipv4.ip_nonlocal_bind = 1' >>/etc/sysctl.conf [root@lb02 conf]# sysctl -p|grep net.ipv4.ip_nonlocal_bind net.ipv4.ip_nonlocal_bind = 1 [root@lb02 conf]# pkill nginx [root@lb02 conf]# ../sbin/nginx -t [root@lb02 conf]# ../sbin/nginx
④ 查看 Keepalilved 配置文件(多實例):
說明:192.168.136.100 這個 VIP 在 lb01 上是 MASTER,在 lb02 上是 BACKUP;
192.168.136.200 這個 VIP 在 lb02 上是 MASTER,在 lb01 上是 BACKUP;
[root@lb01 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 站點首頁文件:
[root@lb01 conf]# ip add|egrep "136.100|136.200" # lb01 提供服務的 VIP 是 100。 inet 192.168.136.100/24 scope global secondary eth0:1 [root@lb02 conf]# ip add|egrep "136.100|136.200" # lb02 提供服務的 VIP 是 200。 inet 192.168.136.200/24 scope global secondary eth0:2
[root@lnmp01 ~]# cat /application/nginx/html/blog/index.html blog.etiantian.org 150 [root@lnmp02 ~]# cat /application/nginx/html/blog/index.html blog.etiantian.org 151
⑥ 在負載均衡器測試訪問 blog 站點:
[root@lb02 conf]# vim /etc/hosts # lb02 上面提供服務的 VIP 爲 200。 192.168.136.200 blog.etiantian.org
[root@lb02 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 結果以下:
刷新後實現負載均衡:
經過訪問 blog.etiantian.org 結果以下:
刷新後實現負載均衡:
⑧ 把 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:
[root@lb02 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 的工做狀況:
[root@lb01 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 [root@lb02 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 服務能夠來回切換,可是數據庫千萬不能用該方式切換,由於把數據庫從主切到備,用戶在備上寫數據,再切回主會致使主從數據庫數據不一致的狀況(通常數據庫經過手動切換)。
服務器網線鬆動等網絡故障; 服務器硬件故障發生損壞現象而崩潰; Nginx 服務死掉。 提示:keepalived 是服務器級別的切換(基於系統的,不是基於軟件的)。
一、問題描述:負載均衡服務器沒宕機,但 Nginx 服務宕了,如何保證高可用正常切換?
思路:監控 Nginx 服務狀態,若是不正常就停掉 Keepalived 或 halt 關機。
模擬問題場景以下:
[root@lb01 conf]# pkill nginx [root@lb01 conf]# lsof -i :80 [root@lb01 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 域名沒法訪問:
方法一:經過守護進程腳本實現:
[root@lb01 scripts]# ps -C nginx PID TTY TIME CMD 3436 ? 00:00:00 nginx 3437 ? 00:00:00 nginx [root@lb01 scripts]# ps -C nginx --no-header 3482 ? 00:00:00 nginx 3483 ? 00:00:00 nginx [root@lb01 scripts]# ps -C nginx --no-header|wc -l 2
[root@lb01 scripts]# pkill nginx [root@lb01 scripts]# ps -C nginx --no-header [root@lb01 scripts]# ps -C nginx --no-header|wc -l 0
[root@lb01 scripts]# /application/nginx/sbin/nginx [root@lb01 conf]# mkdir -p /server/scripts/ [root@lb01 conf]# cd /server/scripts/ [root@lb01 scripts]# vim check_w_proxy.sh [root@lb01 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
[root@lb01 scripts]# yum install dos2unix -y [root@lb01 scripts]# dos2unix check_w_proxy.sh [root@lb01 scripts]# sh check_w_proxy.sh & # 讓腳本後臺運行。 [1] 3510
測試過程:
[root@lb01 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 [root@lb01 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 [root@lb01 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
[root@lb01 scripts]# pkill nginx # 殺掉 Nginx 服務進程。 [root@lb01 scripts]# ifconfig|egrep "136.100|136.200" # VIP 沒有飄移。 inet addr:192.168.136.100 Bcast:0.0.0.0 Mask:255.255.255.0 [root@lb01 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 不嘗試啓動:
[root@lb01 scripts]# vim check_w_proxy.sh [root@lb01 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
從新執行該腳本:
[root@lb01 scripts]# ps -ef|grep check # 查看該守護進程。 root 3510 3087 0 Jun23 pts/1 00:00:00 sh check_w_proxy.sh [root@lb01 scripts]# jobs # 查看後臺執行的程序。 [1]+ Running sh check_w_proxy.sh & [root@lb01 scripts]# fg # 拿到前臺執行。 sh check_w_proxy.sh ^C # 經過 Ctrl + c 中止該程序的運行。 [root@lb01 scripts]# sh check_w_proxy.sh & # 再讓腳本後臺運行。 [1] 4178 [root@lb01 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 [root@lb01 scripts]# ifconfig|egrep "136.100|136.200" # VIP 工做正常。 inet addr:192.168.136.100 Bcast:0.0.0.0 Mask:255.255.255.0
[root@lb01 scripts]# pkill nginx # 殺掉 Nginx 進程。 [root@lb01 scripts]# Stopping keepalived: [ OK ] # 守護進程自動關閉 Keepalived。 [1]+ Exit 1 sh check_w_proxy.sh [root@lb01 scripts]# ps -ef|grep nginx # 查看 Nginx 進程(沒有了)。 root 4374 3087 0 00:16 pts/1 00:00:00 grep nginx [root@lb01 scripts]# ps -ef|grep nginx|grep -v grep [root@lb01 scripts]# ifconfig|egrep "136.100|136.200" # VIP 沒有了。
到 lb02 查看 VIP 漂移的狀況:
[root@lb02 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 配置文件:
[root@lb01 scripts]# 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_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 } }
② 重啓並測試配置結果:
[root@lb01 scripts]# /application/nginx/sbin/nginx # 啓動 Nginx。 [root@lb01 scripts]# /etc/init.d/keepalived stop # 關閉 Keepalived 服務。 Stopping keepalived: [ OK ] [root@lb01 scripts]# /etc/init.d/keepalived start # 啓動 Keepalived 服務。 Starting keepalived: [ OK ] [root@lb01 scripts]# chmod +x check_w_proxy.sh # 給腳本加執行權限。 [root@lb01 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 [root@lb01 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上面:
[root@lb01 ~]# ip add|grep 136.100 # lb01 上的 VIP 正常工做。 inet 192.168.136.100/24 scope global secondary eth0:1 [root@lb01 ~]# pkill nginx # 殺掉 Nginx 進程。 [root@lb01 ~]# ps -ef|grep keepalived|grep -v grep # 觸發腳本關掉了 Keepalived 服務。 [root@lb01 ~]# ip add|grep 136.100 # lb01 上的 VIP 沒有了(漂移到 lb02 了)。 [root@lb02 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 [root@lb01 ~]# /application/nginx/sbin/nginx # 從新啓動 Nginx 服務。 [root@lb01 ~]# /etc/init.d/keepalived start # 從新啓動 Keepalived 服務。 Starting keepalived: [ OK ] [root@lb01 ~]# ip add|grep 136.100 # lb01 上的 VIP 恢復了正常工做。 inet 192.168.136.100/24 scope global secondary eth0:1 [root@lb02 scripts]# ip add|egrep "136.100|136.200" # lb02 恢復正常工做狀態。 inet 192.168.136.200/24 scope global secondary eth0: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 # 這個就是指定多播地址的配置。 }
三、配置指定文件接收 Keepalived 服務日誌:
默認狀況下 Keepalived 服務日誌會輸出到系統日誌 /var/log/message,和其餘日誌信息混合在一塊兒很不方便,能夠將其調整成獨立的文件記錄 Keepalived 服務日誌。
[root@lb01 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" [root@lb01 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" [root@lb01 scripts]# sed -i '14 s#KEEPALIVED_OPTIONS="-D"#KEEPALIVED_OPTIONS="-D -d -S 0"#g' /etc/sysconfig/keepalived # 修改內容。 [root@lb01 scripts]# sed -n '14p' /etc/sysconfig/keepalived KEEPALIVED_OPTIONS="-D -d -S 0"
② 修改 /etc/rsyslog.conf 文件添加以下內容:
[root@lb01 scripts]# tail -3 /etc/rsyslog.conf # keepalived local0.* /var/log/keepalived.log # ### end of the forwarding rule ###
[root@lb01 scripts]# /etc/init.d/rsyslog restart # 重啓 rsyslog。 Shutting down system logger: [ OK ] Starting system logger: [ OK ] [root@lb01 scripts]# cat /var/log/keepalived.log [root@lb01 scripts]# /etc/init.d/keepalived restart Stopping keepalived: [FAILED] Starting keepalived: [ OK ] [root@lb01 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】
[root@lb01 scripts]# vim /etc/rsyslog.conf [root@lb01 scripts]# sed -n '42p' /etc/rsyslog.conf *.info;mail.none;authpriv.none;cron.none;local0.none /var/log/messages [root@lb01 scripts]# /etc/init.d/rsyslog restart Shutting down system logger: [ OK ] Starting system logger: [ OK ] [root@lb01 scripts]# > /var/log/messages # 清空系統日誌。 [root@lb01 scripts]# > /var/log/keepalived.log # 清空 Keepalived 日誌。 [root@lb01 scripts]# /etc/init.d/keepalived restart Stopping keepalived: [ OK ] Starting keepalived: [ OK ] [root@lb01 scripts]# cat /var/log/messages # 系統日誌爲空(再也不記錄 Keepalived 日誌)。
[root@lb01 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 ```. **四、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 就更好了)還活着,就說明裂腦了。 在備節點開發腳本測試是否發生裂腦問題:
[root@lb01 conf]# cd /server/scripts/
[root@lb01 scripts]# vim check_split_brain.sh
[root@lb01 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 [ $? -eq 0 -a ip add|grep "$lb01_vip"|wc -l
-eq 1 ]thenecho "Ha is split brain.Warning."elseecho "Ha is OK"fisleep 5done[root@lb02 scripts]# sh check_split_brain.sh # 執行腳本檢查結果。Ha is OKHa is OK