使用Kubernetes和Docker進行簡單的領導者選舉

jopen 8年前發布 | 13K 次閱讀 Kubernetes

【編者的話】Kubernetes簡化了運行在集群中的服務部署和運維管理,然而,它也簡化了這些管理工作的部署。本篇文章將會展示如何在分布式應用系統中使用Kubernetes來簡單地運行領導者選舉。

概述

為了可靠性和伸縮性,分布式系統通常會復制多個服務任務,但往往有必要指定一個副本作為領導者負責協調所有的副本。

通常在領導者選舉中,一組有機會成為領導者的候選者都是可以確認的。這些候選者都競相宣布自己是領導者,其中會有一個候選者脫穎而出成為領導者。一旦贏了選舉之后,領導者將會繼續以領導者身份發送“心跳”來更新他們的位置。而其它的候選者將會周期性地作出嘗試來成為領導者,這套機制確保了如果當前的領導者由于某些原因失效了,可以快速指定新的領導者。

領導者選舉的實現通常需要任一一套分布式協調系統比如ZooKeeper、etcd或者Consul,使用它們來取得共識,或者交替實現自己的共識算法。接下來我們將會看到Kubernetes如何使得在應用中進行領導者選舉明顯更容易。

Kubernetes中領導者選舉的實現

領導者選舉的第一個要求是對于有意成為領導者的一組候選者的規范,Kubernetes已經使用了Endpoints來表示一組包含服務的Pods副本,所以我們將重用這個相同的對象(旁白:你可能會認為我們將使用ReplicationControllers,但它們被綁定到一個特定的二進制軟件包,即使在執行滾動更新的過程中也通常需要一個領導者)。

執行領導者選舉將使用Kubernetes API中的兩個屬性:

● ResourceVersions——每個API都有一個唯一的ResourceVersions,用戶可以使用這些版本在Kubernetes對象上執行Compare-and-Swap操作。

● Annotations——每個API都可以被用于客戶端的任意鍵/值對注解。

鑒于這些原語,使用選主的代碼相對簡單,可以在這兒找到相關代碼,運行如下:

$ kubectl run leader-elector --image=gcr.io/google_containers/leader-elector:0.4 --replicas=3 -- --election=example

這將會創建一個有三個副本的領導者選舉組:

$ kubectl get pods

NAME                   READY     STATUS    RESTARTS   AGE

leader-elector-inmr1   1/1       Running   0          13s

leader-elector-qkq00   1/1       Running   0          13s

leader-elector-sgwcq   1/1       Running   0          13s

為了查看哪一個Pod被選為了領導者,用戶可以訪問Pods的日志,在下面的位置替換為你自己的Pod的名字:

${pod_name}, (e.g. leader-elector-inmr1 from the above)



$ kubectl logs -f ${name}

leader is (leader-pod-name)

或者,用戶可以直接檢查Endpoints對象:

‘example’ is the name of the candidate set from the above kubectl run … command

$ kubectl get endpoints example -o yams

現在需要驗證領導者選舉是否生效,在另外一個終端中執行:

$ kubectl delete pods (leader-pod-name)

這個命令將會刪除已有的領導者,因為Replication Controller管理Pods組,一個新的Pod將會替換掉已經刪除的,從而確保副本數目仍然為3。通過領導者選舉,這三個Pod中將會有一個被選為領導者,并且領導者角色還會失效轉移到不同的Pod上。因為Kubernetes框架中Pod在終止前會有一個寬限期,通常是持續30~40秒。

領導者選舉容器提供了一個簡單的Web服務器,可以運行在任何地址上(比如 http://localhost:4040 ),我們可以通過刪除一個已有的領導者選舉組并創建一個新的來測試這個容器,此處可以另外傳入一個形如-http=(host):(port) 規格的配置到鏡像中,這樣就會導致每一個組成員通過Webhook來獲得有關領導者的服務信息。

delete the old leader elector group

$ kubectl delete rc leader-elector

create the new group, note the --http=localhost:4040 flag

$ kubectl run leader-elector --image=gcr.io/google_containers/leader-elector:0.4 --replicas=3 -- --election=example --http=0.0.0.0:4040

create a proxy to your Kubernetes api server

$ kubectl proxy

接著可以訪問:

http://localhost:8001/api/v1/proxy/namespaces/default/pods/(leader-pod-name):4040/

然后就會看到:

{

"name":"(name-of-leader-here)"

}

領導者選舉與sidecars

太好了,現在可以通過HTTP來進行領導者選舉和找出領導者,但怎么能在您自己的應用程序中使用它們呢?這就需要引入Sidecars的概念。在Kubernetes中,Pods由一個或者多個容器組成,通常,這意味著添加sidecars容器到主應用程序中組成一個Pod(對于這個主題的更詳細的處理,請看我以前的博客文章)。

領導者選舉容器可以作為一個Sidecars來從自己的應用中使用,Pod中的任何容器對誰是當前的選主感興趣的都可以簡單地通過 http://localhost:4040 來訪問,然后返回一個簡單的JSON對象,其中包含了當前選主的名字。既然Pod中的所有容器共享了相同的網絡命名空間,就不再需要服務發現了!

舉個例子,有一個簡單的Node.js應用程序連接到領導者選舉Sidecar,然后打印出這個是否是當前的選主,領導人選舉Sidecar將其標識符設置為默認的主機名。

var http = require('http');

// This will hold info about the current master

var master = {};



// The web handler for our nodejs application

var handleRequest = function(request, response) {

response.writeHead(200);

response.end("Master is " + master.name);

};



// A callback that is used for our outgoing client requests to the sidecar

var cb = function(response) {

var data = '';

response.on('data', function(piece) { data = data + piece; });

response.on('end', function() { master = JSON.parse(data); });

};



// Make an async request to the sidecar at http://localhost:4040

var updateMaster = function() {

var req = http.get({host: 'localhost', path: '/', port: 4040}, cb);

req.on('error', function(e) { console.log('problem with request: ' + e.message); });

req.end();

};



// Set up regular updates

updateMaster();

setInterval(updateMaster, 5000);



// set up the web server

var www = http.createServer(handleRequest);

www.listen(8080);

當然,可以使用任何語言,選擇支持HTTP和JSON來使用這個Sidecar。

總結

希望我已經向你展示了是多么容易為分布式應用程序使用Kubernetes來構建領導者選舉。在以后的部分我們將向您展示Kubernetes是如何使得構建分布式系統更容易。與此同時,還前往 Google容器引擎 或kubernetes.io來開始使用Kubernetes。

原文鏈接: Simple leader election with Kubernetes and Docker (翻譯:胡震)

來自: http://dockone.io/article/968

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!