Keepalived 原理與實戰
阿新 • • 發佈:2020-05-25
# Keepalived 原理與實戰
> 隨著系統架構的逐漸演化,伺服器的數量和結構會越來越複雜,例如 Web 伺服器叢集的搭建,提高了系統的效能,同時也提高了系統維護的複雜度,我們需要對叢集中各臺伺服器進行監控,來保證為使用者提供服務的是正常執行的伺服器,整體系統的`可用性`就至關重要。
## Keepalived 簡介
### 什麼是Keepalived ?
Keepalived一個基於[VRRP](https://link.zhihu.com/?target=http%3A//en.wikipedia.org/wiki/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 雙機主備原理](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/03/2020-05-20-151648.png)
## Keepalived 選舉策略
### 選舉策略
首先,每個節點有一個初始優先順序,由配置檔案中的`priority`配置項指定,MASTER 節點的 priority 應比 BAKCUP 高。執行過程中 keepalived 根據 vrrp_script 的 `weight` 設定,增加或減小節點優先順序。規則如下:
1. `weight`值為正時,指令碼檢測成功時”weight”值會加到”priority”上,檢測失敗時不加
- 主失敗: 主priority < 備priority+weight之和時會切換
- 主成功: 主priority+weight之和 > 備priority+weight之和時,主依然為主,即不發生切換
2. `weight`為負數時,指令碼檢測成功時”weight”不影響”priority”,檢測失敗時,Master節點的權值將是“priority“值與“weight”值之差
- 主失敗: 主priotity-abs(weight) < 備priority時會發生切換
- 主成功: 主priority > 備priority 不切換
3. 當兩個節點的優先順序相同時,以節點發送`VRRP通告`的 IP 作為比較物件,IP較大者為MASTER。
### priority 和 weight 的設定
1. 主從的優先順序初始值priority和變化量weight設定非常關鍵,配錯的話會導致無法進行主從切換。比如,當MASTER初始值定得太高,即使script指令碼執行失敗,也比BACKUP的priority + weight大,就沒法進行VIP漂移了。
2. 所以priority和weight值的設定應遵循: abs(MASTER priority - BAKCUP priority) < abs(weight)。一般情況下,初始值MASTER的priority值應該比較BACKUP大,但不能超過weight的絕對值。 另外,當網路中不支援多播(例如某些雲環境),或者出現網路分割槽的情況,keepalived BACKUP節點收不到MASTER的VRRP通告,就會出現腦裂(split brain)現象,此時叢集中會存在多個MASTER節點。
## Keepalived 實戰進階
### Keepalived 安裝部署
1. 下載安裝包
Keepalived 官網下載地址:https://www.keepalived.org/download.html
![image-20200521210358933](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/03/2020-05-21-130359.png)
2. 解壓
```bash
tar -zxvf keepalived-2.0.18.tar.gz
```
3. 解壓後進入到解壓出來的目錄,看到會有`configure`,那麼就可以做配置了(配置安裝和nginx一模一樣)
![image-20200521210723704](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/03/2020-05-21-130724.png)
4. 使用`configure`命令配置安裝目錄與核心配置檔案所在位置
```bash
./configure --prefix=/usr/local/keepalived --sysconf=/etc
```
- prefix:keepalived安裝的位置
- sysconf:keepalived核心配置檔案所在位置,固定位置,改成其他位置則keepalived啟動不了,/var/log/messages中會報錯
配置過程中可能會出現警告資訊,如下所示:
![image-20200521211303189](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/03/2020-05-21-131303.png)
解決方法:安裝 libnl/libnl-3 依賴 `yum -y install libnl libnl-devel`,重新`configure`一下就好了。
5. 安裝keepalived
```bash
make && make install
```
6. 進入到`/etc/keepalived`,該目錄下為keepalived核心配置檔案
### Keepalived 配置
#### 把 Keepalived 註冊為系統服務
進入解壓縮安裝包的 `etc` 資料夾
![image-20200521222326891](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/05/2020-05-21-142327.png)
將系統配置檔案拷貝至系統 `etc`檔案
```bash
cp init.d/keepalived /etc/init.d/
cp sysconfig/keepalived /etc/sysconfig/
```
刷新系統服務,載入新新增的 Keepalived 服務
```bash
systemctl daemon-reload
```
#### 主伺服器(Master)配置
1. 通過命令 `vim keepalived.conf` 開啟配置檔案,詳細配置如下
```bash
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
}
}
```
**附:檢視網絡卡名稱**
![image-20200521214418246](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/03/2020-05-21-134419.png)
2. 啟動 Keepalived
在sbin目錄中進行啟動(同nginx),如下圖:
![image-20200521214728691](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/03/2020-05-21-134728.png)
3. 檢視程序
```bash
ps -ef|grep keepalived
```
![image-20200521214838919](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/03/2020-05-21-134839.png)
4. 檢視虛擬 IP(VIP)
在網絡卡 ens33 下,多了一個 `192.168.1.108` ,這個就是虛擬ip
![image-20200521220643981](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/05/2020-05-21-140644.png)
#### Keepalived 實現雙機主備高可用
在配置完 Keepalived 主伺服器節點後,接下來就可以配置備用伺服器節點了,備用伺服器配置如下:
```bash
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
```bash
# 啟動keepalived
systemctl start keepalived
# 停止keepalived
systemctl stop keepalived
# 重啟keepalived
systemctl restart keepalived
```
檢視備用伺服器 Keepalived 程序
![image-20200522235349567](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/05/2020-05-22-155350.png)
現在主伺服器節點 `192.168.1.104`以及備用伺服器節點 `192.168.1.105`以及 Keepalived 虛擬 IP `192.168.1.105`已配置完畢
![image-20200522235637330](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/05/2020-05-22-155638.png)
![image-20200522235724708](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/05/2020-05-22-155725.png)
這裡我在本地將 Keepalived 虛擬IP `192.168.1.108`已對映至 `www.keep.com`
![image-20200522235859619](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/05/2020-05-22-155859.png)
所以直接訪問 `www.keep.com` 即可訪問主伺服器節點
![image-20200523000014318](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/05/2020-05-22-160014.png)
當主伺服器節點的 Keepalived 服務不可用時(這裡我直接將主伺服器的 Keepalived 服務直接停止`systemctl stop keepalived.service`,便於測試),虛擬IP 自動繫結至備用伺服器節點地址
![image-20200523000333384](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/05/2020-05-22-160333.png)
#### Keepalived 配置 Nginx 自動重啟
1. 增加Nginx重啟檢測指令碼
```bash
vim /etc/keepalived/check_nginx_alive_or_not.sh
```
```shell
#!/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`
2. 在 keepalived.conf 配置定時監聽 nginx 狀態指令碼
```bash
vrrp_script check_nginx_alive {
script "/etc/keepalived/check_nginx_alive_or_not.sh"
interval 2 # 每隔兩秒執行上一行指令碼
weight 10 # 如果指令碼執行成功,則升級權重+10
# weight -10 # 如果指令碼執行失敗,則升級權重-10
}
```
3. 在`vrrp_instance`中新增監控的指令碼
```bash
track_script {
check_nginx_alive # 追蹤 nginx 指令碼
}
```
4. 重啟Keepalived使得配置檔案生效
```bash
systemctl restart keepalived
```
#### Keepalived 實現雙主熱備高可用
![image-20200523004644961](https://blog-figure-bed.oss-cn-shanghai.aliyuncs.com/2020/05/2020-05-22-164645.png)
首先需要配置雲服務的 DNS 解析配置和負載均衡,詳細配置參考:
- 阿里雲:https://help.aliyun.com/document_detail/52528.html
- 騰訊雲:https://cloud.tencent.com/document/product/302/11358
Keepalived 雙主熱備詳細配置:
規則:以一個虛擬ip分組歸為同一個路由
**主節點配置**
```nginx
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
}
}
```
**備用節點配置**
```nginx
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
}
}
```
## 參考文件
- https://www.huweihuang.com/linux-notes/keepalived/keepalived-introduct