在講解使用 Docker Stack 部署應用之前,有幾個前置處理需要完成。
? Swarm 模式:應用將采用 Docker Stack 部署,而 Stack 依賴 Swarm 模式。
? 標簽:某個 Swarm worker 節(jié)點需要自定義標簽。
? 密鑰:應用所需的密鑰需要在部署前創(chuàng)建完成。
接下來的講解中會完成基于 Linux 的三節(jié)點 Swarm 集群搭建,同時能滿足上面應用的全部前置依賴。完成之后,實驗環(huán)境如下圖所示。
接下來內(nèi)容分為 3 個步驟。
? 創(chuàng)建新的 Swarm。
? 添加節(jié)點標簽。
? 創(chuàng)建密鑰。
首先創(chuàng)建新的三節(jié)點 Swarm 集群。
⒈ 初始化 Swarm
在任意 Swarm 管理節(jié)點的機器上,運行下面的命令。
$ docker swarm init
Swarm initialized: current node (lhma...w4nn) is now a manager.
<Snip>
⒉ 添加工作節(jié)點
復制前面輸出中出現(xiàn)的 docker swarm join 命令。將復制內(nèi)容粘貼到工作節(jié)點上并運行。
//Worker 1 (wrk-1)
wrk-1$ docker swarm join --token SWMTKN-1-2hl6...-...3lqg 172.31.40.192:2377
This node joined a swarm as a worker.
//Worker 2 (wrk-2)
wrk-2$ docker swarm join --token SWMTKN-1-2hl6...-...3lqg 172.31.40.192:2377
This node joined a swarm as a worker.
⒊ 確認當前 Swarm 由一個管理節(jié)點和兩個工作節(jié)點構(gòu)成
在管理節(jié)點中運行下面的命令。
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
lhm...4nn * mgr-1 Ready Active Leader
b74...gz3 wrk-1 Ready Active
o9x...um8 wrk-2 Ready Active
Swarm 集群目前就緒。payment_gateway 服務配置了部署約束,限制該服務只能運行在有 pcidss=yes 標簽的工作節(jié)點之上。本步驟中將在 wrk-1 上添加該節(jié)點標簽。
在實際操作中,添加該標簽之前必須將某個 Docker 節(jié)點按 PCI 規(guī)范進行標準化。但是,這只是一個實驗環(huán)境,所以就暫且跳過這一過程,直接將標簽添加到 wrk-1 節(jié)點。
在 Swarm 管理節(jié)點運行下面的命令。
⒈ 添加節(jié)點標簽到 wrk-1
$ docker node update --label-add pcidss=yes wrk-1
Node 標簽只在 Swarm 集群之內(nèi)生效。
⒉ 確認節(jié)點標簽
$ docker node inspect wrk-1
[
{
"ID": "b74rzajmrimfv7hood6l4lgz3",
"Version": {
"Index": 27
},
"CreatedAt": "2018-01-25T10:35:18.146831621Z",
"UpdatedAt": "2018-01-25T10:47:57.189021202Z",
"Spec": {
"Labels": {
"pcidss": "yes"
},
<Snip>
wrk-1 工作節(jié)點現(xiàn)在已經(jīng)配置完成,所以該節(jié)點可以運行 payment_gateway 服務副本了。
應用定義了 4 個密鑰,這些都需要在應用部署前創(chuàng)建。
postgress_password。
staging_token。
revprox_cert。
revprox_key。
在管理節(jié)點運行下面的命令,來創(chuàng)建這些密鑰。
⒈ 創(chuàng)建新的鍵值對
密鑰中有 3 個是需要加密 key 的。在本步驟中會創(chuàng)建加密 key,下一步會將加密 key 放到 Docker 密鑰文件當中。
$ openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout domain.key -x509 -days 365 -out domain.crt
⒉ 創(chuàng)建 revprox_cert、revprox_key 以及 postgress_password 密鑰
$ docker secret create revprox_cert domain.crt
cqblzfpyv5cxb5wbvtrbpvrrj
$ docker secret create revprox_key domain.key
jqd1ramk2x7g0s2e9ynhdyl4p
$ docker secret create postgres_password domain.key
njpdklhjcg8noy64aileyod6l
⒊ 創(chuàng)建 stage_token 密鑰
$ echo staging | docker secret create staging_token -
sqy21qep9w17h04k3600o6qsj
⒋ 列出所有密鑰
$ docker secret ls
ID NAME CREATED UPDATED
njp...d6l postgres_password 47 seconds ago 47 seconds ago
cqb...rrj revprox_cert About a minute ago About a minute ago
jqd...l4p revprox_key About a minute ago About a minute ago
sqy...qsj staging_token 23 seconds ago 23 seconds ago
上面已經(jīng)完成了全部的前置準備。是時候開始部署應用了!
如果還沒有代碼,請先復制應用的 GitHub 倉庫到 Swarm 管理節(jié)點。
$ git clone https://github.com/dockersamples/atsea-sample-shop-app.git
Cloning into 'atsea-sample-shop-app'...
remote: Counting objects: 636, done.
Receiving objects: 100% (636/636), 7.23 MiB | 3.30 MiB/s, done. remote:
Total 636 (delta 0), reused 0 (delta 0), pack-reused 636 Resolving
deltas: 100% (197/197), done.
Checking connectivity... done.
$ cd atsea-sample-shop-app
現(xiàn)在已經(jīng)擁有了源碼,可以開始部署應用了。
Stack 通過docker stack deploy 命令完成部署。基礎(chǔ)格式下,該命令允許傳入兩個參數(shù)。
? Stack 文件的名稱。
? Stack 的名稱。
應用的 GitHub 倉庫中包含一個名為 docker-stack.yml 的 Stack 文件。這里會使用該文件。這里為 Stack 起名 seastack。
在 Swarm 管理節(jié)點的 atsea-sample-shop-app 目錄下運行下面的命令。
$ docker stack deploy -c docker-stack.yml seastack
Creating network seastack_default
Creating network seastack_back-tier
Creating network seastack_front-tier
Creating network seastack_payment
Creating service seastack_database
Creating service seastack_appserver
Creating service seastack_visualizer
Creating service seastack_payment_gateway
Creating service seastack_reverse_proxy
可以運行 docker network ls 以及 docker service ls 命令來查看應用的網(wǎng)絡和服務情況。
下面是命令輸出中幾個需要注意的地方。
網(wǎng)絡是先于服務創(chuàng)建的。這是因為服務依賴于網(wǎng)絡,所以網(wǎng)絡需要在服務啟動前創(chuàng)建。
Docker 將 Stack 名稱附加到由他創(chuàng)建的任何資源名稱前作為前綴。在本例中,Stack 名為 seastack,所以所有資源名稱的格式都如:seastack_。例如,payment 網(wǎng)絡的名稱是 seastack_payment。而在部署之前創(chuàng)建的資源則沒有被重命名,比如密鑰。
另一個需要注意的點是出現(xiàn)了新的名為 seastack_default 的網(wǎng)絡。該網(wǎng)絡并未在Stack文件中定義,那為什么會創(chuàng)建呢?每個服務都需要連接到網(wǎng)絡,但是 visualizer 服務并沒有指定具體的網(wǎng)絡。因此,Docker 創(chuàng)建了名為 seastack_default 的網(wǎng)絡,并將 visualizer 連接到該網(wǎng)絡。
可以通過兩個命令來確認當前 Stack 的狀態(tài)。docker stack ls 列出了系統(tǒng)中全部 Stack,包括每個 Stack 下面包含多少服務。docker stack ps <stack-name> 針對某個指定 Stack 展示了更詳細的信息,例如期望狀態(tài)以及當前狀態(tài)。下面一起來了解下這兩條命令。
$ docker stack ls
NAME SERVICES
Seastack 5
$ docker stack ps seastack
NAME NODE DESIRED STATE CURRENT STATE
seastack_reverse_proxy.1 wrk-2 Running Running 7 minutes ago
seastack_payment_gateway.1 wrk-1 Running Running 7 minutes ago
seastack_visualizer.1 mgr-1 Running Running 7 minutes ago
seastack_appserver.1 wrk-2 Running Running 7 minutes ago
seastack_database.1 wrk-2 Running Running 7 minutes ago
seastack_appserver.2 wrk-1 Running Running 7 minutes ago
在服務啟動失敗時,docker stack ps 命令是首選的問題定位方式。該命令展示了 Stack 中每個服務的概況,包括服務副本所在節(jié)點、當前狀態(tài)、期望狀態(tài)以及異常信息。從下面的輸出信息中能看出 reverse_proxy 服務在 wrk-2 節(jié)點上兩次嘗試啟動副本失敗。
$ docker stack ps seastack
NAME NODE DESIRED CURRENT ERROR
STATE STATE
reverse_proxy.1 wrk-2 Shutdown Failed "task: non-zero exit (1)"
\_reverse_proxy.1 wrk-2 Shutdown Failed "task: non-zero exit (1)"
如果想查看具體某個服務的詳細信息,可以使用 docker service logs 命令。讀者需要將服務名稱 /ID 或者副本 ID 作為參數(shù)傳入。如果傳入服務名稱或 ID,可以看到所有服務副本的日志信息。如果傳入的是副本 ID,則只會看到對應副本的日志信息。
下面的 docker service logs 命令展示了 seastack_reverse_proxy 服務的全部副本日志,其中包含了前面輸出中的兩次副本啟動失敗的日志。
#1host not found#1host not found
輸出內(nèi)容為了適應頁面展示,已經(jīng)經(jīng)過裁剪,但是還是可以看到全部 3 個服務副本的日志(兩個啟動失敗,1 個正在運行)。每行的開始都是副本的名稱,包括服務名稱、副本序號、副本 ID 以及副本所在主機的名稱。接下來是具體的日志輸出。
提示:大家可能已經(jīng)注意到前面日志中全部副本的序號都是 1。這是因為 Docker 每次只創(chuàng)建一個副本,并且只有當前面的副本啟動失敗時才會創(chuàng)建新的。
因為輸出內(nèi)容經(jīng)過裁剪,所以具體原因很難明確,但看起來前兩次副本啟動失敗原因是其依賴的某個服務仍然在啟動中(一種啟動時服務間依賴導致的競爭條件)。
可以繼續(xù)跟蹤日志(--follow),查看日志尾部內(nèi)容(--tail),或者獲取額外的詳細信息(--details)。