marathon-lb-什么是服務發現?(轉)


摘要: 將容器應用部署到集群時,其服務地址,即IP端口, 是由集群系統動態分配的。那么,當我們需要訪問這個服務時,如何確定它的地址呢?這時,就需要服務發現(Service Discovery)了。本文將以Nginx的部署為例,介紹服務發現的原理與實踐。

一. 單機部署Nginx

Nginx作為網頁服務器,功能與Apache一致。使用Docker, 可以快速部署Nginx。

1. 下載Nginx鏡像

sudo docker pull nginx:1.10

2. 運行Nginx容器

sudo docker run -d \
-p 8080:80 \
nginx:1.10

其中,-d選項表示Nginx容器在后台運行,-p選項表示主機的8080端口映射為容器的80端口。

3. 訪問Nginx服務

使用瀏覽器服務Nginx

http://192.168.59.1:8080

或者使用curl命令訪問Nginx, 其返回結果為html文件。

curl 192.168.59.1:8080

Nginx的服務地址是192.168.59.1:8080,其中,192.168.59.1是運行Nginx容器的主機的IP,而8080是Nginx提供服務的端口。

可知,將容器應用部署到單個主機上時,服務的IP即為運行容器的主機IP,而服務的端口可以通過-p選項手動指定,這時服務地址相當於是靜態分配的,因此不存在服務發現的問題。然而,當我們將容器應用部署到多個節點的集群時呢?

二. Mesos/Marathon集群中部署Nginx

首先,可以按照基於Docker搭建多節點Mesos/Marathon介紹的方法,快速搭建3個節點的Mesos/Marathon集群。部署Nginx時,可以不使用服務發現,也可以使用Marathon LB提供服務發現。通過對比兩種方式,可以更好地理解服務發現。

1. 不使用服務發現

Nginx定義(nginx1.json):

{
"id": "nginx1",
"cpus": 0.2,
"mem": 20.0,
"instances": 1,
"healthChecks": [{
"path": "/"
}],
"container": {
"type": "DOCKER",
"docker": {
"image": "nginx:1.10",
"network": "BRIDGE",
"portMappings": [{ "containerPort": 80, "hostPort": 0, "protocol": "tcp" }]
}
}
}

其中,instances為1,表示僅部署單個Nginx容器; hostPort為0,表示Nginx容器綁定的主機端口由Marathon隨機分配。

部署Nginx:

curl -Ss \
- X POST \
- H "Content-Type: application/json" \
- -data "@nginx1.json" \
http://127.0.0.1:8080/v2/apps | python2.7 -mjson.tool

這時,Nginx容器可能運行node2(192.168.59.2)上,也可能運行在node3(192.168.59.3)上,因此Nginx服務的IP是無法事先確定的。而Nginx容器綁定的主機端口由Marathon隨機分配,也不確定。

當然,服務端口可以通過hostPort指定,但是這樣做並不合適,因為有可能會發生端口沖突。當集群中運行了非常多不同的服務時,靜態分配端口是不現實的,也限制了集群的靈活性與擴展性

在Slave節點上使用docker ps命令可以獲取Nginx服務的IP與端口。

node2(192.168.59.2)

sudo docker ps | grep nginx
b863d 407b880 nginx:1.10 "nginx -g 'daemon off" 15 minutes ago Up 15 minutes 443/tcp, 0.0.0.0:31575->80/tcp mesos-d34d0b5b-c3b1-4020-9bb2-bb8582252bf3-S0.d2de6d05-9751-4fbe-af10-d7e35e9e6c7b

node3(192.168.59.3)

sudo docker ps | grep nginx

可知Nginx服務的IP與端口分別為192.168.59.231575,即Nginx的服務地址為:http://192.168.59.2:31575

每次重新部署Nginx時,其IP和端口會發生變化,這就意味着每次都要手動去查詢服務地址,這很不方便,且無法將部署任務自動化。在容器集群中,通常需要運行非常多不同的應用,這就意味着服務發現是容器集群系統的必備功能。

2. 使用Marathon LB提供服務發現

Marathon LB是Marathon的服務發現系統。Marathon LB通過使用Haproxy實現了代理服務器的功能。

通過使用Marathon LB可以配置服務的固定端口,而服務的IP就是運行Marathon LB的節點IP。Marathon LB會監聽Marathon的調度事件,獲取容器實際運行的IP與端口,然后更新Haproxy的配置文件。因此,當重新部署Nginx時,我們仍然可以通過固定的IP與端口訪問該服務。

Nginx定義(nginx2.json):

{
"id": "nginx2",
"labels": {
"HAPROXY_GROUP": "external"
},
"cpus": 0.2,
"mem": 20.0,
"instances": 1,
"healthChecks": [{
"path": "/"
}],
"container": {
"type": "DOCKER",
"docker": {
"image": "nginx:1.10",
"network": "BRIDGE",
"portMappings": [{ "containerPort": 80, "hostPort": 0, "servicePort": 10000, "protocol": "tcp" }]
}
}
}

其中,nginx2.json只有HAPROXY_GROUPservicePort兩處修改。HAPROXY_GROUP為external,表示Nginx將使用分組為external的Marathon LB做服務發現。servicePort為10000,表示Nginx將使用Marathon LB節點的10000端口提供服務。

部署Nginx:

curl -Ss \
- X POST \
- H "Content-Type: application/json" \
- -data "@nginx2.json" \
http://127.0.0.1:8080/v2/apps | python2.7 -mjson.tool

這時,Nginx服務的IP為運行Marathon LB的節點IP,即192.168.59.1,而Nginx服務的端口為servicePort指定的端口,即10000。因此,Nginx的服務地址為:http://192.168.59.1:10000。而Nginx容器的實際地址為http://192.168.59.2:31270,Marathon LB使用Haproxy作為代理服務器轉發的服務請求。Marathon LB會監聽Marathon的調度事件,獲取容器實際運行的IP與端口,然后更新Haproxy的配置文件。下面即為Marathon LB自動生成的Haproxy配置文件:

frontend nginx2_10000
bind *:10000
mode http
use_backend nginx2_10000
 
backend nginx2_10000
balance roundrobin
mode http
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk GET /
timeout check 20s
server 192_168_59_2_31270 192.168.59.2:31270 check inter 60s fall 4

可知Haproxy中,niginx服務的前端(frontend)地址為: *:10000,而后端(backend)地址為: 192.168.59.2:31270。Haproxy負責將服務請求轉發到Nginx容器。

當我們重新部署Nginx時,Nginx容器的IP和端口會發生變化,Marathon LB會更新Haproxy的配置文件,因此我們仍然可以通過http://192.168.59.1:10000訪問服務。

因此,Marathon LB的任務就是發現服務的地址(IP和端口),然后用戶就不用每次手動查詢了。bamboonixy實現了同樣的功能。

三. 參考

  1. Understanding Modern Service Discovery with Docker
  2. 基於Docker技術構建PaaS雲平台
  3. Youzan 服務發現概述

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM