一、簡介
軟體負載均衡一般通過兩種方式來實作:基于作業系統的軟負載實作和基于第三方應用的軟負載實作。
LVS 就是基于 Linux 作業系統實作的一種軟負載,HAProxy就是開源的并且基于第三應用實作的軟負載。HAProxy 相比 LVS 的使用要簡單很多,功能方面也很豐富。目前,HAProxy 支援兩種主要的代理模式:"tcp"即 4 層(大多用于郵件伺服器、内部協定通信伺服器等)和 7 層(HTTP)在 4 層模式下, HAproxy僅在用戶端和伺服器之間轉發雙向流量。 7 層模式下, HAProxy 會分析協定,并且能通過允許、拒絕、交換、增加、修改或者删除請求(request)或者回應(response)裡指定内容來控制協定,這種操作要基于特定規則。
詳情可以HAProxy 官方網站(http://haproxy.1wt.eu)可以下載下傳配置說明文檔(configuration.txt)和架構檔案(architecture.txt)作為參考。
二、拓撲圖
三、 配置過程
注:
OS:Centos 6.5x86_64
己經安裝的包組 :
1
<code>#yum groupinstall -y </code><code>"Development tools"</code> <code>"Server Platform Development"</code>
前提:
HAproxy A與B要做到
主機名解析
時間同步
無密鑰登入
1、HAproxy A配置
安裝keepalived、haproxy
<code>#yum install -y keepalived haproxy</code>
配置keepalived
編輯/etc/keepalived/keepalived.conf
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
<code>! Configuration File </code><code>for</code> <code>keepalived</code>
<code> </code>
<code>global_defs {</code>
<code> </code><code>notification_email {</code>
<code> </code><code>root@localhost</code>
<code> </code><code>essuninfo@localhost</code>
<code> </code><code>}</code>
<code> </code><code>notification_email_from essuninfo@localhost</code>
<code> </code><code>smtp_connect_timeout 3</code>
<code> </code><code>smtp_server 127.0.0.1</code>
<code> </code><code>router_id LVS_DEVEL</code>
<code>}</code>
<code>vrrp_script chk_haproxy {</code>
<code> </code><code>script </code><code>"killall -0 haproxy"</code>
<code> </code><code>interval 1</code>
<code> </code><code>weight 2</code>
<code>vrrp_instance VI_1 {</code>
<code> </code><code>interface eth0</code>
<code> </code><code>state MASTER</code>
<code> </code><code>priority 201</code>
<code> </code><code>virtual_router_id 109</code>
<code> </code><code>garp_master_delay 1</code>
<code> </code><code>authentication {</code>
<code> </code><code>auth_type PASS</code>
<code> </code><code>auth_pass password</code>
<code> </code><code>}</code>
<code> </code><code>track_interface {</code>
<code> </code><code>eth0</code>
<code> </code><code>virtual_ipaddress {</code>
<code> </code><code>172.16.1.103</code><code>/16</code> <code>dev eth0 label eth0:0</code>
<code> </code><code>track_script {</code>
<code> </code><code>chk_haproxy</code>
<code> </code>
<code> </code>
<code> </code><code>notify_master </code><code>"/etc/keepalived/notify.sh master"</code>
<code> </code><code>notify_backup </code><code>"/etc/keepalived/notify.sh backup"</code>
<code> </code><code>notify_fault </code><code>"/etc/keepalived/notify.sh fault"</code>
<code>vrrp_instance VI_2 {</code>
<code> </code><code>state BACKUP</code>
<code> </code><code>priority 99</code>
<code> </code><code>virtual_router_id 52</code>
<code> </code><code>172.16.1.109</code><code>/16</code> <code>dev eth0 label eth0:1</code>
通知腳本
<code>#!/bin/bash</code>
<code># description: An example of notify script</code>
<code>#</code>
<code>vip=172.16.1.103</code>
<code>contact=</code><code>'root@localhost'</code>
<code>notify() {</code>
<code> </code><code>mailsubject=</code><code>"`hostname` to be $1: $vip floating"</code>
<code> </code><code>mailbody=</code><code>"`date '+%F\ %T'`: vrrp transition, `hostname` changed to be $1"</code>
<code> </code><code>echo</code> <code>$mailbody | mail -s </code><code>"$mailsubject"</code> <code>$contact</code>
<code>case</code> <code>"$1"</code> <code>in</code>
<code> </code><code>master)</code>
<code> </code><code>notify master</code>
<code> </code><code>/etc/rc</code><code>.d</code><code>/init</code><code>.d</code><code>/haproxy</code> <code>start</code>
<code> </code><code>exit</code> <code>0</code>
<code> </code><code>;;</code>
<code> </code><code>backup)</code>
<code> </code><code>notify backup</code>
<code> </code><code>/etc/rc</code><code>.d</code><code>/init</code><code>.d</code><code>/haproxy</code> <code>stop</code>
<code> </code><code>fault)</code>
<code> </code><code>notify fault</code>
<code> </code><code>*)</code>
<code> </code><code>echo</code> <code>'Usage: `basename $0` {master|backup|fault}'</code>
<code> </code><code>exit</code> <code>1</code>
<code>esac</code>
<code>#chmod +x /etc/keepalived/notify.sh</code>
配置haproxy
編輯配置檔案 /etc/haproxy/haproxy.cfg
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<code>#---------------------------------------------------------------------</code>
<code># Example configuration for a possible web application. See the</code>
<code># full configuration options online.</code>
<code># http://haproxy.1wt.eu/download/1.4/doc/configuration.txt</code>
<code># Global settings</code>
<code>global </code><code>#全局配置區域</code>
<code> </code><code>log 127.0.0.1 local2 </code><code>#日志将通過rsyslog進行歸檔記錄</code>
<code> </code><code>chroot </code><code>/var/lib/haproxy</code> <code>#運作的安裝路徑</code>
<code> </code><code>pidfile </code><code>/var/run/haproxy</code><code>.pid </code><code>#pid檔案存放的位置</code>
<code> </code><code>maxconn 4000 </code><code>#最大連接配接</code>
<code> </code><code>user haproxy </code><code>#運作haproxy的使用者</code>
<code> </code><code>group haproxy </code><code>#運作haprixy的組</code>
<code> </code><code>daemon </code><code>#以背景模式運作haproxy</code>
<code> </code><code># turn on stats unix socket</code>
<code> </code><code>stats socket </code><code>/var/lib/haproxy/stats</code>
<code># common defaults that all the 'listen' and 'backend' sections will</code>
<code># use if not designated in their block</code>
<code>defaults</code>
<code> </code><code>mode http </code><code>#工作模式</code>
<code> </code><code>log global </code><code>#記錄日志</code>
<code> </code><code>option httplog</code>
<code> </code><code>option dontlognull </code><code>#不記錄健康檢查的日志資訊</code>
<code> </code><code>option http-server-close </code><code>#啟用伺服器端主動關閉</code>
<code> </code><code>option forwardfor except 127.0.0.0</code><code>/8</code> <code>#傳遞用戶端IP</code>
<code> </code><code>option redispatch </code><code>#當後端伺服器組中的某一台主機故障後,能夠自動将請求重定向到組内的其它主機</code>
<code> </code><code>retries 3 </code><code>#請求重試次數</code>
<code> </code><code>timeout http-request 10s </code><code>#http請求逾時時間</code>
<code> </code><code>timeout queue 1m </code><code>#一個請求在隊列裡的逾時時間</code>
<code> </code><code>timeout connect 10s </code><code>#連接配接伺服器逾時時間</code>
<code> </code><code>timeout client 1m </code><code>#用戶端逾時時間</code>
<code> </code><code>timeout server 1m </code><code>#用戶端逾時時間</code>
<code> </code><code>timeout http-keep-alive 10s</code>
<code> </code><code>timeout check 10s </code><code>#心跳檢測逾時時間</code>
<code> </code><code>maxconn 3000 </code><code>#最大連接配接數</code>
<code># main frontend which proxys to the backends</code>
<code>frontend proxy *:80</code>
<code> </code><code>acl url_static path_beg -i </code><code>/static</code> <code>/images</code> <code>/javascript</code> <code>/stylesheets</code>
<code> </code><code>acl url_static path_end -i .jpg .gif .png .css .js</code>
<code> </code><code>use_backend static </code><code>if</code> <code>url_static</code>
<code> </code><code>default_backend dynamic</code>
<code># static backend for serving up images, stylesheets and such</code>
<code>backend static </code><code>#後端排程</code>
<code> </code><code>balance roundrobin </code><code>#排程算法</code>
<code> </code><code>server web2 192.168.1.108:80 inter 1500 rise 2 fall 3 check maxconn 5000</code>
<code>#----------------------------------------</code>
<code>listen statistics</code>
<code> </code><code>mode http </code><code># http 7 層模式</code>
<code> </code><code>bind *:8080 </code><code>#監聽位址</code>
<code> </code><code>stats </code><code>enable</code> <code>#啟用狀态監控</code>
<code> </code><code>stats auth admin:essun </code><code>#驗證的使用者與密碼</code>
<code> </code><code>stats uri </code><code>/admin</code><code>?status </code><code>#通路路徑</code>
<code> </code><code>stats admin </code><code>if</code> <code>TRUE </code><code>#如果驗證通過了就允許登入</code>
<code> </code><code>stats refresh 6s </code><code>#每6秒重新整理一次</code>
<code> </code><code>acl allow src 172.16.1.0</code><code>/24</code> <code>#允許的IP位址</code>
<code> </code><code>tcp-request content accept </code><code>if</code> <code>allow </code><code>#如果允許的位址段就允許通路</code>
<code> </code><code>tcp-request content reject </code><code>#拒絕非法連接配接</code>
<code># round robin balancing between the various backends</code>
<code>backend dynamic</code>
<code> </code><code>balance roundrobin</code>
<code> </code><code>server web2 192.168.1.40:80 check inter 1500 rise 2 fall 3 maxconn 5000</code>
<code>#伺服器定義,serverid為web2,check inter 1500是檢測心跳頻率</code>
<code>#rise 2是2次正确認為伺服器可用</code>
<code>#fall 3是3次失敗認為伺服器不可用</code>
<code>#最大連接配接資料為5000</code>
<code>server web3 192.168.1.104:80 check inter 1500 rise 2 fall 3 maxconn 5000</code>
将此檔案同時也複制到HAproxy B上一份
2、HAproxy B的配置
修改keepalived在配置檔案(/etc/keepalived/keepalived.conf)
<code>! Configuration File </code><code>for</code> <code>keepalived</code>
<code> </code>
<code> </code><code>priority 200</code>
<code> </code>
<code> </code>
<code> </code><code>priority 100</code>
修改通知腳本
<code>vip=</code><code>172.16</code><code>.</code><code>1.109</code>
<code> </code><code>echo $mailbody | mail -s </code><code>"$mailsubject"</code> <code>$contact</code>
<code> </code><code>/etc/rc.d/init.d/haproxy start</code>
<code> </code><code>exit </code><code>0</code>
<code> </code><code>/etc/rc.d/init.d/haproxy stop</code>
<code> </code><code>echo </code><code>'Usage: `basename $0` {master|backup|fault}'</code>
<code> </code><code>exit </code><code>1</code>
由于HAproxy A中的haporxy配置與HAporxy B 的配置檔案相同從HAproxy A中發過來一份放在同一目錄下即可
<code>#scp -p /etc/haproxy/haproxy.cnf </code><code>192.168</code><code>.</code><code>1.109</code><code>:/etc/haproxy/</code>
3、測試一下keepalived功能
HAproxy B 上面的ip位址
<a href="http://s3.51cto.com/wyfs02/M00/25/8F/wKiom1Nkc9bA-JzsAAQbqKtLbzM402.jpg" target="_blank"></a>
将ha2上的keepalived停止後,ip位址己經轉移到了ha1上了
<a href="http://s3.51cto.com/wyfs02/M00/25/8F/wKioL1Nkc_izz9NBAARTu0RtDks122.jpg" target="_blank"></a>
當ha2啟動後,172.16.1.109還是會回到ha2上面。
4、安裝後端的web服務
web1 靜态頁面 (192.168.1.108)
<code>#yum install -y httpd</code>
<code>[root@essun ~]# cd /</code><code>var</code><code>/www/html/</code>
<code>[root@essun html]# echo </code><code>"<h1>這是一個靜态頁面,位址為192.168.1.108</h1>"</code> <code>> index.html</code>
<code>[root@essun html]# ll</code>
<code>total </code><code>4</code>
<code>-rw-r--r-- </code><code>1</code> <code>root root </code><code>59</code> <code>May </code><code>3</code> <code>12</code><code>:</code><code>50</code> <code>index.html</code>
<code>[root@essun html]# cat index.html</code>
<code><h1>這是一個靜态頁面,位址為</code><code>192.168</code><code>.</code><code>1.108</code><code></h1></code>
<code>[root@essun html]# service httpd start</code>
<code>Starting httpd: httpd: apr_sockaddr_info_get() failed </code><code>for</code> <code>essun.node3.com</code>
<code>httpd: Could not reliably determine the server's fully qualified domain name, using </code><code>127.0</code><code>.</code><code>0.1</code> <code>for</code> <code>ServerName</code>
<code> </code><code>[ OK ]</code>
<code>[root@essun html]# curl http:</code><code>//192.168.1.108</code>
在/var/www/html中放一張圖檔,僅供測試
web2 動态頁面 (192.168.1.40)
<code>[root@essun yum.repos.d]</code><code># yum install -y httpd php php-mysql mysql-server mysql-devel</code>
<code>[root@essun yum.repos.d]</code><code># cd /var/www/html/</code>
<code>[root@essun html]</code><code># vim index.php</code>
<code>[root@essun html]</code><code># service httpd restart</code>
<code>Stopping httpd: [FAILED]</code>
<code>Starting httpd: httpd: apr_sockaddr_info_get() failed </code><code>for</code> <code>essun.node4.com</code>
<code>httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 </code><code>for</code> <code>ServerName</code>
<code>[root@essun html]</code><code># cat index.php</code>
<code><h1>我是動态頁面,位址是192.168.1.40<</code><code>/h1</code><code>></code>
<code><?php</code>
<code> </code><code>phpinfo();</code>
<code>?></code>
<code>[root@essun html]</code><code># curl -I http://192.168.1.40/index.php</code>
<code>HTTP</code><code>/1</code><code>.1 200 OK</code>
<code>Date: Sat, 03 May 2014 05:11:47 GMT</code>
<code>Server: Apache</code><code>/2</code><code>.2.15 (CentOS)</code>
<code>X-Powered-By: PHP</code><code>/5</code><code>.3.3</code>
<code>Connection: close</code>
<code>Content-Type: text</code><code>/html</code><code>; charset=UTF-8</code>
web3 動态頁面(192.168.1.104)
<code>[root@essun yum.repos.d]</code><code># service httpd restart</code>
<code>Starting httpd: [ OK ]</code>
<code><h1>我也是動态頁面,位址是192.168.1.104<</code><code>/h1</code><code>></code>
<code>[root@essun yum.repos.d]</code><code># curl -I http://192.168.1.104</code>
<code>Date: Sat, 03 May 2014 05:14:22 GMT</code>
四、測試
1、利用兩個vip任意一個測試一下
靜态頁面測試
<a href="http://s3.51cto.com/wyfs02/M00/25/90/wKiom1NkkzrSxJ6AAAHNA-t0B4Y260.jpg" target="_blank"></a>
動态頁面測試 web3 (192.168.1.104)
<a href="http://s3.51cto.com/wyfs02/M00/25/90/wKiom1Nkk5Sxs60uAAKQX7mpE4I883.jpg" target="_blank"></a>
監控頁面,驗證使用者身份
<a href="http://s3.51cto.com/wyfs02/M00/25/90/wKioL1NklOGCK9cEAAEkEELQ1Uw160.jpg" target="_blank"></a>
驗證通過後
<a href="http://s3.51cto.com/wyfs02/M02/25/90/wKiom1NklUuCdLbOAAaZ205nWuA099.jpg" target="_blank"></a>
其中一個keepalived當機後完不會影響到服務的正常的運作
<a href="http://s3.51cto.com/wyfs02/M01/25/90/wKioL1Nklx3S74OGAAV06sAYa1k937.jpg" target="_blank"></a>
本文轉自 jinlinger 51CTO部落格,原文連結:http://blog.51cto.com/essun/1405893,如需轉載請自行聯系原作者