Docker學習筆記 — Swarm搭建Docker集羣

Swarm介紹


Swarm是Docker公司在2014年12月初發布的一套較爲簡單的工具,用來管理Docker集羣,它將一羣Docker宿主機變成一個單一的,虛擬的主機。Swarm使用標準的Docker API接口作爲其前端訪問入口,換言之,各種形式的Docker Client(docker client in go, docker_py, docker等)均可以直接與Swarm通信。Swarm幾乎全部用Go語言來完成開發,上週五,4月17號,Swarm0.2發佈,相比0.1版本,0.2版本增加了一個新的策略來調度集羣中的容器,使得在可用的節點上傳播它們,以及支持更多的Docker命令以及集羣驅動。

Swarm deamon只是一個調度器(Scheduler)加路由器(router),Swarm自己不運行容器,它只是接受docker客戶端發送過來的請求,調度適合的節點來運行容器,這意味着,即使Swarm由於某些原因掛掉了,集羣中的節點也會照常運行,當Swarm重新恢復運行之後,它會收集重建集羣信息。下面是Swarm的結構圖:

這裏寫圖片描述

這裏寫圖片描述

如何使用Swarm


有3臺機器:
sclu083:10.13.181.83
sclu084:10.13.181.84
atsg124:10.32.105.124
利用這三臺機器創建一個Docker集羣,其中sclu083同時充當swarm manager管理集羣。

Swarm安裝

最簡單的安裝Swarm的方式就是用Docker官方提供的Swarm鏡像:

$ sudo docker pull swarm

Docker集羣管理需要服務發現(Discovery service backend)功能。Swarm支持以下幾種discovery service backend:Docker Hub上面內置的服務發現功能,本地的靜態文件描述集羣(static file describing the cluster),etcd(順帶說一句,etcd這玩意貌似很火很有前途,有時間研究下),consul,zookeeper和一些靜態的ip列表(a static list of ips)。本文會詳細介紹前面兩種方法backend的使用。

在使用Swarm進行集羣管理之前,需要先把準備加入集羣的所有的節點的docker deamon的監聽端口修改爲0.0.0.0:2375,可以直接使用 sudo docker –H tcp://0.0.0.0:2375 &命令,也可以在配置文件中修改

$ sudo vim /etc/default/docker

在文件的最後面添加下面這句

D0OCKER_OPTS="-H 0.0.0.0:2375 –H unix:///var/run/docker.sock"

這裏寫圖片描述

注意:一定是要在所有的節點上進行修改,修改之後要重啓docker deamon

$ sudo service docker restart
第一種方法:使用Docker Hub上面內置的服務發現功能

第一步
在任何一個節點上面執行swarm create命令來創建一個集羣標誌。這條命令執行完畢之後,swarm會前往Docker Hub上內建的發現服務中獲取一個全球唯一的token,用以唯一的標識swarm管理的Docker集羣。

$ sudo docker run --rm swarm create

我們在sclu084 這臺機器上執行上面的命令

這裏寫圖片描述

返回的token是d947b55aa8fb9198b5d13ad81f61ac4d,這個token一定要記住,因爲接下來的操作都會用到這一個token。

第二步
在所有的要加入集羣的機器上面執行swarm join命令,把機器加入集羣。

本次試驗就是要在所有的三臺機器上執行命令。

$ sudo docker run –-rm swarm join –addr=ip_address:2375 token://d947b55aa8fb9198b5d13ad81f61ac4d

在IP地址爲10.13.181.84機器上面執行

這裏寫圖片描述

執行這條命令後不會立即返回 ,我們手動通過Ctrl+C返回。

第三步
啓動swarm manager。

因爲我們要讓sclu083充當Swarm管理節點,所以我們要在這臺機器上面執行swarm manage命令

$ sudo docker run –d –p 2376:2375 swarm manage token:// d947b55aa8fb9198b5d13ad81f61ac4d

重點內容需要注意的是:在這條命令中,第一:要以daemon的形式運行swarm;第二:端口映射:2376可以更換成任何一個本機沒有佔用的端口,一定不能是2375,否則就會出問題。

執行結果如下如所示:

這裏寫圖片描述

執行完這個命令之後,整個集羣已經啓動起來了。

現在可以在任何一個節點上查看集羣上的所有節點了。

這裏寫圖片描述

之後可以在任何一臺安裝了docker的機器上面通過命令(命令中要指明swarm maneger 機器的IP地址和端口)在這個集羣上面運行Dcoker容器操作。

現在在10.13.181.85這臺機器上面查看集羣的節點的信息。info命令可以換成任何一個Swarm支持的docker命令,這些命令可以查看官方文檔

$ sudo docker –H 10.13.181.83:2376 info

這裏寫圖片描述

由上圖的結果,我們可以發現一個問題:明明這個小集羣中是有3個節點的,但是info命令只顯示了2個節點。還缺少節點10.32.105.124。爲什麼會出現這個情況呢?

因爲10.32.105.124這臺機器沒有設置上面的docker daemon監聽0.0.0.0:2375這個端口,所以Swarm沒辦法吧這個節點加入集羣中來。

在使用Docker Hub內置的發現服務時,會出現一個問題,就是使用swarm create時會出現

time="2015-04-21T08:56:25Z" level=fatal msg="Get https://discovery-stage.hub.docker.com/v1/clusters/d947b55aa8fb9198b5d13ad81f61ac4d: dial tcp: i/o timeout"

類似於這樣的錯誤,不知道是什麼原因,有待解決。(可能是防火牆的問題)

當使用Docker Hub內置的服務發現功能出現問題時,可以使用下面的第二種方法。

第二種方法:使用文件

第二種方法相對而言比第一種方法要簡單,也更不容易出現timeout的問題。

第一步
在sclu083這臺機器上新建一個文件,把要加入集羣的機器的IP地址寫進去

這裏寫圖片描述

第二步
在sclu083這臺機器上面執行swarm manage命令:

$ sudo docker run –d –p 2376:2375 –v $(pwd)/cluster:/tmp/cluster swarm manage file:///tmp/cluster

這裏寫圖片描述

注意:這裏一定要使用-v命令,因爲cluster文件是在本機上面,啓動的容器默認是訪問不到的,所以要通過-v命令共享。還有,file:///千萬不能忘記了。

可以看到,swarm已經運行起來了。現在可以查看下集羣節點信息了,使用命令:

$ sudo docker run –rm –v $(pwd)/cluster:/tmp/cluster swarm list file:///tmp/cluster

這裏寫圖片描述

(在使用文件作爲服務發現的時候,貌似manage list命令只能在swarm manage節點上使用,在其他節點上好像是用不了)

好了,現在集羣也已經運行起來了,可以跟第一種方法一樣在其他機器上使用集羣了。同樣在sclu085 機器上做測試:

這裏寫圖片描述

可以看到,成功訪問並且節點信息是正確的。接下來可以把上面的info命令替換成其他docker可執行命令來使用這個曉得Docker集羣了。

Swarm調度策略


Swarm在schedule節點運行容器的時候,會根據指定的策略來計算最適合運行容器的節點,目前支持的策略有:spread, binpack, random.

Random顧名思義,就是隨機選擇一個Node來運行容器,一般用作調試用,spread和binpack策略會根據各個節點的可用的CPU, RAM以及正在運行的容器的數量來計算應該運行容器的節點。

在同等條件下,Spread策略會選擇運行容器最少的那臺節點來運行新的容器,binpack策略會選擇運行容器最集中的那臺機器來運行新的節點(The binpack strategy causes Swarm to optimize for the container which is most packed.)。

使用Spread策略會使得容器會均衡的分佈在集羣中的各個節點上運行,一旦一個節點掛掉了只會損失少部分的容器。

Binpack策略最大化的避免容器碎片化,就是說binpack策略儘可能的把還未使用的節點留給需要更大空間的容器運行,儘可能的把容器運行在一個節點上面。

過濾器


Constraint Filter

通過label來在指定的節點上面運行容器。這些label是在啓動docker daemon時指定的,也可以寫在/etc/default/docker這個配置文件裏面。

$ sudo docker run –H 10.13.181.83:2376 –name redis_083 –d –e constraint:label==083 redis

Affinity Filter

使用-e affinity:container==container_name / container_id –-name container_1可以讓容器container_1緊挨着容器container_name / container_id執行,也就是說兩個容器在一個node上面執行(You can schedule 2 containers and make the container #2 next to the container #1.)

先在一臺機器上啓動一個容器

$ sudo docker -H 10.13.181.83:2376 run --name redis_085 -d -e constraint:label==085 redis

接下來啓動容器redis_085_1,讓redis_085_1緊挨着redis_085容器運行,也就是在一個節點上運行

$ sudo docker –H 10.13.181.83:2376 run –d –name redis_085_1 –e affinity:container==redis_085 redis

通過-e affinity:image=image_name命令可以指定只有已經下載了image_name的機器才運行容器(You can schedule a container only on nodes where the images are already pulled)

下面命令在只有redis鏡像的節點上面啓動redis容器:

$ sudo docker –H 100.13.181.83:2376 run –name redis1 –d –e affinity:image==redis redis

下面這條命令達到的效果是:在有redis鏡像的節點上面啓動一個名字叫做redis的容器,如果每個節點上面都沒有redis容器,就按照默認的策略啓動redis容器。

$ sudo docker -H 10.13.181.83:2376 run -d --name redis -e affinity:image==~redis redis

Port filter

Port也會被認爲是一個唯一的資源

$ sudo docker -H 10.13.181.83:2376 run -d -p 80:80 nginx

執行完這條命令,任何使用80端口的容器都是啓動失敗。



轉載自
Docker Swarm學習教程

發佈了88 篇原創文章 · 獲贊 91 · 訪問量 108萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章