Keepalived 高可用服務
一、Keepalived 詳解配置
1、Keepalived 軟體介紹:
Keeplived 軟體起初就是專為 LVS 負載均衡軟體設計的,用來管理並監控 LVS 集群系統中各個伺服器節點的狀態,後來又加入了可以實現高可用的 VRRP 功能。因此 Keepalived 除了能夠管理 LVS 軟體外,還可以作為其他服務(Nginx、Haproxy、MySQL 等)的高可用解決方案軟體。
Keeplived 軟體主要是通過 VRRP 協議實現高可用功能的,VRRP 出現的目的就是為了解決靜態路由單點故障問題的,它能夠保證當個別節點宕機時,整個網路可以不間斷的執行,所以 Keepalived 一方面具有配置管理 LVS 的功能,同時還具有對 LVS 下面節點進行健康檢查的功能,另一方面也可實現系統網路服務的高可用性。
Keeplived 軟體的官方網站是
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)、搭建環境準備:
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 節點特殊引數的不同:
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:
② 此時在主節點可以看到虛擬 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 負載均衡實現高可用:
方案一:兩臺負載同時啟動 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 的首頁檔案:
重新整理後訪問到 Web 02 的首頁檔案:
⑦ 此時讓 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 結果如下:
重新整理後實現負載均衡:
通過訪問 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:
[[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 域名無法訪問:
方法一:通過守護程序指令碼實現:
[[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 配置檔案:
[[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