1. 程式人生 > >Keepalived+LVS+nginx搭建nginx高可用叢集

Keepalived+LVS+nginx搭建nginx高可用叢集

       nginx是一款非常優秀的反向代理工具,支援請求分發,負載均衡,以及快取等等非常實用的功能。在請求處理上,nginx採用的是epoll模型,這是一種基於事件監聽的模型,因而其具備非常高效的請求處理效率,單機併發能力能夠達到上百萬。nginx接收到的請求可以通過負載均衡策略分發到其下一級的應用伺服器,這些伺服器一般是以叢集方式部署的,因而在效能不足的情況下,應用伺服器可以通過加機器的方式擴充套件流量。此時,對於一些特大型的網站,效能的瓶頸就來自於nginx了,因為單機的nginx的併發能力是有上限的,而nginx本身是不支援叢集模式的,因而此時對nginx的橫向擴充套件就顯得尤為重要。

       keepalived是一款伺服器狀態檢測和故障切換的工具。在其配置檔案中,可以配置主備伺服器和該伺服器的狀態檢測請求。也就是說keepalived可以根據配置的請求,在提供服務期間不斷向指定伺服器傳送請求,如果該請求返回的狀態碼是200,則表示該伺服器狀態是正常的,如果不正常,那麼keepalived就會將該伺服器給下線掉,然後將備用伺服器設定為上線狀態。

        lvs是一款用於四層負載均衡的工具。所謂的四層負載均衡,對應的是網路七層協議,常見的如HTTP協議是建立在七層協議上的,而lvs作用於四層協議上,也即:傳輸層,網路層,資料鏈路層和物理層。這裡的傳輸層主要協議有TCP和UDP協議,也就是說lvs主要支援的方式是TCP和UDP。也正是因為lvs是處於四層負載均衡上的,因而其處理請求的能力比常見的伺服器要高非常多,比如nginx的請求處理就是建立在網路七層上的,lvs的負載均衡能力是nginx的十倍以上。

       通過上面的介紹,我們可以發現,在特大型網站中,應用伺服器是可以橫向擴容的,而nginx是不支援橫向擴容的,此時nginx就會成為效能瓶頸。而lvs是一款負載均衡工具,因而如果我們結合lvs和nginx,那麼就可以通過部署多臺nginx伺服器,通過lvs的負載均衡能力,將請求均衡的分發到各個nginx伺服器上,再由nginx伺服器分發到各個應用伺服器,這樣,我們就實現了nginx的橫向擴充套件了。由於nginx本質上也是一款應用伺服器,因而其也有可能宕機,因而這裡結合keepalived就可以實現nginx的故障檢測和服務切換。也就是說,通過keepalived+lvs+nginx,我們實現了nginx的高可用叢集模式。

       在上面的介紹中,我們會注意到,雖然keepalived+lvs+nginx實現了nginx的叢集模式,但是在我們使用nginx的時候,其本身是有一個ip和埠的,預設監聽的埠是80和443,那麼lvs是如何實現將請求分發給具有不同ip和埠的nginx伺服器的呢?這裡就是通過虛擬ip實現的,所謂虛擬ip就是對外提供一個公共的ip,外部客戶端請求的都是這個ip,lvs在接收到虛擬ip的請求之後,通過配置的排程器和負載均衡策略,選擇一個目標nginx伺服器,然後將請求轉發給該伺服器。這裡lvs有兩個概念,就是排程器和負載均衡策略,所謂的排程器指的是lvs將會以何種方式處理請求和響應資料,其主要有三種排程器:

  • Virtual Server via Network Address Translation(VS/NAT):這種方式的主要原理是,使用者傳送請求到虛擬ip上後,lvs會根據負載均衡演算法選擇一個目標處理服務,然後將請求報文中的目標ip地址修改為計算得到的目標伺服器,並且傳送給該伺服器。對於響應的報文,排程器會將目標伺服器返回的響應資料中的源地址修改為虛擬ip地址。通過這種方式,對客戶端而言,其形式上面向的是一臺伺服器。不過這種方式的缺點在於,所有的響應資料都需要通過排程器,如果請求量比較大的情況下,那麼排程器就會成為整個系統的瓶頸。
  • Virtual Server via IP Tunneling(VS/TUN):這種方式主要解決的就是VS/NAT中,響應資料會經過排程器的問題。同VS/NAT一樣 ,排程器還是會接收請求的資料,並且將報文中的目標ip修改為目標服務的ip,但是在目標服務處理完資料之後,其會直接將響應報文中的源ip修改為虛擬ip,然後將請求傳送給客戶端。通過這種方式,響應資料就由各個目標服務進行了處理,而無需通過排程器進行返回,這種方式會大大提高系統的吞吐量,而且由於一般請求報文比響應報文小很多,排程器也只需要處理請求報文,那麼系統的整體負載將會被均攤到各個伺服器上。
  • Virtual Server via Direct Routing(VS/DR):這種方式相對於VS/TUN,其主要區別在於,VS/NAT是將請求報文中的ip地址修改為目標服務的ip地址,而VS/DR則是直接將請求報文中的MAC地址修改為目標地址,這種方式效率會更高,因為VS/TUN中的ip地址最終還是需要轉換為MAC地址來發送資料的。

1. 環境準備

1. VMware;
2. 4臺CentOs7虛擬主機:172.16.28.130, 172.16.28.131, 172.16.28.132, 172.16.28.133
3. 系統服務:LVS, Keepalived
4. Web伺服器:nginx
5. 叢集搭建:LVS DR模式

2. 軟體安裝

        在四臺虛擬機器上,我們以如下方式搭建叢集:

172.16.28.130 lvs+keepalived
172.16.28.131 lvs+keepalived
172.16.28.132 nginx
172.16.28.133 nginx

        這裡我們使用172.16.28.130172.16.28.131兩臺機器作為lvs+keepalived的工作機器,也就是說這兩臺機器的作用主要是進行負載均衡和故障檢測和下線的;我們使用172.16.28.132172.16.28.133兩臺機器作為應用伺服器,主要是對外提供服務的。這四臺伺服器作為整個後端叢集服務,並且對外提供的虛擬ip是172.16.28.120。需要說明的是,這裡的keepalived所檢測的服務是兩臺lvs伺服器,這兩臺伺服器,一臺作為master伺服器,一臺作為backup伺服器,兩者在負載均衡的配置上是完全一樣的。在正常情況下,客戶端請求虛擬ip的時候,lvs會將該請求轉發到master伺服器上,然後master伺服器根據配置的負載均衡策略選擇一臺應用伺服器,並且將請求傳送給該應用伺服器進行處理。如果在某個時刻,lvs的master伺服器由於故障宕機了,keepalived就會檢測到該故障,並且進行故障下線,然後將backup機器上線用於提供服務,從而實現故障轉移的功能。

2.1 lvs+keepalived安裝

        在172.16.28.130172.16.28.131上安裝ipvs和keepalived:

# 安裝ipvs
sudo yum install ipvsadm
# 安裝keepalived
sudo yum install keepalived

        在172.16.28.132172.16.28.133上安裝nginx:

# 安裝nginx
sudo yum install nginx

        需要注意的是,在兩臺nginx伺服器上需要將防火牆關閉,否則lvs+keepalived的兩臺機器就無法將請求傳送到兩臺nginx伺服器上來:

# 關閉防火牆
systemctl disable firewalld.service

        檢視兩臺負載均衡機器是否支援lvs:

sudo lsmod |grep ip_vs
# 如果看到如下結果,則說明是支援的
[zhangxufeng@localhost ~]$ sudo lsmod|grep ip_vs
ip_vs                 145497  0
nf_conntrack          137239  1 ip_vs
libcrc32c              12644  3 xfs,ip_vs,nf_conntrack

        如果上述命令沒有任何結果,則執行sudo ipvsadm命令啟動ipvs之後,再通過上述命令進行檢視即可。啟動ipvs之後,我們就可以在/etc/keepalived/目錄下編輯keepalived.conf檔案,我們以172.16.28.130機器作為master機器,master節點配置如下:

# Global Configuration
global_defs {
  lvs_id director1  # 指定lvs的id
}

# VRRP Configuration
vrrp_instance LVS {
  state MASTER	# 指定當前節點為master節點
  interface ens33	# 這裡的ens33是網絡卡的名稱,通過ifconfig或者ip addr可以檢視
  virtual_router_id 51	# 這裡指定的是虛擬路由id,master節點和backup節點需要指定一樣的
  priority 151	# 指定了當前節點的優先順序,數值越大優先順序越高,master節點要高於backup節點
  advert_int 1	# 指定傳送VRRP通告的間隔,單位是秒
  authentication {
    auth_type PASS	# 鑑權,預設通過
    auth_pass 123456	# 鑑權訪問密碼
  }

  virtual_ipaddress {
    172.16.28.120	# 指定了虛擬ip
  }

}

# Virtual Server Configuration - for www server
# 後臺真實主機的配置
virtual_server 172.16.28.120 80 {
  delay_loop 1	# 健康檢查的時間間隔
  lb_algo rr	# 負載均衡策略,這裡是輪詢
  lb_kind DR	# 排程器型別,這裡是DR
  persistence_time 1	# 指定了持續將請求打到同一臺真實主機的時間長度
  protocol TCP	# 指定了訪問後臺真實主機的協議型別

  # Real Server 1 configuration
  # 指定了真實主機1的ip和埠
  real_server 172.16.28.132 80 {
    weight 1	# 指定了當前主機的權重
    TCP_CHECK {
      connection_timeout 10	# 指定了進行心跳檢查的超時時間
      nb_get_retry 3	# 指定了心跳超時之後的重複次數
      delay_before_retry 3	# 指定了在嘗試之前延遲多長時間
    }
  }

  # Real Server 2 Configuration
  real_server 172.16.28.133 80 {
    weight 1	# 指定了當前主機的權重
    TCP_CHECK {
      connection_timeout 10	# 指定了進行心跳檢查的超時時間
      nb_get_retry 3	# 指定了心跳超時之後的重複次數
      delay_before_retry 3	# 指定了在嘗試之前延遲多長時間
    }
  }
}

        上面是master節點上keepalived的配置,對於backup節點,其配置與master幾乎是一致的,只是其state和priority引數不同。如下是backup節點的完整配置:

# Global Configuration
global_defs {
  lvs_id director2  # 指定lvs的id
}

# VRRP Configuration
vrrp_instance LVS {
  state BACKUP	# 指定當前節點為master節點
  interface ens33	# 這裡的ens33是網絡卡的名稱,通過ifconfig或者ip addr可以檢視
  virtual_router_id 51	# 這裡指定的是虛擬路由id,master節點和backup節點需要指定一樣的
  priority 150	# 指定了當前節點的優先順序,數值越大優先順序越高,master節點要高於backup節點
  advert_int 1	# 指定傳送VRRP通告的間隔,單位是秒
  authentication {
    auth_type PASS	# 鑑權,預設通過
    auth_pass 123456	# 鑑權訪問密碼
  }

  virtual_ipaddress {
    172.16.28.120	# 指定了虛擬ip
  }

}

# Virtual Server Configuration - for www server
# 後臺真實主機的配置
virtual_server 172.16.28.120 80 {
  delay_loop 1	# 健康檢查的時間間隔
  lb_algo rr	# 負載均衡策略,這裡是輪詢
  lb_kind DR	# 排程器型別,這裡是DR
  persistence_time 1	# 指定了持續將請求打到同一臺真實主機的時間長度
  protocol TCP	# 指定了訪問後臺真實主機的協議型別

  # Real Server 1 configuration
  # 指定了真實主機1的ip和埠
  real_server 172.16.28.132 80 {
    weight 1	# 指定了當前主機的權重
    TCP_CHECK {
      connection_timeout 10	# 指定了進行心跳檢查的超時時間
      nb_get_retry 3	# 指定了心跳超時之後的重複次數
      delay_before_retry 3	# 指定了在嘗試之前延遲多長時間
    }
  }

  # Real Server 2 Configuration
  real_server 172.16.28.133 80 {
    weight 1	# 指定了當前主機的權重
    TCP_CHECK {
      connection_timeout 10	# 指定了進行心跳檢查的超時時間
      nb_get_retry 3	# 指定了心跳超時之後的重複次數
      delay_before_retry 3	# 指定了在嘗試之前延遲多長時間
    }
  }
}

        將master和backup配置成完全一樣的原因是,在master宕機時,可以根據backup的配置進行服務的無縫切換。

        在lvs+keepalived機器配置完成之後,我們下面配置兩臺應用伺服器的nginx配置。這裡我們是將nginx作為應用伺服器,在其配置檔案中配置返回狀態碼為200,並且會將當前主機的ip返回,如下是其配置:

worker_processes auto;
# pid /run/nginx.pid;

events {
  worker_connections 786;
}

http {
  server {
    listen 80;

    # 這裡是直接返回200狀態碼和一段文字
    location / {
      default_type text/html;
      return 200 "Hello, Nginx! Server [email protected]\n";
    }
  }
}
worker_processes auto;
# pid /run/nginx.pid;

events {
  worker_connections 786;
}

http {
  server {
    listen 80;

    # 這裡是直接返回200狀態碼和一段文字
    location / {
      default_type text/html;
      return 200 "Hello, Nginx! Server [email protected]\n";
    }
  }
}

        可以看到,兩臺機器返回的文字中主機ip是不一樣的。nginx配置完成後,可以通過如下命令進行啟動:

sudo nginx

        在啟動nginx之後,我們需要配置虛擬ip,這是因為我們使用的lvs排程器是DR模式,前面我們講到過,這種模式下,對客戶端的響應是真實伺服器直接返回給客戶端的,而真實伺服器需要將響應報文中的源ip修改為虛擬ip,這裡配置的虛擬ip就是起這個作用的。我們編輯/etc/init.d/lvsrs檔案,寫入如下內容:

#!/bin/bash

ifconfig lo:0 172.16.28.120 netmask 255.255.255.255 broadcast 172.16.28.120 up
route add -host 172.16.28.120 dev lo:0

echo "0" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce

exit 0
  • lo:表示當前主機真實網絡卡的名稱;
  • 172.16.28.120:表示虛擬ip;

        編寫完成後執行該指令碼檔案即可。然後將兩臺lvs+keepalived機器上的keepalived服務啟動起來即可:

sudo service keepalived start

        最後可以通過如下命令檢視配置的lvs+keepalived的策略:

[zhangxufeng@localhost keepalived]$ sudo ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.16.28.120:80 rr
  -> 172.16.28.132:80             Route   1      0          0

2.2 叢集測試

        根據上述步驟,我們配置完成了一個lvs+keepalived+nginx的叢集。在瀏覽器中,我們可以訪問http://172.16.28.120即可看到如下響應:

Hello, Nginx! Server [email protected]

        多次重新整理瀏覽器之後,可以看到瀏覽器中顯示的文字切換如下,這是因為lvs的負載均衡策略產生的:

Hello, Nginx! Server [email protected]

3. 小結

        本文首先對lvs和keepalived的工作原理進行了講解,分別介紹了其工作的幾種模式,然後對lvs+keepalived+nginx搭建nginx叢集的方式進行詳細講解,並且說明了其中所需