這個簡短的教程幫你快速開始使用Registrator。完整參看,查看運行參考node
Registrator監控新建的Docker容器,而且檢查斷定這些容器提供的服務。從咱們的目的出發,任何監聽在某個端口的程序都是服務。Registrator發如今容器內發現的任務服務,都將被添加到一個服務註冊端,好比Consul或etcd。
在這個教程中,咱們將使用Registrator和Consul,運行一個Redis容器並自動添加到Consul。nginx
咱們須要一個運行Docker的主機,能夠是一個本地的boot2doker虛擬機和一個安裝了docker client能夠鏈接到虛擬機的shell。
咱們在容器裏運行一個Server模式的consul實例redis
$ docker run -d --name=consul --net=host gliderlabs/consul-server -bootstrap
Consul在產品模式下的不是這樣運行的,咱們這裏使用這種方式完成教程。如今咱們能夠訪問經過Docker主機的IP訪問Consul的HTTP API。docker
$ curl $(boot2doker ip):8500/v1/catalog/services {"consul":[]}
如今咱們能夠啓動Registrator了。shell
Registrator運行在每臺主機上,咱們這裏只有一臺主機,就運行一次就行。啓動Registrator須要配置如何鏈接到註冊機,即這裏的Consul。
除了標誌選項,惟一須要的參數就是註冊機URI。註冊機URI編碼了註冊機類型,如何鏈接等選項。json
$ docker run -d \ --name=registrator --net=host \ gliderlabs/registrator:latest \ consul://localhost:8500
先說一下Docker運行參數。首先,咱們獨立的運行容器和命名。咱們也採用主機網絡模式。這確保Registrator擁有實際主機的主機名和IP,也使Registrator更容易鏈接到Consul。咱們也必須掛載Docker socket。bootstrap
最後一行是Registrator運行參數,只有註冊機URI。咱們使用consul//localhost:8500,由於Registrator和Consul 運行在同一個網口。ubuntu
$ docker logs registrator
咱們應該能夠看到Registrator運行起來並在「監聽Docker事件"。Registrator正常運行了。後端
如今當你啓動的容器若是提供任何服務,他們將被添加到Consul。咱們如今運行標準鏡像庫的Redis:
$ docker run -d -P --name=redis redis
咱們使用-P
發佈全部端口,除了Registrator咱們不常常這樣使用。這樣不只發佈了容器的全部端口,並且隨機分配了一個主機端口。從Registrator和Consul提供服務發現的角度看,端口並不重要。儘管還有一些狀況,你仍然想手動指定端口。
咱們再來看看Consul的服務端:
$ curl $(boot2docker ip):8500/v1/catalog/services {"consul":[],"redis":[]}
如今Consul已經有了一個redis服務。咱們能夠經過Consul的服端API查看更多諸如服務發佈端口等信息:
$ curl $(boot2docker ip):8500/v1/catalog/service/redis [{"Node":"boot2docker","Address":"10.0.2.15","ServiceID":"boot2docker:redis:6379","ServiceName":"redis","ServiceTags":null,"ServiceAddress":"","ServicePort":32768}]
若是咱們移除redis容器,咱們可以看到服務也從consul移除了。
$ docker rm -f redis redis $ curl $(boot2docker ip):8500/v1/catalog/service/redis []
就到這了。我知道單獨來看這並沒什麼意義,可是當服務註冊到Consul後你能夠作不少事情。固然,這超出了Registrator的範圍,它作的就是把容器中的服務放進Consul。
這還有不少方法配置Registrator,而且有不少方法運行容器,自定義服務。想了解這些,去看看運行參考和服務模型
Registrator設計是在每一個主機上運行一次。你能夠在一個集羣中運行單個Registrator,可是在每一個主機上運行可使你或得更好的擴展屬性和更簡單的配置。從必定程度的自動化來講,每一個主機都運行比在某個地方運行一次更簡單。
docker run [docker options] gliderlabs/registrator[:tag] [options] <registry uri>
Registrator要求和推薦一些Docker選項,也有它本身的選項集,而後須要個註冊機URI。下面是一個運行Registrator的經典方式:
$ docker run -d \ --name=registrator \ --net=host \ --volume=/var/run/docker.sock:/tmp/docker.sock \ gliderlabs/registrator:latest \ consul://localhost:8500
Option | Required | Description |
---|---|---|
--volume=/var/run/docker.sock:/tmp/docker.sock | yes | 容許Registrator訪問Docker API |
--net=host | recommended | 幫助Registrator獲取主機級的IP和主機名 |
與設置主機網絡模式相比,另外一個可選的方案是設置容器名字爲宿主主機名(-h $HOSTNAME
),而且使用下面Registrator的-ip選項。
Option | Since | Description |
---|---|---|
-cleanup | v7 | 清理懸掛服務 |
-deregister | v6 | 取消註冊退出的服務 "always"或"on-success".缺省值:always |
-internal | 使用暴露端口代替發佈端口 | |
-ip | v6 | 強制設置註冊服務使用的IP地址 |
-resync | v6 | 服務再同步頻率。缺省值:0,never |
-retry-attempts | v7 | 與註冊機後臺創建鏈接的最大重試次數 |
-retry-interval | v7 | 重試間隔(以毫秒爲單位) |
-tags | v5 | 強制設置全部註冊服務的都好分割的tags |
-ttl | 服務TTL。缺省值0,no expiry(註冊機後臺惟一支持) | |
-ttl-refresh | 服務TTL刷新頻率(註冊機後臺惟一支持) | |
-useIdFromLabel | 使用存儲在給定label的IP地址,這個label在容器中設置,用以註冊Consul。 |
若是設置了-internal
選項,Registrator會註冊docker內部IP和端口,而不是映射到主機的端口。
默認狀況下,註冊服務時,Registrator會嘗試解析當前主機名來設置服務地址。若是你想強制指定服務地址爲某個特定地址,你能夠指定-ip
參數。
對於支持TTL超期的註冊機後端,Registrator支持設置和刷新服務的TTLs,使用-ttl
和-ttl-refresh
。
若是你想無限制的重連嘗試,可使用-retry-attempts -1
。
-resync
選項控制Registrator查詢Docker中全部容器而且註冊全部服務的頻率。這個選項容許Registrator和服務註冊機從新找到掉出同步的服務。要謹慎使用這個選項,它會通知已經註冊到你服務上的全部觀察者,可能會迅速淹沒你的系統(好比consul-template就大量使用監測)。
若是consul配置要求提供ACL令牌,Registrator須要知道,或者你會在consul的docker容器中看到警告。
[WARN] consul.catalog: Register of service 'redis' on 'hostname' denied due to ACLs
ACL令牌經過一個環境變量傳入docker:CONSUL_HTTP_TOKEN
。
$ docker run -d \ --name=registrator \ --net=host \ --volume=/var/run/docker.sock:/tmp/docker.sock \ -e CONSUL_HTTP_TOKEN=<your acl token> \ gliderlabs/registrator:latest \ consul://localhost:8500
<backend>://<address>[/<path>]
註冊機後臺使用URI來定義。架構是支持的註冊機名字。地址是用來鏈接註冊機的一個主機或者主機和端口。一些註冊機支持一個定義的路徑,好比做爲前綴在服務定義中供基於註冊機的key-value使用。
因此支持的後端參考,查看註冊機後端
Registrator主要關注的那些要被添加到服務發現註冊機的服務。對咱們而言,全部監聽在某個端口的程序都是服務。若是一個容器監聽了多個端口,它就又多個服務。
服務,包括來自容器的信息和用戶在容器上定義的元數據被建立成一個服務對象。這個服務對象隨後被傳遞給註冊機後端,嘗試放置到一個特定的註冊項。
type Service struc { ID string //unique service instance ID Name string //service name IP string //IP address service is located at Port int //Port service is listening on Tags []string //extra tags to classify service Attrs map[string]string //extra attribute metadata }
Name,Tags,Attrs,ID
字段能夠被用戶自定義的容器元數據覆蓋。你可使用前綴SERVICE_
或者SERVICE_x_
,其中x
是內部暴露端口的環境變量或者標籤設置這些值。例如,SERVICE_NAME=customerdb
和SERVICE_80_NAME=api
你在這些環境變量中使用的端口指的是在這個端口上的特定服務。名字中沒有使用端口的元數據變量用做全部服務的缺省值,或者便捷的指向暴露的單個服務。
Attrs
字段集合全部使用其餘字段名的關鍵字,例如,SERVICE_REGION=us-east
。
由於元數據被存儲爲環境變量或者標籤,所以容器做者能夠在Dockerfile中包含他們本身的元數據定義。操做者仍然可以覆蓋這些做者定義的缺省值。
缺省狀況下,你能夠指望Registrator從那些已經顯式發佈端口(例如使用'-p'或者-P
)的容器中獲取服務。這對於那些以主機網絡模式運行的容器也是正確的,所以你必須發佈端口,即便它沒什麼作任何網絡智慧的事情。
$ docker run --net=host -p 8080:8080 -p 8443:8443 ...
若是使用-internal
選項運行,相反它將尋找暴露的端口。這些能夠在Dockerfile中隱式設置或者使用docker run --expose=8080...
顯式設定。
你也能夠經過設置一個叫SERVICE_IGNORE
的標籤或者環境變量告訴Registrator忽略一個容器。
若是你須要在某些容器中忽略幾個服務,你可使用SERVICE_<port>_IGNORE=true
。
服務名是你在服務發現查找中使用的。缺省狀況下,服務名按下面的格式肯定:
<base(container-image)>[-<exposed-port> if >1 ports]
使用容器鏡像的基礎,若是鏡像是gliderlabs/footbar
,服務名就是footbar
。若是鏡像是redis
,服務名就是簡單的redis
。
並且若是一個容器有多個暴露端口,它將各自追加內部暴露端口以區別。例如,一個鏡像nginx
有兩個暴露端口,80和443,將產生兩個服務,分別命名nginx-80
和nginx-443
。
你可使用標籤或者環境變量,SERVICE_NAME
或者'SERVICE_x_NAME',其中x
是內部暴露端口,覆蓋這些缺省名字。注意若是一個容器有多個暴露端口,設置SERVICE_NAME
會致使多個服務命名爲SERVICE_NAME-<exposed port>
。
IP和端口組成了服務名解析的地址。這有許多方法Registrator可以依賴你的設置判斷IP地址和端口。缺省狀況下,端口就是發佈的公共端口,IP將是你的主機IP。
因爲自動斷定正確的IP是困難的,推薦使用-ip
選項顯式告訴Registrator使用什麼IP。
若是你使用-internal
選項,Regisrator會使用暴露端口和docker分配的內部容器IP。
Tags和attributes是服務額外的元數據字段。並非全部的後端都支持他們。事實上,目前consul支持tags,而且最近的v1.0.7以KV元數據的形式添加了對attributes的支持,可是沒有其餘的後端支持attributes。
Attributes也能被後端用來註冊特定的特性,不只僅是元數據。例如,consul使用他們指定specifying HTTP health checks
。
ID是服務示例在集羣內的惟一標識。大部分狀況下,它是一個實現細節,一般用戶使用服務名而不是ID。Registrator使用一我的機友好的字符串,基於下面的格式編碼了有用的信息在ID中:
<hostname>:<container-name>:<exposed-port>[:udp if udp]
ID包括了主機名,幫助你識別服務運行的主機。這也是Registrator運行在主機網絡模式下或者設置Registrator的主機名爲寄宿主機的主機名重要的緣由。不然它將是Registrator容器的ID,那沒有什麼用處。
這個服務的容器名稱也包含進來了。它使用容器名稱代替容器ID,由於它更人性化,而且用戶可配置。
爲了識別出容器中這個服務,它使用內部暴露端口。這表明這個服務在容器內在這個端口上監聽。咱們使用這個是由於它比公共的發佈端口更好的表達了這個服務。一個公共的端口多是一個任意的54292,然而暴露的端口多是80,表示它是一個HTTP服務。
最後,若是服務定義爲UDP,這會被包括到ID中與監聽在相同端口的TCP服務區別開。
儘管這可使用容器的SERVICE_ID
或者SERVICE_x_ID
覆蓋,可是不推薦這樣作。
$ docker run -d --name redis.0 -p 10000:6379 progrium/redis
Service
結果是:
{ "ID": "hostname:redis.0:6379", "Name": "redis", "Port": 10000, "IP": "192.168.1.102", "Tags": [], "Attrs": {} }
$ docker run -d --name redis.0 -p 10000:6379 \ -e "SERVICE_NAME=db" \ -e "SERVICE_TAGS=master,backups" \ -e "SERVICE_REGION=us2" progrium/redis
Service
結果是:
{ "ID": "hostname:redis.0:6379", "Name": "db", "Port": 10000, "IP": "192.168.1.102", "Tags": ["master", "backups"], "Attrs": {"region": "us2"} }
記住並非全部的Service
對象都會被註冊後端使用。例如,目前不支持註冊任意attributes。這個字段留做未來使用。
逗號可能能夠經過反斜槓轉義,像下面的例子:
$ docker run -d --name redis.0 -p 10000:6379 \ -e "SERVICE_NAME=db" \ -e "SERVICE_TAGS=/(;\\,:-_)/" \ -e "SERVICE_REGION=us2" progrium/redis
$ docker run -d --name nginx.0 -p 4443:443 -p 8000:80 progrium/nginx
兩個Service
對象的結果:
[ { "ID": "hostname:nginx.0:443", "Name": "nginx-443", "Port": 4443, "IP": "192.168.1.102", "Tags": [], "Attrs": {}, }, { "ID": "hostname:nginx.0:80", "Name": "nginx-80", "Port": 8000, "IP": "192.168.1.102", "Tags": [], "Attrs": {} } ]
$ docker run -d --name nginx.0 -p 4443:443 -p 8000:80 \ -e "SERVICE_443_NAME=https" \ -e "SERVICE_443_ID=https.12345" \ -e "SERVICE_443_SNI=enabled" \ -e "SERVICE_80_NAME=http" \ -e "SERVICE_TAGS=www" progrium/nginx
兩個Service
對象的結果:
[ { "ID": "https.12345", "Name": "https", "Port": 4443, "IP": "192.168.1.102", "Tags": ["www"], "Attrs": {"sni": "enabled"}, }, { "ID": "hostname:nginx.0:80", "Name": "http", "Port": 8000, "IP": "192.168.1.102", "Tags": ["www"], "Attrs": {} } ]
$ docker run -d --name redis.0 -p 10000:6379 \ -l "SERVICE_NAME=db" \ -l "SERVICE_TAGS=master,backups" \ -l "SERVICE_REGION=us2" dockerfile/redis
Service
結果:
{ "ID": "hostname:redis.0:6379", "Name": "db", "Port": 10000, "IP": "192.168.1.102", "Tags": ["master", "backups"], "Attrs": {"region": "us2"} }
Registrator支持不少後端註冊機。爲了發揮Registrator的用途,你須要運行其中一個。下面是被支持後端使用的註冊URI和它們的特性文檔。
consul://<address>:<port> consul-unix://<filepath> consul-tls://<address>:<port>
Consul是推薦的註冊機,由於它專門爲服務發現提供了健康檢查服務。
若是沒有指定地址和端口,默認將使用127.0.0.1:8500。
consul支持tags,但不是任意服務attributes。
當使用consul-tls
架構,Registrator經過TLS與Consul通訊。你必須設置下面的環境變量:CONSUL_CAERT
:CA 文件位置, CONSUL_TLSKEY
:Key位置
瞭解更多關於Consul檢查參數信息,查看API documentation。
這個特性只能在Consul 0.5及更新版本中使用。容器經過環境變量或者標籤指定的這些額外的元數據用來在服務中註冊一個HTTP健康檢查。
SERVICE_80_CHECK_HTTP=/health/endpoint/path SERVICE_80_CHECK_INTERVAL=15s SERVICE_80_CHECK_TIMEOUT=1s # optional, Consul default used otherwise
它適用於任何端口的服務,不只僅是80端口。若是它是惟一的服務,你也可使用
SERVICE_CHECK_HTTP
這個特性只能在Consul 0.5及更新版本中使用。容器經過環境變量或者標籤指定的這些額外的元數據用來在服務中註冊一個HTTPS健康檢查。
SERVICE_443_CHECK_HTTPS=/health/endpoint/path SERVICE_443_CHECK_INTERVAL=15s SERVICE_443_CHECK_TIMEOUT=1s # optional, Consul default used otherwise
這個特性只能在Consul 0.6及更新版本中使用。容器經過環境變量或者標籤指定的這些額外的元數據用來在服務中註冊一個TCP健康檢查。
SERVICE_443_CHECK_TCP=true SERVICE_443_CHECK_INTERVAL=15s SERVICE_443_CHECK_TIMEOUT=3s # optional, Consul default used otherwise
這個特性很難用,由於它讓你指定一個腳本檢查從Consul運行。若是在容器中運行Consul,你就被限制只能在那個容器中運行。例如,curl必須按照以使用這個特性:
SERVICE_CHECK_SCRIPT=curl --silent --fail example.com
任務no-TTL檢查的缺省間隔是10秒,可是你可使用_CHECK_INTERVAL
設置。檢查命令可使用$SERVICE_IP
和$SERVICE_PORT
佔位符插值:
SERVICE_CHECK_SCRIPT=nc $SERVICE_IP $SERVICE_PORT | grep OK
你也能夠向consul註冊一個TTL Check。記住這意味着Consul將期待一個常規的心跳ping到他的API,用以保持服務標誌健康。
SERVICE_CHECK_TTL=30s
缺省的當一個服務在Consul註冊時,狀態被設置爲"critical"。你能夠指定初始的健康檢查狀態:
SERVICE_CHECK_INITIAL_STATUS=passing
Consul可能撤銷註冊一個服務,若是檢查在critical
狀態超過設定的時間值。若是啓用,這應該比可期待的恢復故障更長。
SERVICE_CHECK_DEREGISTER_AFTER=10m
consulkv://<address>:<port>/<prefix> consulkv-unix://<filepath>:/<prefix>
這是一個分離後端,使用Consul的key-value存儲代替它的本地服務目錄。這種表現更像etcd,由於它有類似的語義,可是目前不支持TTLs。
若是沒有指定地址和端口,默認是127.0.0.1:8500
。
使用Registry URI前綴,服務定義存儲爲下面的格式:
<prefix>/<service-name>/<service-id> = <ip>:<port>
etcd://<address>:<port>/<prefix>
Etcd工做方式與Consul KV類似,並且支持服務TTLs。它目前也不支持服務attributes和tags。
若是沒有指定地址和端口,它將使用默認值127.0.0.1:2379
。
使用Registry URI做爲前綴,服務定義被儲存爲下面的格式:
<prefix>/<service-name>/<service-id> = <ip>:<port>
skydns2://<address>:<port>/<domain>
SkyDNS2 使用etcd,所以這個後端寫服務定義的格式兼容SkyDNS2。path不能被省略,必須是一個對SkyDNS有效的DNS域名。
若是沒有指定地址和端口,它將是默認值:127.0.0.1:2379
。
使用Registry URI和域名cluster.local
,服務定義存儲爲下面的格式:
/skydns/local/cluster/<service-name>/<service-id> = {"host":"<ip>","port":<port>}
SkyDNS要求服務ID是一個有效的DNS主機名,所以這個後端要求容器用一個有效的DNS名字覆蓋服務ID。例如:
$ docker run -d --name redis-1 -e SERVICE_ID=redis-1 -p 6379:6379 redis
Zookeeper後端讓你發佈臨時的znodes到zookeeper。這個模式在指定zookeeper路徑後可使用。zookeeper後端支持發佈一個json格式的znode body,完成定義服務attributes/tags,也包括服務名和容器id。URI示例:
$ registrator zookeeper://zookeeper.host/basepath $ registrator zookeeper://192.168.1.100:9999/basepath
在zookeeper URI指定的base path中,registrator將爲服務建立下面的包括一個JSON入口路徑樹:
<service-name>/<service-port> = <JSON>
JSON將包括髮布容器服務的全部信息。例以下面的容器啓動:
docker run -i -p 80 -e 'SERVICE_80_NAME=www' -t ubuntu:14.04 /bin/bash
將產生的zookeeper path和JSON znode body:
/basepath/www/80 = {"Name":"www","IP":"192.168.1.123","PublicPort":49153,"PrivatePort":80,"ContainerID":"9124853ff0d1","Tags":[],"Attrs":{}}
原文鏈接:點擊這裏