淺述 Docker 的容器編排

語言: CN / TW / HK

點選進入“PHP開源社群”    

免費獲取進階面試、文件、影片資源

概述

作為容器引擎,Docker為容器化的應用程式提供了開放標準,使得開發者可以用管理應用程式的方式來管理基礎架構,實現快速交付、測試和部署程式碼。隨著容器的大量使用,又產生了如何協調、排程和管理容器的問題,Docker的容器編排應運而生。所謂容器編排,通俗一點可以理解為叢集管理。

Docker的容器編排工具有很多,最出名的當屬Compose、Machine和Swarm,合稱Docker三劍客。其中Compose和Machine是第三方的,而Swarm則是Docker官方的容器編排工具,已經被整合在Docker中了。

Swarm由三大部分組成:

  • swarm:叢集管理

  • node:節點管理

  • service:服務管理

叢集與節點管理

使用 docker swarm 命令,可以建立或加入叢集,Docker叢集中的節點分為manager和worker兩種。這兩種節點,都可以執行Docker容器,但只有manager節點,擁有管理功能。

一個叢集中,即便只有manager節點也可以正常的工作。

2.1 建立叢集

我測試的環境有兩臺機器,ip地址分別為192.168.1.220和192.168.1.116。下面在192.168.1.220上建立叢集:

# docker swarm init
Swarm initialized: current node (ppmurem8j7mdbmgpdhssjh0h9) is now a manager.

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

docker swarm join --token SWMTKN-1-3e4l8crbt04xlqfxwyw6nuf9gtcwpw72zggtayzy8clyqmvb5h-7o6ww4ftwm38dz7ydbolsz3kd 192.168.1.220:2377

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

執行 docker swarm init 後,叢集就被建立好了。當前的機器,自動成為叢集的manager節點,並且輸出了其他機器加入叢集的方式,

即:

docker swarm join --token SWMTKN-1-3e4l8crbt04xlqfxwyw6nuf9gtcwpw72zggtayzy8clyqmvb5h-7o6ww4ftwm38dz7ydbolsz3kd 192.168.1.220:2377。

使用這個token加入的節點,是worker節點,如果想加入一個新的manager節點,可以執行 docker swarm join-token manager,它也會輸出一串類似的命令,執行就可以以manager的方式加入。如果忘記加入的命令,也可以使用docker swarm join-token worker 進行檢視。

2.2 加入叢集

下面在192.168.1.116上執行加入命令:

# docker swarm join --token SWMTKN-1-12dlq70adr3z38mlkltc288rdzevtjn73xse7d0qndnjmx45zs-b1kwenzmrsqb4o5nvni5rafcr 192.168.1.220:2377
This node joined a swarm as a worker.

這裡發生了一個小插曲,在我建立叢集的兩臺機器的時區不一致,導致在加入worker節點時報錯:

Error response from daemon: error while validating Root CA Certificate: x509: certificate has expired or is not yet valid

在更新了220的時區後,依然無法加入。於是,我刪除了叢集又重新建立,就可以了。沒有嘗試使用docker swarm update是不是也可以。

加入了集群后,可以在manager節點上,查詢叢集的節點:

# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
9b4cmakc4hpc9ra4rruy5x5yo * localhost.localdomain Ready Active Leader 20.10.3
hz50cnwrbk4vxa7h0g23ccil9 zhangmh-virtual-machine Ready Active 20.10.1

2.3 退出叢集

在192.168.1.116上執行下面命令,可以退出叢集:

# docker swarm leave                                                                                                           
Node left the swarm.

再次檢視節點:

# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
9b4cmakc4hpc9ra4rruy5x5yo * localhost.localdomain Ready Active Leader 20.10.3
hz50cnwrbk4vxa7h0g23ccil9 zhangmh-virtual-machine Down Active 20.10.1

發現剛退出的這個節點還在,只是狀態變成了Down。需要在manager節點中刪除:

# docker node rm hz50cnwrbk4vxa7h0g23ccil9
hz50cnwrbk4vxa7h0g23ccil9
# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
9b4cmakc4hpc9ra4rruy5x5yo * localhost.localdomain Ready Active Leader 20.10.3
xby86ffkqw3axyfkwd4s7nubz zhangmh-virtual-machine Ready Active 20.10.1

這樣才真正刪除了節點。

如果退出的節點是manager節點,需要強制退出,即:docker swarm leave -f。

2.4 將節點提升為 manager 節點

只有一個manager的叢集是不穩定的,當manager節點崩潰時,整個叢集就群龍無首了。Docker認為,一個叢集中應該至少有三個manager節點,並且有一半以上的manager節點是可達的,才能保證叢集的正常執行。當叢集中只有兩個manager節點,且有一個節點出現問題時,整個叢集還是處於不可用的狀態。

當然,對於我們測試,是沒有必要的,我們只需要使用兩個manager節點,測試一下是否可以主從切換就可以了。使用下面的命令,可以直接將workder節點提升為manager節點:

# docker node promote xby86ffkqw3axyfkwd4s7nubz
Node xby86ffkqw3axyfkwd4s7nubz promoted to a manager in the swarm.
# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
9b4cmakc4hpc9ra4rruy5x5yo * localhost.localdomain Ready Active Leader 20.10.3
xby86ffkqw3axyfkwd4s7nubz zhangmh-virtual-machine Ready Active Reachable 20.10.1

OK,現在有兩個manager節點了,192.168.1.220的狀態為leader,即當前是領導節點,192.168.1.116的狀態為Reachable,是可達的。下面關閉192.168.1.220節點的Docker服務:

# systemctl stop docker
Warning: Stopping docker.service, but it can still be activated by:
docker.socket

關閉時輸出了一個警告,意思是Docker服務已經被關閉了,但它仍然可被docker.socket服務喚醒。再次檢視節點狀態:

# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
9b4cmakc4hpc9ra4rruy5x5yo * localhost.localdomain Ready Active Reachable 20.10.3
xby86ffkqw3axyfkwd4s7nubz zhangmh-virtual-machine Ready Active Leader 20.10.1

可以看到192.168.1.116已經成為了Leader,並且,192.168.1.220也已經被喚醒。

由此可見,Docker叢集的穩定是相當不錯的。

服務管理

叢集中各節點都配置好後,就可以建立服務了。Docker的服務其實就是啟動容器,並且賦予了容器副本和負載均衡的能力。以之前建立的ws:1.0為例,建立5個副本:

# docker service create --replicas 5 --name ws -p 80:8000 ws:1.0
image ws:1.0 could not be accessed on a registry to record
its digest. Each node will access ws:1.0 independently,
possibly leading to different nodes running different
versions of the image.

1nj3o38slbo2zwt5p69l1qi5t
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

服務已經建立並運行了,使用瀏覽器訪問192.168.1.220和192.168.1.116的80埠都可以訪問。

使用 docker service ls 命令可以檢視ws服務:

# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
1nj3o38slbo2 ws replicated 5/5 ws:1.0 *:80->8000/tcp

使用 docker service ps ws 命令可檢視ws服務的程序:

# docker service ps ws
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
jpckj0mn24ae ws.1 ws:1.0 zhangmh-virtual-machine Running Running 6 minutes ago
yrrdn4ntb089 ws.2 ws:1.0 localhost.localdomain Running Running 6 minutes ago
mdjxadbmlmhs ws.3 ws:1.0 zhangmh-virtual-machine Running Running 6 minutes ago
kqdwfrddbaxd ws.4 ws:1.0 localhost.localdomain Running Running 6 minutes ago
is2iimz1v4eb ws.5 ws:1.0 zhangmh-virtual-machine Running Running 6 minutes ago

可以看到有兩個程序執行在192.168.1.220上,三個程序執行在192.168.1.116上。我在瀏覽器上訪問了幾次之後 ,使用 docker service logs ws 命令檢視服務的日誌:

# docker service logs ws
ws.5[email protected] | [I 210219 01:57:23 web:2239] 200 GET / (10.0.0.2) 3.56ms
ws.5[email protected] | [W 210219 01:57:23 web:2239] 404 GET /favicon.ico (10.0.0.2) 0.97ms
ws.5[email protected] | [I 210219 01:57:28 web:2239] 200 GET / (10.0.0.4) 0.82ms
ws.5[email protected] | [W 210219 01:57:28 web:2239] 404 GET /favicon.ico (10.0.0.4) 0.79ms
ws.1[email protected] | [I 210219 02:01:45 web:2239] 304 GET / (10.0.0.2) 1.82ms
ws.1[email protected] | [I 210219 02:01:59 web:2239] 304 GET / (10.0.0.2) 0.49ms
ws.1[email protected] | [I 210219 02:02:01 web:2239] 304 GET / (10.0.0.2) 2.05ms
ws.1[email protected] | [I 210219 02:02:02 web:2239] 304 GET / (10.0.0.2) 0.89ms
ws.1[email protected] | [I 210219 02:02:02 web:2239] 304 GET / (10.0.0.2) 1.13ms
ws.1[email protected] | [I 210219 02:02:03 web:2239] 304 GET / (10.0.0.2) 0.92ms
ws.1[email protected] | [I 210219 02:02:03 web:2239] 304 GET / (10.0.0.2) 2.19ms
ws.1[email protected] | [I 210219 02:02:20 web:2239] 304 GET / (10.0.0.2) 1.00ms

可以看到即使我訪問的是192.168.1.220,而實際訪問的然是192.168.1.116上的程序。

如果把192.168.1.116關機,其上執行的程序會自動轉移到192.168.1.220的節點中,因為192.168.1.116現在是manager節點,如果停止,叢集會進入不可用的狀態,所以,需要先將其降級為worker節點:

# docker node demote xby86ffkqw3axyfkwd4s7nubz
Manager xby86ffkqw3axyfkwd4s7nubz demoted in the swarm.

然後,將192.168.1.116關機。

# docker service ps ws
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
jrj9ben9vr5c ws.1 ws:1.0 localhost.localdomain Running Running 57 minutes ago
yrrdn4ntb089 ws.2 ws:1.0 localhost.localdomain Running Running about an hour ago
opig9zrmp261 ws.3 ws:1.0 localhost.localdomain Running Running 57 minutes ago
kqdwfrddbaxd ws.4 ws:1.0 localhost.localdomain Running Running about an hour ago
hiz8730pl3je ws.5 ws:1.0 localhost.localdomain Running Running 57 minutes ago

可以看到5個程序都轉移到192.168.1.220上運行了。

# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bc4c457ce769 ws:1.0 "/bin/sh -c 'python …" 3 hours ago Up 3 hours ws.5.hiz8730pl3je7qvo2lv6k554b
c846ac1c4d91 ws:1.0 "/bin/sh -c 'python …" 3 hours ago Up 3 hours ws.3.opig9zrmp2619t4e1o3ntnj2w
214daa36c138 ws:1.0 "/bin/sh -c 'python …" 3 hours ago Up 3 hours ws.1.jrj9ben9vr5c3biuc90xtoffh
17842db9dc47 ws:1.0 "/bin/sh -c 'python …" 3 hours ago Up 3 hours ws.4.kqdwfrddbaxd5z78uo3zsy5sd
47185ba9a4fd ws:1.0 "/bin/sh -c 'python …" 3 hours ago Up 3 hours ws.2.yrrdn4ntb089t6i66w8xvq8r9
# docker kill bc4c457ce769
bc4c457ce769

殺死第5個程序後,等待幾秒再檢視程序:

# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
416b55e8d174 ws:1.0 "/bin/sh -c 'python …" About a minute ago Up About a minute ws.5.fvpm334t2zqbj5l50tyx5glr6
c846ac1c4d91 ws:1.0 "/bin/sh -c 'python …" 3 hours ago Up 3 hours ws.3.opig9zrmp2619t4e1o3ntnj2w
214daa36c138 ws:1.0 "/bin/sh -c 'python …" 3 hours ago Up 3 hours ws.1.jrj9ben9vr5c3biuc90xtoffh
17842db9dc47 ws:1.0 "/bin/sh -c 'python …" 3 hours ago Up 3 hours ws.4.kqdwfrddbaxd5z78uo3zsy5sd
47185ba9a4fd ws:1.0 "/bin/sh -c 'python …" 3 hours ago Up 3 hours ws.2.yrrdn4ntb089t6i66w8xvq8r9

第5個程序又被啟動。

Docker服務的副本數量是可以動態調整的,比如系統負載過高,需要新增副本時,只需要執行:

# docker service scale ws=6
ws scaled to 6
overall progress: 6 out of 6 tasks
1/6: running [==================================================>]
2/6: running [==================================================>]
3/6: running [==================================================>]
4/6: running [==================================================>]
5/6: running [==================================================>]
6/6: running [==================================================>]
verify: Service converged

這樣,就增加了一個副本。

服務建立好以後,就可以隨著Docker的系統服務被啟動,只要執行:

systemctl enable docker

剛才建立的叢集和服務都會開機啟動,不用擔心機器重啟導致程式執行不正常。

共享資料卷

首先,使用 docker volume create 命令建立一個數據卷:

# docker volume create ws_volume
ws_volume

建立完成後,使用 docker volume ls 命令可檢視現有的資料卷:

# docker volume ls
DRIVER VOLUME NAME
local ws_volume

使用 docker inspect 命令可檢視資料卷的詳細資訊:

# docker inspect ws_volume
[
{
"CreatedAt": "2021-02-19T14:09:58+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/ws_volume/_data",
"Name": "ws_volume",
"Options": {},
"Scope": "local"
}
]

在建立service時,可使用 --mount 引數將資料卷掛載到service中:

# docker service create --replicas 2 --name ws -p 80:8000 --mount type=volume,src=ws_volume,dst=/volume ws:1.0
image ws:1.0 could not be accessed on a registry to record
its digest. Each node will access ws:1.0 independently,
possibly leading to different nodes running different
versions of the image.

iiiit9slq9qqwcdwwi0w0mcz5
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service converged

--mount 有很多的子引數,把它們寫成key=value的形式,然後用逗號隔開即可,最簡單的,只需要設定type、src、dst三個引數即可。

*宣告:本文於網路整理,版權歸原作者所有,如來源資訊有誤或侵犯權益,請聯絡我們刪除或授權事宜

END

PHP開源社群

掃描關注  進入”PHP資料“

免費獲取進階

面試、文件、影片資源

點選“檢視原文”獲取更多