返回文章列表

Docker Swarm 叢集管理與擴充套件實務

本文探討 Docker Swarm 的叢集管理與擴充套件實務,包含叢集狀態檢視、服務擴充套件與容器分配、節點維護與容器遷移、服務縮放、管理節點高用性組態、多主機網路設定、滾動更新策略以及效能調校技巧,涵蓋了實際操作中常見的指令與組態說明,並以 `gotwitter` 應用程式為例,演示如何在 Docker Swarm

容器技術 DevOps

Docker Swarm 作為 Docker 官方提供的容器協調工具,簡化了多容器應用程式的佈署和管理。理解 Swarm 的核心概念,如節點狀態、服務副本、容器分配等,是有效運用 Swarm 的基礎。透過 docker node lsdocker service ps 等指令,可以即時監控叢集和服務的執行狀態。節點維護過程中,使用 drain 模式可以確保服務不中斷,並示範如何使用覆寫網路讓不同主機上的容器互相溝通,以及如何調整系統引數來最佳化網路效能。

Docker Swarm 叢集管理與擴充套件實務

Docker Swarm 是 Docker 官方提供的容器協調工具,用於管理和擴充套件多個 Docker 容器。在本章節中,我們將探討 Docker Swarm 的叢集管理與擴充套件功能。

叢集狀態檢視

首先,我們需要檢視 Docker Swarm 叢集的狀態。使用 docker node ls 命令可以列出叢集中的所有節點。

root@swarm2:~# docker node ls
ID            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS
4i0lko1qdwqp4x1aqwn6o7obh   swarm1     Ready     Active         Unreachable
9gyk5t22ngndbwtjof80hpg54 * swarm2     Ready     Active         Leader
b9dyyc08ehtnl62z7e3ll0ih3   swarm3     Ready     Active         Reachable

內容解密:

  • docker node ls:列出叢集中的所有節點。
  • ID:節點的唯一識別碼。
  • HOSTNAME:節點的主機名稱。
  • STATUS:節點的狀態(Ready 表示正常)。
  • AVAILABILITY:節點的可用性(Active 表示可用)。
  • MANAGER STATUS:節點的管理者狀態(Leader 表示主管理節點)。

服務擴充套件與容器分配

當我們建立一個服務並擴充套件其副本數量時,Docker Swarm 會自動在叢集中的各個節點上分配容器。

root@swarm2:~# docker service ps helloworld
ID            NAME          IMAGE   NODE      DESIRED STATE   CURRENT STATE
bb8nwud2h75xpvkxouwt8rftm   helloworld.1   alpine   swarm2    Running         Running 26 secs
2hb76h8m7oop9pit4jgok2jiu    \_ helloworld.1   alpine   swarm1    Shutdown        Running 2 min
5lxefcjclasna9as4oezn34i8   helloworld.2   alpine   swarm3    Running         Running 2 min

內容解密:

  • docker service ps helloworld:列出 helloworld 服務的所有容器。
  • ID:容器的唯一識別碼。
  • NAME:容器的名稱。
  • IMAGE:容器使用的映像檔。
  • NODE:容器執行的節點。
  • DESIRED STATE:容器的期望狀態。
  • CURRENT STATE:容器的當前狀態。

節點維護與容器遷移

當需要維護某個節點時,可以將其可用性設定為 drain,這樣 Docker Swarm 就會將該節點上的容器遷移到其他節點。

root@swarm2:~# docker node update --availability drain swarm3
swarm3
root@swarm2:~# docker service ps helloworld | grep swarm3
5lxefcjclasna9as4oezn34i8 \_ helloworld.2   alpine   swarm3    Shutdown        Shutdown 19 secs

內容解密:

  • docker node update --availability drain swarm3:將 swarm3 節點的可用性設定為 drain
  • docker service ps helloworld | grep swarm3:檢視 helloworld 服務在 swarm3 節點上的容器狀態。

服務擴充套件與縮減

Docker Swarm 允許我們輕鬆地擴充套件或縮減服務的副本數量。

root@swarm2:~# docker service scale helloworld=20
helloworld scaled to 20
root@swarm2:~# docker service ls
ID            NAME          REPLICAS   IMAGE   COMMAND
5gmrllue1sgd   helloworld    20/20     alpine   ping google.com

內容解密:

  • docker service scale helloworld=20:將 helloworld 服務的副本數量擴充套件到 20。
  • docker service ls:列出所有服務的狀態。

管理者節點的高用性

為了確保 Docker Swarm 叢集的高用性,建議使用奇數個管理者節點。

內容解密:

  • 使用奇數個管理者節點可以確保在部分節點故障時,叢集仍能正常運作。
  • N 個管理者節點可以容忍 (N-1)/2 個節點故障。

綜上所述,Docker Swarm 提供了一套強大的容器協調工具,能夠幫助我們輕鬆地管理和擴充套件多個 Docker 容器。透過合理地組態和管理叢集,我們可以確保服務的高用性和可擴充套件性。

使用 Docker Swarm 擴充套件服務

現在我們已經設定好了 Docker Swarm,接下來將使用它來協調佈署和滾動升級我們的服務。要佈署的應用程式映像應該在所有 Swarm 節點上都可用,可以透過自定義的登入檔或 Docker Hub 取得。在本章中,我們已將 gotwitter 映像推播到 Docker Hub,因此該映像可作為 titpetric/gotwitter 使用。

磁碟空間

根據 titpetric/gotwitter 在 Docker Hub 上的頁面,該映像在寫作時的壓縮大小約為 5MB。需要注意的是,這是壓縮後的尺寸,實際大小將透過命令 docker images | grep gotwitter 報告:

# docker images | grep gotwitter
titpetric/gotwitter latest 65d327973482 8 secs ago 12MB

為什麼磁碟大小很重要?正如您現在所瞭解的,映像的大小從幾MB 到幾GB 不等。如果您想在硬體上擴充套件服務,您需要提前規劃,並提供必要的磁碟空間以相應地擴充套件服務。我們建立的 Swarm 節點組態了 160GB 的磁碟空間。為了簡化計算,我們計劃使用大約 120GB 用於容器——以我們的應用程式容器為例,這將使我們能夠在一個節點上執行大約 10,000 個容器。如果容器大小約為 1GB,我們只能執行大約 120 個。當然,在我們的例子中,磁碟並不是限制因素,但 RAM 使用率可能會成為瓶頸。

RAM 使用率

我們為每個 Swarm 管理節點組態了 8GB 的 RAM。檢查 gotwitter 應用程式,我們可以看到它使用的記憶體小於 10MB。這個數字在應用程式執行一段時間後可能會更高,因此在組態容器時請記住這一點。

# docker stats gotwitter
CONTAINER           MEM USAGE / LIMIT       MEM %               NET I/O             BLOCK I/O
gotwitter           8.559 MiB / 1.886 GiB   0.44%               648 B / 648 B       8.262 MB / 0 B

內容解密:

這段程式碼展示瞭如何使用 docker stats 命令來監控容器的資源使用情況,包括記憶體使用率。在這個例子中,gotwitter 容器使用了大約 8.559 MiB 的記憶體,佔總記憶體限制(1.886 GiB)的 0.44%。這表明該容器的記憶體使用率相對較低。

建立多主機網路

此時,值得一提的是,我們在書的開頭建立的橋接網路僅限於單個主機。為了使容器在 Docker Swarm 中的不同主機之間可被發現,我們需要在其中一個管理節點(在我們的例子中,所有節點都是管理節點,因為我們沒有工作節點)上建立一個覆寫網路。

# docker network create \
--driver overlay \
--subnet 10.0.0.0/20 \
--attachable \
party-swarm

內容解密:

這段程式碼用於建立一個名為 party-swarm 的覆寫網路,使用 --driver overlay 指定網路驅動為覆寫網路,並透過 --subnet 指定了子網範圍為 10.0.0.0/20--attachable 選項允許非受管理的容器(即透過 docker run 命令啟動的容器)連線到該網路。

服務佈署與測試

我們可以透過建立一個 Redis 服務來測試 party-swarm 網路的功能。

root@swarm1:~# docker service create --replicas 1 --network party-swarm --name redis -p 6379:6379 redis:3.2-alpine

內容解密:

這段程式碼建立了一個名為 redis 的服務,使用 redis:3.2-alpine 映象,並將其連線到 party-swarm 網路。同時,它將容器的 6379 埠對映到主機的 6379 埠。

檢查 Redis 容器的網路組態:

root@swarm1:~# docker exec -it redis.1.kcd5v3xxiwro830tn8oab6a4d ifconfig eth2 | grep "inet addr"
inet addr:10.0.0.3 Bcast:0.0.0.0 Mask:255.255.255.0

內容解密:

這段程式碼進入正在執行的 Redis 容器,並執行 ifconfig eth2 命令來檢視其網路組態。結果顯示該容器的 IP 地址為 10.0.0.3

在不同的主機上建立一個新的容器,並測試與 Redis 服務的連線:

root@swarm3:~# docker run --rm --net=party-swarm alpine ifconfig eth0 | grep "inet addr"
inet addr:10.0.0.4 Bcast:0.0.0.0 Mask:255.255.240.0

root@swarm3:~# docker run -it --rm --net=party-swarm alpine sh -c "echo quit | nc redis 6379"
+OK

root@swarm3:~# docker run --rm --net=party-swarm alpine ping -c1 redis
PING redis (10.0.0.2): 56 data bytes
64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.098 ms

內容解密:

這段程式碼首先在 swarm3 主機上建立了一個新的容器,並檢查了其 IP 地址。然後,它透過 nc 命令測試了與 Redis 服務的連線,最後透過 ping 命令驗證了 Redis 服務的虛擬 IP(VIP)是否正確解析並可達。

Docker Swarm 網路架構與效能調校

Docker Swarm 是一種容器協調工具,能夠讓多個 Docker 主機協同工作,提供高用性和可擴充套件性。在 Docker Swarm 中,服務(Service)是核心概念之一。當你建立一個服務並將其附加到網路時,Swarm 會為該服務分配一個虛擬 IP(VIP)。這個 VIP 對應於根據服務名稱的 DNS 別名。網路上的容器透過 gossip 協定分享服務的 DNS 對映,因此網路上的任何容器都可以使用服務名稱存取該服務。

Docker Swarm 網路架構

在 Docker Swarm 中,每個服務都有一個 VIP,它負責將流量路由到該服務的個別容器。例如,如果你建立了一個名為 redis 的服務,Swarm 會為其分配一個 VIP,如 10.0.0.2。你可以使用 docker service inspect 命令檢視該服務的 VIP。

root@swarm3:~# docker service inspect --format='{{json .Endpoint.VirtualIPs}}' redis
[{"NetworkID":"kc8yy8tc62qrmq4xhqu4g74yl","Addr":"10.255.0.5/16"},{"NetworkID":"q3l72085za9s20fwxfix83i7k","Addr":"10.0.0.2/20"}]

在這個例子中,redis 服務有兩個網路介面卡,分別對應於兩個不同的網路。因為你使用了 -p 6379:6379 引數,Docker 也將容器新增到「ingress」網路中,這使得你可以從主機轉發流量到個別服務的 VIP。

網路架構圖示

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 網路架構圖示

rectangle "0.0.1" as n1
rectangle "0.0.2" as n2
rectangle "0.0.3" as n3
rectangle "0.0.4" as n4

n1 --> n2
n2 --> n3
n3 --> n4

@enduml

此圖示展示了 Docker 主機、VIP 和容器之間的關係。

系統調校以支援大量容器

當你在單一主機上執行大量容器(例如 1000 個)時,你可能會遇到一些限制。為了提高系統的承載能力,你需要調整一些系統引數。

ARP 快取調校

在執行大量容器時,你可能會遇到 ARP 快取溢位的問題,導致 neighbour table overflow! 錯誤。為瞭解決這個問題,你需要增加 ARP 快取的閾值。

sysctl -w net.ipv4.neigh.default.gc_thresh1=8096
sysctl -w net.ipv4.neigh.default.gc_thresh2=8096
sysctl -w net.ipv4.neigh.default.gc_thresh3=8096

其他系統調校引數

除了 ARP 快取調校之外,你還可以調整其他系統引數來提高系統的效能。

# 提高連線埠範圍
net.ipv4.ip_local_port_range=1024 65000

# 重用關閉的 socket
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_fin_timeout=15

# 增加 backlog socket 的數量
net.core.somaxconn=4096
net.core.netdev_max_backlog=4096

# 調整 TCP 連線引數
net.ipv4.tcp_max_syn_backlog=20480
net.ipv4.tcp_max_tw_buckets=400000
net.ipv4.tcp_no_metrics_save=1

內容解密:

  1. net.ipv4.ip_local_port_range=1024 65000:這個引數定義了可用於連線的本地埠範圍。預設情況下,這個範圍可能太小,無法支援大量連線。
  2. net.ipv4.tcp_tw_reuse=1net.ipv4.tcp_fin_timeout=15:這些引數控制著 socket 的重用和關閉逾時。它們可以幫助更快地回收關閉的 socket。
  3. net.core.somaxconn=4096net.core.netdev_max_backlog=4096:這些引數控制著 backlog socket 的數量。它們可以幫助提高系統處理連線請求的能力。
  4. net.ipv4.tcp_max_syn_backlog=20480net.ipv4.tcp_max_tw_buckets=400000:這些引數控制著 TCP 連線的處理。它們可以幫助提高系統處理連線請求的能力。

Docker Swarm 滾動更新與擴充套件服務

Docker Swarm 提供了一個強大的容器協調工具,讓開發者能夠輕鬆地管理和擴充套件容器化的應用程式。在本章中,我們將探討如何使用 Docker Swarm 進行滾動更新和擴充套件服務。

建立服務與滾動更新

首先,我們建立一個名為 gotwitter 的服務,並指定 --replicas 10 以啟動 10 個副本。同時,我們使用 --update-parallelism 5 引數來控制滾動更新的平行度。

docker service create -e PORT=80 \
--replicas 10 \
--network party-swarm \
--update-parallelism 5 \
--name gotwitter \
-p 80:80 titpetric/gotwitter

內容解密:

  • docker service create:建立一個新的服務。
  • -e PORT=80:設定環境變數 PORT80
  • --replicas 10:啟動 10 個服務副本。
  • --network party-swarm:將服務連線到 party-swarm 網路。
  • --update-parallelism 5:在滾動更新期間,同時更新 5 個副本。
  • --name gotwitter:命名服務為 gotwitter
  • -p 80:80:將主機的 80 埠對映到容器的 80 埠。
  • titpetric/gotwitter:使用的 Docker 映象名稱。

當需要進行滾動更新時,可以使用 docker service update 命令,並指定新的映象。

docker service update --image titpetric/gotwitter gotwitter

內容解密:

  • docker service update:更新現有的服務。
  • --image titpetric/gotwitter:指定新的 Docker 映象。
  • gotwitter:要更新的服務名稱。

滾動更新的過程是:

  1. Swarm 關閉指定數量的副本(由 --update-parallelism 控制)。
  2. Swarm 啟動相同數量的新副本。
  3. 等待健康檢查透過。
  4. 將流量路由到新的副本。
  5. 重複此過程,直到所有副本都更新完成。

擴充套件服務到 1000 個容器

在進行滾動更新之前,我們需要確保系統組態正確,並且關閉健康檢查以避免在擴充套件過程中造成不必要的延遲。

docker service update --no-healthcheck gotwitter

內容解密:

  • docker service update:更新現有的服務。
  • --no-healthcheck:停用健康檢查。

然後,我們可以使用 docker service scale 命令將服務擴充套件到 1000 個容器。

docker service scale gotwitter=1000

內容解密:

  • docker service scale:擴充套件或縮減服務的副本數量。
  • gotwitter=1000:將 gotwitter 服務的副本數量設定為 1000。

健康檢查的注意事項

在大規模佈署中,健康檢查可能會引入額外的延遲。建議增加健康檢查的間隔時間,以避免過多的資源佔用。