Docker的集群實戰之Swarm模式

  • 2019 年 12 月 12 日
  • 筆記

點擊上方「編程三分鐘」,馬上關注,技術原來如此簡單。

隨著業務規模的擴大,一台機器的Docker已經無法滿足我們的要求,為了保證性能和高可用,Docker提供了一種叫Swarm的解決方案。

他可以跨多個Docker主機來部署容器,具有完備的安全機制、內置負載均衡器;支援擴縮容、升級和回滾。

這次讓我們用Swarm來部署一個2節點集群,並使用其負載均衡特性部署一個2副本Web應用。

何謂Swarm?

一個Swarm集群由一個或多個Docker節點組成。這些節點可以是物理機、虛擬機等。只要保證節點之間的網路通暢即可。Docker Swarm的結構如下:

上圖是六個節點的集群,我們來引入三個概念:

節點:分為管理節點(Manager)或工作節點(Worker)兩種類型,Manager負責監控集群狀態、分發任務到Worker等操作;Woker負責接收Manager發來的任務並執行,每個節點就是一台Docker主機,Manager同時也是Worker節點,因為老闆某種程式上來說也是員工,只不過老闆是在為自己打工。

服務:服務是Worker節點執行任務相關的概念,把每個在Swarm上跑的應用都是以服務的方式運行。

副本:每個服務為了達到高可用,會複製部署多個,部署了三個我們就稱這個服務部署了三個副本。

負載均衡:Swarm自帶負載均衡器,用來處理的請求。

值得一提的是Swarm的配置和狀態資訊保存在位於所有Manager上的分散式etcd資料庫中;同時在集群內部,有一個安全系統,用於節點間通訊加密、認證和授權等操作,這整個過程都是自動的,和etcd一樣不需要任何配置,幾乎察覺不到他們的存在。

  • Docker Swarm自docker 1.12版本以後已經和Docker直接集成在一起了,一條命令就可以啟用。

第0步 – 準備

我們要搭建一個兩節點集群,整個集群只有一個服務,兩個副本,每個副本就是一個容器,均勻分布在每個節點上。

準備:

  1. 兩個互通的Docker主機 主機名為host01 host02
  2. 一個能獲取到主機名的html網站鏡像

第1步 – 初始化Swarm模式

(創建第一個manager)

使用以下命令把docker轉成Swarm模式。

$ docker swarm init  

執行完這條命令,當前節點就成為了Manager節點,並打出一個token,以後在拓展的時候就要用的到token驗證了。

host01執行    $ docker swarm init    Swarm initialized: current node (hzdjc2iv3m7onlz54k8hkhfpe) is now a manager.    To add a worker to this swarm, run the following command:        docker swarm join --token SWMTKN-1-1hkuj0ya0ppj2qbmnq3tiqtyfbudo3wp6xcfmy446tadde1gpl-2ldsknja98b6s94k4pc3huno4 172.17.0.15:2377    To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.  

172.17.0.15是host01的ip,2377是Swarm默認的集群管理埠,加入集群就是向此埠通訊。這個埠要控制好訪問許可權來防止不信任的用戶或者節點訪問到。

第2步 – 加入集群

集群的好處就是崩潰一個節點的時候,節點上運行的容器就會自動遷移到其他正常節點上。

要向集群加入新的節點,首先要做的就是獲得token

#輸出添加worker所需要的token    $ docker swarm join-token -q worker    #輸出添加manager所需要的token    $ docker swarm join-token -q manager  

我們現在host01已經創建為manager節點了,現在把host02節點以worker的身份加入集群。

在host02上執行以下命令(命令較長,>代表換行)

$ token=$(ssh -o StrictHostKeyChecking=no 172.17.0.15     > "docker swarm join-token -q worker") && echo $token    Warning: Permanently added '172.17.0.15' (ECDSA) to the list of known hosts.    SWMTKN-1-1hkuj0ya0ppj2qbmnq3tiqtyfbudo3wp6xcfmy446tadde1gpl-2ldsknja98b6s94k4pc3huno4  

在host02上執行以下命令,可以遠程登陸host01並把worker所需的token賦值到token變數中(172.17.0.15是host01的ip)

$ docker swarm join 172.17.0.15:2377 --token $token    This node joined a swarm as a worker.  

向manager節點發加入集群的請求,token為附帶參數(根據token來判斷新加入的節點角色)

默認情況下,manager將自動接受添加到集群的新節點。

可以使用docker node ls來查看節點狀態

$ docker node ls    ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION    hzdjc2iv3m7onlz54k8hkhfpe * host01 Ready Active Leader 18.09.5    c5fsn2z7p1tw5iqwa2d54698m host02 Ready Active 18.09.5

第3步 – 創建覆蓋網路

(overlay網路)

在創建服務之前,需要創建一個覆蓋網路,它是一個二層網路(沒有匯聚層)。

以下命令將創建一個名為skynet的新overlay網路。註冊到此網路的所有容器都可以互相通訊,不管部署在哪個節點上。 第一台

$ docker network create -d overlay skynet  8t0ntbrcbo  

第4步 – 部署服務

默認情況下,Docker會均勻的把副本部署在集群中,如果刪掉一個節點,上面所有的服務都會重新分配在其他機器上。

現在就要把我們準備好的鏡像拿出來了,一個名為hostname-web:v1的鏡像,他部署在哪台機器上就到獲取到哪個主機的hostname,設置到容器內部的index.html里。

manager執行

docker service create --name http --network skynet --replicas 2 -p 80:80 hostname-web:v1  

--name 服務名

--network 指定網路 --replicas 副本數

-p 映射埠

上面的命令創建了一個名為http的服務,指定的網路為上一步創建的skynet覆蓋網路,2個副本,映射80到容器中的80埠,使用hostname-web:v1鏡像。

請求80埠就是在訪問服務,swarm會在所有副本之間進行負載均衡,

可以在manager上運行docker service ls查看狀態

$ docker service ls    ID NAME MODE REPLICAS IMAGE PORTS    tvidvge94pzt http replicated 2/2 hostname-web:v1  

可以使用docker ps分別在兩個主機上查看創建的鏡像,這裡我們就不廢話了。

在host01上請求,查看結果

$ curl host01    <h1>host01</h1>    $ curl host01    <h1>host02</h1>  

第5步 – 檢查狀態

查看服務下所有的容器列表詳細資訊,包括容器跑在哪台機器上,用的什麼鏡像,跑了多長時間等。

$ docker service ps http    ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS    zydwyr2tpzd4 http.1 hostname-web:v1 host02 Running Running 3 minutes ago    38ih400au70t http.2 hostname-web:v1 host01 Running Running 3 minutes ago  

查看服務的詳細資訊和配置

$ docker service inspect --pretty http  

可以使用docker node ls來查看節點狀態

$ docker node ls    ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION    hzdjc2iv3m7onlz54k8hkhfpe * host01 Ready Active Leader 18.09.5    c5fsn2z7p1tw5iqwa2d54698m host02 Ready Active 18.09.5  

可以把上面輸出結果的第一列ID當做docker node ps 的參數,查詢此節點上的服務列表,如果用self參數則代表本機。

擴容與縮容自動均衡

我們可以在服務運行的時候,修改副本數量實現自動擴容

執行以下命令把http服務擴容成五個副本運行。

$ docker service scale http=5    http scaled to 5    overall progress: 5 out of 5 tasks    1/5: running    2/5: running    3/5: running    4/5: running    5/5: running    verify: Service converged  

在host01上查看擴容結果,可以看到有兩個容器,另一台機器上有三個容器。Swarm會盡量保證各個副本均勻的分布在每個節點上(就算負載大的機器還是會被均勻分配,有興趣可以研究真正的負載均衡方案,也歡迎在留言器和我交流)

$ docker ps    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES    fe374853b402  hostname-web:v1 "/app" 48 seconds ago Up 47seconds 80/tcp http.3.8xx1eo4qop3ctefim9k685xz7    01241f07c109  hostname-web:v1 "/app" 7 minutes ago Up 7 minutes 80/tcp http.2.38ih400au70tvbs76xa10xmpa  

小結

docker swarm init初始化新的Swarm,並把當前節點設置為第一個Manager。

docker swarm join-token --tags <token>節點加入集群

docker swarm join-token -q manager|worker列印加入集群時節點對應角色所需要的token

docker node ls列出所有節點資訊

docker node ps <id>查看某個節點下的所有服務

docker service create創建服務

docker service inspect <service>服務詳細資訊

docker service ps <service>服務的副本(容器)資訊

docker service scale <service>=<number>擴縮容

docker service update更新服務屬性

docker service logs查看服務日誌

docker service rm刪除服務(在不做確認的情況下刪掉服務的所有副本)

Docker 還有滾動升級、自動鎖機制等優秀的特性,感興趣可以一起學習一下~