基于Docker + Consul + Nginx + Consul-Template + Registrator的服務(wù)自動負載均衡實現(xiàn)
本文搭建的consul為單節(jié)點版本 , 集群版 參考文章1
參考文章:
- 基于Docker + Consul + Nginx + Consul-Template的服務(wù)負載均衡實現(xiàn)
- 用 consul + consul-template + registrator + nginx 打造真正可動態(tài)擴展的服務(wù)架構(gòu)
- 8分鐘學會Consul集群搭建及微服務(wù)概念
docker-composer相關(guān)知識點
- 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 相關(guān)知識點
- Client模式 就是客戶端模式。是 Consul 節(jié)點的一種模式,這種模式下,所有注冊到當前節(jié)點的服務(wù)會被轉(zhuǎn)發(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 表示服務(wù)端 IP為10.211.55.2
# -datacenter=dc1 數(shù)據(jù)中心名稱
# -join=10.211.55.4 表示加入10.211.55.4節(jié)點的集群
- 服務(wù)發(fā)現(xiàn)協(xié)議 Consul 采用 http 和 DNS 協(xié)議,etcd 只支持 http
服務(wù)注冊:Consul 支持兩種方式實現(xiàn)服務(wù)注冊,一種是通過 Consul 的服務(wù)注冊 Http API,由服務(wù)自己調(diào)用 API 實現(xiàn)注冊,另一種方式是通過 json 格式的配置文件實現(xiàn)注冊,將需要注冊的服務(wù)以 json 格式的配置文件給出。Consul 官方建議使用第二種方式。
- 服務(wù)定義參數(shù)
| 環(huán)境變量Key | 環(huán)境變量Value | 說明 |
|---|---|---|
| SERVICE_ID | web-001 | 可以為GUID或者可讀性更強變量,保證不重復 |
| SERVICE_NAME | web | 如果ID沒有設(shè)置,Consul會將name作為id,則有可能注冊失敗 |
| SERVICE_TAGS | nodejs,web | 服務(wù)的標簽,用逗號分隔,開發(fā)者可以根據(jù)標簽來查詢一些信息 |
| SERVICE_IGNORE | Boolean | 是否忽略本Container,可以為一些不需要注冊的Container添加此屬性 |
實現(xiàn)原理
- 通過 Nginx 自身實現(xiàn)負載均衡和請求轉(zhuǎn)發(fā)
- 通過 Consul-template 的 config 功能實時監(jiān)控 Consul 集群節(jié)點的服務(wù)和數(shù)據(jù)的變化;
實時的用 Consul 節(jié)點的信息替換 Nginx 配置文件的模板,并重新加載配置文件
Consul-template 和 nginx 必須安裝在同一臺機器上,因為 Consul-template 需要動態(tài)修改 nginx 的配置文件 nginx.conf,然后執(zhí)行 nginx -s reload 命令進行路由更新,達到動態(tài)負載均衡的目的
- registrator,它可以通過跟本地的 docker 引擎通信,來獲取本地啟動的容器信息,并且注冊到指定的服務(wù)發(fā)現(xiàn)管理端。
數(shù)據(jù)流向: docker 容器數(shù)據(jù)-> registrator -> consul ->consul-template -> nginx
鏡像構(gòu)建
- 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變化
總結(jié)測試
最先我未去指定容器的啟動順序(deponds_on) 導致docker-compose up 后訪問http://localhost 報錯 nginx 502
原因是因為 registrator容器先于web容器啟動,導致未將web容器注冊到consul 所以生成的nginx配置文件中,沒用web參與負載