摘要:是一個(gè)鍵值存儲(chǔ),用于共享配置以及服務(wù)發(fā)現(xiàn)。對(duì)于我們而言,意味著注冊(cè)進(jìn)程必須考慮到端口映射。這個(gè)方法被用于管理服務(wù)發(fā)現(xiàn)。如果未指定,將被從的端口映射找到意味著,你必須在運(yùn)行的命令中指定它,比如。為了測(cè)試取消登記,停止一個(gè)容器將立即從中移除。
注:該文由 adetante 編寫,該文的原文地址為 Service discovery with Docker - 2
該文緊接著上篇文章 Docker 與服務(wù)發(fā)現(xiàn) - 1
在上一篇文章中,我們看到了一個(gè)簡(jiǎn)單的方法,通過使用 Synapse 來做基于同一臺(tái) Docker 主機(jī)上的多個(gè)容器的服務(wù)發(fā)現(xiàn)。
現(xiàn)在,我們想在多臺(tái) Docker 主機(jī)上部署相同的應(yīng)用,來擴(kuò)展不同的服務(wù)以及確保容錯(cuò)性。
這次,在架構(gòu)中我們需要一個(gè)新的組件: etcd 。
etcdetcd 是一個(gè)鍵值存儲(chǔ),用于共享配置以及服務(wù)發(fā)現(xiàn)。它使用 GO 編寫,并且是 CoreOS 發(fā)行版的一部分。etcd 集群提供了高可用的機(jī)制:基于 Raft,它允許一組 etcd 實(shí)例組成一個(gè)集群。
etcd 提供了 REST API,允許客戶端創(chuàng)建,更新和刪除鍵??蛻舳诉€可以監(jiān)聽發(fā)生在特定鍵上的變化(客戶端將被通知在該鍵上或者是鍵的目錄的每次變化)。當(dāng)創(chuàng)建一個(gè)鍵,客戶端可以定義一個(gè) TTL (存活時(shí)間),當(dāng)客戶端不再更新這個(gè)鍵的時(shí)候,它將會(huì)被自動(dòng)清除,這個(gè)對(duì)于服務(wù)注冊(cè)是非常有用的。
概述原理就是 Docker 容器注冊(cè)進(jìn) etcd 集群:當(dāng)一個(gè)應(yīng)用的實(shí)例作為一個(gè) Docker 容器啟動(dòng)的時(shí)候,該容器自己注冊(cè)進(jìn) etcd 集群 ,當(dāng)一個(gè)容器停止或者是應(yīng)用掛掉的時(shí)候,對(duì)應(yīng)的鍵將被移除出 etcd 集群。
Haproxy 只需要簡(jiǎn)單的查找 etcd 來獲取可用的后端來提供 HTTP 服務(wù),Haproxy 監(jiān)聽 etcd 的變化并且相應(yīng)的更新配置。
在這篇文章中,我將描述服務(wù)注冊(cè)部分的解決方案,關(guān)于 Haproxy 的發(fā)現(xiàn)部分將在下一篇文章中描述。
Docker 的動(dòng)態(tài)端口映射Docker 是一個(gè)非常偉大的工具,它提供了很多的功能來簡(jiǎn)化應(yīng)用程序的部署。但它有一個(gè)新的方式管理以及部署這些應(yīng)用。
其中的一個(gè)方式就是對(duì)外公開的端口關(guān)聯(lián)應(yīng)用的能力。
當(dāng)你啟動(dòng)一個(gè) Docker 容器,你可以使用以下命令:
docker run -p 8000 myApplication
-p 8000 參數(shù)意味著你可以暴露 8000 端口運(yùn)行這個(gè)容器,并且在 Docker 主機(jī)上是一個(gè)隨機(jī)的端口。我們的應(yīng)用在 Docker 容器中是監(jiān)聽的 8000 端口,但是這個(gè)端口將被映射到 Docker 主機(jī)上的一個(gè)動(dòng)態(tài)端口。為了查看映射的端口,當(dāng)容器正在運(yùn)行的時(shí)候,你可以使用 docker ps 命令:
ONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6275ea4e2ebd coreos/etcd:latest /opt/etcd/bin/etcd 2 weeks ago Up 1 seconds 0.0.0.0:49153->4001/tcp, 0.0.0.0:49154->7001/tcp pensive_leakey
在以上的輸出中,你可以看到 PORTS 列的在容器中的 4001 端口被映射成了 在 Docker 主機(jī)上的 O.O.O.O:49153。
對(duì)于我們而言,意味著注冊(cè)進(jìn)程必須考慮到端口映射。我們必須注冊(cè)映射端口,而不是應(yīng)用監(jiān)聽的端口。同樣的,我們必須使用 Docker 主機(jī)的 IP 代替容器的 IP 來注冊(cè)。
服務(wù)注冊(cè)為了把服務(wù)注冊(cè)進(jìn) etcd ,我們有以下不同的解決方案:
應(yīng)用它自己能建立一個(gè)連接到 etcd,并且創(chuàng)建一個(gè) key 來通知其他的服務(wù)它正在運(yùn)行。當(dāng)停止的時(shí)候,應(yīng)用必須移除該 key 。它可能在服務(wù)終止的時(shí)候會(huì)變得更加復(fù)雜,但是使用 TTL ,我們可以使損失降到最小(key 不會(huì)被立即移除,僅僅在 TTl 后才被移除)。但是這意味著應(yīng)用必須感知到注冊(cè)進(jìn)程:必須知道 etcd 實(shí)例的清單列表,必須保持一個(gè)循環(huán)定期的刷新 etcd 中的 key 。。。我更喜歡應(yīng)用能與注冊(cè)進(jìn)程完全獨(dú)立。
在容器啟動(dòng)的時(shí)候,執(zhí)行一個(gè)啟動(dòng)腳本來創(chuàng)建 etcd 中的 key ,然后在停止的時(shí)候移除它。它可能在通知應(yīng)用停止的時(shí)候會(huì)變得更加復(fù)雜。而且,這還有一個(gè)風(fēng)險(xiǎn),就是在應(yīng)用完全啟動(dòng)之前, key 已經(jīng)在 etcd 中被創(chuàng)建了,然后 Haproxy 可能轉(zhuǎn)發(fā) HTTP 請(qǐng)求到容器中,盡管應(yīng)用還未啟動(dòng)。
一個(gè) ‘sidekick’ 進(jìn)程,運(yùn)行在同樣的容器中,能處理應(yīng)用的注冊(cè)和健康檢查。這個(gè)方法被 CoreOS 用于管理服務(wù)發(fā)現(xiàn)。這就是我將在示例中使用的解決方案。
Sidekick 進(jìn)程用于注冊(cè)負(fù)責(zé)注冊(cè)的進(jìn)程執(zhí)行以下任務(wù):
調(diào)用 Docker API 來檢索應(yīng)用在容器中的對(duì)外i端口映射到本地主機(jī)的端口
執(zhí)行應(yīng)用的健康檢查:當(dāng)應(yīng)用可用,使用 Docker 主機(jī)的 IP 和端口 創(chuàng)建或是更新 etcd 中的 key
當(dāng)應(yīng)用沒有正確響應(yīng),或者容器停止了:從 etcd 中移除 key
為了執(zhí)行這些任務(wù),我使用 GO 寫了一些程序,可用的版本在我的 GitHub 倉庫中:github.com/adetante/dockreg。
這個(gè)程序接收以下參數(shù):
--etcd:必須的,用于注冊(cè)的 etcd 的服務(wù)列表,使用以下格式:
--etcd http://host1:port1,http://host2:port2
--key:可選的,程序在 etcd 中為 keys 創(chuàng)建的父目錄的名字,默認(rèn)的值是 service 。
--port:必須的,應(yīng)用用于注冊(cè)的本地端口
--docker:可選的,用于訪問 Docker API 的 Docker UNIX socket,默認(rèn)的值是 /var/run/docker.sock。(看 Docker Introspection)
--ip:可選的,放進(jìn) etcd 的 Docker 主機(jī)的 IP 地址。如果未指定,IP 將被從 Docker API 的端口映射找到(意味著,你必須在 docker 運(yùn)行的命令中指定它,比如 docker run -p 8000::192.168.1.54)。
這個(gè)進(jìn)程將每 5 秒請(qǐng)求應(yīng)用監(jiān)聽的 --port,如果它在 3 秒內(nèi)沒有得到響應(yīng),key 將被從 etcd 中移除,否則,一個(gè) key 將被創(chuàng)建在 etcd 服務(wù)器的以下路徑:/keys/{service}/{ip}:{mapped_port}。
Docker 回顧正如你以上所見,dockreg 進(jìn)程通過一個(gè) Unix Domain socket(/var/run/docker.sock)訪問 Docker API。這是必須的,因?yàn)?Docker 沒有提供其他的方式來獲取容器的信息。這個(gè)需求在 Docker repository 中被討論(see issues 7421 and 3778 for example),這個(gè)在未來的版本可能會(huì)實(shí)現(xiàn)。目前,唯一的方法就是通過共享容器的 docker.sock 來實(shí)現(xiàn)這個(gè)需求。它并不理想,因?yàn)榘踩颍ㄊ褂眠@個(gè)接口,在安全認(rèn)證之外,容器能訪問和修改很多信息)。
為了分享 Docker socket,意味著容器必須以 -v 選項(xiàng)啟動(dòng):
docker run -p 8000 -v /var/run/docker.sock:/var/run/docker.sock myApplication
如果一個(gè)端口映射已經(jīng)在容器中定義,JSON 響應(yīng)內(nèi)容包含的一些東西如下:
"NetworkSettings": { "Bridge": "docker0", "Gateway": "172.17.42.1", "IPAddress": "172.17.0.4", "IPPrefixLen": 16, "PortMapping": null, "Ports": { "8000/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "49155" } ] } }
dockreg 將使用響應(yīng)中的 ports 數(shù)據(jù)來找回對(duì)外服務(wù)的端口(和 IP 地址)。
現(xiàn)在開始作為一個(gè)概念驗(yàn)證,我在基于 Vagrant 構(gòu)建的 2 個(gè)主機(jī)上創(chuàng)建了一個(gè) demo,首先,克隆 vagrant 倉庫:
git clone [email protected]:adetante/dockreg-vagrant.git
這個(gè)倉庫包含:
用于創(chuàng)建 2 個(gè)主機(jī)的 Vagrantfile?;A(chǔ)的 Vagrant box 是一個(gè) Ubuntu 14.04 以及 放進(jìn) VM 的 2 個(gè) Docker 鏡像:ubuntu 和 etcd,這個(gè)僅僅是用于完成主機(jī)加速。
NodeJS 示例程序,我們想部署進(jìn) Docker 容器中的。
一個(gè) dockreg 的構(gòu)建工具
一個(gè) Dockerfile 用于構(gòu)建一個(gè)鏡像,包含 NodeJS app 和 dockreg sidekick 進(jìn)程。
當(dāng)開始的時(shí)候,vagrant 腳本(build.sh) 將啟動(dòng)一個(gè) etcd 容器,作為一個(gè) host-1 和 host-2 的集群配置。下一步,它將構(gòu)建一個(gè)包含 NodeJS app 和 dockreg sidekick 進(jìn)程的鏡像,Dockerfile 如下:
FROM ubuntu:trusty RUN apt-get update && apt-get install -y python python-setuptools nodejs && easy_install supervisor && mkdir /var/log/dockreg EXPOSE 8000 CMD [] ENTRYPOINT ["/usr/local/bin/supervisord","-c","/etc/supervisord.conf"] ADD supervisord.conf /etc/supervisord.conf ADD dockreg /usr/bin/dockreg ADD node-app/server.js /root/server.js RUN chmod a+x /usr/bin/dockreg
在這個(gè)構(gòu)建鏡像中,一個(gè) supervisord 進(jìn)程將啟動(dòng) NodeJS 應(yīng)用和 dockreg 進(jìn)程。
Supervisord 配置如下:
[supervisord] nodaemon=true logfile=/var/log/dockreg/supervisord.log logfile_maxbytes=50MB logfile_backups=4 loglevel=info pidfile=/var/run/supervisord.pid [program:nodejs-server] command=nodejs /root/server.js autorestart=unexpected stdout_logfile=/var/log/dockreg/http.stdout stdout_logfile_maxbytes=1MB stdout_logfile_backups=10 stderr_logfile=/var/log/dockreg/http.stderr stderr_logfile_maxbytes=1MB stderr_logfile_backups=10 [program:dockreg] command=/usr/bin/dockreg --port 8000 --etcd http://%(ENV_ETCD_PORT_4001_TCP_ADDR)s:%(ENV_ETCD_PORT_4001_TCP_PORT)s --ip %(ENV_IP)s autorestart=unexpected stdout_logfile=/var/log/dockreg/dockreg.stdout stdout_logfile_maxbytes=1MB stdout_logfile_backups=10 stderr_logfile=/var/log/dockreg/dockreg.stderr stderr_logfile_maxbytes=1MB stderr_logfile_backups=10
是時(shí)間開始了,啟動(dòng)一個(gè)主機(jī):
vagrant up host-1
在 boot 日志中,你將看到 Docker 容器的構(gòu)建進(jìn)程。在最后:
Successfully built a98722a9f44b
下一步,登陸進(jìn) VM:
vagrant ssh host-1
檢查 etcd 容器是否在運(yùn)行:
docker ps
你可以使用以下的地址訪問 etcd :http://10.1.0.101:4001/v2/machines
下一步,啟動(dòng)一個(gè)新的容器,運(yùn)行 NodeJS app:
docker run -d -p 8000 -v /var/run/docker.sock:/var/run/docker.sock -e IP=10.1.0.101 --link etcd:etcd local/dockreg
當(dāng)容器啟動(dòng)的時(shí)候,可以在 etcd 中看到注冊(cè):
curl http://10.1.0.101:4001/v2/keys/service { "action": "get", "node": { "key": "/service", "dir": true, "nodes": [ { "key": "/service/10.1.0.101:49155", "value": "running", "expiration": "2014-08-26T21:17:28.431730841Z", "ttl": 19, "modifiedIndex": 23, "createdIndex": 23 } ], "modifiedIndex": 3, "createdIndex": 3 } }
在這個(gè)示例中,暴露的端口是 49155。
訪問應(yīng)用:
curl http://10.1.0.101:49155 Hello from 2d151d56f838
成功,下一步,啟動(dòng)第二個(gè)主機(jī):
vagrant up host-2
一旦運(yùn)行,檢查已經(jīng)加入到集群中的新的 etcd 的實(shí)例:
curl http://10.1.0.102:4001/v2/machines http://10.1.0.101:4001, http://10.1.0.102:4001
檢查已經(jīng)復(fù)制的插入進(jìn) host-1 的 key:
curl http://10.1.0.102:4001/v2/keys/service { "action": "get", "node": { "key": "/service", "dir": true, "nodes": [ { "key": "/service/10.1.0.101:49155", "value": "running", "expiration": "2014-08-26T21:39:07.415916256Z", "ttl": 17, "modifiedIndex": 73, "createdIndex": 73 } ], "modifiedIndex": 3, "createdIndex": 3 }
現(xiàn)在,登陸 host-2 (vagrant ssh host-2),然后啟動(dòng)一個(gè)新的應(yīng)用容器:
docker run -d -p 8000 -v /var/run/docker.sock:/var/run/docker.sock -e IP=10.1.0.102 --link etcd:etcd local/dockreg
http://10.1.0.101:4001/v2/keys/service 和 http://10.1.0.102:4001/v2/keys/service 現(xiàn)在可以顯示運(yùn)行在 host-2 上的新的實(shí)例(或許需要花一點(diǎn)時(shí)間用于應(yīng)用啟動(dòng))。
還需要一個(gè)新的??jī)H僅需要再一次運(yùn)行前面的 docker run 命令?,F(xiàn)在 etcd 包含 3 個(gè)實(shí)例。
為了測(cè)試取消登記,停止一個(gè)容器:
docker stop fdd27afacbbb
key 將立即從 etcd 中移除。
總結(jié)在這個(gè)例子中,我們看到了一種把 Docker 容器注冊(cè)進(jìn)一個(gè)外部配置存儲(chǔ)的方法。通過使用一個(gè) sidekick 進(jìn)程,服務(wù)注冊(cè)完全獨(dú)立于應(yīng)用,并且它提供了更精確的監(jiān)控。
達(dá)到這個(gè)目標(biāo)的其他可選方案,The CoreOS project 提議了一份工具列表來簡(jiǎn)化注冊(cè)和服務(wù)發(fā)現(xiàn)。
在下一篇文章中,我將描述基于 HAProxy 和 etcd 的服務(wù)發(fā)現(xiàn)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/26340.html
摘要:為了動(dòng)態(tài)配置管理,當(dāng)我們啟動(dòng)和停止一個(gè)新容器的時(shí)候,我們想后端能自動(dòng)注冊(cè)進(jìn)負(fù)載均衡器。這是基本需求,叫做服務(wù)發(fā)現(xiàn)我們想負(fù)載均衡器能自動(dòng)發(fā)現(xiàn)提供服務(wù)的容器。一個(gè)團(tuán)隊(duì)開發(fā)的簡(jiǎn)單的服務(wù)發(fā)現(xiàn)的工具。服務(wù)發(fā)現(xiàn)目標(biāo)是減少或消除組件之間的手動(dòng)的連接。 注:該文由 adetante 編寫,原文地址為 Service discovery with Docker 這篇博客的第一篇文章,我將寫一篇...
摘要:運(yùn)行在上的微服務(wù)服務(wù)發(fā)現(xiàn)與注冊(cè)在上一節(jié)中,我們學(xué)習(xí)了如何在上構(gòu)建一個(gè)風(fēng)格的微服務(wù)。接下來,我們將學(xué)習(xí)如何把運(yùn)行在上的微服務(wù)暴露在服務(wù)中心上,以便客戶端的調(diào)用。資源服務(wù)在關(guān)閉時(shí)需要將服務(wù)實(shí)例在服務(wù)中心進(jìn)行注銷操作。響應(yīng)用戶的終止。 運(yùn)行在 Docker 上的微服務(wù) - 服務(wù)發(fā)現(xiàn)與注冊(cè) tags: Docker Microservice RESTful etcd Author: And...
摘要:后續(xù)將其他節(jié)點(diǎn)加入集群都會(huì)用到這個(gè)值將節(jié)點(diǎn)加入集群查看節(jié)點(diǎn)信息相關(guān)命令創(chuàng)建服務(wù)更新服務(wù)刪除服務(wù)減少服務(wù)實(shí)例增加服務(wù)實(shí)例查看所有服務(wù)查看服務(wù)的容器狀態(tài)查看服務(wù)的詳細(xì)信息。前言本篇是Docker第十三篇,Docker的使用至此就介紹完成,接下來繼續(xù)Kubernetes。Docker系列文章:為什么要學(xué)習(xí)DockerDocker基本概念Docker鏡像基本原理Docker容器數(shù)據(jù)卷Dockerfi...
摘要:之前提到的文件即可利用以下模板生成請(qǐng)注意,其中的與就是占位符。如將某一特定部署至生產(chǎn)環(huán)境并運(yùn)行個(gè)實(shí)例。而另一種方式則是使用等負(fù)載均衡器即服務(wù)器端發(fā)現(xiàn)??芍嘏渲们夷軌蛟谧兏l(fā)生后立即將請(qǐng)求路由至新實(shí)例。 如今與Mesos相關(guān)的文章可謂層出不窮,不過展示能夠直接用于生產(chǎn)的完整基礎(chǔ)設(shè)施的資料卻相當(dāng)少見。在今天的文章中,我將介紹各組件的配置與使用方式,旨在幫助大家利用Mesos構(gòu)建起持續(xù)交付且...
摘要:服務(wù)發(fā)現(xiàn)服務(wù)發(fā)現(xiàn)被容器處理。主機(jī)首先,我們啟動(dòng)注冊(cè)我們的地址是。首先,啟動(dòng)然后,啟動(dòng)一個(gè)簡(jiǎn)單的客戶端容器并傳給它。這時(shí),構(gòu)造一些請(qǐng)求給服務(wù)端口來看他們的負(fù)載。同樣地,的事件和容器減輕了服務(wù)注冊(cè)和使用注冊(cè)服務(wù)發(fā)現(xiàn)比如的困難。 使用 Etcd 和 Haproxy 做 Docker 服務(wù)發(fā)現(xiàn) 標(biāo)簽(空格分隔): Etcd Haproxy Docker 服務(wù)發(fā)現(xiàn) architecture ...
閱讀 2436·2019-08-29 13:53
閱讀 2517·2019-08-29 11:32
閱讀 3057·2019-08-28 17:51
閱讀 3803·2019-08-26 10:45
閱讀 3523·2019-08-23 17:51
閱讀 2992·2019-08-23 16:56
閱讀 3345·2019-08-23 16:25
閱讀 3099·2019-08-23 14:15