本篇内容主要用三個腳本來實作LVS的配置。腳本1:lvs.sh 是配置在負載均衡端,腳本2:realserver.sh 是配置後端Real Server伺服器上的。腳本3:check_lvs.sh 是用在負載均衡端上來測試後端伺服器的健康狀态的腳本,如有一個Real Server 當機就會自動清除,如果恢複了就再加上,後端所有伺服器都當機了,會把負載均衡端提供的錯誤頁面加到叢集中來。
規劃:
負載均衡:
DIP:192.168.1.11
VIP:192.168.1.10
背景Real Server有兩個分别為:
rs1:192.168.1.9
rs2:192.168.1.8
在192.168.1.11上安裝ipvsadm和httpd服務,當在後端伺服器都當機時提供錯誤頁面。
yum install ipvsadm -y
在rs1,rs2上分别安裝httpd服務,并啟動服務,提供網頁。
yum install httpd -y
在192.168.1.11伺服器上編寫腳本lvs.sh
cd /opt/scripts
vim lvs.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<code>#!/bin/bash</code>
<code>#</code>
<code># LVS script for VS/DR</code>
<code># chkconfig: - 90 10</code>
<code>. </code><code>/etc/rc</code><code>.d</code><code>/init</code><code>.d</code><code>/functions</code>
<code> </code>
<code>VIP=192.168.1.10</code>
<code>DIP=192.168.1.11</code>
<code>RIP1=192.168.1.9</code>
<code>RIP2=192.168.1.8</code>
<code>PORT=80</code>
<code>RSWEIGHT1=2</code>
<code>RSWEIGHT2=5</code>
<code>case</code> <code>"$1"</code> <code>in</code>
<code> </code><code>start)</code>
<code> </code><code>/sbin/ifconfig</code> <code>eth0:0 $VIP broadcast $VIP netmask 255.255.255.255 up </code>
<code> </code><code>#啟用eth0:0來配置VIP</code>
<code> </code><code>/sbin/route</code> <code>add -host $VIP dev eth0:0</code>
<code> </code><code>#添加VIP路由資訊</code>
<code> </code><code>echo</code> <code>1 > </code><code>/proc/sys/net/ipv4/ip_forward</code>
<code> </code><code>#打開ip轉發功能</code>
<code> </code><code>/sbin/iptables</code> <code>-F</code>
<code> </code><code>/sbin/iptables</code> <code>-Z</code>
<code> </code><code>#清空iptables規則</code>
<code> </code>
<code> </code><code>/sbin/ipvsadm</code> <code>-C</code>
<code> </code><code>/sbin/ipvsadm</code> <code>-A -t $VIP:80 -s wlc</code>
<code> </code><code>/sbin/ipvsadm</code> <code>-a -t $VIP:$PORT -r $RIP1:$PORT -g -w $RSWEIGHT1</code>
<code> </code><code>/sbin/ipvsadm</code> <code>-a -t $VIP:$PORT -r $RIP2:$PORT -g -w $RSWEIGHT2</code>
<code> </code><code>#添加ipvs規則</code>
<code> </code><code>/bin/touch</code> <code>/var/lock/subsys/ipvsadm</code> <code>&> </code><code>/dev/null</code>
<code> </code><code>#建立鎖檔案</code>
<code> </code><code>;;</code>
<code> </code><code>stop)</code>
<code> </code><code>echo</code> <code>0 > </code><code>/proc/sys/net/ipv4/ip_forward</code>
<code> </code><code>/sbin/ifconfig</code> <code>eth0:0 down</code>
<code> </code><code>/sbin/route</code> <code>del $VIP</code>
<code> </code><code>/bin/rm</code> <code>-f </code><code>/var/lock/subsys/ipvsadm</code>
<code> </code><code>echo</code> <code>"ipvs is stopped...."</code>
<code> </code><code>status)</code>
<code> </code><code>if</code> <code>[ ! -e </code><code>/var/lock/subsys/ipvsadm</code> <code>]; </code><code>then</code>
<code> </code><code>echo</code> <code>"ipvsadm is stopped ..."</code>
<code> </code><code>else</code>
<code> </code><code>echo</code> <code>"ipvs is running ..."</code>
<code> </code><code>ipvsadm -L -n</code>
<code> </code><code>fi</code>
<code> </code><code>*)</code>
<code> </code><code>echo</code> <code>"Usge: $0 {start|stop|status}"</code>
<code>esac</code>
此腳本可以加到系統服務清單中,并可以設定開機自動啟動。
在後端伺服器rs1和rs2中編寫腳本realserver.sh如下:
<code># Script to start LVS DR real server.</code>
<code># description: LVS DR real server</code>
<code>. </code><code>/etc/rc</code><code>.d</code><code>/init</code><code>.d</code><code>/functions</code>
<code>host=`</code><code>/bin/hostname</code><code>`</code>
<code> </code><code>/sbin/ifconfig</code> <code>lo down</code>
<code> </code><code>/sbin/ifconfig</code> <code>lo up</code>
<code> </code><code>echo</code> <code>1 > </code><code>/proc/sys/net/ipv4/conf/lo/arp_ignore</code>
<code> </code><code>echo</code> <code>2 > </code><code>/proc/sys/net/ipv4/conf/lo/arp_announce</code>
<code> </code><code>echo</code> <code>1 > </code><code>/proc/sys/net/ipv4/conf/all/arp_ignore</code>
<code> </code><code>echo</code> <code>2 > </code><code>/proc/sys/net/ipv4/conf/all/arp_announce</code>
<code> </code><code>/sbin/ifconfig</code> <code>lo:0 $VIP broadcast $VIP netmask 255.255.255.255 up</code>
<code> </code><code>/sbin/route</code> <code>add -host $VIP dev lo:0</code>
<code> </code><code>/sbin/ifconfig</code> <code>lo:0 down</code>
<code> </code><code>echo</code> <code>0 > </code><code>/proc/sys/net/ipv4/conf/lo/arp_ignore</code>
<code> </code><code>echo</code> <code>0 > </code><code>/proc/sys/net/ipv4/conf/lo/arp_announce</code>
<code> </code><code>echo</code> <code>0 > </code><code>/proc/sys/net/ipv4/conf/all/arp_ignore</code>
<code> </code><code>echo</code> <code>0 > </code><code>/proc/sys/net/ipv4/conf/all/arp_announce</code>
<code> </code><code>islothere=`</code><code>/sbin/ifconfig</code> <code>lo:0 | </code><code>grep</code> <code>$VIP`</code>
<code> </code><code>isrothere=`</code><code>netstat</code> <code>-rn | </code><code>grep</code> <code>"lo:0"</code> <code>| </code><code>grep</code> <code>$VIP`</code>
<code> </code><code>if</code> <code>[ ! </code><code>"$islothere"</code> <code>-o ! </code><code>"isrothere"</code> <code>];</code><code>then</code>
<code> </code><code># Either the route or the lo:0 device</code>
<code> </code><code># not found.</code>
<code> </code><code>echo</code> <code>"LVS-DR real server Stopped."</code>
<code> </code><code>echo</code> <code>"LVS-DR real server Running."</code>
<code> </code><code>echo</code> <code>"$0: Usage: $0 {start|status|stop}"</code>
<code> </code><code>exit</code> <code>1</code>
完成後可以啟動腳本了。
LVS自身沒有對後端伺服器的健康狀态檢測功能,下面在192.168.1.11伺服器上來使用腳本來每5s種檢測下背景伺服器健康狀态,并實作自動清除當機的伺服器,恢複後可以自動添加。
vim check_lvs.sh
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<code>VIP=192.168.19.211</code>
<code>CPORT=80</code>
<code>FAIL_BACK=127.0.0.1</code>
<code>RS=(</code><code>"192.168.19.245"</code> <code>"192.168.19.219"</code><code>) </code><code>#定義一個數組并指派</code>
<code>declare</code> <code>-a RSSTATUS </code><code>#定義一個空數組</code>
<code>RW=(</code><code>"2"</code> <code>"1"</code><code>)</code>
<code>RPORT=80</code>
<code>TYPE=g </code><code>#定義為DR模型</code>
<code>CHKLOOP=3</code>
<code>LOG=</code><code>/var/log/ipvsmonitor</code><code>.log</code>
<code> </code><code>#定義一個添加規則的函數 </code>
<code>addrs() {</code>
<code> </code><code>if</code> <code>ipvsadm -L -n | </code><code>grep</code> <code>"$1:$RPORT"</code> <code>&> </code><code>/dev/null</code><code>;</code><code>then</code>
<code> </code><code>return</code> <code>0</code>
<code> </code><code>else</code>
<code> </code><code>ipvsadm -a -t $VIP:$CPORT -r $1:$RPORT -$TYPE -w $2</code>
<code> </code><code>[ $? -</code><code>eq</code> <code>0 ] && </code><code>return</code> <code>0 || </code><code>return</code> <code>1</code>
<code> </code><code>fi</code>
<code>}</code>
<code>#定義删除規則的函數 </code>
<code>delrs() {</code>
<code> </code><code>ipvsadm -d -t $VIP:$CPORT -r $1:$RPORT</code>
<code>#定義是否要添加錯誤頁面的規則的函數 </code>
<code>ifaddls() {</code>
<code> </code><code>if</code> <code>[ ${RSSTATUS[0]} -</code><code>eq</code> <code>0 ];</code><code>then</code>
<code> </code><code>if</code> <code>[ ${RSSTATUS[1]} -</code><code>eq</code> <code>0 ];</code><code>then</code>
<code> </code><code>if</code> <code>ipvsadm -L -n | </code><code>grep</code> <code>"127.0.0.1:80"</code> <code>&> </code><code>/dev/null</code><code>;</code><code>then</code>
<code> </code><code>echo</code> <code>"`date '+%F %T'` All RS is Down and Local web is up"</code> <code>>> $LOG</code>
<code> </code><code>else</code>
<code> </code><code>ipvsadm -a -t $VIP:$CPORT -r 127.0.0.1:80 -$TYPE</code>
<code> </code><code>[ $? -</code><code>eq</code> <code>0 ]; </code><code>echo</code> <code>"`date '+%F %T'` All RS is Down! Local 127.0.0.1:80 is up!!!"</code> <code>>> $LOG</code>
<code> </code><code>fi</code>
<code> </code><code>ipvsadm -d -t $VIP:$CPORT -r 127.0.0.1:80</code>
<code> </code><code>if</code> <code>ipvsadm -L -n | </code><code>grep</code> <code>"127.0.0.1:80"</code> <code>&> </code><code>/dev/null</code><code>;</code><code>then</code>
<code> </code><code>ipvsadm -d -t $VIP:$CPORT -r 127.0.0.1:80</code>
<code>#定義檢測後端伺服器服務健康狀态的函數 </code>
<code>checkrs() {</code>
<code> </code><code>local</code> <code>I=1</code>
<code> </code><code>while</code> <code>[ $I -</code><code>le</code> <code>$CHKLOOP ];</code><code>do</code>
<code> </code><code>if</code> <code>curl --connect-timeout 1 http:</code><code>//</code><code>$1 &> </code><code>/dev/null</code><code>; </code><code>then</code>
<code> </code><code>return</code> <code>0</code>
<code> </code><code>let</code> <code>I++</code>
<code> </code><code>done</code>
<code> </code><code>return</code> <code>1</code>
<code>#檢測腳本初始化函數 </code>
<code>initstatus() {</code>
<code> </code><code>local</code> <code>I</code>
<code> </code><code>local</code> <code>COUNT=0</code>
<code> </code><code>for</code> <code>I </code><code>in</code> <code>${RS[*]};</code><code>do</code>
<code> </code><code>if</code> <code>ipvsadm -L -n | </code><code>grep</code> <code>"$I:$RPORT"</code> <code>&& > </code><code>/dev/null</code><code>; </code><code>then</code>
<code> </code><code>RSSTATUS[$COUNT]=1</code>
<code> </code><code>RSSTATUS[$COUNT]=0</code>
<code> </code><code>let</code> <code>COUNT++</code>
<code>#腳本開始執行: </code>
<code>initstatus</code>
<code>ifaddls</code>
<code>while</code> <code>:; </code><code>do</code> <code>#無限循環</code>
<code> </code><code>let</code> <code>COUNT=0</code>
<code> </code><code>if</code> <code>checkrs $I; </code><code>then</code>
<code> </code><code>if</code> <code>[ ${RSSTATUS[$COUNT]} -</code><code>eq</code> <code>0 ];</code><code>then</code>
<code> </code><code>addrs $I ${RW[$COUNT]}</code>
<code> </code><code>[ $? -</code><code>eq</code> <code>0 ] && RSSTATUS[$COUNT]=1 && </code><code>echo</code> <code>"`date '+%F %T'`, $I is back."</code> <code>>> $LOG</code>
<code> </code><code>if</code> <code>[ ${RSSTATUS[$COUNT]} -</code><code>eq</code> <code>1 ]; </code><code>then</code>
<code> </code><code>delrs $I</code>
<code> </code><code>[ $? -</code><code>eq</code> <code>0 ] && RSSTATUS[$COUNT]=0 && </code><code>echo</code> <code>"`date '+%F %T'`, $I is gone."</code> <code>>> $LOG</code>
<code> </code><code>ifaddls</code>
<code> </code><code>sleep</code> <code>5 </code><code>#睡眠5s再循環</code>
<code>done</code>
本文轉自 ZhouLS 51CTO部落格,原文連結:http://blog.51cto.com/zhou123/1683975