HAproxy docker swarm 部署記錄
久聞 Haproxy 是一個非常知名的負載均衡 (Load Balancing) 軟體,最近心血來潮,想來研究在分散式 docker-swarm 的環境來用 HAproxy 模擬負載均衡。部署的內容很簡單,先起多個不直接對外的 web server 服務,然後再啟動一個 Haproxy 做反向代理 (reverse proxy) 來為這些背後的 web server 做負載均衡以及對外的窗口。
首先,我用 python 寫了一個簡單的 http server 程式來模擬真正的 web server。
1 | import os |
程式的內容為 client 向 server 發出請求後,會在瀏覽器頁面上印出該 server 的 hostname,如此就可以很方便的觀察之後負載均衡的行爲。
先來看看本次 docker swarm 的部署編排,docker-stack.yml
如下。
1 | version: '3.7' |
這裡我打算起三個 web server 以及一個 HAproxy,並將 endpoint_mode
設為 dnsrr(DNS Round Robin)
而不用預設的 vip(virtual IP)
,因為 docker swarm 也有自己內部的負載均衡機制叫 routing mesh,會轉傳外部的請求到其中一個作用的 container。如果是預設的 vip
最後只會回應一個虛擬的 ip,無法得知其他 container replicas 的 ip,造成的結果就是 HAproxy 只會偵測到一台 web server。因此如果要使用外部的負載均衡就必須指定 dnsrr
模式才可跳過 routing mesh 取得多個 container ip。
然後就是關鍵的 HAproxy 設定部分了,HAproxy 的設定檔為 haproxy.cfg
,內容如下所示。
1 | global |
設定檔中有很多不同的區塊,在此不一一贅述這篇文章有非常詳盡的介紹。這裡挑幾個重點區塊設定來說明,首先是 resolvers
區塊,docker 有自己內部的 dns 服務,可以允許在同一個 docker 網路中的服務用自己的服務名稱來連線,這裡使用 docker 內部的 dns 服務 127.0.0.11:53
來讓 HAproxy 自動解析真實 container ip。
再來就是 backend
web_service 區塊設定,server-template
參數可以快速的建立多個 server 設定而不用個別慢慢下。web- 3
中的web-
表示 server 名稱的前綴,3
表示 server 名稱的總數,因此會產生 web-1、web-2、web-3 共三個 server,剛好與前面我設定的replicas: 3
對應。如果實際的 replicas 比較少,則空下來的 server 會自動 disable 掉。
同時也要指定 resolvers docker
讓 HAproxy 知道要使用哪個 dns resolver,init-addr libc,none
則指示 HAproxy 再啟動時就執行服務發現,並且在無任何 wed server 也繼續執行。
最後到了啟動的步驟了,輸入以下指令來啟動 docker swarm 服務。
1 | docker stack deploy -c=docker-stack.yml haproxy-practice |
接著不停的重整瀏覽器可以觀察每次的 hostname 都會受到負載均衡而有所不同。
也可以瀏覽 /my-stats
來查看 HAproxy 的管理頁面看看個別服務的情形。
這次部署的相關程式碼也同步於 github 上。
reference: