Keepalived 原理與實戰
隨着系統架構的逐漸演化,服務器的數量和結構會越來越復雜,例如 Web 服務器集群的搭建,提高了系統的性能,同時也提高了系統維護的復雜度,我們需要對集群中各台服務器進行監控,來保證為用戶提供服務的是正常運行的服務器,整體系統的
可用性
就至關重要。
Keepalived 簡介
什么是Keepalived ?
Keepalived一個基於VRRP 協議來實現的 LVS 服務高可用方案,可以利用其來解決單點故障。一個LVS服務會有2台服務器運行Keepalived,一台為主服務器(MASTER),一台為備份服務器(BACKUP),但是對外表現為一個虛擬IP
,主服務器會發送特定的消息給備份服務器,當備份服務器收不到這個消息的時候,即主服務器宕機的時候, 備份服務器就會接管虛擬IP,繼續提供服務,從而保證了高可用性。
Keepalived 的作用
如上述所說,Keepalived 提供了很好的高可用性保障服務
,它可以檢查服務器的狀態,如果有服務器出現問題,Keepalived 會將其從系統中移除,並且同時使用備份服務器代替該服務器的工作,當這台服務器可以正常工作后,Keepalived 再將其放入服務器群中,這個過程是 Keepalived 自動完成的,不需要人工干涉,我們只需要修復出現問題的服務器即可。
Keepalived 原理
基於VRRP協議的理解
Keepalived 是以 VRRP
協議為實現基礎的,VRRP全稱Virtual Router Redundancy Protocol
,即虛擬路由冗余協議
。
虛擬路由冗余協議,可以認為是實現路由器高可用的協議,即將N台提供相同功能的路由器組成一個路由器組,這個組里面有一個master 和多個 backup,master 上面有一個對外提供服務的 VIP(Virtual IP Address)
(該路由器所在局域網內其他機器的默認路由為該 vip),master 會發組播,當 backup 收不到 vrrp 包時就認為 master 宕掉了,這時就需要根據 VRRP 的優先級來選舉
一個 backup 當 master。這樣的話就可以保證路由器的高可用了。
keepalived 主要有三個模塊,分別是core、check 和 vrrp。core 模塊為keepalived的核心,負責主進程的啟動、維護以及全局配置文件的加載和解析。check 負責健康檢查,包括常見的各種檢查方式。vrrp 模塊是來實現 VRRP 協議的。
基於TCP/IP協議的理解
以檢測 web 服務器為例,Keepalived 從3個層次來檢測服務器的狀態
Layer3 、Layer4 以及 Layer7 工作在IP/TCP協議棧的IP層,TCP層,及應用層,原理分別如下:
Layer3:
Keepalived使用Layer3的方式工作時,Keepalived會定期向服務器群中的服務器發送一個ICMP的數據包(既我們平時用的Ping程序),如果發現某台服務的IP地址沒有激活,Keepalived 便報告這台服務器失效,並將它從服務器群中剔除,這種情況的典型例子是某台服務器被非法關機。Layer3 的方式是以服務器的IP地址
是否有效作為服務器工作正常與否的標准。
Layer4:
如果您理解了Layer3的方式,Layer4就容易了。Layer4主要以TCP 端口的狀態
來決定服務器工作正常與否。如 web server 的服務端口一般是80,如果 Keepalived 檢測到80端口沒有啟動,則 Keepalived 將把這台服務器從服務器群中剔除。
Layer7:
Layer7 就是工作在具體的應用層了,比Layer3,Layer4要復雜一點,在網絡上占用的帶寬也要大一些。Keepalived 將根據用戶的設定檢查服務器程序的運行是否正常,如果與用戶的設定不相符,則 Keepalived 將把服務器從服務器群中剔除。
Keepalived 選舉策略
選舉策略
首先,每個節點有一個初始優先級,由配置文件中的priority
配置項指定,MASTER 節點的 priority 應比 BAKCUP 高。運行過程中 keepalived 根據 vrrp_script 的 weight
設定,增加或減小節點優先級。規則如下:
weight
值為正時,腳本檢測成功時”weight”值會加到”priority”上,檢測失敗時不加- 主失敗: 主priority < 備priority+weight之和時會切換
- 主成功: 主priority+weight之和 > 備priority+weight之和時,主依然為主,即不發生切換
weight
為負數時,腳本檢測成功時”weight”不影響”priority”,檢測失敗時,Master節點的權值將是“priority“值與“weight”值之差- 主失敗: 主priotity-abs(weight) < 備priority時會發生切換
- 主成功: 主priority > 備priority 不切換
- 當兩個節點的優先級相同時,以節點發送
VRRP通告
的 IP 作為比較對象,IP較大者為MASTER。
priority 和 weight 的設定
- 主從的優先級初始值priority和變化量weight設置非常關鍵,配錯的話會導致無法進行主從切換。比如,當MASTER初始值定得太高,即使script腳本執行失敗,也比BACKUP的priority + weight大,就沒法進行VIP漂移了。
- 所以priority和weight值的設定應遵循: abs(MASTER priority - BAKCUP priority) < abs(weight)。一般情況下,初始值MASTER的priority值應該比較BACKUP大,但不能超過weight的絕對值。 另外,當網絡中不支持多播(例如某些雲環境),或者出現網絡分區的情況,keepalived BACKUP節點收不到MASTER的VRRP通告,就會出現腦裂(split brain)現象,此時集群中會存在多個MASTER節點。
Keepalived 實戰進階
Keepalived 安裝部署
- 下載安裝包
Keepalived 官網下載地址:https://www.keepalived.org/download.html
-
解壓
tar -zxvf keepalived-2.0.18.tar.gz
-
解壓后進入到解壓出來的目錄,看到會有
configure
,那么就可以做配置了(配置安裝和nginx一模一樣) -
使用
configure
命令配置安裝目錄與核心配置文件所在位置./configure --prefix=/usr/local/keepalived --sysconf=/etc
- prefix:keepalived安裝的位置
- sysconf:keepalived核心配置文件所在位置,固定位置,改成其他位置則keepalived啟動不了,/var/log/messages中會報錯
配置過程中可能會出現警告信息,如下所示:
解決方法:安裝 libnl/libnl-3 依賴
yum -y install libnl libnl-devel
,重新configure
一下就好了。 -
安裝keepalived
make && make install
-
進入到
/etc/keepalived
,該目錄下為keepalived核心配置文件
Keepalived 配置
把 Keepalived 注冊為系統服務
進入解壓縮安裝包的 etc
文件夾
將系統配置文件拷貝至系統 etc
文件
cp init.d/keepalived /etc/init.d/
cp sysconfig/keepalived /etc/sysconfig/
刷新系統服務,加載新添加的 Keepalived 服務
systemctl daemon-reload
主服務器(Master)配置
- 通過命令
vim keepalived.conf
打開配置文件,詳細配置如下
global_defs {
# 路由id:當前安裝keepalived的節點主機標識符,保證全局唯一
router_id keep_104
}
vrrp_instance VI_1 {
# 表示狀態是MASTER主機還是備用機BACKUP
state MASTER
# 該實例綁定的網卡名稱
interface ens33
# 保證主備節點一致即可
virtual_router_id 51
# 權重,master權重一般高於backup,如果有多個,那就是選舉,誰的權重高,誰就當選
priority 100
# 主備之間同步檢查時間間隔,單位秒
advert_int 2
# 認證權限密碼,防止非法節點進入
authentication {
auth_type PASS
auth_pass 1111
}
# 虛擬出來的ip,可以有多個(vip)
virtual_ipaddress {
192.168.1.108
}
}
附:查看網卡名稱
-
啟動 Keepalived
在sbin目錄中進行啟動(同nginx),如下圖:
-
查看進程
ps -ef|grep keepalived
-
查看虛擬 IP(VIP)
在網卡 ens33 下,多了一個
192.168.1.108
,這個就是虛擬ip
Keepalived 實現雙機主備高可用
在配置完 Keepalived 主服務器節點后,接下來就可以配置備用服務器節點了,備用服務器配置如下:
global_defs {
router_id keep_105
}
vrrp_instance VI_1 {
# 備用機設置為BACKUP
state BACKUP
interface ens33
virtual_router_id 51
# 權重低於MASTER
priority 80
advert_int 2
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
# 注意:主備兩台的vip都是一樣的,綁定到同一個vip
192.168.1.108
}
}
啟動 Keepalived
# 啟動keepalived
systemctl start keepalived
# 停止keepalived
systemctl stop keepalived
# 重啟keepalived
systemctl restart keepalived
查看備用服務器 Keepalived 進程
現在主服務器節點 192.168.1.104
以及備用服務器節點 192.168.1.105
以及 Keepalived 虛擬 IP 192.168.1.105
已配置完畢
這里我在本地將 Keepalived 虛擬IP 192.168.1.108
已映射至 www.keep.com
所以直接訪問 www.keep.com
即可訪問主服務器節點
當主服務器節點的 Keepalived 服務不可用時(這里我直接將主服務器的 Keepalived 服務直接停止systemctl stop keepalived.service
,便於測試),虛擬IP 自動綁定至備用服務器節點地址
Keepalived 配置 Nginx 自動重啟
-
增加Nginx重啟檢測腳本
vim /etc/keepalived/check_nginx_alive_or_not.sh
#!/bin/bash A=`ps -C nginx --no-header |wc -l` # 判斷nginx是否宕機,如果宕機了,嘗試重啟 if [ $A -eq 0 ];then /usr/local/nginx/sbin/nginx # 等待一小會再次檢查nginx,如果沒有啟動成功,則停止keepalived,使其啟動備用機 sleep 3 if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then killall keepalived fi fi
增加運行權限
chmod +x /etc/keepalived/check_nginx_alive_or_not.sh
-
在 keepalived.conf 配置定時監聽 nginx 狀態腳本
vrrp_script check_nginx_alive { script "/etc/keepalived/check_nginx_alive_or_not.sh" interval 2 # 每隔兩秒運行上一行腳本 weight 10 # 如果腳本運行成功,則升級權重+10 # weight -10 # 如果腳本運行失敗,則升級權重-10 }
-
在
vrrp_instance
中新增監控的腳本track_script { check_nginx_alive # 追蹤 nginx 腳本 }
-
重啟Keepalived使得配置文件生效
systemctl restart keepalived
Keepalived 實現雙主熱備高可用
首先需要配置雲服務的 DNS 解析配置和負載均衡,詳細配置參考:
- 阿里雲:https://help.aliyun.com/document_detail/52528.html
- 騰訊雲:https://cloud.tencent.com/document/product/302/11358
Keepalived 雙主熱備詳細配置:
規則:以一個虛擬ip分組歸為同一個路由
主節點配置
global_defs {
router_id keep_104
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.108
}
}
vrrp_instance VI_2 {
state BACKUP
interface ens33
virtual_router_id 52
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.138
}
}
備用節點配置
global_defs {
router_id keep_105
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.108
}
}
vrrp_instance VI_2 {
state MASTER
interface ens33
virtual_router_id 52
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.138
}
}