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 | > docker swarm init --advertise-addr <MANAGER-IP> |
如果要加入新的 worker node 就像下面這樣加入
1 | > docker swarm join --token <TOKEN> <worker IP> |
在建置好各個機器之後,可以來部署服務,指令如下:
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 | > echo "Secret" | docker secret create my_secret - |
傳 secret 給 service 的話可以在一開始 create 的時候丟進去或者 update 再丟
1 | > docker service create --name="nginx" --secret="my_secret" nginx:latest |
Limit resource
我們可以限制 cpu 或者記憶體等等資原在各個 service 身上
1 | --limit-cpu |
stack file
Docker Stack 是 docker-compose 的延伸,在原本的 docker-compose 已經定義了 service 的長相,但docker stack file 還要寫上一些跟部署有關的參數
例如原本的 docker-compose file 長這樣:
1 | version: '3' |
其中 mongo service 的 image 是直接從線上拉的沒問題,但 nodejs 的 image 是 local 的,需要先把他推到 registry
1 | services: |
1 | > docker-compose push |
接著補上跟部署有關的參數
1 | version: '3' |
接著就可以部署這個 stack 了
1 | > docker stack deploy --compose-file docker-compose.yml stackdemo |
1 | > docker stack ls |
Commands
1 | > docker node ls |
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