Docker(六):Docker 三劍客之 Docker Swarm

純潔的微笑發表於2018-04-21

實踐中會發現,生產環境中使用單個 Docker 節點是遠遠不夠的,搭建 Docker 叢集勢在必行。然而,面對 Kubernetes, Mesos 以及 Swarm 等眾多容器叢集系統,我們該如何選擇呢?它們之中,Swarm 是 Docker 原生的,同時也是最簡單,最易學,最節省資源的,比較適合中小型公司使用。

Docker Swarm 介紹

Swarm 在 Docker 1.12 版本之前屬於一個獨立的專案,在 Docker 1.12 版本釋出之後,該專案合併到了 Docker 中,成為 Docker 的一個子命令。目前,Swarm 是 Docker 社群提供的唯一一個原生支援 Docker 叢集管理的工具。它可以把多個 Docker 主機組成的系統轉換為單一的虛擬 Docker 主機,使得容器可以組成跨主機的子網網路。

Docker Swarm 是一個為 IT 運維團隊提供叢集和排程能力的編排工具。使用者可以把叢集中所有 Docker Engine 整合進一個「虛擬 Engine」的資源池,通過執行命令與單一的主 Swarm 進行溝通,而不必分別和每個 Docker Engine 溝通。在靈活的排程策略下,IT 團隊可以更好地管理可用的主機資源,保證應用容器的高效執行。

Docker(六):Docker 三劍客之 Docker Swarm

Docker Swarm 優點

任何規模都有高效能表現

對於企業級的 Docker Engine 叢集和容器排程而言,可擴充性是關鍵。任何規模的公司——不論是擁有五個還是上千個伺服器——都能在其環境下有效使用 Swarm。
經過測試,Swarm 可擴充性的極限是在 1000 個節點上執行 50000 個部署容器,每個容器的啟動時間為亞秒級,同時效能無減損。

靈活的容器排程

Swarm 幫助 IT 運維團隊在有限條件下將效能表現和資源利用最優化。Swarm 的內建排程器(scheduler)支援多種過濾器,包括:節點標籤,親和性和多種容器部策略如 binpack、spread、random 等等。

服務的持續可用性

Docker Swarm 由 Swarm Manager 提供高可用性,通過建立多個 Swarm master 節點和制定主 master 節點當機時的備選策略。如果一個 master 節點當機,那麼一個 slave 節點就會被升格為 master 節點,直到原來的 master 節點恢復正常。
此外,如果某個節點無法加入叢集,Swarm 會繼續嘗試加入,並提供錯誤警報和日誌。在節點出錯時,Swarm 現在可以嘗試把容器重新排程到正常的節點上去。

和 Docker API 及整合支援的相容性
Swarm 對 Docker API 完全支援,這意味著它能為使用不同 Docker 工具(如 Docker CLI,Compose,Trusted Registry,Hub 和 UCP)的使用者提供無縫銜接的使用體驗。

Docker Swarm 為 Docker 化應用的核心功能(諸如多主機網路和儲存卷管理)提供原生支援。開發的 Compose 檔案能(通過 docker-compose up )輕易地部署到測試伺服器或 Swarm 叢集上。Docker Swarm 還可以從 Docker Trusted Registry 或 Hub 裡 pull 並 run 映象。

綜上所述,Docker Swarm 提供了一套高可用 Docker 叢集管理的解決方案,完全支援標準的 Docker API,方便管理排程叢集 Docker 容器,合理充分利用叢集主機資源

** 並非所有服務都應該部署在Swarm叢集內。資料庫以及其它有狀態服務就不適合部署在Swarm叢集內。**

相關概念

節點

執行 Docker 的主機可以主動初始化一個 Swarm 叢集或者加入一個已存在的 Swarm 叢集,這樣這個執行 Docker 的主機就成為一個 Swarm 叢集的節點 (node) 。節點分為管理 (manager) 節點和工作 (worker) 節點。

管理節點用於 Swarm 叢集的管理,docker swarm 命令基本只能在管理節點執行(節點退出叢集命令 docker swarm leave 可以在工作節點執行)。一個 Swarm 叢集可以有多個管理節點,但只有一個管理節點可以成為 leader,leader 通過 raft 協議實現。

工作節點是任務執行節點,管理節點將服務 (service) 下發至工作節點執行。管理節點預設也作為工作節點。你也可以通過配置讓服務只執行在管理節點。下圖展示了叢集中管理節點與工作節點的關係。

Docker(六):Docker 三劍客之 Docker Swarm

服務和任務

任務 (Task)是 Swarm 中的最小的排程單位,目前來說就是一個單一的容器。
服務 (Services) 是指一組任務的集合,服務定義了任務的屬性。服務有兩種模式:

  • replicated services 按照一定規則在各個工作節點上執行指定個數的任務。
  • global services 每個工作節點上執行一個任務

兩種模式通過 docker service create 的 --mode 引數指定。下圖展示了容器、任務、服務的關係。

Docker(六):Docker 三劍客之 Docker Swarm

建立 Swarm 叢集

我們知道 Swarm 叢集由管理節點和工作節點組成。我們來建立一個包含一個管理節點和兩個工作節點的最小 Swarm 叢集。

初始化叢集

檢視虛擬主機,現在沒有

docker-machine ls
NAME   ACTIVE   DRIVER   STATE   URL   SWARM   DOCKER   ERRORS

使用 virtualbox 建立管理節點

docker-machine create --driver virtualbox manager1
#進入管理節點
docker-machine ssh manager1

執行 sudo -i 可以進入Root 許可權

我們使用 docker swarm init 在 manager1 初始化一個 Swarm 叢集。

docker@manager1:~$ docker swarm init --advertise-addr 192.168.99.100
Swarm initialized: current node (j0o7sykkvi86xpc00w71ew5b6) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-47z6jld2o465z30dl7pie2kqe4oyug4fxdtbgkfjqgybsy4esl-8r55lxhxs7ozfil45gedd5b8a 192.168.99.100:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

如果你的 Docker 主機有多個網路卡,擁有多個 IP,必須使用 --advertise-addr 指定 IP。
執行 docker swarm init 命令的節點自動成為管理節點。

命令 docker info 可以檢視 swarm 叢集狀態:

Containers: 0
Running: 0
Paused: 0
Stopped: 0
  ...snip...
Swarm: active
  NodeID: dxn1zf6l61qsb1josjja83ngz
  Is Manager: true
  Managers: 1
  Nodes: 1
  ...snip...

命令 docker node ls 可以檢視叢集節點資訊:

docker@manager1:~$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
1ipck4z2uuwf11f4b9mnon2ul *   manager1            Ready               Active              Leader

退出虛擬主機

docker@manager1:~$ exit 

增加工作節點

上一步初始化了一個 Swarm 叢集,擁有了一個管理節點,在 Docker Machine 一節中我們瞭解到 Docker Machine 可以在數秒內建立一個虛擬的 Docker 主機,下面我們使用它來建立兩個 Docker 主機,並加入到叢集中。

建立虛擬主機 worker1

建立主機

$ docker-machine create -d virtualbox worker1

進入虛擬主機 worker1

$ docker-machine ssh worker1

加入 swarm 叢集

docker@worker1:~$ docker swarm join \
    --token SWMTKN-1-47z6jld2o465z30dl7pie2kqe4oyug4fxdtbgkfjqgybsy4esl-8r55lxhxs7ozfil45gedd5b8a \
    192.168.99.100:2377

This node joined a swarm as a worker.  

退出虛擬主機

docker@worker1:~$ exit 

建立虛擬主機 worker2

建立

$ docker-machine create -d virtualbox worker2

入虛擬主機worker2

$ docker-machine ssh worker2

加入 swarm 叢集

docker@worker2:~$ docker swarm join \
    --token SWMTKN-1-47z6jld2o465z30dl7pie2kqe4oyug4fxdtbgkfjqgybsy4esl-8r55lxhxs7ozfil45gedd5b8a \
    192.168.99.100:2377

This node joined a swarm as a worker. 

退出虛擬主機

docker@worker2:~$ exit 

兩個工作節點新增完成

檢視叢集

進入管理節點:

docker-machine ssh manager1

宿主機子上檢視虛擬主機

docker@manager1:~$ docker-machine ls
NAME       ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
manager1   *        virtualbox   Running   tcp://192.168.99.100:2376           v17.12.1-ce
worker1    -        virtualbox   Running   tcp://192.168.99.101:2376           v17.12.1-ce
worker2    -        virtualbox   Running   tcp://192.168.99.102:2376           v17.12.1-ce

在主節點上面執行 docker node ls 查詢叢集主機資訊

docker@manager1:~$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
1ipck4z2uuwf11f4b9mnon2ul *   manager1            Ready               Active              Leader
rtcpqgcn2gytnvufwfveukgrv     worker1             Ready               Active
te2e9tr0qzbetjju5gyahg6f7     worker2             Ready               Active

這樣我們就建立了一個最小的 Swarm 叢集,包含一個管理節點和兩個工作節點。

部署服務

我們使用 docker service 命令來管理 Swarm 叢集中的服務,該命令只能在管理節點執行。

新建服務

進入叢集管理節點:

docker-machine ssh manager1

使用 docker 中國映象

docker search alpine 
docker pull registry.docker-cn.com/library/alpine

現在我們在上一節建立的 Swarm 叢集中執行一個名為 helloworld 服務。

docker@manager1:~$ docker service create --replicas 1 --name helloworld alpine ping ityouknow.com
rwpw7eij4v6h6716jvqvpxbyv
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged

命令解釋:

  • docker service create 命令建立一個服務
  • --name 服務名稱命名為 helloworld
  • --replicas 設定啟動的示例數
  • alpine指的是使用的映象名稱,ping ityouknow.com指的是容器執行的bash

使用命令 docker service ps rwpw7eij4v6h6716jvqvpxbyv 可以檢視服務進展

docker@manager1:~$ docker service ps rwpw7eij4v6h6716jvqvpxbyv
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
rgroe3s9qa53        helloworld.1        alpine:latest       worker1            Running             Running about a minute ago

使用 docker service ls 來檢視當前 Swarm 叢集執行的服務。

docker@manager1:~$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
yzfmyggfky8c        helloworld          replicated          0/1                 alpine:latest

監控叢集狀態

登入管理節點 manager1

docker-machine ssh manager1

執行 docker service inspect --pretty <SERVICE-ID> 查詢服務概要狀態,以 helloworld 服務為例:

docker@manager1:~$  docker service inspect --pretty helloworld

ID:             rwpw7eij4v6h6716jvqvpxbyv
Name:           helloworld
Service Mode:   Replicated
 Replicas:      1
Placement:
UpdateConfig:
 Parallelism:   1
 On failure:    pause
 Monitoring Period: 5s
 Max failure ratio: 0
 ...
 Rollback order:    stop-first
ContainerSpec:
 Image:         alpine:latest@sha256:7b848083f93822dd21b0a2f14a110bd99f6efb4b838d499df6d04a49d0debf8b
 Args:          ping ityouknow.com
Resources:
Endpoint Mode:  vip

執行 docker service inspect helloworld 查詢服務詳細資訊。

執行docker service ps <SERVICE-ID> 檢視那個節點正在執行服務:

docker@manager1:~$  docker service ps helloworld
NAME                                    IMAGE   NODE     DESIRED STATE  LAST STATE
helloworld.1.8p1vev3fq5zm0mi8g0as41w35  alpine  worker1  Running        Running 3 minutes

在工作節點檢視任務的執行情況

docker-machine ssh  worker1

在節點執行docker ps 檢視容器的執行狀態。

docker@worker1:~$   docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
96bf5b1d8010        alpine:latest       "ping ityouknow.com"   4 minutes ago       Up 4 minutes                            helloworld.1.rgroe3s9qa53lf4u4ky0tzcb8

這樣的話,我們在 Swarm 叢集中成功的執行了一個 helloworld 服務,根據命令可以看出在 worker1 節點上執行。

彈性伸縮實驗

我們來做一組實驗來感受 Swarm 強大的動態水平擴充套件特性,首先動態調整服務例項個數。

調整例項個數

增加或者減少服務的節點數

調整 helloworld 的服務例項數為2個

docker service update --replicas 2 helloworld

檢視那個節點正在執行服務:

docker service ps helloworld
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                 ERROR                              PORTS
rgroe3s9qa53        helloworld.1        alpine:latest       manager1            Running             Running 8 minutes ago
a61nqrmfhyrl        helloworld.2        alpine:latest       worker2             Running             Running 9 seconds ago

調整 helloworld 的服務例項數為1個

docker service update --replicas 1 helloworld

再次檢視節點執行情況:

docker service ps helloworld
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                 ERROR                              PORTS
a61nqrmfhyrl        helloworld.2        alpine:latest       worker2             Running             Running about a minute ago

再次調整 helloworld 的服務例項數為3個

docker service update --replicas 3 helloworld
helloworld
overall progress: 3 out of 3 tasks
1/3: running   [==================================================>]
2/3: running   [==================================================>]
3/3: running   [==================================================>]
verify: Service converged

檢視節點執行情況:

docker@manager1:~$ docker service ps helloworld
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR                              PORTS
mh7ipjn74o0d        helloworld.1        alpine:latest       worker2             Running             Running 40 seconds ago
1w4p9okvz0xw        helloworld.2        alpine:latest       manager1            Running             Running 2 minutes ago
snqrbnh4k94y        helloworld.3        alpine:latest       worker1             Running             Running 32 seconds ago

刪除叢集服務

docker service rm helloworld

調整叢集大小

動態調整 Swarm 叢集的工作節點。

新增叢集

建立虛擬主機 worker3

$ docker-machine create -d virtualbox worker3

入虛擬主機 worker3

$ docker-machine ssh worker3

加入swarm 叢集

docker@worker3:~$ docker swarm join \
    --token SWMTKN-1-47z6jld2o465z30dl7pie2kqe4oyug4fxdtbgkfjqgybsy4esl-8r55lxhxs7ozfil45gedd5b8a \
    192.168.99.100:2377

This node joined a swarm as a worker. 

退出虛擬主機

docker@worker3:~$exit 

在主節點上面執行 docker node ls 查詢叢集主機資訊

登入主節點

docker-machine ssh  manager1

檢視叢集節點

docker@manager1:~$  docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
j0o7sykkvi86xpc00w71ew5b6 *   manager1            Ready               Active              Leader
xwv8aixasqraxwwpox0d0bp2i     worker1             Ready               Active
ij3z1edgj7nsqvl8jgqelrfvy     worker2             Ready               Active
i31yuluyqdboyl6aq8h9nk2t5     worker3             Ready               Active

可以看出叢集節點多了 worker3

退出 Swarm 叢集

如果 Manager 想要退出 Swarm 叢集, 在 Manager Node 上執行如下命令:

docker swarm leave  

就可以退出叢集,如果叢集中還存在其它的 Worker Node,還希望 Manager 退出叢集,則加上一個強制選項,命令列如下所示:

docker swarm leave --force

在 Worker2 上進行退出測試,登入 worker2 節點

docker-machine ssh  worker2

執行退出命令

docker swarm leave 

檢視叢集節點情況:

docker@manager1:~$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
j0o7sykkvi86xpc00w71ew5b6 *   manager1            Ready               Active              Leader
xwv8aixasqraxwwpox0d0bp2i     worker1             Ready               Active
ij3z1edgj7nsqvl8jgqelrfvy     worker2             Down                Active
i31yuluyqdboyl6aq8h9nk2t5     worker3             Ready               Active

可以看出叢集節點 worker2 狀態已經下線

也可以再次加入

docker@worker2:~$ docker swarm join \
>     --token SWMTKN-1-47z6jld2o465z30dl7pie2kqe4oyug4fxdtbgkfjqgybsy4esl-8r55lxhxs7ozfil45gedd5b8a \
>     192.168.99.100:2377
This node joined a swarm as a worker.

再次檢視

docker@manager1:~$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
j0o7sykkvi86xpc00w71ew5b6 *   manager1            Ready               Active              Leader
xwv8aixasqraxwwpox0d0bp2i     worker1             Ready               Active
0agpph1vtylm421rhnx555kkc     worker2             Ready               Active
ij3z1edgj7nsqvl8jgqelrfvy     worker2             Down                Active
i31yuluyqdboyl6aq8h9nk2t5     worker3             Ready               Active

可以看出叢集節點 worker2 又重新加入到了叢集中

重新搭建命令

使用 VirtualBox 做測試的時候,如果想重複實驗可以將實驗節點刪掉再重來。

//停止虛擬機器
docker-machine stop [arg...]  //一個或多個虛擬機器名稱

docker-machine stop   manager1 worker1 worker2
//移除虛擬機器
docker-machine rm [OPTIONS] [arg...]

docker-machine rm manager1 worker1 worker2

停止、刪除虛擬主機後,再重新建立即可。

總結

通過對 Swarm 的學習,強烈感覺到自動化水平擴充套件的魅力,這樣在公司流量爆發的時候,只需要執行一個命令就可以完成例項上線。如果再根據公司的業務流量做自動化控制,那就真正實現了完全自動的動態伸縮。

舉個例子,我們可以利用指令碼監控公司的業務流量,當流量是某個級別的時候我們啟動對應的N個節點數,當流量減少的時候我們也動態的減少服務例項個數,既可以節省公司資源,也不用操心業務爆發被流量擊垮。Docker 能發展的這麼好還是有原因的,容器化是 DevOps 最重要的一個環節,未來容器化的技術會越來越豐富和完善,智慧化運維可期待。

參考

Getting started with swarm mode
Docker — 從入門到實踐
關於Docker Swarm的用途詳細介紹

相關文章