Docker 學習筆記(第十集:docker 叢集管理工具 swarm )

chenggx發表於2020-09-09

Swarm 是 Docker 引擎內建(原生)的叢集管理和編排工具

學習 swarm 一定要理解的幾個重要概念

  • 節點

  • 服務

  • 任務

節點

一臺物理或雲主機加入 docker 叢集,那麼這臺主機就是一個節點。

節點分為管理 (manager) 節點和工作 (worker) 節點。

管理節點用於叢集的管理,一個 Swarm 叢集可以有多個管理節點,但只有一個管理節點可以成為 leader。

工作節點是任務執行節點,管理節點將服務 (service) 下發至工作節點執行。

管理節點預設也作為工作節點。你也可以透過配置讓工作節點只進行任務排程。

Docker 官網的這張圖片形象的展示了叢集中管理節點與工作節點的關係。

管理節點與工作節點的關係

任務和服務

任務 (Task)是 Swarm 中的最小的排程單位,目前來說就是一個單一的容器。任務包含一個 Docker 容器和在容器中執行的命令。

服務 (Services) 是指一組任務的集合,服務定義了任務的屬性。服務有兩種模式:

  • replicated services(副本模式) 按照一定規則在各個工作節點上執行指定個數的任務。

  • global services(全域性模式) 每個工作節點上執行一個任務

兩種模式透過 docker service create 的 –mode 引數指定。

swarm 叢集基本操作

  • 三臺安裝了 Docker 的主機,各主機間可以通訊。

  • Docker 版本必須大於 1.12

  • 需要開啟 tcp 2377 埠、tcp/udp 7946 埠、udp 4789 埠

  • 選一臺主機作為管理節點,獲取其 ip 地址

docker-machine

Docker Machine 是 Docker 官方提供的一個工具,它可以幫助我們在遠端的機器上安裝 Docker,或者在虛擬機器 host 上直接安裝虛擬機器並在虛擬機器中安裝 Docker。我們還可以透過 docker-machine 命令來管理這些虛擬機器和 Docker。

安裝 docker-machine
  1. 首先下載可執行檔案 github.com/docker/machine/releases

  2. 將下載好的檔案移動到 /usr/local/bin/docker-machine 目錄下並改名為 docker-machine

  3. 執行 sudo chmod +x /usr/local/bin/docker-machine 命令為其新增可執行許可權

  4. 執行如下命令,驗證是否安裝成功


$ docker-machine -v

docker-machine version 0.16.1, build cce350d7
初始化叢集

第一步:如下命令建立 一個 Docker 主機作為管理節點。


$ docker-machine create -d virtualbox manager

由於眾所周知的原因下載 boot2docker 特別慢,我們透過 boot2docker 專案頁面直接下載該檔案,然後將該檔案移動到該 /Users/使用者名稱/.docker/machine/cache 目錄下。最後重新執行建立的命令就可以了

第二步:在管理節點上初始化一個 swarm 叢集


// ssh 到虛擬機器中

$ docker-machine ssh manager

// 初始化 swarm 叢集,並指定管理節點 ip 地址

docker@manager:~$ docker swarm init --advertise-addr 192.168.99.100

Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) is now a manager.

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

docker swarm join

--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c

192.168.99.100:2377

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

執行 docker swarm init 命令的節點自動成為管理節點。

第三步:建立工作節點,並加入 swarm 叢集

worker 1


$ docker-machine create -d virtualbox worker1

$ docker-machine ssh worker1

// 工作節點初始化叢集的時候會自動給出該命令。

docker@worker1:~$ docker swarm join

--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c

192.168.99.100:2377

This node joined a swarm as a worker.

透過該 docker swarm join-token worker 命令獲取加入叢集的命令

worker2


$ docker-machine create -d virtualbox worker2

$ docker-machine ssh worker2

docker@worker1:~$ docker swarm join

--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c

192.168.99.100:2377

This node joined a swarm as a worker.

第四步:檢視節點狀態


// 該命令只能在管理節點使用

$ docker node ls

ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION

jnn6cji3hy22ninkymqxer49q * manager Ready Active Leader 19.03.12

r5sce06gn9351jvotf6xp1r53 worker1 Ready Active 19.03.12

ssdfsdfs2df32dfk34dc3498 worker1 Ready Active 19.03.12

Docker 引擎透過主機名自動為節點命名

MANAGER 列標識群中的管理器節點。Leader 表示管理節點,空表示工作節點

部署一個服務

$ docker service create --replicas 1 --name helloworld busybox ping baidu.com

wo27l49vowb7reote7apzqn8d

overall progress: 1 out of 1 tasks

1/1: running [==================================================>]

verify: Service converged
  • –preplicas 1 指定副本個數為 1 個(即在叢集中啟動一個容器執行)

  • –name 指定服務名稱為 helloworld

  • busybox 指定映象為 busybox

  • ping baidu.com 指定執行的命令

檢視當前執行的服務

$ docker service ls

ID NAME MODE REPLICAS IMAGE PORTS

wo27l49vowb7 helloworld replicated 1/1 busybox:latesttcp
檢視服務詳情

$ docker service inspect --pretty helloworld

ID: wo27l49vowb7reote7apzqn8d

Name: helloworld

Service Mode: Replicated

Replicas: 1

Placement:

UpdateConfig:

Parallelism: 1

On failure: pause

Monitoring Period: 5s

Max failure ratio: 0

Update order: stop-first

RollbackConfig:

Parallelism: 1

On failure: pause

Monitoring Period: 5s

Max failure ratio: 0

Rollback order: stop-first

ContainerSpec:

Image: busybox:latest@sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977

Args: ping baidu.com

Init: false

Resources:

Endpoint Mode: vip
  • –pretty 以更好看的格式顯示(不指定的話將以 json 格式顯示)
檢視服務執行在哪個接點上

docker@manager:~$ docker service ps helloworld

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS

re3rdqvnsoa3 helloworld.1 busybox:latest worker1 Running Running 11 minutes ago

我們可以看到該服務執行在 worker1 節點上。讓我們 ssh 到 worker1 節點執行 docker ps 命令,發現確實有容器在執行。而我們 ssh 到其他節點上執行 docker ps 會發現並沒有容器在執行。

擴充套件叢集中的服務

必須在管理節點操作


$ docker service scale helloworld=5

helloworld 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

$ docker service ps helloworld

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS

re3rdqvnsoa3 helloworld.1 busybox:latest worker1 Running Running about an hour ago

4tjmgtulmkx0 helloworld.2 busybox:latest worker2 Running Running 38 minutes ago

zl3u08rsrm72 helloworld.3 busybox:latest manager Running Running 38 minutes ago

am36krqw6o97 helloworld.4 busybox:latest manager Running Running 39 minutes ago

tsbhagfz6fx6 helloworld.5 busybox:latest worker1 Running Running 39 minutes ago
  • 我們可以看到新增加了 4 個任務分佈在manager、worker1、worker2 上。

  • ssh 到各個主機執行 docker ps 檢視主機執行容器的狀態

刪除叢集中的服務

必須在管理節點操作


$ docker service rm helloworld

helloworld

docker@manager:~$ docker service ls

ID NAME MODE REPLICAS IMAGE PORTS

其他主機需要等一會再檢視執行的容器是否刪除

動態升級服務

建立一個低版本的 redis 服務


$ docker service create --replicas 3 --name redis --update-delay 10s redis:3.0.6

vep8ciixn4otmt9g0khd98z5d

overall progress: 3 out of 3 tasks

1/3: running [==================================================>]

2/3: running [==================================================>]

3/3: running [==================================================>]

verify: Service converged
  • –update-delay 設定更新任務之間的延遲時間(20h10m5s 表示延遲為 20 小時 10 分鐘 5 表)

  • –update-parallelism 設定同時更新任務的最大數(預設值為 1)

  • –update-failure-action 設定更新任務失敗後執行的動作(預設設定為如果在更新過程中的任何時候任務返回失敗,則排程程式將暫停更新)

更新 redis


$ docker service update --image redis:3.0.7 redis

上面的命令實際執行流程為:

  1. 暫停第一個任務

  2. 為停止的任務安排更新計劃

  3. 啟動一個新版本的容器

  4. 如果任務的返回“RUNNING”,則等待指定的延遲時間後開始下一個任務

  5. 如果任務返回“FAILED”,則暫停更新。

檢視當前服務狀態

可以看出服務的更新是暫停老版本,增加新版本


docker@manager:~$ docker service ps redis

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS

jbojkid2itrn redis.1 redis:3.0.7 worker2 Running Running 3 minutes ago

r4nyfe94e5ms \_ redis.1 redis:3.0.6 worker2 Shutdown Shutdown 3 minutes ago

t8umvvy4bf80 redis.2 redis:3.0.7 manager Running Running 2 minutes ago

rhunef6vi2dk \_ redis.2 redis:3.0.6 manager Shutdown Shutdown 3 minutes ago

w2jcya0tc9cv redis.3 redis:3.0.7 worker1 Running Running 2 minutes ago

sz1ptkhmak6q \_ redis.3 redis:3.0.6 worker1 Shutdown Shutdown 2 minutes ago
設定節點為 Drain 狀態

目前我們的所有節點都為 Active 狀態,也就是所有節點都可以接受任務。但有時候我們想指定某個節點正在維護,不進行任務處理,那麼我們就要對節點的狀態進行更改。


// 為了後面檢視方便,刪除上面進行建立的 redis 服務

$ docker service rm redis

//重新建立一個 redis 服務

$ docker service create --replicas 3 --name redis --update-delay 10s redis:3.0.6

// 檢視當前服務執行狀態(每個節點執行一個任務)

$ docker service ps redis

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS

ffhwf4i243yc redis.1 redis:3.0.6 worker2 Running Running 35 seconds ago

sflv38rtetvh redis.2 redis:3.0.6 manager Running Running 35 seconds ago

kzn7cn15rrye redis.3 redis:3.0.6 worker1 Running Running 35 seconds ago

// 將 worker1 節點設為 Drain 狀態

$ docker node update --availability drain worker1

worker1

// 檢視當前服務執行狀態(注意 worker1 節點服務的狀態已經為關閉,worker2 節點上又多了一個任務)

$ docker service ps redis

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS

ffhwf4i243yc redis.1 redis:3.0.6 worker2 Running Running about a minute ago

sflv38rtetvh redis.2 redis:3.0.6 manager Running Running about a minute ago

ir0nvesyhrea redis.3 redis:3.0.6 worker2 Running Running less than a second ago

kzn7cn15rrye \_ redis.3 redis:3.0.6 worker1 Shutdown Shutdown less than a second ago

Routing Mesh (路由網格)

Routing Mesh 是 docker swarm 提供的確保服務在多節點網路上可用的叢集網路機制。

當我們建立一個服務的時候,如果將埠釋出出來,那麼所有節點都會加入到這個路由網格中,當我們在外部透過任意主機 ip 和釋出的埠訪問服務的時候,無論該主機上時候啟動服務,我們都能訪問的到。(負載均衡)

在使用之前需要先開啟如下埠:

  • TCP/UDP 的 7946 埠

  • UDP 的 4789 埠

格式:


docker service create

--name <SERVICE-NAME>

--publish published=<PUBLISHED-PORT>,target=<CONTAINER-PORT>

<IMAGE>
  • SERVICE-NAME 自定義服務的名稱

  • PUBLISHED-PORT 對外發布的埠號

  • CONTAINER-PORT 容器的埠號

  • IMAGE 服務所使用的映象

啟動 nginx 服務併發布埠


$ docker service create --name web --publish published=8080,target=80 --replicas 2 nginx

// 檢視服務當前執行在哪個節點上

$ docker service ps web

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS

kuocqhmt4rl7 web.1 nginx:latest worker1 Running Running 40 seconds ago

s3ybcckxdrnb web.2 nginx:latest manager Running Running 40 seconds ago

// 檢視當前所有節點

$ docker node ls

ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION

3px1nw94x2wmnr0k7846hpksh * manager Ready Active Leader 19.03.12

ibhxsuf055peywhawgp7hslav worker1 Ready Active 19.03.12

ny1e3wd4l7enyh0pp547azefe worker2 Ready Active 19.03.12

各節點 ip 地址

  • manager 192.168.99.100

  • worker1 192.168.99.101

  • worker2 192.168.99.102

訪問各個節點

訪問結果

我們發現即使 worker2 節點沒有執行 nginx 容器,但我們依然可以透過 worker2 節點訪問釋出的服務。

對已存在的服務釋出埠


docker service update

--publish-add published=<PUBLISHED-PORT>,target=<CONTAINER-PORT>

<SERVICE>

繞過 Routing Mesh

不具體講解了,沒有想到實際的應用場景。


$ docker service create --name dns-cache

--publish published=53,target=53,protocol=udp,mode=host

--mode global

dns-cache

服務全域性模式(global service)

上面的各種示例都是基於副本模式,下面開始全域性模式。


$ docker service create

--mode global

--publish mode=host,target=80,published=8080

--name=nginx

nginx:latest

使用上面的命令可以在當前的每個工作節點啟動一個 nginx 容器,這時如果有一個節點掛掉了,那麼並不會在其他節點重啟啟動一個新的容器。而如果我們這時在新增一個新的節點,那麼當這個新的節點加入 swarm 叢集的時候,該節點也會自動啟動一個 nginx 容器。

overlay 網路

該網路可以連線 swarm 叢集中的一個或多個服務

建立 overlay 網路


$ docker network create --driver overlay my-network

建立服務的時候加入 overlay 網路


$ docker service create --replicas 3 --network my-network --name my-web nginx

將現有的服務加入 overlay 網路


$ docker service update --network-add my-network my-web

將現有服務從 overlay 網路中斷開


$ docker service update --network-rm my-network my-web

在 Swarm 叢集中管理敏感資料

建立 secret

格式:docker secret create <secret-name> <file-name>


$ printf  "This is a secret" | docker secret create my_secret_data -

因為我們透過讀取標準輸入的方式,所以最後使用 - 標記

建立一個 redis 服務並授權方位 secret


$ docker service create --name redis --secret my_secret_data redis:alpine

預設情況下,容器可以透過 /run/secrets/<secret_name> 路徑訪問金鑰。或者可以使用 target 選項自定義容器上的檔名。

檢視當前服務執行狀態


$ docker service ps redis

ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS

bp0ylcmxw6ll redis.1 redis:alpine worker1 Running Running about a minute ago

驗證 secret


// 根據上面檢視的資料,進入 worker1 容器

$ docker-machine ssh worker1

// 獲取 worker1 容器執行的 redis 服務

$ docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

aa049d4173e1 redis:alpine "docker-entrypoint.s…" 8 minutes ago Up 8 minutes 6379/tcp redis.1.bp0ylcmxw6llv9icvhgrk189f

// 進入 redis 容器

$ docker exec -it redis.1.bp0ylcmxw6llv9icvhgrk189f sh

//在容器中檢視 secret

# cat /run/secrets/my_secret_data

This is a secret

使用中的 secret 無法刪除


// 進入 manager 節點

$ docker-machine ssh manager

$ docker secret rm my_secret_data

Error response from daemon: rpc error: code = InvalidArgument desc = secret 'my_secret_data' is in use by the following service: redis

docker@manager:~$

透過更新的方式刪除 secret


$ docker service update --secret-rm my_secret_data redis

redis

overall progress: 1 out of 1 tasks

1/1: running [==================================================>]

verify: Service converged

刪除服務和 secret


$ docker service rm redis

$ docker secret rm my_secret_data

在 Swarm 叢集中管理非敏感資料(配置)

使用方式與 secret 相似

docker 17.06引入了swarm service configs。允許你在服務映像或執行容器之外儲存非敏感資訊

注意:config 僅能在 Swarm 叢集中使用。

建立 config


// 建立一個名為 redis.conf 的檔案,內容為 port:6380

$ cat redis.conf

port 6380

// 建立 config

$ docker config create redis.conf redis.conf

$ docker config ls

ID NAME CREATED UPDATED

fkamdbup3egw8752bm4ixrsm2 redis.conf 23 minutes ago 23 minutes ago

跟 secret 使用類似

建立 redis 服務並授權其方位 config


$ docker service create

--name redis

--config redis.conf

--publish published=6379,target=6380

redis:latest

redis-server /redis.conf

或顯式的指定路徑


$ docker service create

--name redis

--config source=redis.conf,target=/etc/redis.conf

--publish published=6379,target=6380

redis:latest

redis-server /etc/redis.conf

以上兩種建立服務的方法都可以

驗證 config

使用 redis 管理工具連線 redis,連結地址填寫 192.168.99.100

連線配置

連線結果

使用中的 config 無法刪除


$ docker config rm redis.conf

Error response from daemon: rpc error: code = InvalidArgument desc = config 'redis.conf' is in use by the following service: redis

透過更新的方式刪除 config


docker service update --config-rm redis.conf redis

docker config rm redis.conf

redis.conf

移除 redis 服務


$ docker service rm redis

程式設計師的藝術人生

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章