天天看點

實踐:在CentOS7.3部署 keepalived 高可用nginx(負載均衡)

背景:

既然有了Lvs+keepalived這樣高性能的組合,那為何還要有Nginx+keepalived呢,keepalived的初衷就是為了Lvs而設計的,我們都知道Lvs是一個四層的負載均衡裝置,雖然有着高性能的優勢,但同時它卻沒有後端伺服器的健康檢查機制,keepalived為lvs設計了一系列的健康檢查機制TCP_CHECK,UDP_CHECK,HTTP_GET等。同時lvs也可以自己寫健康檢查腳腳本。或者結合ldirectory來實作後端檢測。但是固LVS始終無法擺脫它是一個四層裝置,無法對上層協定進行解析。Nginx不一樣,Nginx是一個七層的裝置可以對七層協定進行解析,可以對一些請求進行過濾,還可以對請求結果進行緩存。這些都是Nginx獨有的優勢。但是keepalived并沒有為Nginx提供健康檢測。需要自己去寫一些腳步來進行健康檢測。關于keepalived+lvs的建構可參考我的另一篇博文:

<a href="http://ljohn.blog.51cto.com/11932290/1980547" target="_blank">http://ljohn.blog.51cto.com/11932290/1980547</a>

更新:2017.11.28

筆者寫了一個Ansible-role 一鍵部署《keppalived+nginx 高可用叢集》

<a href="https://github.com/Ljohn001/Ansible-roles/tree/master/Ansible-keepalived-nginx-role">https://github.com/Ljohn001/Ansible-roles/tree/master/Ansible-keepalived-nginx-role</a>

CentOS6.9,CentOS7.4 經過反複測試沒毛病。正真實作一件就搞定,都準備放棄腳本投奔Ansible了。

廢話不多說開始建構 keppalived+nginx 高可用叢集

1、首先還是要準備環境

四台機器(CentOS7.3)

192.168.0.56 ---&gt; proxy1 (nginx)

192.168.0.57 ---&gt; proxy2 (nginx)

192.168.0.58 ---&gt; web1 (httpd)

192.168.0.59 ---&gt; web1 (httpd)

拓撲

<a href="https://s5.51cto.com/oss/201711/13/b99635652a623d2b48bcb4da7f1fe025.jpg" target="_blank"> </a>

注:

<code>1、這裡需要保持4台機器時間同步</code>

<code># ntpdate IP(ntp時鐘伺服器自行搭建不多介紹)</code>

<code>*</code><code>/5</code> <code>* * * * root </code><code>/usr/sbin/ntpdate</code> <code>192.168.1.99 &amp;&gt;</code><code>/dev/null</code><code>;hwclock -w</code>

<code>2、為了操作的友善後面配置對所有參與機器進行免密處理</code>

<code># ssh-keygen -t rsa -P '' -f "/root/.ssh/id_rsa"</code>

<code># for i in 56 57 58 59;do ssh-copy-id -i .ssh/id_rsa.pub [email protected].$i;done</code>

2、配置realserver(web1和web2)

a、安裝web程式

注意這裡的realserver 可以是任何web容器(tomcat、jetty、httpd、nginx..),因為是學習,是以這裡使用httpd來示範

<code>#yum install httpd -y</code>

<code>#systemctl restart httpd</code>

<code># netstat -nultp| grep httpd##確定httpd啟動</code>

<code>tcp6       0      0 :::80                   :::*                    LISTEN      4619</code><code>/httpd</code>

<code>配置頁面</code>

<code>web1:</code>

<code># echo "&lt;h1&gt;The page from web1(58)&lt;/h1&gt;" &gt; /var/www/html/index.html</code>

<code>web2:</code>

<code># echo "&lt;h1&gt;The page from web1(59)&lt;/h1&gt;" &gt; /var/www/html/index.html</code>

b、設定VIP及核心參數

<code>#編寫腳本如下:</code>

<code># cat setka.sh</code>

<code>#!/bin/bash</code>

<code>vip=192.168.0.100</code>

<code>case</code> <code>$1 </code><code>in</code>

<code>start)</code>

<code>echo</code> <code>1 &gt; </code><code>/proc/sys/net/ipv4/conf/all/arp_ignore</code>

<code>echo</code> <code>1 &gt; </code><code>/proc/sys/net/ipv4/conf/lo/arp_ignore</code>

<code>echo</code> <code>2 &gt; </code><code>/proc/sys/net/ipv4/conf/all/arp_announce</code>

<code>echo</code> <code>2 &gt; </code><code>/proc/sys/net/ipv4/conf/lo/arp_announce</code>

<code>ifconfig</code> <code>lo:0 $vip broadcast $vip netmask 255.255.255.255 up</code>

<code>;;</code>

<code>stop)</code>

<code>ifconfig</code> <code>lo:0 down</code>

<code>echo</code> <code>0 &gt; </code><code>/proc/sys/net/ipv4/conf/all/arp_ignore</code>

<code>echo</code> <code>0 &gt; </code><code>/proc/sys/net/ipv4/conf/lo/arp_ignore</code>

<code>echo</code> <code>0 &gt; </code><code>/proc/sys/net/ipv4/conf/all/arp_announce</code>

<code>echo</code> <code>0 &gt; </code><code>/proc/sys/net/ipv4/conf/lo/arp_announce</code>

<code>esac</code>

<code># bash setka.sh start   #運作該腳本設定相關核心參數及VIP位址。</code>

<code># cat /proc/sys/net/ipv4/conf/lo/arp_ignore   #核心參數設定成功</code>

<code>1</code>

<code># cat /proc/sys/net/ipv4/conf/all/arp_announce</code>

<code>2</code>

<code># ifconfig lo:0   #VIP設定成功</code>

<code>lo:0      Link encap:Local Loopback</code>

<code>inet addr:192.168.137.10  Mask:255.255.255.255</code>

<code>UP LOOPBACK RUNNING  MTU:65536  Metric:1</code>

<code># scp setka.sh [email protected]:/root  #拷貝一份給web2并執行</code>

<code>setka.sh                                                                                         100%  547     0.5KB</code><code>/s</code>   <code>00:00</code>

3、配置nginx proxy1和2 負載均衡

a、兩台proxy都安裝nginx

<code>yum </code><code>install</code> <code>-y nginx</code>

b、配置nginx proxy

<code>vim </code><code>/etc/nginx/nginx</code><code>.conf</code>

<code>upstream backserver {</code>

<code>server 192.168.0.58:80 weight=1 max_fails=3 fail_timeout=3s;</code>

<code>server 192.168.0.59:80 weight=2 max_fails=3 fail_timeout=3s;</code>

<code>}</code>

<code>server {</code>

<code>listen       80;</code>

<code>server_name  localhost;</code>

<code>location / {</code>

<code>root   html;</code>

<code>index  index.html index.htm;</code>

<code>proxy_pass http:</code><code>//backserver</code><code>;</code>

<code>proxy_set_header X-Real-IP $remote_addr;</code>

<code>proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;</code>

複制一份至另一台proxy(nginx)

<code># scp /etc/nginx/nginx.conf [email protected]:/etc/nginx/nginx.conf</code>

<code># systemctl restart nginx;ssh 192.168.0.57 ‘systemctl restart nginx’</code>

c、測試通路

<code># for i in {1..10};do curl http://192.168.0.56;done</code>

<code>&lt;h1&gt;The page from web1(58)&lt;</code><code>/h1</code><code>&gt;</code>

<code>&lt;h1&gt;The page from web1(59)&lt;</code><code>/h1</code><code>&gt;</code>

<code># for i in {1..10};do curl http://192.168.0.57;done</code>

#注:這裡可以看出,每台proxy(nginx) 都完成了負載均衡配置,且實作了負載均衡排程。細心的同學發現後端real server 配置的權重1:2,排程大緻請求排程傳回也為1:2

4、配置keepalived 高可用nginx

a、每台proxy安裝httpd 和keepalived

<code># yum install -y httpd keepalived</code>

每台proxy 配置Sorry頁面,這裡一旦後端伺服器同時無法通路,會自動調用本地的httpd服務

<code># echo "&lt;h1&gt;Sorry,Under maintances(56).&lt;/h1&gt;" &gt;/var/www/html/index.html</code>

<code># echo "&lt;h1&gt;Sorry,Under maintances(57).&lt;/h1&gt;" &gt;/var/www/html/index.html</code>

<code># 編輯各個proxy 的 nginx.conf,添加在upstream下添加</code>

<code>server 127.0.0.1:8080 backup;</code>

<code>或者:</code><code># sed -i '/server 192.168.0.59:80 weight=2 max_fails=3 fail_timeout=3s;/a\server 127.0.0.1:8080 backup;' /etc/nginx/nginx.conf</code>

b、編輯配置檔案

proxy1:

<code># cat /etc/keepalived/keepalived.conf</code>

<code>! Configuration File </code><code>for</code> <code>keepalived</code>

<code>global_defs {</code>

<code>notification_email {</code>

<code>root@localhost    </code><code>#定義郵箱報警的郵箱位址</code>

<code>notification_email_from root@localhost </code><code>#定義發送報警資訊的位址</code>

<code>smtp_server 127.0.0.1 </code><code>#定義發送郵件的郵件伺服器位址</code>

<code>smtp_connect_timeout 30 </code><code>#定義發送郵件的逾時時間</code>

<code>router_id ha_nginx </code><code>#全局辨別</code>

<code>vrrp_script chk_nginx {    </code><code>#定義檢查nginx服務的腳本</code>

<code>script </code><code>"/etc/keepalived/chk_nginx.sh"</code>  <code>#腳本重新開機nginx,如果程序還是無法檢測到,則強制停止keepalived</code>

<code>interval 2 </code><code>#檢查的間隔時間</code>

<code>weight -2 </code><code>#檢查失敗的話權重減2</code>

<code>fall 2 </code><code>#檢查失敗2次才認為是真正的檢查失敗</code>

<code>vrrp_instance VI_1 {</code>

<code>state MASTER</code>

<code>interface ens33</code>

<code>virtual_router_id 51</code>

<code>priority 100  </code><code>#備用機器的keepalived的權重要小于這個權重,并且當nginx服務挂掉後100-2要小于備用機器的權重。</code>

<code>advert_int 1</code>

<code>smtp_alert </code><code>#比較重要 定義使用郵件發送,不然上面的郵件定義都是沒有用的,使用了這個當狀态發生改變就會發送郵件報警</code>

<code>authentication {</code>

<code>auth_type PASS</code>

<code>auth_pass 1111</code>

<code>track_script {    </code><code>#定義使用哪個腳本來檢查。</code>

<code>chk_nginx</code>

<code>virtual_ipaddress {</code>

<code>192.168.0.100</code><code>/16</code> <code>dev ens33 label ens33:1</code>

##拷貝配置檔案至proxy2

<code># scp /etc/keepalived/keepalived.conf [email protected]:/etc/keepalived/keepalived.conf</code>

proxy2:

修改keepalived.conf 如下兩個參數:

state BACKUP

priority 99

#這裡貼出我實驗的配置

# cat /etc/keepalived/keepalived.conf

<code>script </code><code>"/etc/keepalived/chk_nginx.sh"</code> <code>#腳本重新開機nginx,如果程序還是無法檢測到,則強制停止keepalived</code>

<code>state BACKUP</code>

<code>priority 99  </code><code>#備用機器的keepalived的權重要小于這個權重,并且當nginx服務挂掉後100-2要小于備用機器的權重。</code>

c、nginx檢測腳本

#腳本先判斷是否有nginx程序,然後如果沒有,則會重新開機nginx,如果程序還是無法檢測到,則強制停止keepalived,啟用備用節點的作為master。

#該腳本可以有效防止HA腦裂,發現無發啟動nginx嘗試重新開機,不行再将keepalived關閉,徹底移除此節點。

<code>#cat /etc/keepalived/chk_nginx.sh</code>

<code>N=`</code><code>ps</code> <code>-C nginx --no-header|</code><code>wc</code> <code>-l`</code>

<code>if</code> <code>[ $N -</code><code>eq</code> <code>0 ];</code><code>then</code>

<code>systemctl restart keepalived</code>

<code>sleep</code> <code>1</code>

<code>if</code> <code>[ `</code><code>ps</code> <code>-C nginx --no-header|</code><code>wc</code> <code>-l` -</code><code>eq</code> <code>0 ];</code><code>then</code>

<code>systemctl stop keepalived</code>

<code>fi</code>

d、啟動keepalived及nginx

<code># systemctl restart nginx;ssh 192.168.0.57 'systemctl restart nginx'</code>

<code># systemctl restart keepalived.service;ssh 192.168.0.57 'systemctl restart keepalived.service'</code>

5、測試

1、檢視位址是否在proxy1上:

<code># ip a</code>

<code>1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN qlen 1</code>

<code>link</code><code>/loopback</code> <code>00:00:00:00:00:00 brd 00:00:00:00:00:00</code>

<code>inet 127.0.0.1</code><code>/8</code> <code>scope host lo</code>

<code>valid_lft forever preferred_lft forever</code>

<code>inet6 ::1</code><code>/128</code> <code>scope host</code>

<code>2: ens33: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000</code>

<code>link</code><code>/ether</code> <code>00:0c:29:d6:84:65 brd ff:ff:ff:ff:ff:ff</code>

<code> </code><code>inet 192.168.0.56</code><code>/24</code> <code>brd 192.168.0.255 scope global ens33</code>

<code>  </code><code>inet 192.168.0.100</code><code>/16</code> <code>scope global ens33:1</code>

<code>inet6 fe80::20c:29ff:fed6:8465</code><code>/64</code> <code>scope link</code>

測試網頁是否能夠打開。

<code># for i in {1..5};do curl http://192.168.0.100;done</code>

這裡能夠正常通路,測試通過。

2、關閉主節點的keepalived測試VIP是否能夠漂移至備用節點

<code>[root@node2 keepalived]</code><code># ip a</code>

<code>link</code><code>/ether</code> <code>00:0c:29:7c:92:ae brd ff:ff:ff:ff:ff:ff</code>

<code>   </code><code>inet 192.168.0.57</code><code>/24</code> <code>brd 192.168.0.255 scope global ens33</code>

<code> </code><code>inet 192.168.0.100</code><code>/16</code> <code>scope global ens33:1</code>

<code>inet6 fe80::20c:29ff:fe7c:92ae</code><code>/64</code> <code>scope link</code>

檢視VIP是否能正常通路

5、由于我們配置的搶占模式,一旦主節點恢複,則VIP會直接漂回去。

<code>[root@node1 ~]</code><code># systemctl  start  keepalived</code>

<code>[root@node1 ~]</code><code># ip a</code>

<code>inet 192.168.0.56</code><code>/24</code> <code>brd 192.168.0.255 scope global ens33</code>

測試VIP通路

VIP位址又被主節點搶回來,服務正常通路,通過測試

最後我們來看下一下備用節點的在主節點keepalived關閉時,系統到底做了什麼

##檢視日志,觀察VIP漂移的整個過程

1、傳遞MASTER的狀态

2、設定自己為MASTER狀态,

3、設定VIP 虛拟位址

4、發送ARP廣播位址 ,位址為:192.168.0.100 #告訴大家我現在叫MASTER,對外提供服務了。

備用節點上/var/log/messages:

Nov 13 16:46:02 localhost Keepalived_vrrp[12348]: VRRP_Instance(VI_1) Transition to MASTER STATE

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: VRRP_Instance(VI_1) Entering MASTER STATE

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: VRRP_Instance(VI_1) setting protocol VIPs.

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: Sending gratuitous ARP on ens33 for 192.168.0.100

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on ens33 for 192.168.0.100

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: Sending gratuitous ARP on ens33 for 192.168.0.100

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: Remote SMTP server [127.0.0.1]:25 connected.

FAQ:

Q:再/var/log/messages日志中發現:Unable to access script `killall`

A:因為centos7精簡安裝,沒有killall指令,需要安裝一下

# yum install psmisc -y

至此在CentOS7.3上完成了:keepalived 高可用nginx,有興趣的同學可以玩一下,有什麼問題,還請批評指正。

本文轉自 ljohnmail 51CTO部落格,原文連結:http://blog.51cto.com/ljohn/1981369,如需轉載請自行聯系原作者

繼續閱讀