一、背景與簡介
? ? ? ? 為了服務的高可用性,避免單點故障問題,通常我們使用"冗余設計思想"進行架構設計。冗余設計思想,本質就是將同一個應用或者服務放置在多臺不同的服務器上[雞蛋不放在同一個籃子里],這樣減少整體服務宕機的可能性。我們通過概率學就能簡單知道,例如一臺服務器宕機的概率為1%,那么2臺一樣的機器同時宕機的概率就是0.01x0.01=0.01%, 依次類推,冗余的服務器越多,那么整體服務宕機的可能性就越小。? 但是高可用和成本成正比關系,一個服務的可用性越高,付出的成本越高。
? ? ? ? 通常在應用的業務部署中間件中,Nginx扮演著反向代理與流量分發的角色。 例如之前我所在的公司將服務部署在本地IDC機房,整體對外、對內的流量都是經過Nginx作為網關入口。 如果Nginx存在單點問題,所在的服務器一旦發生宕機或者整個Nginx服務不可用,那么對業務的影響是致命的。
? ? ? ? 所以我們需要保證Nginx入口網關的高可用性。? 我們學過一種編程思想:? 面向抽象編程。 在這里,我們可以將要暴露Nginx網關服務的IP給到客戶端的是VIP(Virtual IP)而非實際代理的物理IP。 我們將多個提供服務的物理IP形成一個邏輯IP組。VIP是一個虛擬IP(抽象層), VIP會時刻只對應一個物理IP, 一旦對應的物理IP發生故障,則可以漂移到這個邏輯IP組內健康的物理IP, 從而實現客戶端無感故障遷移(客戶端無效更改VIP地址,同時這個過程對于客戶端而言是無感知的、透明的),實現服務的高可用。
? ? ? ? 架構圖如下:
? ? ? ? DNS服務器直接將域名綁定A記錄指向VIP地址: 172.20.0.110, 客戶端通過域名進行訪問Nginx網關服務即可,后面Nginx網關服務無論是升級、故障轉移等等,客戶端無須修改域名或者代碼,實現Nginx網關服務高可用以及無感故障轉移。
二、開源組件Keepalived
1、基本介紹
? ? ? ? 很幸運的是要實現上述的Nginx網關服務高可用問題,開源界有一個成熟的、可靠的中間件就是keepalived。
? ? ? ? 網上資料是這么介紹keepalived:?
????????Keepalived 軟件起初是專為LVS負載均衡軟件設計的,用來管理并監控LVS集群系統中各個服務節點的狀態,后來又加入了可以實現高可用的VRRP功能。因此,Keepalived除了能夠管理LVS軟件外,還可以作為其他服務(例如:Nginx、Haproxy、MySQL等)的高可用解決方案軟件。
????????Keepalived軟件主要是通過VRRP協議實現高可用功能的。VRRP是Virtual Router RedundancyProtocol(虛擬路由器冗余協議)的縮寫,VRRP出現的目的就是為了解決靜態路由單點故障問題的,它能夠保證當個別節點宕機時,整個網絡可以不間斷地運行。
????????所以,Keepalived 一方面具有配置管理LVS的功能,同時還具有對LVS下面節點進行健康檢查的功能,另一方面也可實現系統網絡服務的高可用功能。
2、總結概括
? ? ? ? Keepalived是一個通過VRRP網絡協議、提供VIP漂移技術來實現冗余高可用設計的一個開源中間件。?
? ? ? ? 通過合理的配置Keepalived我們就可以實現服務的高可用。
三、案例實驗
1、實驗的目標以及實驗環境
? ? ? 本次實驗都是基于docker-compose實現.
? ? ? ?設計有2個容器(2臺服務器),分別是172.20.0.2作為主服務器、172.20.0.3作為備用服務器,? 服務器上都部署了Nginx服務, 我們需要要暴露這個服務給到其他客戶端提供一個VIP。? 后面測試主服務器宕機的時候,訪問VIP是否訪問到了172.20.0.3的頁面。等主服務器又恢復正常的時候,訪問VIP是否訪問到的是172.20.0.2的頁面。
? ? ? ? Dockerfile內容如下:
FROM centos:7
RUN yum update -y
USER root
RUN yum install epel-release -y
RUN yum update -y
RUN yum install nginx keepalived -y
RUN yum install vim net-tools iproute -y
? ? ? ? ?運行的目錄結構如下:
? ? ? ? docker-compose.yaml內容如下:
version: "3"
services:nginx-master: # 172.20.0.2build:context: ./docker/working_dir: "/root/"privileged: truehostname: "nginx-master"expose:- 80entrypoint: ["tail", "-f", "/dev/null"]nginx-backup: # 172.20.0.3build:context: ./docker/working_dir: "/root/"privileged: truehostname: "nginx-backup"expose:- 80entrypoint: [ "tail", "-f", "/dev/null" ]
? ? ? ? 運行著2個容器, 執行docker-compose up -d --build
2、測試兩個容器顯示的頁面內容
? ? ? ? 在宿主機上執行curl命令,分別curl 2個IP查看返回Nginx提供的頁面內容:
3、配置nginx-master容器(172.20.0.2)的keepalived.conf
? 文件位于/etc/keepalived/keepalived.conf
global_defs {#keepalived節點唯一ID標識名稱router_id keep_02
}vrrp_instance VI_1 {#節點角色: MASTER、BACKUPstate MASTER #綁定VIP的網卡名稱interface eth0 #虛擬路由ID組, 備用節點和主節點必須屬于同一個組virtual_router_id 172 #節點優先級, 取值范圍 0-255, 主節點的優先級要大于備用節點priority 100 #主備同步檢查時間間隔advert_int 1 #認證信息,主備一致authentication { auth_type PASSauth_pass 1234}#VIP地址virtual_ipaddress {172.20.0.110 }
}
?啟動keepalived:??
keepalived -n -l # -n 前臺運行 -l 顯示運行日志
?此時查看ip addr:? ?可以看到VIP? 172.20.0.110 已經綁定在eth0網卡上了
? 宿主機此時curl 172.20.0.110得到結果是綁定在了master主節點的內容:
?
4、配置nginx-backup容器(172.20.0.3)的keepalived.conf
global_defs {#keepalived節點唯一ID標識名稱router_id keep_03
}vrrp_instance VI_1 {#節點角色: MASTER、BACKUPstate BACKUP #綁定VIP的網卡名稱interface eth0 #虛擬路由ID組, 備用節點和主節點必須屬于同一個組virtual_router_id 172 #節點優先級, 取值范圍 0-255, 主節點的優先級要大于備用節點priority 90 #主備同步檢查時間間隔advert_int 1 #認證信息,主備一致authentication { auth_type PASSauth_pass 1234}#VIP地址virtual_ipaddress {172.20.0.110 }
}
? 啟動keepalived:
keepalived -n -l # -n 前臺運行 -l 顯示運行日志
? ?
此時查看: ip addr? ? ?主節點keepalived還正常運行,自然備用節點拿不到VIP
5、模擬主節點故障,手動關閉keepalived
此時在宿主機訪問VIP? curl? 172.20.0.110:
????????此時我們看到,同樣是訪問VIP地址, 第4步驟訪問的時候返回的是master: 172.20.0.2, 但是我們手動關閉主節點的keepalived進程模擬故障的時候, 再次curl VIP地址, 訪問得到的內容就是backup: 172.20.0.3 。?
? ? ? ? 此時已經發生故障轉移了,但是客戶端訪問的VIP沒發生變化,我們在宿主機上執行的curl命令一模一樣,但是返回的內容不一樣了(實際情況來說,沒出故障前以及出故障之后,得到的AIP的內容應該是一致的。 只是在這里做演示,讓大家看情況故障轉移過程,所以故意讓返回的頁面內容存在差異,容易對比)
6、模擬恢復主節點故障,啟動keepalived進程
? ? ? ? 此時我們再次訪問curl VIP :? curl 172.20.0.110, 得到的內容又是master: 172.20.0.110, VIP已經實現了故障轉移(IP漂移)
四、?總結
? ? ? ? 整個測試流程還算簡單、清晰的。? 我們使用keepalived要注意幾點:
? ? ? ? ????????1、主節點、備用節點要屬于同一個廣播域,也就是同一個交換機下
? ? ? ????????? 2、啟動keepalived默認是后臺運行,啟動后進入后臺。但是為了更好調試錯誤加入了-n參數進行前臺運行, 為了顯示日志便于排錯又增加了-l參數。? 所以整體參數是
keepalived -n -l
? ? ? ????????? 3、通過ip addr查看VIP代替ifconfig, ifconfig有時候是看不到VIP的存在,只看到了物理IP的存在
? ? ? ? 那使用Keepalived上述過程,就能確保服務高正無憂、毫無缺點了么?? 其實不盡然。
? ? ? ? 1、大家會發現VIP時刻只會漂移到一個物理IP上,那么BACKUP備用節點都處于閑置狀態,是不是太浪費資源了呢?
? ? ? ? 2、IP漂移或者不漂移是通過Keepalived進程是否存活來決定的。 那么如果存在一種情況就是Keepalived進程存活,此時拿到了VIP,但是Nginx掛了, 那本質上就是VIP拿到了占著茅坑不拉屎,整個服務都掛了。這種情況又該如何處理IP及時漂移到可用Nginx節點來達到高可用的目的呢???
? ? ? ? 預知后事如何,請聽下回分解~