在我們的架構體系中,后端服務器經常會前置一臺Nginx服務器做反向代理,把請求分發到后端服務器,也就是常見的負載均衡,如下

但是這里存在一個單點故障的問題,如果前置的Nginx掛掉了,請求便無法到達后端服務器,整個后端服務便不可用了

我們的解決思路是加多一臺前置的nginx(nginx-2)來做負載均衡,在平時不對外提供服務,當nginx-1不可用的時,nginx-2 瞬間把nginx-1的任務接管過來,保證對外的服務不間斷

那在這里我們遇到了兩個問題
Q1 : nginx-1 和 nginx-2都有各自的ip地址,那我們對外服務的ip地址應該是哪一個?兩臺nginx之間進行切換的時候,對外的IP怎么做到固定不變?
Q2 : nginx-2 要怎么知道nginx-1是否可用?他們之間怎么去建立一套溝通機制?
Keepalived可以幫助我們解決這兩個問題
什么是Keepalived
Keepalived起初是為負載均衡設計的,用于管理集群中的各個節點,
后來加入了VRRP(虛擬路由冗余協議)可以用來實作多種服務的高可用,
我們先把每個nginx節點都安裝上Keepalived,再來看看它是怎么作業的,
Keepalived安裝配置
1 下載原始碼包
cd /usr/local/src
wget https://www.keepalived.org/software/keepalived-2.0.20.tar.gz
2 解壓
tar -zxvf keepalived-2.0.20
3 配置
cd keepalived-2.0.20
手動指定安裝目錄,不然默認會安裝到/usr/local目錄下,檔案太零散,這里我們手動指定一下
./configure --prefix /usr/local/keepalived
4 安裝
make && make install
5 為組態檔創建軟鏈接
keepalived 啟動時默認讀取的組態檔是/etc/keepalived/keepalived.conf
ln -s /usr/local/keepalived/etc/keepalived /etc/keepalived
6 keepalived配置
vi /etc/keepalived/keepalived.conf
配置如下:
global_defs { # 全域配置
router_id nginx_master # keepalived 服務器唯一標志
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh" #nginx檢測腳本,nginx宕機后自動重啟
interval 2 #檢測時間間隔
weight -20
}
vrrp_instance v_1 {
state MASTER #狀態,只有MASTER跟BACKUP兩種,需要大寫,會自動切換狀態
interface eth0 #通信網卡
mcast_src_ip 10.211.55.15 #本機ip
virtual_router_id 100 #虛擬路由id 主從一致 可以用虛擬ip的最后一段
priority 100 #優先級
advert_int 1 #MASTER跟BACKUP之間健康檢查間隔(vrrp組播周期)
authentication { #驗證型別和密碼 主從密碼要一致
auth_type PASS
auth_pass 1111
}
track_script{
chk_nginx #檢測腳本
}
virtual_ipaddress {
10.211.55.100 #虛擬ip,可以設定多個
}
}
這里我們對引數做一下解釋:
global_defs: 全域配置
? ? router_id: 標記該keepalived服務器
vrrp_script: vrrp腳本定義
??script:腳本路徑
??interval:腳本運行間隔
??weight:權重變化的幅度,這個在后面選舉程序會用到
vrrp_instance:vrrp實體定義
??state :標記該機器在整個vrrp實體中,處于什么樣的角色,是MASTER(主)還是BACKUP(備),但是這只是初始化時理想的角色分配,該機器的角色是變化的,不是固定的,另外一點是,機器加入vrrp虛擬路由組時,初始角色都是BACKUP,再根據實際情況判斷是是否需要調整,
??virtual_router_id:虛擬路由的id ,這個需要主備保持一致,否則不生效
??priority:優先級,MASTER的初始優先級應當比BACKUP要高,在選舉程序中,優先級高的充當MASTER的的角色
??advert_int:VRRP的組播周期,在同一個虛擬路由中,MASTER會定期向BACKUP設備發送VRRP包,告知BACKUP當前MASTER的優先級,BACKUP自行判斷是否需要選舉為MASTER,advert_int就是指定這個組播間隔
??authentication:指定驗證型別和驗證密碼,主備需要保持一致
track_script:指定健康監測需要運行的腳本,這里我們指定nginx的健康監測腳本
??virtual_ipaddress:虛擬路由地址,這里可以根據需要指定多個
7 添加nginx檢查健康腳本
vi /etc/keepalived/nginx_check.sh
內容如下
#!/bin/bash
A=`ps -C nginx --no-header|wc -l`
if [ $A -eq 0 ];then
exit 1
#/usr/local/nginx/sbin/nginx
#sleep 2
#if [ `ps -C nginx --no-header|wc -l` -eq 0 ];then
#systemctl stop keepalived
#fi
else
exit 0
fi
大意就是檢查nginx行程是否還存在,不存在的話狀態碼為1,keepliaved會用到這個狀態碼
用#注釋掉的部分是嘗試將nginx行程啟動,如果重啟失敗殺死keepalived行程,為了方便演示,先把重啟nginx這部分注釋掉
8 把keepalived 加入到開機啟動項
systemctl enable keepalived
9啟動keepalived
systemctl start keepalived
檢查是否啟動成功
ps -ef | grep keepalived
這么一來,keepalibved 我們就安裝配置好了
當我們把兩臺nginx服務器上安裝的keepalived啟動后,會產生一個虛擬的ip(VIP)10.211.55.100,此時作為MASTER的nginx-1擁有這個vip,外部通過這個虛擬IP來訪問,不在使用10.211.55.15

請求是怎么到達nginx-1這臺機器上的
請求經過路由,路由如果發現沒有10.211.55.100這個IP的arp映射,向局域網內機器發送arp包等待回傳,nginx-1回傳10.211.55.100和mac地址的映射,路由將其快取,方便下次訪問,并將請求指向nginx-1
keepalived故障轉移是怎么實作的
我們一起來看看在整個生命周期中,keepalived是怎么作業的,
我們分別將兩臺機器 15、16上的nginx啟動,再把keepalived分別啟動起來
我們15這臺的keepalibved的優先級配置的是100, 16這臺優先級配置的是90
因此當我們兩臺的keepalived都啟動之后,15這臺就優先占有了10.211.55.100這個ip
我們看看啟動keepalived時,都做了些什么操作
當我們先啟動15這臺的keepalived時

在keepalived啟動時,默認會將自身先定義為BACKUP,等待MASTER節點的VRRP包,直到等待超時,才會進入MASTER狀態,設定VIP,發起組播,
而16這臺優先級有90的在啟動程序中就沒有轉為MASTER,因為它收到的優先級比自己高

我們訪問可以看到此時該IP被15占有

此時我們將15機器(MASTER)上的nginx行程殺掉
killall nginx
從keepalived的日志中可以看到,優先級由100降到80,并且收到路由組內一個更高的優先級90,MASTER進入BACKUP狀態,移除VIP

不是只有MASTER能發組播嗎?那15節點收到的組播包是哪來的?
我們來看16(原來的BACKUP)的日志

可以看到BACKUP收到MASTER的組播VRRP包,發現MASTER的優先級比自己低,立馬進入MASTER狀態,設定VIP,并開始組播,之前的MASTER收到組播,轉為BACKUP
此時我們訪問該IP,可以發現該IP被nginx-2占有

總結:
keepalived 同一個虛擬路由組內,MASTER通過VRRP協議向其他成員發送資料包,內容是自身優先級,其他BACKUP成員如果發現自身的優先級比MASTER高,就會轉為MATSER,并設定VIP,向其他節點組播VRRP包,原來的MASTER節點接收到的優先級比自身高,就會轉為BACKUP狀態
優先級是怎么進行變動的?
每個keepalived實體都有一個初始化的優先級priority
根據服務健康狀態檢測腳本的不同狀態值,動態改變當前實體的優先級,變動幅度是設定的weight權重值

具體的腳本上面安裝程序中有
腳本的狀態值,1代表失敗,0代表成功,
當設定的weight > 0時,腳本回傳值如果是0,優先級調整為priority = priority + weight
,腳本回傳值如果是1,優先級不變
當設定的weight < 0時,腳本回傳值如果是1,優先級調整為priority = priority + weight,腳本回傳值如果是0,優先級不變
這里看起來有點繞,所以建議大家weight設定為負數,并且weight的絕對值要大于初始化時節點間的優先級差值,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/242315.html
標籤:其他
上一篇:博客營銷,你值得擁有
下一篇:linux常用命令大全(五)
