docker service create
說明 | 建立新的服務 |
---|---|
用法 | docker service create [選項] IMAGE [指令] [參數...] |
Swarm 此指令適用於 Swarm 編排器。
說明
根據指定的參數建立服務。
**注意**
這是一個叢集管理指令,必須在 Swarm 管理節點上執行。要瞭解管理節點和工作節點,請參閱文件中Swarm 模式章節。
選項
選項 | 預設值 | 說明 |
---|---|---|
--cap-add | API 1.41+ 新增 Linux 功能 | |
--cap-drop | API 1.41+ 捨棄 Linux 功能 | |
--config | API 1.30+ 指定要公開給服務的設定 | |
--constraint | 放置限制 | |
--container-label | 容器標籤 | |
--credential-spec | API 1.29+ 受管服務帳戶的憑證規格(僅限 Windows) | |
-d, --detach | API 1.29+ 立即退出,而不是等待服務收斂 | |
--dns | API 1.25+ 設定自訂 DNS 伺服器 | |
--dns-option | API 1.25+ 設定 DNS 選項 | |
--dns-search | API 1.25+ 設定自訂 DNS 搜尋網域 | |
--endpoint-mode | vip | 端點模式 (vip 或 dnsrr) |
--entrypoint | 覆寫映像檔的預設 ENTRYPOINT | |
-e, --env | 設定環境變數 | |
--env-file | 讀取環境變數檔案 | |
--generic-resource | 使用者定義的資源 | |
--group | API 1.25+ 為容器設定一個或多個補充使用者群組 | |
--health-cmd | API 1.25+ 用於檢查健康狀態的指令 | |
--health-interval | API 1.25+ 執行檢查的間隔時間 (毫秒|秒|分|小時) | |
--health-retries | API 1.25+ 連續失敗次數達到此值時,回報服務不健康 | |
--health-start-interval | API 1.44+ 在啟動期間執行檢查的間隔時間 (毫秒|秒|分|小時) | |
--health-start-period | API 1.29+ 容器啟動並初始化的期間,在此期間重試次數不計入不穩定狀態 (毫秒|秒|分|小時) | |
--health-timeout | API 1.25+ 允許單次檢查執行的最長時間 (毫秒|秒|分|小時) | |
--host | API 1.25+ 設定一或多個自定義主機到 IP 的映射 (主機:IP) | |
--hostname | API 1.25+ 容器主機名稱 | |
--init | API 1.37+ 在每個服務容器內使用 init 來轉發訊號和回收行程 | |
--isolation | API 1.35+ 服務容器隔離模式 | |
-l, --label | 服務標籤 | |
--limit-cpu | 限制 CPU 使用量 | |
--limit-memory | 限制記憶體使用量 | |
--limit-pids | API 1.41+ 限制最大行程數 (預設 0 = 無限制) | |
--log-driver | 服務的日誌驅動程式 | |
--log-opt | 日誌驅動程式選項 | |
--max-concurrent | API 1.41+ 同時執行的任務數 (預設值等於 --replicas) | |
--mode | replicated(副本模式) | 服務模式 (replicated , global , replicated-job , global-job ) |
--mount | 將檔案系統掛載到服務 | |
--name | 服務名稱 | |
--network | 網路連接 | |
--no-healthcheck | API 1.25+ 禁用任何容器指定的 HEALTHCHECK | |
--no-resolve-image | API 1.30+ 不要查詢 registry 以解析映像檔摘要和支援的平台 | |
--oom-score-adj | API 1.46+ 調整主機的 OOM 偏好設定 (-1000 到 1000) | |
--placement-pref | API 1.28+ 新增放置偏好設定 | |
-p, --publish | 將埠發佈為節點埠 | |
-q, --quiet | 隱藏進度輸出 | |
--read-only | API 1.28+ 將容器的根檔案系統掛載為唯讀 | |
--replicas | 任務數量 | |
--replicas-max-per-node | API 1.40+ 每個節點的最大任務數 (預設 0 = 無限制) | |
--reserve-cpu | 保留 CPU | |
--reserve-memory | 保留記憶體 | |
--restart-condition | 符合條件時重新啟動 (none , on-failure , any ) (預設 any ) | |
--restart-delay | 重新啟動嘗試之間的延遲 (奈秒|微秒|毫秒|秒|分|小時) (預設 5 秒) | |
--restart-max-attempts | 放棄前的最大重新啟動次數 | |
--restart-window | 用於評估重新啟動策略的視窗 (奈秒|微秒|毫秒|秒|分|小時) | |
--rollback-delay | API 1.28+ 任務回滾之間的延遲 (奈秒|微秒|毫秒|秒|分|小時) (預設 0 秒) | |
--rollback-failure-action | API 1.28+ 回滾失敗時的動作 (pause , continue ) (預設 pause ) | |
--rollback-max-failure-ratio | API 1.28+ 回滾期間可容忍的失敗率 (預設 0) | |
--rollback-monitor | API 1.28+ 每次任務回滾後監控失敗的持續時間 (奈秒|微秒|毫秒|秒|分|小時) (預設 5 秒) | |
--rollback-order | API 1.29+ 回滾順序 (start-first , stop-first ) (預設 stop-first ) | |
--rollback-parallelism | 1 | API 1.28+ 同時回滾的最大任務數 (0 表示一次全部回滾) |
--secret | API 1.25+ 指定要公開給服務的密鑰 | |
--stop-grace-period | 強制關閉容器前的等待時間 (奈秒|微秒|毫秒|秒|分|小時) (預設 10 秒) | |
--stop-signal | API 1.28+ 停止容器的訊號 | |
--sysctl | API 1.40+ Sysctl 選項 | |
-t, --tty | API 1.25+ 分配一個偽終端 (pseudo-TTY) | |
--ulimit | API 1.41+ Ulimit 選項 | |
--update-delay | 更新之間的延遲 (奈秒|微秒|毫秒|秒|分|小時) (預設 0 秒) | |
--update-failure-action | 更新失敗時的動作 (pause , continue , rollback ) (預設 pause ) | |
--update-max-failure-ratio | API 1.25+ 更新期間可容忍的失敗率 (預設 0) | |
--update-monitor | API 1.25+ 每次任務更新後監控失敗的持續時間 (奈秒|微秒|毫秒|秒|分|小時) (預設 5 秒) | |
--update-order | API 1.29+ 更新順序 (start-first , stop-first ) (預設 stop-first ) | |
--update-parallelism | 1 | 同時更新的最大任務數 (0 表示一次全部更新) |
-u, --user | 使用者名稱或 UID (格式: <名稱|uid>[:<群組|gid>]) | |
--with-registry-auth | 將 registry 驗證詳細資訊傳送至 swarm 代理程式 | |
-w, --workdir | 容器內的工作目錄 |
範例
建立服務
$ docker service create --name redis redis:3.0.6
dmu1ept4cxcfe8k8lhtux3ro3
$ docker service create --mode global --name redis2 redis:3.0.6
a8q9dasaafudfs8q8w32udass
$ docker service ls
ID NAME MODE REPLICAS IMAGE
dmu1ept4cxcf redis replicated 1/1 redis:3.0.6
a8q9dasaafud redis2 global 1/1 redis:3.0.6
使用私有 registry 上的映像檔建立服務 (--with-registry-auth)
如果您的映像檔位於需要登入的私有 registry 上,請在登入後,將 --with-registry-auth
旗標與 docker service create
搭配使用。如果您的映像檔儲存在私有 registry registry.example.com
上,請使用如下命令
$ docker login registry.example.com
$ docker service create \
--with-registry-auth \
--name my_service \
registry.example.com/acme/my_image:latest
這會使用加密的 WAL 日誌,將您本地客戶端的登入權杖傳遞到部署服務的 swarm 節點。有了這些資訊,節點就能夠登入 registry 並提取映像檔。
建立具有 5 個副本任務的服務 (--replicas)
使用 --replicas
旗標設定副本服務的副本任務數量。以下命令建立一個具有 5
個副本任務的 redis
服務
$ docker service create --name redis --replicas=5 redis:3.0.6
4cdgfyky7ozwh3htjfw0d12qv
上述命令設定了服務的*期望*任務數量。即使命令立即返回,服務的實際擴展可能需要一些時間。REPLICAS
欄顯示服務的實際和期望副本任務數量。
在以下範例中,期望狀態為 5
個副本,但目前 RUNNING
任務的數量為 3
個
$ docker service ls
ID NAME MODE REPLICAS IMAGE
4cdgfyky7ozw redis replicated 3/5 redis:3.0.7
一旦所有任務都建立完成且處於 RUNNING
狀態,實際任務數量將等於期望數量
$ docker service ls
ID NAME MODE REPLICAS IMAGE
4cdgfyky7ozw redis replicated 5/5 redis:3.0.7
使用密鑰建立服務 (--secret)
使用 --secret
旗標,讓容器可以存取密鑰。
建立指定密鑰的服務
$ docker service create --name redis --secret secret.json redis:3.0.6
4cdgfyky7ozwh3htjfw0d12qv
建立指定密鑰、目標、使用者/群組 ID 和模式的服務
$ docker service create --name redis \
--secret source=ssh-key,target=ssh \
--secret source=app-key,target=app,uid=1000,gid=1001,mode=0400 \
redis:3.0.6
4cdgfyky7ozwh3htjfw0d12qv
若要授予服務存取多個密鑰的權限,請使用多個 --secret
旗標。
如果未指定目標,密鑰會位於容器中的 /run/secrets
。如果未指定目標,則密鑰的名稱會用作容器中的記憶體內檔案名稱。如果指定了目標,則會使用該目標作為檔案名稱。在上面的範例中,會針對指定的每個密鑰目標建立兩個檔案:/run/secrets/ssh
和 /run/secrets/app
。
使用設定檔 (--config) 建立服務
使用 --config
旗標,讓容器可以存取設定檔。
使用設定檔建立服務。設定檔將會掛載到 redis-config
,其擁有者為在容器內執行指令的使用者(通常是 root
),且檔案模式為 0444
或可供所有人讀取。您可以將 uid
和 gid
指定為數字 ID 或名稱。使用名稱時,提供的群組/使用者名稱必須已存在於容器中。mode
指定為 4 位數的序列,例如 0755
。
$ docker service create --name=redis --config redis-conf redis:3.0.6
使用設定檔建立服務,並指定目標位置和檔案模式
$ docker service create --name redis \
--config source=redis-conf,target=/etc/redis/redis.conf,mode=0400 redis:3.0.6
若要授予服務存取多個設定檔的權限,請使用多個 --config
旗標。
如果未指定目標,設定檔會位於容器中的 /
。如果未指定目標,則設定檔的名稱會用作容器中的檔案名稱。如果指定了目標,則會使用該目標作為檔案名稱。
使用滾動更新策略建立服務
$ docker service create \
--replicas 10 \
--name redis \
--update-delay 10s \
--update-parallelism 2 \
redis:3.0.6
當您執行服務更新時,排程器一次最多會更新 2 個任務,更新間隔為 10 秒
。如需詳細資訊,請參閱滾動更新教學。
設定環境變數 (-e, --env)
這會為服務中的所有任務設定環境變數。例如
$ docker service create \
--name redis_2 \
--replicas 5 \
--env MYVAR=foo \
redis:3.0.6
若要指定多個環境變數,請指定多個 --env
旗標,每個旗標都帶有一個獨立的鍵值對。
$ docker service create \
--name redis_2 \
--replicas 5 \
--env MYVAR=foo \
--env MYVAR2=bar \
redis:3.0.6
使用特定主機名稱 (--hostname) 建立服務
此選項會將 Docker 服務容器的主機名稱設定為特定字串。例如
$ docker service create --name redis --hostname myredis redis:3.0.6
在服務上設定中繼資料 (-l, --label)
標籤是一個 key=value
鍵值對,用於將中繼資料套用到服務。若要使用兩個標籤標記服務
$ docker service create \
--name redis_2 \
--label com.example.foo="bar" \
--label bar=baz \
redis:3.0.6
如需標籤的詳細資訊,請參閱套用自訂中繼資料。
新增繫結掛載、磁碟區或記憶體檔案系統 (--mount)
Docker 支援三種不同的掛載類型,允許容器讀取或寫入主機作業系統或記憶體檔案系統上的檔案或目錄。這些類型分別是資料磁碟區(通常簡稱為磁碟區)、繫結掛載、tmpfs 和命名管道。
**繫結掛載**會讓主機上的檔案或目錄可供掛載其中的容器使用。繫結掛載可以是唯讀或讀寫。例如,容器可以透過繫結掛載主機的 /etc/resolv.conf
來共用其主機的 DNS 資訊,或者容器可以將日誌寫入其主機的 /var/log/myContainerLogs
目錄。如果您使用繫結掛載,且您的主機和容器對權限、存取控制或其他此類細節有不同的概念,則會遇到可攜性問題。
**命名磁碟區**是一種將容器所需的持續性資料與用於建立容器的映像檔和主機電腦分離的機制。命名磁碟區由 Docker 建立和管理,即使目前沒有容器使用它,命名磁碟區仍然存在。命名磁碟區中的資料可以在容器和主機電腦之間共用,也可以在多個容器之間共用。Docker 使用**磁碟區驅動程式**來建立、管理和掛載磁碟區。您可以使用 Docker 指令備份或還原磁碟區。
**tmpfs** 會在容器內掛載 tmpfs 以用於揮發性資料。
**npipe** 會將主機上的命名管道掛載到容器中。
考慮一種情況,您的映像檔啟動了一個輕量級網頁伺服器。您可以將該映像檔用作基礎映像檔,複製您網站的 HTML 檔案,並將其打包到另一個映像檔中。每次您的網站變更時,您都需要更新新的映像檔並重新部署所有服務您網站的容器。更好的解決方案是將網站儲存在命名磁碟區中,並在每個網頁伺服器容器啟動時將其附加到容器。若要更新網站,您只需更新命名磁碟區即可。
如需命名磁碟區的詳細資訊,請參閱資料磁碟區。
下表描述適用於服務中繫結掛載和命名磁碟區的選項
選項 | 必要 | 說明 |
---|---|---|
類型 | 掛載類型,可以是volume, bind, tmpfs,或npipe。如果未指定類型,則預設為volume
| |
src 或 source | 適用於type=bind和type=npipe |
|
dst 或 destination 或 target | 是 | 容器內的掛載路徑,例如/some/path/in/container/。如果路徑在容器的檔案系統中不存在,引擎會在掛載磁碟區或繫結掛載之前,在指定的位置建立一個目錄。 |
readonly 或 ro | 引擎會掛載繫結和磁碟區讀寫,除非在掛載繫結或磁碟區時指定了readonly選項。請注意,設定readonly繫結掛載可能不會使其子掛載readonly,具體取決於核心版本。另請參閱bind-recursive.
|
繫結掛載的選項
以下選項僅適用於繫結掛載 (type=bind
)
選項 | 說明 |
---|---|
繫結傳播 | 請參閱繫結傳播章節。 |
一致性 | 掛載的一致性需求;其中之一
|
bind-recursive | 預設情況下,子掛載也會遞迴地進行綁定掛載。但是,當綁定掛載使用readonly選項配置時,這種行為可能會造成混淆,因為子掛載可能不會掛載為唯讀,具體取決於內核版本。設定bind-recursive來控制遞迴綁定掛載的行為。 值可以是以下其中之一:
|
bind-nonrecursive | bind-nonrecursive自 Docker Engine v25.0 起已棄用。請改用bind-recursive。 值是可選的
|
綁定傳播
綁定傳播是指在給定綁定掛載或具名磁碟區中建立的掛載是否可以傳播到該掛載的副本。考慮一個掛載點 `/mnt`,它也掛載在 `/tmp` 上。傳播設定控制 `/tmp/a` 上的掛載是否也可用於 `/mnt/a`。每個傳播設定都有一個遞迴的對應設定。在遞迴的情況下,考慮 `/tmp/a` 也掛載為 `/foo`。傳播設定控制 `/mnt/a` 和/或 `/tmp/a` 是否會存在。
對於綁定掛載和磁碟區掛載,`bind-propagation` 選項預設為 `rprivate`,並且僅可針對綁定掛載進行配置。換句話說,具名磁碟區不支援綁定傳播。
- **`shared`**:原始掛載的子掛載會公開給副本掛載,副本掛載的子掛載也會傳播到原始掛載。
- **`slave`**:類似於共享掛載,但僅限單向。如果原始掛載公開了子掛載,則副本掛載可以看到它。但是,如果副本掛載公開了子掛載,則原始掛載看不到它。
- **`private`**:掛載是私有的。其中的子掛載不會公開給副本掛載,副本掛載的子掛載也不會公開給原始掛載。
- **`rshared`**:與 shared 相同,但傳播也會延伸到任何原始或副本掛載點中巢狀的掛載點,以及從這些掛載點延伸。
- **`rslave`**:與 `slave` 相同,但傳播也會延伸到任何原始或副本掛載點中巢狀的掛載點,以及從這些掛載點延伸。
- **`rprivate`**:預設值。與 `private` 相同,表示原始或副本掛載點中任何位置的掛載點都不會朝任一方向傳播。
有關綁定傳播的更多資訊,請參閱 共享子樹的 Linux 內核文件。
具名磁碟區的選項
以下選項僅能用於具名磁碟區 (`type=volume`)
選項 | 說明 |
---|---|
volume-driver | 用於磁碟區的 volume-driver 外掛程式名稱。預設為"local",如果磁碟區不存在,則使用本地磁碟區驅動程式建立磁碟區。 |
volume-label | 要套用至建立時磁碟區的一個或多個自訂中繼資料(「標籤」)。例如,volume-label=mylabel=hello-world,my-other-label=hello-mars。有關標籤的更多資訊,請參閱套用自訂中繼資料。 |
volume-nocopy | 預設情況下,如果您將空的磁碟區附加到容器,並且容器中的掛載路徑 (dst) 中已存在檔案或目錄,則引擎會將這些檔案和目錄複製到磁碟區中,允許主機存取它們。設定volume-nocopy停用將檔案從容器的檔案系統複製到磁碟區並掛載空磁碟區。 值是可選的
|
volume-opt | 特定於給定磁碟區驅動程式的選項,在建立磁碟區時會傳遞給驅動程式。選項以逗號分隔的鍵/值對列表形式提供,例如,volume-opt=some-option=some-value,volume-opt=some-other-option=some-other-value。有關給定驅動程式的可用選項,請參閱該驅動程式的文件。 |
tmpfs 的選項
以下選項僅能用於 tmpfs 掛載 (`type=tmpfs`);
選項 | 說明 |
---|---|
tmpfs-size | tmpfs 掛載的大小,單位為位元組。在 Linux 中預設無限制。 |
tmpfs-mode | tmpfs 的檔案模式,以八進位制表示。(例如"700"或"0700"。)在 Linux 中預設為"1777"。 |
「--mount」和「--volume」之間的差異
`--mount` 旗標支援 `docker run` 的 `-v` 或 `--volume` 旗標支援的大多數選項,但有一些重要的例外
`--mount` 旗標允許您*針對每個磁碟區*指定磁碟區驅動程式和磁碟區驅動程式選項,而無需事先建立磁碟區。相反,`docker run` 允許您使用 `--volume-driver` 旗標指定所有磁碟區共用的單個磁碟區驅動程式。
`--mount` 旗標允許您在建立磁碟區之前為磁碟區指定自訂中繼資料(「標籤」)。
當您將 `--mount` 與 `type=bind` 一起使用時,主機路徑必須指向主機上*現有的*路徑。如果路徑不存在,則不會為您建立路徑,服務將會因錯誤而失敗。
`--mount` 旗標不允許您使用 `Z` 或 `z` 旗標(用於 `selinux` 標籤)重新標記磁碟區。
使用具名磁碟區建立服務
以下範例建立使用具名磁碟區的服務
$ docker service create \
--name my-service \
--replicas 3 \
--mount type=volume,source=my-volume,destination=/path/in/container,volume-label="color=red",volume-label="shape=round" \
nginx:alpine
對於服務的每個副本,引擎都會從部署任務的預設(「本地」)磁碟區驅動程式請求名為「my-volume」的磁碟區。如果磁碟區不存在,引擎會建立新的磁碟區並套用「顏色」和「形狀」標籤。
啟動任務時,磁碟區會掛載在容器內的 `/path/in/container/` 上。
請注意,預設的(「本地」)磁碟區是一個本地範圍的磁碟區驅動程式。這表示根據任務部署的位置,該任務會取得一個新的名為「my-volume」的磁碟區,或與相同服務的其他任務共用相同的「my-volume」。如果在容器內執行的軟體未設計用於處理寫入相同位置的並行處理程序,則多個容器寫入單一共用磁碟區可能會導致資料損毀。另請考慮容器可能會由 Swarm 編排器重新排程並部署在不同的節點上。
建立使用匿名磁碟區的服務
以下指令會使用 /path/in/container
上的匿名磁碟區建立具有三個複本的服務
$ docker service create \
--name my-service \
--replicas 3 \
--mount type=volume,destination=/path/in/container \
nginx:alpine
在此範例中,未指定磁碟區的名稱 (source
),因此會為每個任務建立一個新的磁碟區。這可確保每個任務都有自己的磁碟區,並且磁碟區不會在任務之間共用。使用匿名磁碟區的任務完成後,這些磁碟區就會被移除。
建立使用繫結掛載主機目錄的服務
以下範例會在支援服務的容器中繫結掛載主機目錄 /path/in/container
$ docker service create \
--name my-service \
--mount type=bind,source=/path/on/host,destination=/path/in/container \
nginx:alpine
設定服務模式 (--mode)
服務模式決定這是複本服務還是全域服務。複本服務會執行指定數量的任務,而全域服務則會在 swarm 中的每個作用中節點上執行。
以下指令會建立全域服務
$ docker service create \
--name redis_2 \
--mode global \
redis:3.0.6
指定服務限制 (--constraint)
您可以透過定義限制運算式來限制可以排程任務的節點集合。限制運算式可以使用相符 (==
) 或排除 (!=
) 規則。多個限制會尋找滿足每個運算式 (AND 相符) 的節點。限制可以如下方式比對節點或 Docker Engine 標籤
節點屬性 | 相符項目 | 範例 |
---|---|---|
node.id | 節點 ID | node.id==2ivku8v2gvtg4 |
node.hostname | 節點主機名稱 | node.hostname!=node-2 |
node.role | 節點角色 (manager /worker ) | node.role==manager |
node.platform.os | 節點作業系統 | node.platform.os==windows |
node.platform.arch | 節點架構 | node.platform.arch==x86_64 |
node.labels | 使用者定義的節點標籤 | node.labels.security==high |
engine.labels | Docker Engine 的標籤 | engine.labels.operatingsystem==ubuntu-24.04 |
engine.labels
適用於 Docker Engine 標籤,例如作業系統、驅動程式等。Swarm 管理員可以使用 docker node update
指令新增 node.labels
以供操作使用。
例如,以下將 redis 服務的任務限制為節點類型標籤等於 queue 的節點
$ docker service create \
--name redis_2 \
--constraint node.platform.os==linux \
--constraint node.labels.type==queue \
redis:3.0.6
如果服務限制排除叢集中的所有節點,則會顯示訊息指出找不到合適的節點,但排程器將會啟動協調迴圈,並在合適的節點可用時部署服務。
在以下範例中,找不到滿足限制的節點,導致服務無法與所需狀態協調
$ docker service create \
--name web \
--constraint node.labels.region==east \
nginx:alpine
lx1wrhhpmbbu0wuk0ybws30bc
overall progress: 0 out of 1 tasks
1/1: no suitable node (scheduling constraints not satisfied on 5 nodes)
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
b6lww17hrr4e web replicated 0/1 nginx:alpine
將 region=east
標籤新增至叢集中的節點後,服務就會協調,並部署所需數量的複本
$ docker node update --label-add region=east yswe2dm4c5fdgtsrli1e8ya5l
yswe2dm4c5fdgtsrli1e8ya5l
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
b6lww17hrr4e web replicated 1/1 nginx:alpine
指定服務放置偏好設定 (--placement-pref)
您可以設定服務,將任務平均分配到不同類別的節點。這在平衡資料中心或可用性區域集合上的任務時可能很有用。以下範例說明了這一點
$ docker service create \
--replicas 9 \
--name redis_2 \
--placement-pref spread=node.labels.datacenter \
redis:3.0.6
這使用 --placement-pref
和 spread
策略(目前唯一支援的策略)將任務平均分散到 datacenter
節點標籤的值上。在此範例中,我們假設每個節點都附加了 datacenter
節點標籤。如果 swarm 中節點之間有三個不同的標籤值,則三分之一的任務將放置在與每個值關聯的節點上。即使某個值的節點數量多於另一個值,也是如此。例如,請考慮以下節點集合
- 三個具有
node.labels.datacenter=east
的節點 - 兩個具有
node.labels.datacenter=south
的節點 - 一個具有
node.labels.datacenter=west
的節點
由於我們正在分散 datacenter
標籤的值,並且服務有 9 個複本,因此每個資料中心將會有 3 個複本。有三個節點與值 east
關聯,因此每個節點將會取得為此值保留的三個複本之一。有兩個節點的值為 south
,並且將會在此兩個節點之間分配為此值保留的三個複本,一個節點接收兩個複本,另一個節點只接收一個複本。最後,west
有一個節點將會取得為 west
保留的所有三個複本。
如果一個類別中的節點(例如,具有 node.labels.datacenter=south
的節點)由於限制或資源限制而無法處理其公平份額的任務,則額外的任務將會盡可能分配給其他節點。
放置偏好設定支援引擎標籤和節點標籤。以上範例使用節點標籤,因為標籤是使用 node.labels.datacenter
參考的。若要分散引擎標籤的值,請使用 --placement-pref spread=engine.labels.<labelname>
。
可以將多個放置偏好設定新增至服務。這會建立偏好設定的階層,以便先將任務劃分到一個類別,然後再進一步劃分到其他類別。這在將任務公平地劃分到資料中心之間,然後將每個資料中心內的任務劃分到機架選擇時可能很有用。若要新增多個放置偏好設定,請多次指定 --placement-pref
旗標。順序很重要,並且在做出排程決策時,將會按照指定的順序套用放置偏好設定。
以下範例設定具有多個放置偏好設定的服務。任務首先分散到各個資料中心,然後分散到機架(如個別標籤所示)
$ docker service create \
--replicas 9 \
--name redis_2 \
--placement-pref 'spread=node.labels.datacenter' \
--placement-pref 'spread=node.labels.rack' \
redis:3.0.6
使用 docker service update
更新服務時,--placement-pref-add
會在所有現有放置偏好設定之後附加新的放置偏好設定。--placement-pref-rm
會移除與引數相符的現有放置偏好設定。
指定服務的記憶體需求和限制 (--reserve-memory 和 --limit-memory)
如果您的服務需要最少量的記憶體才能正常執行,您可以使用 --reserve-memory
指定服務只能排程在具有這麼多可用記憶體可供保留的節點上。如果沒有符合條件的節點可用,則不會排程任務,但會保持在擱置狀態。
以下範例要求在排程服務在給定節點上執行之前,該節點上必須有 4GB 的記憶體可用且可保留。
$ docker service create --reserve-memory=4GB --name=too-big nginx:alpine
管理者不會在單一節點上排程一組容器,其組合保留量超過該節點上的可用記憶體。
在排程並執行任務後,--reserve-memory
不會強制執行記憶體限制。使用 --limit-memory
確保任務在節點上使用的記憶體量不超過給定量。此範例將任務使用的記憶體量限制為 4GB。即使您的每個節點只有 2GB 的記憶體,也會排程任務,因為 --limit-memory
是上限。
$ docker service create --limit-memory=4GB --name=too-big nginx:alpine
使用 --reserve-memory
和 --limit-memory
並不能保證 Docker 不會在您的主機上使用比您想要的更多的記憶體。例如,您可以建立許多服務,其記憶體使用量總和可能會耗盡可用記憶體。
您可以透過同時考量主機上執行的其他(非容器化)軟體,來防止這種情況耗盡可用記憶體。如果 --reserve-memory
大於或等於 --limit-memory
,Docker 不會將服務排程到記憶體不足的主機上。--limit-memory
將限制服務的記憶體保持在該限制內,因此如果每個服務都設定了記憶體預留和限制,Docker 服務就不太可能使主機飽和。其他非服務容器或直接在 Docker 主機上執行的應用程式仍然可能耗盡記憶體。
這種方法有一個缺點。預留記憶體也意味著您可能無法最佳利用節點上的可用記憶體。考慮一個在正常情況下使用 100MB 記憶體的服務,但根據負載可能「峰值」達到 500MB。為該服務預留 500MB(以保證在「峰值」時可以使用 500MB)會導致大部分時間浪費 400MB 的記憶體。
簡而言之,您可以採取更保守或更靈活的方法
**保守**:預留 500MB,並限制為 500MB。基本上,您現在將服務容器視為虛擬機,並且您可能會失去容器的一大優勢,即每個主機更高的服務密度。
**靈活**:限制為 500MB,假設如果服務需要超過 500MB,則表示它發生故障。在 100MB「正常」需求和 500MB「峰值」需求之間預留一些記憶體。這假設當此服務處於「峰值」時,其他服務或非容器工作負載可能不會處於峰值。
您採取的方法很大程度上取決於工作負載的記憶體使用模式。在確定方法之前,您應該在正常和峰值條件下進行測試。
在 Linux 上,您也可以使用 cgroups
或其他相關作業系統工具,在主機作業系統層級限制服務在特定主機上的整體記憶體佔用空間。
指定每個節點的最大副本數 (--replicas-max-per-node)
使用 --replicas-max-per-node
旗標設定可在節點上執行的最大副本任務數。以下命令建立一個具有 2 個副本任務但每個節點只有一個副本任務的 nginx 服務。
這種方法的一個有用範例是與 --placement-pref
一起在多個資料中心之間平衡任務,並讓 --replicas-max-per-node
設定確保在維護或資料中心故障期間副本不會遷移到另一個資料中心。
以下範例說明了這一點
$ docker service create \
--name nginx \
--replicas 2 \
--replicas-max-per-node 1 \
--placement-pref 'spread=node.labels.datacenter' \
nginx
將服務附加到現有網路 (--network)
您可以使用覆蓋網路來連接叢集中的一個或多個服務。
首先,使用 docker network create 命令在管理節點上建立一個覆蓋網路
$ docker network create --driver overlay my-network
etjpu59cykrptrgw0z0hk5snf
在叢集模式下建立覆蓋網路後,所有管理節點都可以存取該網路。
當您建立服務並傳遞 --network
旗標以將服務附加到覆蓋網路時
$ docker service create \
--replicas 3 \
--network my-network \
--name my-web \
nginx
716thylsndqma81j6kkkb5aus
叢集會將 my-network 擴展到執行該服務的每個節點。
同一網路上的容器可以使用服務探索互相存取。
--network
的完整語法允許指定別名和驅動程式選項列表:--network name=my-network,alias=web1,driver-opt=field1=value1
將服務埠發佈到叢集外部 (-p, --publish)
您可以使用 --publish
旗標發佈服務埠,使其可在叢集外部使用。--publish
旗標可以採用兩種不同樣式的參數。簡短版本是位置式的,允許您指定以冒號 (:
) 分隔的發佈埠和目標埠。
$ docker service create --name my_web --replicas 3 --publish 8080:80 nginx
還有一個長格式,更易於閱讀,並允許您指定更多選項。建議使用長格式。使用簡短格式時,您無法指定服務的模式。以下是以長格式使用相同服務的範例
$ docker service create --name my_web --replicas 3 --publish published=8080,target=80 nginx
您可以指定的選項是
選項 | 簡短語法 | 長語法 | 說明 |
---|---|---|---|
發佈埠和目標埠 | --publish 8080:80 | --publish published=8080,target=80 | 容器內的目標埠以及使用路由網格 (入口) 或主機級網路對應到節點上的埠。此表格稍後會提供更多選項。建議使用鍵值語法,因為它具有一定的自我說明性。 |
模式 | 無法使用簡短語法設定。 | --publish published=8080,target=80,mode=host | 用於綁定埠的模式,可以是入口或host。如果未指定類型,則預設為入口以使用路由網格。 |
協定 | --publish 8080:80/tcp | --publish published=8080,target=80,protocol=tcp | 要使用的協定,tcp , udp,或sctp。如果未指定類型,則預設為tcp。要綁定兩個協定的埠,請指定-p或--publish旗標兩次。 |
當您使用 ingress
模式發佈服務埠時,叢集路由網格會使服務在每個節點上的已發佈埠上都可存取,無論節點上是否有該服務的任務正在執行。如果您使用 host
模式,則埠僅綁定在執行服務的節點上,並且節點上的指定埠只能綁定一次。您只能使用長語法設定發佈模式。如需更多資訊,請參閱使用叢集模式路由網格。
提供受管服務帳戶的憑證規格 (--credentials-spec)
此選項僅用於使用 Windows 容器的服務。--credential-spec
必須採用 file://<filename>
或 registry://<value-name>
的格式。
使用 file://<filename>
格式時,引用的檔案必須存在於 docker 資料目錄的 CredentialSpecs
子目錄中,Windows 上預設為 C:\ProgramData\Docker\
。例如,指定 file://spec.json
會載入 C:\ProgramData\Docker\CredentialSpecs\spec.json
。
使用 registry://<value-name>
格式時,會從守護程式主機上的 Windows 登錄檔讀取憑證規格。指定的登錄檔值必須位於
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\CredentialSpecs
使用範本建立服務
您可以使用 Go 的 text/template