Docker Swarm 叢集編排
當你的容器應用程式需要跨越多台伺服器部署,並要求具備自動修復 (Self-healing)、水平擴展 (Scaling)、負載均衡 (Load Balancing) 與滾動更新 (Rolling Updates) 等能力時,你就需要叢集編排 (Orchestration) 工具。
雖然 Kubernetes (K8s) 是目前的主流,但對於中小型專案或追求簡單運維的團隊來說,Docker 內建的 Swarm Mode 是一個極佳的選擇,它簡單易用且與 Docker 指令高度整合。
為什麼選擇 Docker Swarm?
Docker Swarm 是 Docker 官方提供的叢集管理工具。它的最大優勢在於:開箱即用。只要你安裝了 Docker,就已經具備了 Swarm,無需額外安裝複雜的組件。
核心優勢:
- 極簡安裝:一條指令即可初始化叢集。
- 宣告式狀態 (Declarative Service Model):你只需定義理想狀態(例如:維持 5 個副本),Swarm 會自動確保實際運行狀態與之相符。
- 內建負載均衡:自動處理內部與外部網路流量派送。
- 安全性:預設啟用 TLS 相互認證,節點間通訊皆經過加密。
Swarm 核心架構
Swarm 叢集由多個 Nodes (節點) 組成,每個節點都是一個 Docker 主機。
節點角色
- Manager Nodes:
- 管理叢集狀態、調度任務並維護集群一致性。
- 使用 Raft 共識演算法 來同步狀態。為了維持高可用性,建議部署奇數個 (1, 3, 5) Manager 節點。
- Worker Nodes:
- 單純接收 Manager 分派的任務並執行容器。
- Manager 節點預設也具備執行任務的能力(可設定為僅限管理)。
服務與任務 (Service & Task)
- Service (服務):這是你在 Swarm 中操作的最小單位。你定義「我要一個 Nginx 服務,副本數為 3」。
- Task (任務):正在節點上執行的單個容器實例。Service 是 Blueprint,Task 是具體的實例。
實戰:建立與管理叢集
初始化叢集 (Manager)
在預計作為管理者的機器執行:
docker swarm init --advertise-addr <MANAGER_IP>
執行後會得到兩行關鍵指令:一行用於加入新的 Manager,另一行用於加入 Worker。
加入工作節點 (Worker)
在其他伺服器上貼上剛產生的 docker swarm join 指令:
docker swarm join --token <TOKEN_STR> <MANAGER_IP>:2377
查看與管理節點
在 Manager 上執行:
# 查看所有節點
docker node ls
# 查看特定節點詳細資訊
docker node inspect <NODE_ID>
節點維護與可用性
你可以手動控制節點的調度狀態:
active:正常狀態,可以接受新任務。pause:暫停狀態,現有任務繼續執行,但不接受新任務。drain:排空狀態,現有任務會被遷移到其他節點,並不接受新任務(常用於系統維護)。
# 將節點改為維護模式
docker node update --availability drain <NODE_ID>
# 恢復節點
docker node update --availability active <NODE_ID>
離開叢集 (Leave)
當節點不再需要參與叢集時:
# 在 Worker 節點執行
docker swarm leave
# 在 Manager 節點執行 (若要強制解散或離開)
docker swarm leave --force
部署與管理 Service
在 Swarm 中,我們使用 docker service 系列指令來管理個別服務。
建立服務
# 建立一個名為 web-service 的服務,啟動 3 個副本,對外開放 80 port
docker service create --name web-service --replicas 3 -p 80:80 nginx:latest
服務模式:Replicated vs Global
- Replicated (預設):根據指定的副本數在各節點分佈。
- Global:在叢集中的「每一個」合格節點上都運行一個容器(常用於監控或日誌收集工具)。
# 建立一個 global 模式的服務
docker service create --name monitor --mode global prometheus-exporter
服務維護指令
當服務上線後,你經常需要進行動態調整:
# 水平擴展 (Scaling)
docker service scale web-service=5
# 更新服務 (例如更換映像檔版本)
docker service update --image nginx:1.25 web-service
# 查看服務日誌
docker service logs -f web-service
# 刪除服務
docker service rm web-service
Swarm 網路與路由 (Routing Mesh)
Swarm 使用 Overlay Network 來實現跨主機的容器通訊。
Overlay 網路
建立一個可以跨越多台伺服器的網路:
docker network create --driver overlay my-net
將服務加入此網路後,容器間可以透過 Service Name 互相訪問,Swarm 會自動處理 VIP (Virtual IP) 的解析與負載均衡。
Ingress Routing Mesh
這是 Swarm 最神奇的功能:你只要訪問叢集中任何一個節點的對外埠號(例如 80),流量都會被自動導向後端真正有運行該容器的節點。這意味著你不需要手動維護容器與 IP 的對應關係。
安全管理:Secrets 與 Configs
在生產環境中,你不應該把密碼或配置寫死在映像檔或環境變數中。
Docker Secrets
用於存取機密資訊(如資料庫密碼、SSL 證書)。Secret 會加密儲存在 Manager 節點中,並僅在任務啟動時掛載給特定的容器。
如何使用 Secrets?
- 掛載路徑:Secrets 預設會被掛載到容器內的
/run/secrets/<secret_name>檔案中(這是一個內存文件系統,不會寫入硬碟)。 - 存取內容:應用程式可以直接讀取該檔案來取得密碼。
- 環境變數模式:許多官方映像檔(如 MySQL、Postgres)支援
_FILE結尾的環境變數,讓你指定 Secret 檔案的路徑。
# 建立一個名為 db_password 的 secret
echo "my_secure_password" | docker secret create db_password -
# 在服務中使用該 secret,並告知 MySQL 從該路徑讀取密碼
docker service create \
--name db \
--secret db_password \
-e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_password \
mysql
Docker Configs
類似於 Secrets,但用於非加密的設定檔(如 nginx.conf 或 prometheus.yml),讓你可以動態更新配置而無需重新建置映像檔。
如何使用 Configs?
- 掛載路徑:預設也是掛載到容器根目錄下的某處,但通常我們會自訂掛載位置。
- 動態更新:當你更新 Config 時,Swarm 會重新啟動關聯的 Service 以套用新設定。
# 1. 建立一個 config (從本地 nginx.conf 檔案)
docker config create my_nginx_config ./nginx.conf
# 2. 建立服務,並將 config 掛載到 Nginx 預設讀取的地方
docker service create \
--name web \
--config source=my_nginx_config,target=/etc/nginx/nginx.conf \
-p 80:80 \
nginx
如何達成 Zero Downtime (零停機) 更新
在生產環境中,更新服務時不希望造成斷線。Docker Swarm 具備強大的滾動更新 (Rolling Update) 機制,其核心在於 update_config 的設定。
滾動更新的關鍵參數
要達成零停機更新,你必須在 deploy 段落配置以下參數:
parallelism:每次同時更新的容器數量。建議設為 1 或較小比例,確保其他容器能繼續服務。order(關鍵):stop-first(預設):先停掉舊容器,再啟動新容器。這會導致短暫的停機。start-first:先啟動新容器,等到新容器健康後,才停掉舊容器。這是達成 Zero Downtime 的關鍵。
delay:每組容器更新之間的等待時間,讓新容器有時間暖機。monitor:新容器啟動後,Swarm 會監控一段時間,確保容器沒有立即閃退。
Health Checks 的重要性
Swarm 判斷容器是否「準備好」進入 Service 負載均衡器,是依據 Health Check (健康檢查)。
如果你的應用程式啟動很慢(例如 Java 或大型框架),但你沒有設定 Health Check,Swarm 可能在應用程式還沒真正啟動完成前就以為它好了,並把流量導過去,這就會造成錯誤。
Dockerfile 或 docker-compose.yaml 中定義 healthcheck,Swarm 才能精準控制更新節奏。大規模部署:Docker Stack
當應用程式包含多個服務時(例如:Frontend + API + DB),我們會使用 docker-compose.yaml 並透過 Docker Stack 進行一次性部署。
範例:docker-compose.yaml
在 Swarm 模式下,Compose 檔案支援 deploy 段落來定義叢集行為:
version: '3.8'
services:
webapp:
image: my-app:v1
networks:
- app-net
deploy:
replicas: 5
update_config:
parallelism: 1
delay: 10s
order: start-first # 先啟動新容器再停止舊容器
monitor: 20s # 監控新容器健康狀況 20 秒
restart_policy:
condition: on-failure
placement:
constraints:
- 'node.role == worker'
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:8080/health']
interval: 30s
timeout: 10s
retries: 3
ports:
- '80:8080'
networks:
app-net:
driver: overlay
管理指令
- 部署或更新 Stack:
docker stack deploy -c docker-compose.yaml my-stack - 查看所有 Stacks:
docker stack ls - 查看 Stack 中的服務:
docker stack services my-stack - 查看 Stack 的任務詳情:
docker stack ps my-stack - 移除整個 Stack:
docker stack rm my-stack
Swarm vs. Kubernetes (K8s)
| 特性 | Docker Swarm | Kubernetes (K8s) |
|---|---|---|
| 安裝與學習 | 極低,與 Docker 完全一致 | 高,有大量的專有名詞與組件 |
| 功能性 | 基本編排功能紮實,適合 90% 場景 | 極其強大,適合極大規模微服務 |
| 生態系統 | 較小 | 巨大 (CNCF 生態圈) |
| 跨雲支援 | 需手動管理各雲端節點 | 各大雲端皆有 Managed Service (EKS, GKE, AKS) |
總結
Docker Swarm 是進入容器編排世界的最佳起點。它對於中小型企業或需要快速部署的場景來說,提供了極高的投資報酬率。如果你已經熟悉 Docker Compose,轉移到 Docker Swarm 只需幾分鐘的時間,卻能讓你的系統具備真正的運維彈性。