2014-02-06 60 views
2

我目前正在修補CoreOS並基於它創建一個集羣。到目前爲止,CoreOS在單個主機上的體驗非常流暢。但是當涉及到服務發現時,事情會變得有點朦朧。不知何故,我沒有得到整體的想法,因此我現在要求在這裏尋求幫助。如何在CoreOS上使用etcd進行服務發現時處理過時的數據?

我想要做的是讓兩個Docker容器在第一個依賴第二個容器的位置運行。如果我們正在談論純粹的Docker,我可以使用linked containers來解決這個問題。到現在爲止還挺好。

但是這種方法無法跨越機器邊界,因爲Docker無法將容器鏈接到多個主機。所以我想知道如何做到這一點。

我有什麼瞭解,到目前爲止是如何處理這個C​​oreOS的想法是利用其etcd服務,這基本上是一個分佈式鍵值存儲是每個主機上訪問通過端口4001在本地,所以您不必與任何網絡詳細信息(作爲etcd的消費者)交易:只需訪問localhost:4001即可,您沒事。

因此,我認爲這意味着當提供服務的Docker啓動時,它會在本地註冊自己(即其IP地址及其端口)etcdetcd需要注意通過網絡分發信息。這樣,例如你鍵值對,例如:

RedisService => 192.168.3.132:49236 

現在,當另一個泊塢窗容器需要訪問RedisService,它會從他們自己的地方etcd的IP地址和端口,至少一次的信息已分發通過網絡。到現在爲止還挺好。

但是現在我有一個問題,我無法回答,這讓我感到困惑了幾天:服務出現故障時會發生什麼?誰清理了etcd裏面的數據?如果沒有清理乾淨,所有客戶端都嘗試訪問不再存在的服務。

我現在所能想到的唯一(可靠的)解決方案是利用etcd的數據TTL功能,但這涉及到一種折衷:要麼發送相當高的網絡流量,要麼發送每隔幾秒鐘發一次心跳,或者你必須忍受陳舊的數據。兩者都不好。

另外,還有,「解決方案」我能想到的是做一個服務註銷本身,當它出現故障,但這種方式只適用於計劃停機,而不是崩潰,電力outeages,...

所以,你如何解決這個問題?

回答

8

有幾種不同的方法可以解決這個問題:搭檔方法,使用ExecStopPost並刪除失敗。我假設三人組合CoreOS,etcdsystemd,但這些概念也可以應用於其他地方。

Sidekick的方法

這涉及到運行一個單獨的進程旁邊的主應用程序,心跳到etcd。簡而言之,這只是一個永久運行的for循環。您可以使用systemd的BindsTo來確保當您的主機停止時,該服務註冊單元也會停止。在ExecStop中,您可以明確地刪除您正在設置的密鑰。我們還設置了60秒的TTL來處理任何不正當的停頓。

[Unit] 
Description=Announce nginx1.service 
# Binds this unit and nginx1 together. When nginx1 is stopped, this unit will be stopped too. 
BindsTo=nginx1.service 

[Service] 
ExecStart=/bin/sh -c "while true; do etcdctl set /services/website/nginx1 '{ \"host\": \"10.10.10.2\", \"port\": 8080, \"version\": \"52c7248a14\" }' --ttl 60;sleep 45;done" 
ExecStop=/usr/bin/etcdctl delete /services/website/nginx1 

[Install] 
WantedBy=local.target 

在複雜的一面,這可能是啓動並擊中/health終點,你的應用程序提供將數據發送到etcd之前運行健康檢查的容器。

ExecStopPost

如果你不想運行主應用程序旁邊的東西,你可以有你的主單元內etcdctl命令在啓動運行和停止。請注意,正如你所提到的,這不會捕獲所有的失敗。

[Unit] 
Description=MyWebApp 
After=docker.service 
Require=docker.service 
After=etcd.service 
Require=etcd.service 

[Service] 
ExecStart=/usr/bin/docker run -rm -name myapp1 -p 8084:80 username/myapp command 
ExecStop=/usr/bin/etcdctl set /services/myapp/%H:8084 '{ \"host\": \"%H\", \"port\": 8084, \"version\": \"52c7248a14\" }' 
ExecStopPost=/usr/bin/etcdctl rm /services/myapp/%H:8084 

[Install] 
WantedBy=local.target 

%H是一個systemd變量,用於替換機器的主機名。如果您對更多變量使用感興趣,請查看CoreOS Getting Started with systemd指南。

拆卸故障

在客戶端,你可以刪除任何情況下,你都無法連接到超過X倍以上。如果您從/services/myapp/instance1獲得500或超時,則可以運行並繼續增加失敗計數,然後嘗試連接到/services/myapp/目錄中的其他主機。

etcdctl set /services/myapp/instance1 '{ \"host\": \"%H\", \"port\": 8084, \"version\": \"52c7248a14\", \"failures\": 1 }' 

當你打你所需的閾值,取出鑰匙與etcdctl

關於心跳會導致的網絡流量 - 在大多數情況下,您應該通過您的提供商運行的本地專用網絡發送此流量,以免流量非常快。無論如何,etcd一直在與同行保持着良好的關係,所以這只是流量的一點點增加。

如果您有任何其他問題,請加入Freenode的#coreos!

+0

非常感謝,這幫了我很多:-)! –

相關問題