除了 HA Proxy 俱備一個 123.123.123.1 (對外的 public ip) , 內部的 Web Server 則是用一個小 Hub 串接為一個 Private LAN , 這樣內部 Server 都與外隔絕了 , 而 HA Proxy 也必須充當 NAT Server , 不然內部的 Web Server 都沒辦法進行更新或 ntp 更新 , 這個架構是一個簡單的網站負載平衡架構 , HA Proxy 會依照設定將流量分別導到 Web Server 1 及 Web Server 2 , 當然也有其他方式可以做到 , 例如 lvs , 但 haproxy 可以做到 L7 的層級 , 雖然效能不能和 lvs 比 , 但也不會慢到那 , 算是一種窮人解決方案
安裝前的準備
- 確定 Haproxy 上有沒有 epel 可以給 yum 用 , 可以參考這篇 http://fedoraproject.org/wiki/EPEL , 去下載 RHEL 6.0 的 rpm 來裝
- 用 yum install haproxy 安裝 haproxy
- 確定一下 haproxy 那台的 iptables service 都要打開
設定方式
要讓 haproxy 以 tproxy 運作通透代理必須設定 ip rule 及 iptables , 從 google 上找到這篇 http://blog.loadbalancer.org/configure-haproxy-with-tproxy-kernel-for-full-transparent-proxy/ , 基本上按照這篇設定 ip rule 及 iptables 是可以動作的 , 但美中不足的是 , 若 Web Server 的 GateWay 都指向 Haproxy 那台 IP , 會發生由 Web Server 本身要抓取自己 url 會等老半天發生錯誤 , 當然也可以透過修改 /etc/hosts 方式解決 , 但總覺得很呆 , 於是又找了一下發現了一招 , 可以由 iptables 設定將特定 sub net 轉成另一組 sub net 來解決 , 於是綜合上述的網址 , ip rule 及 iptables 的設定方法寫成如下
iptables -t mangle -N DIVERT
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
iptables -t mangle -A DIVERT -j MARK --set-mark 111
iptables -t mangle -A DIVERT -j ACCEPT
iptables -A FORWARD -i eth+ -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j NETMAP --to 192.168.10.0/24
ip rule add fwmark 111 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
echo 1 > /proc/sys/net/ipv4/conf/all/forwarding
echo 1 > /proc/sys/net/ipv4/conf/all/send_redirects
echo 1 > /proc/sys/net/ipv4/conf/eth0/send_redirects
注意一下 , iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j NETMAP --to 192.168.10.0/24 部分比較怪異 , 這是把內網(web server) 的 ip 改成 192.168.10 的區段 , 事實上這個區段必須是不存在的 , 這樣才可以內網WEB SERVER對自己的 URL 存取可正常運作 , 當設定好後 , haproxy 的設定檔部分 , 每個 backend server 的設定要加上 source 0.0.0.0 usesrc clientip 才會使用 transparent 模式 , 下面就列出一個以上面架構圖為主的 haproxy 設定範例
global
# 原本有 user 及 group 要註解掉 , 因為這種設定要用 root 才能跑
# user haproxy
# group haproxy
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
balance roundrobin
frontend frontend_main
bind 123.123.123.1:80
option forwardfor
mode http
# 下一行判斷是否為 crazy. 為開頭的網址
acl crazy_ha hdr_dom(host) -i crazy
# 如果符合 crazy_ha 的 rule , 就使用 backend_crazy 的設定
use_backend backend_crazy if crazy_funuv
# 下一行是預設的 backend 設定
default_backend backend_default
# 這個 backend_crazy 只是為了證明 haproxy L7 的用法
backend backend_crazy
mode http
option forwardfor
source 0.0.0.0 usesrc clientip
cookie SERVERID insert nocache indirect
server server1 192.168.0.11:80 weight 1 cookie server1 check
option redispatch
backend backend_default
mode http
option forwardfor
source 0.0.0.0 usesrc clientip
cookie SERVERID insert nocache indirect
server server1 192.168.0.11:80 weight 1 cookie server1 check
server server1 192.168.0.12:80 weight 1 cookie server1 check
option redispatch
以上設定完後並且執行那 ip rule 及iptables 設定後可能會因為 SSH 連線時也是內網 IP 而斷線 , 因為上面紅字的部分的關係啦 , 斷線後重連就好了, 接著重啟 haproxy 就可以觀察一下 web server 中的 httpd log 是否 ip 都換成了真實來源的 IP , 而內網自己抓自己時則會發現 ip 會變成 192.168.10.xx
完B
Pigo前輩你好,
參考了你的文章我試著建立Haproxy 通透模式,不過無論如何都無法成功。
已經嘗試了好幾天了…
我試過:
使用CentOS 5.5 Kernel 更新至 2.6.32,自己編譯iptables 1.4.10, 編譯haproxy 1.4, 測試後 –> 失敗
使用SUSE 11 Kernel 2.6.32, iptables 1.4.x , 編譯haproxy 1.4, 測試後 –> 失敗
使用SL Linux 6 Kernel 2.6.32, iptables 1.4.x, EPEL的haproxy 1.4, 測試後 –> 失敗
最後都是 503 Service Unavaliable,看起來都像是卡在同樣的地方,關掉通透模式正常。
目前是測試環境,Haproxy主機 eth0 內網, eth1外網。後端一台web eth0內網,eth1外網。
HAProxy 連接Web時,通透模式下 連接外網或內網均無法正常運作通透模式。
是否可請你協助一下提點一下問題點可能在哪,或者登入我的測試環境主機協助指點。
如果你願意抽空解惑的話,請透過我的E-mail聯繫我。感激不盡!
@Roby:
內網的Server 是否有將 Gateway 設定成 haproxy 的 ip 呢
謝謝Pigo,的確是要將內網Gateway設定為Haproxy的ip才能正常運作。
那試問一下,如果預設的Gateway不設定為Haproxy的IP,有沒有方式可以正常運作呢?
針對這個問題我思考的方向是用Iptables 進行NAT或者是加上IP route的方式,不知道是否可行?
這個問題 , 我也沒有去實作 , 如果是要針對特定網段傳輸另設 ip route 應該是可以 , 但如果要判斷非 80 port 而走不同 gateway , 我還想不出該怎麼弄呢
我自己是有想過一招 , 不過還沒實做過
就是內網的網卡弄出兩個 ip (alias) , 例如 haproxy 對Server A 的192.168.2.11 , 而Server A預設主 ip 是 192.168.2.10 , 這個主 ip 就是走正常 gateway , 而 192.168.2.11 就設定 gateway 是 haproxy ip , 不知道這樣可不可以
謝謝Pigo, 你提供的方案我會思考並嘗試看看。
其實是我手邊有一些服務主機必須24小時運作,這些主機目前是外網IP。
我原打算上HAProxy後,將這些服務的DNS改為HAProxy來運作,
在DNS完全發佈生效之前(略估最久24小時),外網IP的主機原外網IP還必須繼續使用。
而這些外網主機必須接收到正確的外部Client端IP。
所以我才會有可能不能透過HAProxy當做Gateway的疑慮。
我認為通透模式下,即使HAProxy的Server1設定給他外網IP應該Server1拿不到正確的外部Client IP。
才想請教一下Pigo前輩有沒有什麼方案可以參考。
那把 haproxy 的外網ip也多設幾個 alias ,就是把原server 外網ip都給 haproxy 用 , 等 dns 生效再拿掉應該比較方便吧
謝謝Pigo,目前已經將HAProxy導入運作中,不過…
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j NETMAP –to 192.168.10.0/24
這段看起來沒有運作,我還是需要寫入hosts才能改善抓不到網址的問題。
我的內網是10.1.100.254 (HAProxy) 後端兩台為 10.1.91.11, 10.1.91.12
Netmask 是 255.255.0.0。
即使我加上了NETMAP這段如下:
iptables -t nat -A POSTROUTING -s 10.1.91.0/24 -j NETMAP –to 10.1.99.0/24
在內部的兩台主機測試,用 wget test.mycom.tw/test.html還是無法正常,使用hosts寫死才ok。
不知道是不是因為Netmast 是 /16的原因。這方面Pigo有沒有什麼建議能用NETMAP的方式?
你要不要改成 –to 192.168.0.0/24 試試看
謝謝Pigo,改成–to 192.168.0.0/24 就真的可以了…
我不能理解其中的原因。 理論上之前用的10.1.99.0/24 應該也是不存在的網段。
為何NETMAP功能就會失敗呢?
@pigo
其實我也不太清楚 NETMAP 內部運作原理
我只是猜測你的 SERVER MASK 都是 16 , 10.1.91.0 和 10.1.99.0 都是同一區段 , 做 NETMAP 搞不好就失敗了 , 所以換一個不會重複到的區段應該就可以了
Pigo您好,不知道能不能向您請教一下
當我設定cookie SERVERID insert nocache indirect後
haproxy就會給連進來的client端一個SERVERID的cookie
所以這就表示cookie的機制他已經啟動嗎?
也就是說如果這樣她就會依照client給haproxy的cookie去倒到相對應的後端server這樣嗎?(ex:SERVERID=A 導到A主機)
因為我希望能依照我的設定將client導到我想指派的server
原本的想法是想將他給的SERVERID的值直接改掉
(例如: 原本haproxy丟給client的是SERVERID = A但我經過測試覺得丟給B比較好所以強制改成SERVERID = B)
但我trace 他的source code好久卻都找不到他處理cookie然後導向到後端主機的地方
原本我認為應該是在source code裡proto_http.c下的manage_client_side_appsession這個function裡
但做了測試卻發現好像haproxy跟本沒跑進這個funtion裡
等於好像在做原本預設的roundrobin
所以我才想說是不是設定檔沒有設定好那個功能沒有開啟
又或者是導向server的code另在別處
卡了好久..
希望大大能為我解惑…
感激不盡!!!
@lance
我也沒研究過 source code 喔 , sorry !
To Roby:
你的Netmask 是 255.255.0.0。所以不生效的那一句应该要改成如下才会生效:
iptables -t nat -A POSTROUTING -s 10.1.91.0/16 -j NETMAP –to 10.1.99.0/16
?
請問pigo~
若 HAProxy 的模式是 tcp 不是 http,tproxy 運作是否就會失效…
我測試導 pop3 service,但卻一直失敗…:(
抱歉,我沒試過導 tcp 耶,不過 tcp 和 http 應該是差不多的才對,你要不要試試看直接命令列執行 haproxy 的 debug 模式運作看看 Log , tcp mode 的設定應該不能包含 http 的命令,如 forwardfor