基于Docker + Consul + Nginx + Consul-Template + Registrator的服務自動負載均衡實現(xiàn)
本文搭建的consul為單節(jié)點版本 吸申, 集群版 參考文章1
參考文章:
- 基于Docker + Consul + Nginx + Consul-Template的服務負載均衡實現(xiàn)
- 用 consul + consul-template + registrator + nginx 打造真正可動態(tài)擴展的服務架構
- 8分鐘學會Consul集群搭建及微服務概念
docker-composer相關知識點
- ports 暴露容器端口到主機的任意端口或指定端口, 用法如下
ports:
- "80:80" # 綁定容器的80端口到主機的80端口
- "9000:8080" # 綁定容器的8080端口到主機的9000端口
- "443" # 綁定容器的443端口到主機的任意端口晰甚,容器啟動時隨機分配綁定的主機端口
- links 使得docker容器間通過指定的名字來和目標容器通信
如果使用links則容器間通信 只能通過該使用容器的ip地址來通信或者通過宿主機的ip加上容器暴露出的端口號來通信 (這兩種都有弊端)
links:
- consul_server_master:consul # 當前容器中使用consul 即可獲取容器consul_server_master的ip地址,便于通信
- depends_on 決定容器的依賴, 也就是指定當前容器的啟動順序,必須依賴啟動后才會啟動
depends_on:
- lb
- registrator
consul 相關知識點
- Client模式 就是客戶端模式剩檀。是 Consul 節(jié)點的一種模式桨嫁,這種模式下蔚润,所有注冊到當前節(jié)點的服務會被轉發(fā)到 Server训貌,本身是不持久化這些信息。
- Server模式 表明這個 Consul 是個 Server 康二,這種模式下碳胳,功能和 Client 都一樣,唯一不同的是沫勿,它會把所有的信息持久化的本地挨约,這樣遇到故障味混,信息是可以被保留的。同時可以同步多個consul客戶端的數(shù)據(jù)
Server 節(jié)點之間的數(shù)據(jù)一致性保證協(xié)議使用的是 raft诫惭,而 zookeeper 用的 paxos翁锡,etcd采用的也是raft
command: consul agent -server -bootstrap-expect 1 -advertise 192.168.1.181 -node consul_server_master -data-dir /tmp/data-dir -client 0.0.0.0 -ui
# -bootstrap-expect=2 表示節(jié)點個數(shù)為2個
# -node=consul-server-1 表示節(jié)點名稱為consul-server-1
# -client=0.0.0.0 表示允許連接的客戶端 IP
# -bind=10.211.55.2 表示服務端 IP為10.211.55.2
# -datacenter=dc1 數(shù)據(jù)中心名稱
# -join=10.211.55.4 表示加入10.211.55.4節(jié)點的集群
- 服務發(fā)現(xiàn)協(xié)議 Consul 采用 http 和 DNS 協(xié)議,etcd 只支持 http
服務注冊:Consul 支持兩種方式實現(xiàn)服務注冊夕土,一種是通過 Consul 的服務注冊 Http API馆衔,由服務自己調用 API 實現(xiàn)注冊,另一種方式是通過 json 格式的配置文件實現(xiàn)注冊怨绣,將需要注冊的服務以 json 格式的配置文件給出角溃。Consul 官方建議使用第二種方式。
- 服務定義參數(shù)
環(huán)境變量Key | 環(huán)境變量Value | 說明 |
---|---|---|
SERVICE_ID | web-001 | 可以為GUID或者可讀性更強變量篮撑,保證不重復 |
SERVICE_NAME | web | 如果ID沒有設置减细,Consul會將name作為id,則有可能注冊失敗 |
SERVICE_TAGS | nodejs,web | 服務的標簽赢笨,用逗號分隔未蝌,開發(fā)者可以根據(jù)標簽來查詢一些信息 |
SERVICE_IGNORE | Boolean | 是否忽略本Container,可以為一些不需要注冊的Container添加此屬性 |
實現(xiàn)原理
- 通過 Nginx 自身實現(xiàn)負載均衡和請求轉發(fā)
- 通過 Consul-template 的 config 功能實時監(jiān)控 Consul 集群節(jié)點的服務和數(shù)據(jù)的變化茧妒;
實時的用 Consul 節(jié)點的信息替換 Nginx 配置文件的模板树埠,并重新加載配置文件
Consul-template 和 nginx 必須安裝在同一臺機器上,因為 Consul-template 需要動態(tài)修改 nginx 的配置文件 nginx.conf嘶伟,然后執(zhí)行 nginx -s reload 命令進行路由更新,達到動態(tài)負載均衡的目的
- registrator又碌,它可以通過跟本地的 docker 引擎通信九昧,來獲取本地啟動的容器信息,并且注冊到指定的服務發(fā)現(xiàn)管理端毕匀。
數(shù)據(jù)流向: docker 容器數(shù)據(jù)-> registrator -> consul ->consul-template -> nginx
鏡像構建
- Consul:consul:latest
- Registrator:gliderlabs/registrator:latest
- Nginx和Consul-template:liberalman/nginx-consul-template:latest
- Web: yeasy/simple-web:latest
docker-compose.yml
version: '3'
#backend web application, scale this with docker-compose scale web=3
services:
web:
image: yeasy/simple-web:latest
environment:
- SERVICE_80_NAME=my-web-server
ports:
- "80"
depends_on:
- lb
- registrator
#load balancer will automatically update the config using consul-template
lb:
image: liberalman/nginx-consul-template:latest
hostname: lb
environment:
- SERVICE_IGNORE=true
links:
- consul_server_master:consul
ports:
- "80:80"
depends_on:
- consul_server_master
consul_server_master:
image: consul:latest
hostname: consul_server_master
environment:
- SERVICE_IGNORE=true
ports:
- "8500:8500"
command: consul agent -server -bootstrap-expect 1 -node consul_server_master -data-dir /tmp/consul -client 0.0.0.0 -ui
# listen on local docker sock to register the container with public ports to the consul service
registrator:
image: gliderlabs/registrator:master
hostname: registrator
environment:
- SERVICE_IGNORE=true
links:
- consul_server_master:consul
depends_on:
- consul_server_master
volumes:
- "/var/run/docker.sock:/tmp/docker.sock"
command: -internal consul://consul:8500
測試步驟
- docker-compose 模板所在目錄铸鹰,執(zhí)行
$ sudo docker-compose up
- 訪問 http://localhost 可以看到一個 web 頁面,提示實際訪問的目標地址皂岔。
#2019-12-20 04:12:30: 19 requests from <LOCAL: 172.17.0.6> to WebServer <172.17.0.4>
- 增加web 測試負載
$ sudo docker-compose scale web=3
- 重復刷新http://localhost 觀察ip變化
總結測試
最先我未去指定容器的啟動順序(deponds_on) 導致docker-compose up 后訪問http://localhost 報錯 nginx 502
原因是因為 registrator容器先于web容器啟動蹋笼,導致未將web容器注冊到consul 所以生成的nginx配置文件中,沒用web參與負載