Keepalived+Nginx+Tomcat設定高可用負載均衡系統範例

2023-12-19 06:00:47

前言

目前生產環境的設定越來越多的使用雲服務了,同時負載均衡也基本轉向了雲廠商提供的服務,但對於絕大多數應用來說,自建叢集可能在費用上要更便宜一些,這篇文章也是之前整理的,再次新瓶裝舊酒分享給各位。此範例演示在不使用docker的情況下設定負載均衡,內容keepalived+nginx+tomcat的基礎設定範例,某些特定設定此例中不會出現,在範例中會用到三個虛擬機器器:兩個純命令列用於模擬伺服器端設定,一個帶桌面環境的用於模擬使用者端存取,這樣三臺虛擬機器器使用NAT模式連線的時候是在同一個虛擬網路中,更符合伺服器的實際使用場景,虛擬機器器軟體為VMPlayer,這個對於個人可以免費使用,用起來來不錯,推薦一下。

本範例中是模擬使用場景,機器效能有限,所有nginx和Tomcat就放到一個機器上了,實際場景中如果可以儘量分開,防止nginx所在伺服器出問題時跟著宕掉一個或多個Tomcat。

建立虛擬機器器

此部分是為了照顧對於虛擬機器器安裝不熟悉的同學,如果已經熟悉了虛擬機器器的安裝或有實體機環境等,可以跳過此步驟。

建立伺服器虛擬機器器(mini安裝)

  • 開啟VMPlayer,然後介面如下,點選建立新虛擬機器器

  • 彈出頁面後選擇最後一項,稍後安裝作業系統,這裡一定要選擇這個,因為如果選擇其他直接安裝的話會使用簡易安裝,預設安裝完是帶桌面的

  • 下一步,然後選擇Centos 64位元的作業系統,這個需要針對映象來選擇,我這裡選這個是因為我有現成的64位元映象。

  • 下一步,這裡設定下虛擬機器器的名字和安裝地址,便於區分。

  • 下一步,然後需要設定硬碟,大小隨意(虛擬機器器建立之後硬碟大小隻能增大不能減小了,所以這裡可以設定的小一點,親測設定完成後也就才2G,這裡設定5G應該就足夠了),下邊兩項也是二選一隨意。

  • 下一步,介面如下,這裡我們需要點選「自定義硬體」來設定系統的光碟機,如果實體機的設定低的話可以在這裡降低下虛擬機器器的CPU和記憶體等,命令列模式下的CentOS並不需要多高的設定(單核512M可以無壓力執行)

  • 在開啟的介面中選擇光碟機,然後選擇使用ISO映象,點選瀏覽選擇映象即可,這個映象可以從CentOS官網下載。

  • 之後點選關閉,再點選完成即可,此時的介面如下:

  • 此時虛擬機器器的硬體已經準備完畢,接下來我們點選播放虛擬機器器設定系統,點選後介面如下,選擇第一項Install。

  • 接下來稍等片刻會進入圖形化介面,這裡不用擔心,這個只是安裝的圖形介面,與之後系統沒關係,如下:

  • 因為是要最小化安裝,所以語言預設英文即可,點選Continue,跳轉後的介面為設定介面,我們僅需要修改下圖中紅框的部分,其他的預設即可。

  • 第一項是設定系統的硬碟,這裡我們不需要進行任何設定,點選進入之後直接點選左上角的Done按鈕即可。

  • 第二項是設定系統的網路,預設不連線,所以我們需要點選進入設定頁面,然後將右上角的OFF置成ON,然後點選DONE,之後會跳轉回一開始的設定頁,我們就可以開始系統的安裝了,點選Begin Installation,接下來需要設定使用者。

  • ROOT使用者的密碼是必須要建立的,其他使用者可以根據需要進行建立,這裡我只設定了ROOT使用者的密碼,方便後續的操作,不用考慮許可權問題,實際應用中是要用其他使用者操作的,後續的操作可視情況賦予許可權即可。還有需要注意的是如果使用者的密碼強度很低,需要點選兩次DONE來確定。

  • 接下來就是等待結束重啟即可,至此CentOS就安裝完成了。

建立使用者端虛擬機器器(簡易安裝安裝)

在這個範例中使用者端有兩個用處,一是通過瀏覽器測試伺服器端的服務是否好用;二是通過FTP向伺服器端上傳幾個原始碼包。其實上傳原始碼包這個功能大部分情況下實體機也是可以操作的,但在NAT網路下實體機的瀏覽器在預設是無法存取伺服器端的服務的。

使用者端虛擬機器器對作業系統無限制,只要可以執行瀏覽器即可,其實命令列模式下的linux也是可以存取的,不過不太直觀,如果想用實體機進行存取的話也可以,不過需要將虛擬機器器的網路連線模式改為橋接模式,而且對網路有要求,需要支援DHCP才可以。

安裝過程和伺服器端的很類似,只有第二部有所區別,伺服器需要選擇稍後安裝作業系統,但使用者端的虛擬機器器使用第二項選擇映象即可,之後會提示設定系統的使用者名稱和密碼,之後的步驟就一樣了,而且自定義硬體的時候不再需要設定光碟機。

設定基礎環境

  • 這裡以Server01為範例,其實我們需要設定兩臺的,我使用的使用者是root使用者,實際應用中可能需要在其他使用者下進行,視情況賦予許可權即可。

  • 因為我們需要向虛擬機器器上傳一些用到的軟體(當然可以使用wget來下載,只不過有點麻煩),所以這裡我們實體機或者使用者端使用FTP使用者端進行連線(工具有很多,挑選自己順手的使用,這裡推薦Xftp和FileZilla,對於個人使用都是免費的),虛擬機器器的IP地址可以通過ip addr進行檢視,紅框中就是當前虛擬機器器的IP地址

  • 接下來在FTP使用者端中輸入主機地址,需要注意的是CentOS使用的是SFTP,所以我們輸入的地址應該是sftp://192.168.59.130,輸入賬戶密碼之後點選快速連線,如果看到如下介面則表示連線成功了

  • 現在系統是設定完成了,不過IP是隨機分配的,如果有需要可以將伺服器的地址改為靜態IP,不過這個IP一般不會發生變化,這裡我就先不改了,但是伺服器的話是一定會設定固定IP的。

安裝JDK

  • 我們常用的SUN JDK不支援yum安裝,所以需要從JDK官網下載合適的JDK,這裡我使用的是JDK-8u111-linux-x64.rpm,通過ftp上傳到/usr/local/download下(這個位置隨意),然後分別執行以下命令進行安裝,JDK的預設安裝地址為/usr/java
cd /usr/local/download
rpm -i jdk-8u111-linux-x64.rpm
  • 安裝後即可執行java -version檢視安裝的版本資訊

安裝Tomcat

  • Tomcat是可以通過yum進行安裝的,不過範例中我們需要兩個Tomcat,單獨下載更方便,我這裡下載的是tomcat 7.0.72。通過FTP將tomcat上傳到/usr/local/download下,然後分別執行以下命令解壓並移動到/usr/local下,因為後續要使用兩個Tomcat,所以我們執行兩次操作
tar -xvf apache-tomcat-7.0.72.tar.gz
mv apache-tomcat-7.0.72 /usr/local/Tomcat01
tar -xvf apache-tomcat-7.0.72.tar.gz
mv apache-tomcat-7.0.72 /usr/local/Tomcat02
  • 此時我們的Tomcat已經解壓完成了,接下來是修改埠號,防止兩個Tomcat埠衝突,Tomcat預設會佔用三個埠:8005,8080和8009,這裡我們修改成如下,檔案為/usr/local/Tomcat01/conf/server.xml和/usr/local/Tomcat02/conf/server.xml(這裡如果不熟悉vi編輯器的小夥伴可以將組態檔下載到本地然後修改完成後再上傳回伺服器)
Tomcat01   8015 8081 8019
Tomcat02   8025 8082 8029
  • 修改完成以後我們進入/usr/local/Tomcat01/bin目錄下執行 ./start.sh,會提示Tomcat Started,此時實體機依然是無法存取的,因為防火牆沒有開放埠,執行以下命令開放埠,以下命令僅當前對談有效,增加--permanent可以永久保留埠開放狀態,不過我們是要做的負載均衡中nginx只會存取本機的Tomcat,所以Tomcat的埠沒有必要一直開放,現在測試下就夠了
firewall-cmd --zone=public --add-port=8081/tcp
  • 此時我們在使用者端虛擬機器器中存取 http://192.168.59.130:8081 即可看到Tomcat的歡迎頁了,此時還有一個問題,兩個Tomcat的首頁是一樣的,負載均衡成功後無法分辨來自哪個Tomcat,所以我們要加點東西區分一下,我是在每個歡迎頁的body中增加了一行標識如下,檔案位於/usr/local/Tomcat01/webapps/ROOT/index.jsp

安裝Nginx

nginx可以通過修改源的方式進行yum安裝,有需要的同學可以自行搜尋下,本例中使用原始碼安裝

  • 從官網下載原始碼包後通過FTP將nginx的原始碼上傳到/usr/local/download下,然後執行以下命令解壓,我這裡使用的是1.10.2
tar -xvf nginx-1.10.2.tar.gz
  • 之後我們就要用到gcc來編譯nginx的原始碼了,需要先安裝gcc
yum install gcc
  • 之後分別執行以下命令,--prefix是指定軟體的安裝位置
cd /usr/local/download/nginx-1.10.2
./configure --prefix=/usr/local/nginx 
  • 執行之後我們會的到以下錯誤,我們需要去下載PCRE的原始碼,然後通過FTP上傳到/usr/local/download下,我這裡用的是8.39

  • 解壓縮pcre的原始碼,命令和以前的一樣,解壓後不需要進行其他操作
tar -xvf pcre-8.39.tar.gz
  • 然後我們再次編譯nginx,根據上次的提示我們追加上pcre的原始碼位置
cd /usr/local/download/nginx-1.10.2
./configure --prefix=/usr/local/nginx --with-pcre=/usr/local/download/pcre-8.39
  • 恭喜,又報錯了,這次提示換成了這個,所以我們又需要下載zlib的原始碼,老辦法上傳到老地方,然後解壓,這裡命令就不詳細說了,跟之前一樣,我下載的版本是1.2.8

  • 解壓完成後,我們根據提示追加zlib命令,是的,就追加這兩個,不需要再追加了
cd /usr/local/download/nginx-1.10.2
./configure --prefix=/usr/local/nginx --with-pcre=/usr/local/download/pcre-8.39 --with-zlib=/usr/local/download/zlib-1.2.8
  • 編譯完成了,執行安裝,命令如下
make && make install && make clean
  • 本來以為可以愉快的結束了的,結果。。。。。。

  • 好吧,只能繼續安裝了
yum install gcc-c++
  • 現在執行前一步的make命令安裝就可以了,接下來進入/usr/local/nginx/sbin目錄下執行./nginx啟動nginx,然後分別執行以下命令開放80埠(永久開放的埠在設定後必須執行reload,本次有效的不需要執行,執行reload後本次有效的埠也將失效)
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload
  • 之後我們可以在使用者端的瀏覽器中輸入 http://192.168.59.130 進行測試,如果出現如下頁面表示nginx啟動成功了

  • nginx是可以做成系統服務的,實際應用中大多也是這麼做的,不過這裡只是個範例,就不做成服務了,如果有需要的可以自行百度,當然如果使用yum安裝的話安裝完成就已經註冊服務了。

設定負載均衡

  • 之前Tomcat我們已經做好了設定,接下來只需要在nginx中設定即可,組態檔為/usr/local/nginx/conf/nginx.conf,如下圖新增upstream部分,將localtion部分更改為圖中部分即可,server可以是其他伺服器上的服務,weight越高越容易被分發請求,這裡我暫時寫本機的,另外實際使用中upstream第一行要加入ip_hash來保證同一使用者一次只能存取同一臺伺服器,解決session跨伺服器丟失的問題,如果系統內使用其他方法處理了session的共用問題就不要加了,這個範例中我們就不加入了,因為加入了以後重新整理瀏覽器頁面不會變化。

  • 接下來就可以進行負載均衡的測試了,因為修改過nginx的組態檔所以我們需要重啟一下nginx,然後開啟兩個Tomcat,命令如下:
/usr/local/nginx/sbin/nginx -s stop
/usr/local/nginx/sbin/nginx
/usr/local/Tomcat01/bin/start.sh
/usr/local/Tomcat02/bin/start.sh
  • 接下來可以在實體機的瀏覽器進行測試了,連續存取虛擬機器器的nginx,這時Tomcat歡迎頁就會在01和02之間來回切換,至此負載均衡設定結束,然後大家可以回過頭去再建立一個Server02重新設定一遍了,因為keepalived就需要根據機器分主次了,組態檔是不一樣的,設定完成的話server01的nginx也可以設定將請求分發到server02的tomcat上,不過這裡為了演示就不新增了,後續好區分請求由哪臺機器響應。

設定keepalived

  • 參考Oracle Linux的設定

  • keepalived推薦使用yum安裝,原始碼安裝之後的設定挺複雜的

yum install keepalived
  • 安裝完成後需要設定keepalived的組態檔,檔案位於/etc/keepalived/keepalived.conf,下圖中為需要修改的部分,預設的組態檔中在其後還有很多內容,本範例只是簡單的DEMO,所以那些內容暫時用不上,可以全部刪除,核心設定說明如下:
vrrp_instance VI_1 {
    # 主伺服器為MASTER,其他伺服器均為BACKUP
    state MASTER
    # 通訊用的網路卡,在之前檢視IP時可以看到
    interface eno16777736
    # 主從伺服器此ID必須一致
    virtual_router_id 51
    # 優先順序,主伺服器必須大於其他伺服器,數值越大優先順序越高
    priority 100
    # 主從伺服器必須一致
    authentication {
        auth_type PASS
        auth_pass 1111
    }

    # 虛擬IP地址,主從伺服器必須一致,此IP為使用者端存取時使用的IP
    virtual_ipaddress {
        192.168.59.100
    }
}
  • 設定完此檔案後儲存退出,然後重啟keepalived服務,此時通過ip addr檢視發現主從伺服器上都有192.168.59.100的虛擬IP,原因是防火牆阻止了伺服器之間的vrrp通訊,分別執行以下命令,需要針對自己電腦進行修改的只有interface後的網路卡,其他的照抄即可
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface eno16777736 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface eno16777736 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
firewall-cmd --reload
  • 至此Keepalived的設定也完成了,通過ip addr檢視可發現主服務上帶有192.168.59.100的虛擬IP而從伺服器上沒有,關閉主伺服器的keepalived,虛擬IP則會轉移到從伺服器上來,測試伺服器通過瀏覽器存取 http://192.168.59.100 可看到虛擬IP轉移的效果,頁面會從主伺服器的頁面轉換為從伺服器的頁面,這裡就不上圖片了

  • 完成上述步驟之後keepalived已經可以實現虛擬IP轉移了,但是實際應用當中我們需要的是自動進行虛擬IP的轉移,所以我們還需要設定keepalived的指令碼,使其能夠在某一個nginx無法提供服務的時候自動將虛擬IP轉移到備用伺服器,以下指令碼來自於上邊提供的連結,原理是通過curl存取某一個連結,如果連續兩次三秒沒有響應則降低伺服器的優先順序,我們在/etc/keepalived目錄下建立一個名為check_status.sh的檔案,然後鍵入以下內容

#!/bin/bash
count=0
for (( k=0; k<2; k++ ))
do
    check_code=$( curl --connect-timeout 3 -sL -w "%{http_code}\\n" http://localhost/login.html -o /dev/null )
    if [ "$check_code" != "200" ]; then
        count=$(expr $count + 1)
        sleep 3
        continue
    else
        count=0
        break
    fi
done
if [ "$count" != "0" ]; then
    exit 1
else
    exit 0
fi
  • 因為指令碼後續是需要執行的,所以我們需要賦予可執行的許可權,此指令碼是我們自定義的,沒有什麼安全問題,此項操作需要在root使用者下執行,程式碼如下(這裡感謝 程式人生0407 的提醒)
chmod +x check_status.sh
  • 之後我們在keepalived.conf中設定指令碼,設定內容如下
vrrp_script check_status {
    script "/etc/keepalived/check_status.sh"
    interval 5
    weight -5
}
vrrp_instance VI_1 {
    state MASTER
    interface eno16777736
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.59.100
    }
    track_script {
        check_status
    }
}
  • 設定完成後重啟keepavlied即可,此時如果關閉本機的nginx的話可以看到在5秒後虛擬IP會漂移到備用伺服器上去,這裡因為演示的話圖片太多了,就不上圖片了,nginx退出可以執行nginx -s stop命令,如果是使用yum安裝的nginx可以通過systemctl來停止nginx服務

  • 實際使用當中經常使用到的還有在切換伺服器時傳送郵件用以提醒運維人員主伺服器異常,方法有很多種,此例中就不再贅述,有興趣的可以自行查詢相關資料

本範例到此結束,如果各位有什麼意見或建議,歡迎留言指教,轉載請註明源地址
另說明,markdown檔案中的程式碼由於未知原因傳上來以後格式有點混亂,大家使用的時候注意下格式,不要少個括號之類的。