Keepalived雙機熱備實現高可用

可愛的小佳佳發表於2020-12-29

在我們的架構體系中,後端伺服器經常會前置一臺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配置

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

在這裡插入圖片描述

請求是怎麼到達nginx-1這臺機器上的

請求經過路由,路由發現沒有10.211.55.100的對映,向區域網內機器傳送arp包等待返回,nginx-1返回10.211.55.100和mac地址的對映,路由將其快取,方便下次訪問,並將請求指向nginx-1

keepalived故障轉移是怎麼實現的

作為MASTER的nginx-1 會定時向同一虛擬路由內的其他機器傳送vrrp包,告知他們當前MASTER的優先順序,當BACKUP發現自己的優先順序比MASTER高時,會建立虛擬IP,將自身的角色提升為MASTER,並向其他機器傳送VRRP包,原先的MASTER發現有比自身優先順序更高的的機器,調整自身角色為BACKUP

下面就為大家完整完整展示這個過程
我們分別將兩臺機器 15、16上的nginx啟動,再把keepalived分別啟動起來
我們15這臺的keepalibved的優先順序配置的是100, 16這臺優先順序配置的是90
因此當我們兩臺的keepalived都啟動之後,15這臺就優先佔有了10.211.55.100這個ip

我們看看啟動keepalived時,都做了些什麼操作
我們前面說過,keepalived啟動時,無論你給它定義的角色是MASTER還是BACKUP,都不能決定它的身份,
當先啟動15這臺的keepalived時
在這裡插入圖片描述
它會將自身先定義為BACKUP,等待MASTER的VRRP包,等待超時,才會進入MASTER狀態,設定VIP,發起組播。
而16這臺優先順序有90的在啟動過程中就沒有轉為MASTER
在這裡插入圖片描述

我們訪問可以看到此時該IP被15佔有
在這裡插入圖片描述

此時我們將15機器(MASTER)上的nginx程式殺掉

killall nginx

從keepalived的日誌中可以看到,優先順序由100降到80,並且收到路由組內一個更高的優先順序90,MASTER進入BACKUP狀態,移除VIP
在這裡插入圖片描述

我們來看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例項都有一個初始化的優先順序
根據服務健康狀態的檢測指令碼的不同狀態值,根據設定的weight權重值,動態改變當前例項的優先順序

在這裡插入圖片描述

指令碼的狀態值,1代表失敗,0代表成功
當設定的weight > 0時,指令碼返回值如果是0,優先順序調整為priority = priority + weight
,指令碼返回值如果是1,優先順序不變

當設定的weight < 0時,指令碼返回值如果是1,優先順序調整為priority = priority + weight,指令碼返回值如果是0,優先順序不變

這裡看起來有點繞,所以建議大家weight設定為負數,並且weight的絕對值要大於初始化時節點間的優先順序差值。

相關文章