Docker Swarm introduction

Posted by Anthony Chao on 2021-02-16

Docker swarm

Intro

Docker swarm 模式中,當我們 create service,我們同時會指定想要的狀態(replica 數量 / network / storage resource),Docker engine 會試圖去 maintain 在這個 state

擔任Manager角色的Docker Swarm節點主機,主要管理Docker Swarm叢集運作狀態,所有擔任Manager角色的Docker Swarm節點主機,便需要執行同步、確認、更新、複寫等等Docker Swarm叢集運作狀態的工作任務。

正常的多 manager node 運作方式如下圖

當擔任Manager角色的Docker Swarm節點主機數量「過少」時,有可能因為Manager主機故障損壞,進而導致Docker Swarm叢集崩潰;反之,若Manager角色Docker Swarm節點主機數量「過多」,則會因為叢集維運工作任務的往返網路流量過大,導致同步和更新狀態的寫入效能降低

Docker官方的最佳建議做法當中,擔任Manager角色的Docker Swarm節點主機數量應為「奇數」,最主要是考量Docker Swarm叢集中的「仲裁」(Quorum)及「容錯」(Fault Tolerance)機制。

最小規模應建置「3台」擔任Manager角色的Docker Swarm節點主機,此時可容許「1台」Manager角色主機發生故障損壞事件,並且不影響Docker Swarm叢集的運作,就算建置 4 台 manager 角色主機,還是只能允許 1 台 manager 角色主機故障

名詞解釋

  • node: 主機的別稱, 也可以稱作 host, node 又分成 manager 跟 worker 兩種不同角色

  • service: 在 node 上面執行的 tasks,比方說這個 service 可能包含三個不同的 tasks 並且每個 task 裡面有一個 container

  • replica: 指這個 service 每個正在執行的 task

replicated and global service

docker swarm 裡面的 service 有兩種部署方式: replicated / global

replicated service 指定想要的 replica 數量, 每個 replica 都一樣,會被分配到不同的 worker node 裡面

global service 會在每一個 node 身上跑一個 task(包括 manager node), 不用特別指定 task 數量, 這種通常是用在 monitor agent

下圖的例子是跑一個 three-service replica + 1 global replica

部署

在部署之前需要在機器上面 initial docker swarm(create docker swarm cluster)

1
2
3
4
5
6
7
8
9
10
11
> docker swarm init --advertise-addr <MANAGER-IP>

Swarm initialized: current node (qfqzhk2bumhd2h0ckntrysm8l) is now a
manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-253vezc1pqqgb93c5huc9g3n0hj4p7xik1ziz5c4rsdo3f7iw2-
df098e2jpe8uvwe2ohhhcxd6w \
192.168.0.143:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and
follow the instructions.

如果要加入新的 worker node 就像下面這樣加入

1
2
> docker swarm join --token <TOKEN> <worker IP>
> docker swarm join --token SWMTKN-1-41r5smr3kgfx780781xxgbenin2dp7qikfh9eketc0wrhrkzsn-8lbew6gpgxwd5fkn52l7s6fof 192.168.65.3:2377

在建置好各個機器之後,可以來部署服務,指令如下:

1
> docker service create

下圖表示當指令下下去之後 Docker 會做哪些事情

Docker swarm 會根據指令決定要建多少的任務(tasks)跟容器

以這個例子來說就是這個 service 需要 4 個 replica(tasks), 用的是 alpine 這個 image

1
> docker service create --replicas 4 --name hellogoogle alpine ping google.com

Drain a node

當我們把一個 node drain 掉,表示不在讓它身上有新的 task, 而且會停止現有的 task, 同時把這些 task 分配到其他 node 身上

1
> docker node update --availability drain worker1

可以把一個被 drain 掉的 node 再重新 active

1
> docker node update --availability active worker1

Routing mesh

在 Docker swarm 裡面,所有 node 都會參與 routing mesh 過程,就算這個 node 身上沒有這個 service 的 task,但如果有個 request 進到這個 node,會透過 routing mesh 轉到有這個 task 的 node 身上

像是下面這張圖這樣

我們也可以在外面做一個 load balancer 搭配 routing mesh

參考資料:https://docs.docker.com/engine/swarm/ingress/

secrets / credentials

敏感資料可以用 docker swarm 的 secret 系統儲存

1
2
3
4
5
6
> echo "Secret" | docker secret create my_secret -
# 其中 my_secrt 是這個 secret 的名字
> docker secret ls
# 列出所有 secret
> docker inspect SECRET_NAME
> docker secret rm my_secret

傳 secret 給 service 的話可以在一開始 create 的時候丟進去或者 update 再丟

1
2
3
> docker service  create --name="nginx" --secret="my_secret" nginx:latest
> docker service update --secret-rm="my_secret" nginx
> docker service update --secret-add="my_secret" nginx

Limit resource

我們可以限制 cpu 或者記憶體等等資原在各個 service 身上

1
2
3
4
--limit-cpu
--limit-memory
--reserve-cpu
--reservce-memory

stack file

Docker Stack 是 docker-compose 的延伸,在原本的 docker-compose 已經定義了 service 的長相,但docker stack file 還要寫上一些跟部署有關的參數

例如原本的 docker-compose file 長這樣:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
version: '3'

services:
nodejs:
build:
context: ./
dockerfile: Dockerfile
restart: always
environment:
- DATABASE_HOST=mongo
- PORT=3000
ports:
- '3000:3000'
depends_on: [mongo]
mongo:
image: mongo
ports:
- '27017:27017'
volumes:
- mongo_data:/data/db

volumes:
mongo_data: {}

其中 mongo service 的 image 是直接從線上拉的沒問題,但 nodejs 的 image 是 local 的,需要先把他推到 registry

1
2
3
services:
nodejs:
image: 127.0.0.1:5000/nodejs
1
> docker-compose push

接著補上跟部署有關的參數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
version: '3'

services:
nodejs:
image: 127.0.0.1:5000/nodejs
build:
context: ./
dockerfile: Dockerfile
restart: always
environment:
- DATABASE_HOST=mongo
- PORT=3000
ports:
- '3000:3000'
depends_on: [mongo]
deploy:
replicas: 6
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
resources:
limits:
cpus: "0.1"
memory: 1G
mongo:
image: mongo
ports:
- '27017:27017'
volumes:
- mongo_data:/data/db

volumes:
mongo_data: {}

接著就可以部署這個 stack 了

1
> docker stack deploy --compose-file docker-compose.yml stackdemo
1
2
3
4
5
6
> docker stack ls
# 列出所有 stack
> docker stack ps STACK_NAME
# 列出某個 stack 的所有 service
> docker stack rm STACK_NAME
# 移除某個 stack

Commands

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
> docker node ls
# 列出目前的 node
> docker node promote <docker-node>
# Promote node to manager
> docker node promote <docker-node>
# Demote node to worker
> docker node update --role manager docker-node
# 也可以用 update command 來更改 role
> docker swarm leave
# 在 worker node 裡面離開 swarm
> docker node rm worker1
# 在 manager node 裡面移除某個 worker node
> docker service scale <SERVICE-ID>=<NUMBER-OF-TASKS>
# 改 service 的 scale, 其中的 serviceID 也可以改用 service name
> docker service inspect <SERVICE_NAME>
> docker service rm <SERVICE_NAME>
> docker service update --image nginx:stable nginx
# 更新 service 使用的 image, 預設使用 rolling update
> docker service update --update-parallelism 3 nginx
# 可以指定同時更新多少個 tasks
> docker service rollback nginx
# Docker swarm 可以rollback 到 service 前一個版本
> docker service update --detach=false --update-failure-action rollback nginx
# 也可以在 update 的時候如果有任何失敗就 rollback
> docker service logs hellogoogle
# 看 service 的 log
> docker service logs --follow hellogoogle
# real time 看 log

Note

Docker swarm 節點主機之間,要有下列相關的 port 開啟,否則會造成通訊錯誤

  • TCP Port 2377:用於Docker Swarm叢集管理服務。

  • UDP Port 4789: 用於Docker Swarm叢集Overlay Network跨主機網路流量。

  • TCP/UDP Port 7946:用於Docker Swarm叢集節點主機互相通訊。

  • IP Protocol 50(ESP):用於Docker Swarm叢集Overlay Network跨主機網路流量進行加密時使用。

References

https://gabrieltanner.org/blog/docker-swarm

https://www.netadmin.com.tw/netadmin/zh-tw/feature/167CDFB3615E42229B5C7053DC452755?page=5





prevent_hack