Docker Swarm 作為容器協調工具,其排程策略決定了容器在叢集節點上的分配方式。預設的 spread strategy 力求負載平衡,將容器均勻分佈於各節點。新增節點時,Swarm 不會重新排程已執行容器,僅將新容器分配到新節點。資源限制設定,例如 CPU 和記憶體,會影響 Swarm 的排程決策,資源不足可能導致容器處於 Pending 狀態。透過 --constraint 引數,可以根據節點屬性(如角色、主機名、標籤)設定約束條件,精確控制服務佈署位置。多重約束條件需同時滿足,才能將容器排程到目標節點。更新服務組態後,Swarm 會根據新設定重新排程容器。藉由調整約束條件,可以將服務遷移到特定節點,例如將服務從工作節點遷移到管理節點。

Docker Swarm 排程策略詳解

Docker Swarm 是一種容器協調工具,能夠自動化管理多個 Docker 容器。在 Swarm 中,排程策略(Scheduling Strategy)扮演著至關重要的角色,決定了容器如何在叢集中的不同節點上分配。

均勻排程策略(Spread Scheduling Strategy)

均勻排程策略是 Docker Swarm 的預設排程策略。這種策略會盡量將容器均勻地分配到叢集中的各個節點上,以實作負載平衡。例如,當建立一個具有 6 個副本的 MySQL 服務時,Swarm 會將這 6 個副本分配到不同的節點上。

例項分析

假設有一個包含 2 個節點的 Swarm 叢集:1 個管理節點和 1 個工作節點。當建立一個具有 6 個副本的 MySQL 服務時,Swarm 會將 3 個副本分配到管理節點,將另外 3 個副本分配到工作節點。

~ $ docker service ps -f desired-state=running mysql
ID             NAME          IMAGE          NODE                         DESIRED STATE  CURRENT STATE           ERROR  PORTS
p14bbk7ij1mt   mysql.1       mysql:latest   ip-172-31-29-67.ec2.internal  Running        Running 6 minutes ago         
w0521ik1awjf   mysql.2       mysql:latest   ip-172-31-29-67.ec2.internal  Running        Running 8 minutes ago         
uatsaay7axlc   mysql.3       mysql:latest   ip-172-31-25-121.ec2.internal Running        Running 2 minutes ago         
w1tlw0fom42q   mysql.4       mysql:latest   ip-172-31-29-67.ec2.internal  Running        Running 2 minutes ago         
s09ts9s8np3d   mysql.5       mysql:latest   ip-172-31-25-121.ec2.internal Running        Running 6 minutes ago         
utjo8lwbtzf7   mysql.6       mysql:latest   ip-172-31-25-121.ec2.internal Running        Running 8 minutes ago

新增節點對排程的影響

當向 Swarm 叢集新增節點時,均勻排程策略不會重新排程已經執行的容器。這意味著已經執行的容器將繼續在原來的節點上執行,而新的容器將根據新的節點組態進行排程。

程式碼解析

~ $ docker service ps mysql
ID             NAME          IMAGE          NODE                         DESIRED STATE  CURRENT STATE           ERROR  PORTS
p14bbk7ij1mt   mysql.1       mysql:latest   ip-172-31-29-67.ec2.internal  Running        Running 15 minutes ago        
w0521ik1awjf   mysql.2       mysql:latest   ip-172-31-29-67.ec2.internal  Running        Running 17 minutes ago        
uatsaay7axlc   mysql.3       mysql:latest   ip-172-31-25-121.ec2.internal Running        Running 12 minutes ago        
z9wn2nrzfzt8   \_ mysql.3    mysql:latest   0waa5g3b6j641xtwsygvjvwc1     Shutdown       Running 13 minutes ago        
w1tlw0fom42q   mysql.4       mysql:latest   ip-172-31-29-67.ec2.internal  Running        Running 12 minutes ago        
qc75buhzzct3   \_ mysql.4    mysql:latest   0waa5g3b6j641xtwsygvjvwc1     Shutdown       Running 13 minutes ago        
s09ts9s8np3d   mysql.5       mysql:latest   ip-172-31-25-121.ec2.internal Running        Running 15 minutes ago        
utjo8lwbtzf7   mysql.6       mysql:latest   ip-172-31-25-121.ec2.internal Running        Running 17 minutes ago

#### 內容解密:

上述輸出結果顯示了在新增節點後,容器的排程情況。可以看到,原來的容器仍然在原來的節點上執行,而新增的節點尚未被利用。這是因為均勻排程策略不會重新排程已經執行的容器。

資源限制對排程的影響

Swarm 的排程策略還受到節點資源容量的限制。如果服務所需的資源超過了可用資源,Swarm 將無法排程該服務。

#### 程式碼解析與例項

~ $ docker service create \
> --env MYSQL_ROOT_PASSWORD='mysql' \
> --replicas 1 \
> --name mysql \
> --reserve-cpu 1 --limit-cpu 2 --reserve-memory 256mb --limit-memory 512mb mysql
0qe2thy0dlviroli6k8thist1

#### 內容解密:

這段程式碼建立了一個名為 mysql 的服務,並指定了資源請求和限制。 --reserve-cpu--reserve-memory 用於指定服務所需的最低資源,而 --limit-cpu--limit-memory 用於指定服務可使用的最大資源。

當擴充套件服務到多個副本時,如果節點資源不足,Swarm 將無法排程所有副本。

~ $ docker service scale mysql=5
mysql scaled to 5

#### 程式碼解析

~ $ docker service ps mysql
ID             NAME          IMAGE          NODE                         DESIRED STATE  CURRENT STATE           ERROR  PORTS
opxf4ne7iyy6   mysql.1       mysql:latest   ip-172-31-25-121.ec2.internal Running        Running 4 minutes ago         
x30y3jlea047   mysql.2       mysql:latest   ip-172-31-29-67.ec2.internal  Running        Running 3 minutes ago         
w4ivsbvwqqzq   mysql.3       mysql:latest                            Running        Pending 3 minutes ago         
d3oxy6hxfjh3   mysql.4       mysql:latest                            Running        Pending 3 minutes ago         
ic331aasjpdm   mysql.5       mysql:latest   ip-172-31-44-104.ec2.internal Running        Running 3 minutes ago

#### 內容解密:

輸出結果顯示,部分副本處於 Pending 狀態,表示 Swarm 無法為它們排程合適的節點。這是因為叢集中可用的資源不足以滿足所有副本的需求。

新增工作節點以滿足資源需求

為瞭解決資源不足的問題,可以向 Swarm 叢集新增工作節點。這樣,Swarm 就能夠將 Pending 狀態的副本排程到新的節點上。

~ $ docker service ps mysql
ID             NAME          IMAGE          NODE                         DESIRED STATE  CURRENT STATE           ERROR  PORTS
opxf4ne7iyy6   mysql.1       mysql:latest   ip-172-31-25-121.ec2.internal Running        Running 5 minutes ago         
x30y3jlea047   mysql.2       mysql:latest   ip-172-31-29-67.ec2.internal  Running        Running 4 minutes ago         
w4ivsbvwqqzq   mysql.3       mysql:latest   ip-172-31-2-177.ec2.internal  Running        Running 21 seconds ago       
d3oxy6hxfjh3   mysql.4       mysql:latest   ip-172-31-40-70.ec2.internal  Running        Preparing 30 seconds ago       
ic331aasjpdm   mysql.5       mysql:latest   ip-172-31-44-104.ec2.internal Running        Running 4 minutes ago

#### 圖表說明:此圖示表示在新增工作節點後,Swarm 將 Pending 狀態的副本排程到新的節點上,從而滿足了服務所需的資源。

Docker Swarm 服務排程管理

Docker Swarm 提供了強大的服務排程功能,能夠根據資源使用情況和節點屬性進行靈活的任務分配。本章將探討 Docker Swarm 中的服務排程機制,包括資源管理、排程限制以及如何對服務進行更新和擴充套件。

資源管理與排程

在 Docker Swarm 中,服務的資源使用是由 --reserve-cpu--limit-cpu--reserve-memory--limit-memory 等引數控制的。這些引數確保服務任務不會超出指定的資源限制。例如,當我們建立一個 MySQL 服務時,可以指定其資源限制:

docker service create \
  --env MYSQL_ROOT_PASSWORD='mysql' \
  --replicas 3 \
  --name mysql \
  --reserve-cpu 0.1 \
  --limit-cpu 0.5 \
  --reserve-memory 64mb \
  --limit-memory 128mb \
  mysql

內容解密:

  • --reserve-cpu 0.1:為每個 MySQL 任務保留 0.1 個 CPU 核心。
  • --limit-cpu 0.5:限制每個 MySQL 任務最多使用 0.5 個 CPU 核心。
  • --reserve-memory 64mb:為每個 MySQL 任務保留 64MB 的記憶體。
  • --limit-memory 128mb:限制每個 MySQL 任務最多使用 128MB 的記憶體。

當服務的資源需求超過節點的可用資源時,任務可能會處於 Pending 狀態。更新服務的資源限制只會對新建立的任務生效,已執行的任務不會受到影響。要使已執行的任務使用新的資源設定,需要先將服務縮小到一個任務,然後再擴充套件回所需的副本數量。

docker service scale mysql=1
docker service scale mysql=5

內容解密:

  • 先將 MySQL 服務縮小到 1 個副本,停止多餘的任務。
  • 再將 MySQL 服務擴充套件回 5 個副本,使新的資源設定生效。

新增服務排程限制

Docker Swarm 支援透過排程限制(Scheduling Constraints)來控制服務任務的放置。這些限制可以根據節點屬性、後設資料和引擎後設資料進行設定。建立或更新服務時,可以使用 --constraint 選項來新增排程限制。

例如,若要將 MySQL 服務的任務僅在工作節點(worker nodes)上執行,可以使用以下命令:

docker service create \
  --env MYSQL_ROOT_PASSWORD='mysql' \
  --replicas 3 \
  --constraint node.role==worker \
  --name mysql \
  mysql

內容解密:

  • --constraint node.role==worker:指定 MySQL 服務的任務只能在工作節點上執行。
  • node.role==worker:這是一個節點屬性,用於區分工作節點和管理節點。

節點屬性與排程限制

Docker Swarm 中的節點屬性可以用於定義排程限制,常見的節點屬性包括 node.idnode.hostnamenode.rolenode.labels 等。這些屬性可以幫助管理員更精細地控制服務任務的分配。

節點屬性描述示例
node.id指定節點 IDnode.id==a3r56hj7y
node.hostname指定節點的主機名node.hostname!=ip-10-0-0-ec2.internal
node.role指定節點角色(worker 或 manager)node.role==manager
node.labels指定使用者新增的節點標籤node.labels.db==mysql

Docker Swarm 服務排程深入解析

Docker Swarm 提供了一個強大的容器協調工具,而服務排程是其中一個核心功能。本章將探討 Docker Swarm 的服務排程機制,包括如何使用不同的約束條件來控制服務的佈署。

基礎排程操作

首先,我們來看看如何建立一個服務並在特定的節點上排程任務。Docker Swarm 允許我們使用 --constraint 引數來指定節點的屬性,從而控制服務的佈署位置。

在工作節點上排程服務

以下命令展示瞭如何在兩個工作節點上排程一個 MySQL 服務的三個副本:

docker service create \
--env MYSQL_ROOT_PASSWORD='mysql' \
--replicas 3 \
--name mysql \
mysql

執行 docker service ps 命令後,我們可以看到這三個副本被排程到了兩個工作節點上:

~ $ docker service ps -f desired-state=running mysql
ID        NAME      IMAGE           NODE                            DESIRED STATE  CURRENT STATE           ERROR  PORTS
f5t15mnrft0h  mysql.1  mysql:latest  ip-172-31-29-67.ec2.internal  Running        Running 19 seconds ago         
oxvq4ljuq6yz  mysql.2  mysql:latest  ip-172-31-2-177.ec2.internal  Running        Running 19 seconds ago         
k5jo862lvsxf  mysql.3  mysql:latest  ip-172-31-2-177.ec2.internal  Running        Running 19 seconds ago

在管理節點上排程服務

我們也可以透過指定 --constraint node.id 引數將服務的副本排程到特定的管理節點上:

docker service create \
--env MYSQL_ROOT_PASSWORD='mysql' \
--replicas 3 \
--constraint node.id==<nodeid> \
--name mysql \
mysql

執行後,所有三個副本都會被排程到指定的管理節點上:

~ $ docker service ps -f desired-state=running mysql
ID        NAME      IMAGE           NODE                            DESIRED STATE  CURRENT STATE           ERROR  PORTS
lbttu95qdjvy  mysql.1  mysql:latest  ip-172-31-25-121.ec2.internal  Running        Running 21 seconds ago         
89x0z94on0fb  mysql.2  mysql:latest  ip-172-31-25-121.ec2.internal  Running        Running 21 seconds ago         
3s6508aimdaj  mysql.3  mysql:latest  ip-172-31-25-121.ec2.internal  Running        Running 22 seconds ago

多重排程約束

Docker Swarm 也支援多重排程約束。當使用多個約束條件時,所有的條件都必須被滿足,服務的副本才會被排程到相應的節點上。

例如,我們可以建立一個服務,要求它只在工作節點上執行,並且排除特定的主機名:

docker service create \
--env MYSQL_ROOT_PASSWORD='mysql' \
--replicas 3 \
--constraint node.role==worker \
--constraint node.hostname!=ip-172-31-2-177.ec2.internal \
--name mysql \
mysql

執行後,所有三個副本都會被排程到符合條件的工作節點上:

~ $ docker service ps mysql
ID        NAME      IMAGE           NODE                            DESIRED STATE  CURRENT STATE           ERROR  PORTS
jlfk79mb6m6a  mysql.1  mysql:latest  ip-172-31-29-67.ec2.internal  Running        Running 13 seconds ago         
if5y39ky884q  mysql.2  mysql:latest  ip-172-31-29-67.ec2.internal  Running        Running 13 seconds ago         
zctm6mzbl4du  mysql.3  mysql:latest  ip-172-31-29-67.ec2.internal  Running        Running 13 seconds ago

更新服務以移除約束

如果我們更新服務以移除先前設定的約束條件,Docker Swarm 將根據新的條件重新排程服務的副本:

docker service update \
--constraint-rm node.role==worker \
--constraint-rm node.hostname!=ip-172-31-2-177.ec2.internal \
mysql

更新後,服務的副本將被重新排程到 Swarm 中的所有節點上:

~ $ docker service ps -f desired-state=running mysql
ID        NAME      IMAGE           NODE                            DESIRED STATE  CURRENT STATE           ERROR  PORTS
d22bkgteivot  mysql.1  mysql:latest  ip-172-31-29-67.ec2.internal  Running        Running 46 seconds ago         
mp757499j3io  mysql.2  mysql:latest  ip-172-31-2-177.ec2.internal   Running        Running 49 seconds ago         
jtdxucteb0fl  mysql.3  mysql:latest  ip-172-31-25-121.ec2.internal  Running        Running 53 seconds ago

在管理節點上執行服務

我們可以透過提升工作節點為管理節點,並使用多重約束條件,將服務的副本排程到特定的管理節點上:

docker node promote ip-172-31-2-177.ec2.internal
docker service update \
--constraint-add node.role==manager \
--constraint-add node.hostname==ip-172-31-2-177.ec2.internal \
mysql

詳細解說

  1. 提升工作節點為管理節點:使用 docker node promote 命令將指定的工作節點提升為管理節點。

    docker node promote ip-172-31-2-177.ec2.internal
    

    詳細解說:

    • docker node promote:用於將工作節點提升為管理節點的命令。
    • ip-172-31-2-177.ec2.internal:需要被提升的工作節點的主機名。
  2. 更新服務以新增約束:使用 docker service update 命令並配合 --constraint-add,將服務的副本限制在特定的管理節點上。

    docker service update \
    --constraint-add node.role==manager \
    --constraint-add node.hostname==ip-172-31-2-177.ec2.internal \
    mysql
    

    詳細解說:

    • docker service update:用於更新現有服務組態的命令。
    • --constraint-add node.role==manager:新增約束條件,要求服務的副本只能在管理節點上執行。
    • --constraint-add node.hostname==ip-172-31-2-177.ec2.internal:進一步限制服務的副本只能在主機名為 ip-172-31-2-177.ec2.internal 的管理節點上執行。

透過這些步驟,我們可以靈活地控制 Docker Swarm 中服務的佈署和排程,以滿足不同的需求和場景。

Plantuml 圖表說明

以下 Plantuml 圖表展示了 Docker Swarm 中服務排程的基本流程:

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Docker Swarm 服務排程策略詳解

package "Docker 架構" {
    actor "開發者" as dev

    package "Docker Engine" {
        component [Docker Daemon] as daemon
        component [Docker CLI] as cli
        component [REST API] as api
    }

    package "容器運行時" {
        component [containerd] as containerd
        component [runc] as runc
    }

    package "儲存" {
        database [Images] as images
        database [Volumes] as volumes
        database [Networks] as networks
    }

    cloud "Registry" as registry
}

dev --> cli : 命令操作
cli --> api : API 呼叫
api --> daemon : 處理請求
daemon --> containerd : 容器管理
containerd --> runc : 執行容器
daemon --> images : 映像檔管理
daemon --> registry : 拉取/推送
daemon --> volumes : 資料持久化
daemon --> networks : 網路配置

@enduml

此圖示展示了從建立服務到最終排程副本的整個流程。

圖表解說

  1. 建立服務:定義服務的基本屬性,如映像檔和環境變數。
  2. 定義副本數量:指定需要執行的副本數量。
  3. 設定節點約束:根據需求設定節點的屬性約束,如角色或主機名。
  4. 排程服務副本:根據設定的約束條件,將副本排程到符合要求的節點上。
  5. 檢查副本狀態:監控副本的執行狀態,確保它們正常運作。
  6. 符合條件:如果副本成功執行且符合預期,則保持執行狀態。
  7. 不符合條件:如果副本未能正常執行或不符合預期,則進行重新排程。

透過這個流程圖,我們可以清晰地瞭解 Docker Swarm 中服務排程的工作原理和步驟。