跳至主要内容

7.6 如何在 Swarm 中儲存資料

接續上一個章節,我要先給 volume 能夠跨越伺服器的鴻溝嗎? 這個問題一個答案,就是不行。

volume 只能儲存在固定的節點上,又根據我們前面所提過,Swarm 會自動分配容器到隨機的節點上,那該如何確保 PostgreSQL 放到有 volume 的節點呢?

Docker 給出的解答就是 constraint,也就是透過在服務上貼標籤的方式,限制該服務只能執行在某個節點,自然而然容器也就只會在該節點運行,也算是解決的 volume 的問題。

另一個解決的方案就是使用外部服務,例如 AWS、GCP 都有提供資料庫的服務,很多時候正式的環境都會採用這些現成的資料庫服務,因為這些服務都提供備份以及監測的功能,又能確實解決 Swarm 模式下的資料分佈問題,也算是另外一種解決辦法。

下面就示範如何用貼標籤的方式來讓 PostgreSQL 的 service 運行在固定的節點,讓其能夠固定的連接同一個 volume,避免每次服務開啟時的資料都不固定,會非常困擾。

首先移除掉上一個章節所建立的所有 service。

root@ubuntu-s-1vcpu-512mb-10gb-sgp1-01:~# docker service rm drupal pg <- 不換行
drupal
pg

先列出所有的節點,並確認一下目前在哪一個節點:

root@ubuntu-s-1vcpu-512mb-10gb-sgp1-01:~# docker node list
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
wuq.. * ubuntu Ready Active Reachable 20.10.18
png.. ubuntu Ready Active Reachable 20.10.18
fdm.. ubuntu Ready Active Reachable 20.10.18

可以看到在列表中 ID 上有 『 * 』的節點,就是目前所在的節點,接著就在目前的節點先建立一個 volume,以便 postgres 的服務能夠有儲存空間。

root@ubuntu-s-1vcpu-512mb-10gb-sgp1-01:~# docker volume create pg
pg

接著啟動 postgres 的 service,並且利用 constraint 來強制其運行在有 volume 的節點。

root@ubuntu-s-1vcpu-512mb-10gb-sgp1-01:~# docker service create --name pg --mount source=pg,destination=/var/lib/postgresql/data --constraint node.id==wuqi9exd0f71uah8dcpdvgtw4 --network dev --env POSTGRES_PASSWORD=password postgres:14-alpine
3f7vd6e7qe1tf4fa6v6xez9ng
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged

在 Swarm 模式下 service 的 volume 掛載參數只能用 --mount 的方式,並且要標明 source 以及 target,source 就是 volume 而 target 則為容器內的檔案系統儲存位置,就和 Docker Volume 篇 的概念是一模一樣的。

--mount source=pg,destination=/var/lib/postgresql/data

constraint 的使用方式,則可以分成很多種,這邊我們用最簡單的方式,告訴 Swarm 只會把這個 service 部署到 ID 為 wuqi9exd0f71uah8dcpdvgtw4 的節點,也就是目前這個節點。

--constraint node.id==wuqi9exd0f71uah8dcpdvgtw4

接著可以在目前的節點上,用最傳統的方式來確認 postgres 這個服務是否有運行在這個節點上。

root@ubuntu-s-1vcpu-512mb-10gb-sgp1-01:~# docker container list
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2bf12f2643e1 postgre "doc.." 28 mi.. Up 28 5432/tcp pg.1

接著再來部署 Drupal 這個服務。

root@ubuntu-s-1vcpu-512mb-10gb-sgp1-01:~# docker service create --name drupal --network dev --publish 80:80 drupal:7.92
n3x5950gikz8ih9ynnqc7erna
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged

並且在採用和上一章相同的設定方式,接著新增一篇文章。

新增文章

接著刪除 postgres 的服務,並且重新運行,確認其有連接到 volume,而文章也沒有因為 postgres 的服務刪除而消失不見。

root@ubuntu-s-1vcpu-512mb-10gb-sgp1-01:~# docker service rm pg
pg

root@ubuntu-s-1vcpu-512mb-10gb-sgp1-01:~# docker service create --name pg --mount source=pg,destination=/var/lib/postgresql/data --constraint node.id==wuqi9exd0f71uah8dcpdvgtw4 --network dev --env POSTGRES_PASSWORD=password postgres:14-alpine
se6umxcb1kebskrffiv9dyuju
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged

接著回到網站,會看到文章還是一樣存在,這就是在 Swarm 模式下儲存資料的方式,透過 constraint 的方式強迫服務運行在 volume 存在的節點,確保資料的儲存。