?
This document uses PHP Chinese website manual Release
Swarm服務(wù)使用聲明性模型,這意味著您可以定義所需的服務(wù)狀態(tài),并依靠Docker來維護(hù)此狀態(tài)。該州包括諸如(但不限于)的信息:
服務(wù)容器應(yīng)該運(yùn)行的映像名稱和標(biāo)記
有多少個(gè)容器參與服務(wù)
是否有任何端口暴露給群體外的客戶
當(dāng)Docker啟動(dòng)時(shí)服務(wù)是否應(yīng)該自動(dòng)啟動(dòng)
服務(wù)重新啟動(dòng)時(shí)發(fā)生的特定行為(例如是否使用滾動(dòng)重啟)
服務(wù)可以運(yùn)行的節(jié)點(diǎn)的特性(例如資源約束和布局偏好)
有關(guān)群體模式的概述,請參閱群體模式關(guān)鍵概念。有關(guān)服務(wù)如何工作的概述,請參閱服務(wù)如何工作。
要?jiǎng)?chuàng)建沒有額外配置的單副本服務(wù),只需提供映像名稱即可。該命令啟動(dòng)一個(gè)帶有隨機(jī)生成名稱并且沒有發(fā)布端口的Nginx服務(wù)。這是一個(gè)較為理想的例子,因?yàn)槟鷮o法與Nginx服務(wù)交互。
$ docker service create nginx
該服務(wù)安排在可用節(jié)點(diǎn)上。要確認(rèn)服務(wù)已成功創(chuàng)建并啟動(dòng),請使用以下docker service ls
命令:
$ docker service ls ID NAME MODE REPLICAS IMAGE PORTS a3iixnklxuem quizzical_lamarr replicated 1/1 docker.io/library/nginx@sha256:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268
創(chuàng)建的服務(wù)并不總是立即運(yùn)行。如果服務(wù)的圖像不可用,如果沒有節(jié)點(diǎn)滿足您為服務(wù)配置的要求或其他原因,服務(wù)可能處于掛起狀態(tài)。有關(guān)更多信息,請參閱待定服務(wù)。
要為您的服務(wù)提供名稱,請使用以下--name
標(biāo)志:
$ docker service create --name my_web nginx
就像使用獨(dú)立容器一樣,您可以通過在映像名稱后面添加它來指定服務(wù)容器應(yīng)該運(yùn)行的命令。此示例啟動(dòng)一個(gè)名為helloworld
使用alpine
圖像并運(yùn)行以下命令的服務(wù)ping docker.com
:
$ docker service create --name helloworld alpine ping docker.com
您也可以指定要使用的服務(wù)的圖像標(biāo)記。這個(gè)例子修改了前一個(gè)使用alpine:3.6
標(biāo)簽:
$ docker service create --name helloworld alpine:3.6 ping docker.com
有關(guān)圖像標(biāo)簽分辨率的更多詳細(xì)信息,請參閱指定服務(wù)應(yīng)使用的圖像版本。
您可以使用該docker service update
命令更改有關(guān)現(xiàn)有服務(wù)的幾乎所有內(nèi)容。當(dāng)您更新服務(wù)時(shí),Docker會(huì)停止其容器并使用新配置重新啟動(dòng)它們。
由于Nginx是一個(gè)Web服務(wù),如果您將端口80發(fā)布到群集外部的客戶端,它將會(huì)更好。您可以在創(chuàng)建服務(wù)時(shí)使用-p
或--publish
標(biāo)志來指定。更新現(xiàn)有服務(wù)時(shí),該標(biāo)志是--publish-add
。還有一個(gè)--publish-rm
標(biāo)志可以刪除以前發(fā)布的端口。
假設(shè)my_web
來自上一節(jié)的服務(wù)仍然存在,請使用以下命令將其更新為發(fā)布端口80。
$ docker service update --publish-add 80 my_web
要驗(yàn)證它是否有效,請使用docker service ls
:
$ docker service ls ID NAME MODE REPLICAS IMAGE PORTS 4nhxl7oxw5vz my_web replicated 1/1 docker.io/library/nginx@sha256:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268 *:0->80/tcp
有關(guān)發(fā)布端口如何工作的更多信息,請參閱發(fā)布端口。
您可以更新有關(guān)現(xiàn)有服務(wù)的幾乎每個(gè)配置詳細(xì)信息,包括其運(yùn)行的圖像名稱和標(biāo)記。請參閱創(chuàng)建后更新服務(wù)的圖像。
要?jiǎng)h除服務(wù),請使用該docker service remove
命令。您可以通過其ID或名稱來刪除服務(wù),如docker service ls
命令的輸出中所示。以下命令將刪除該my_web
服務(wù)。
$ docker service remove my_web
以下各節(jié)提供有關(guān)服務(wù)配置的詳細(xì)信息。本主題不包括每個(gè)標(biāo)志或方案。在幾乎所有可以在服務(wù)創(chuàng)建時(shí)定義配置的情況下,您也可以用類似的方式更新現(xiàn)有服務(wù)的配置。
看命令行的引用為docker service create
和docker service update
,或運(yùn)行與所述那些命令中的一個(gè)--help
標(biāo)志。
您可以在容器中為運(yùn)行時(shí)環(huán)境配置以下選項(xiàng):
使用--env
標(biāo)志的環(huán)境變量
使用該--workdir
標(biāo)志的容器內(nèi)的工作目錄
使用該--user
標(biāo)志的用戶名或UID
以下服務(wù)的容器將有一個(gè)環(huán)境變量$MYVAR
設(shè)置為myvalue
,將從該/tmp/
目錄運(yùn)行,并將作為my_user
用戶運(yùn)行。
$ docker service create --name helloworld \ --env MYVAR=myvalue \ --workdir /tmp \ --user my_user \ alpine ping docker.com
要更新現(xiàn)有服務(wù)運(yùn)行的命令,可以使用該--args
標(biāo)志。下面的示例更新一個(gè)已調(diào)用的現(xiàn)有服務(wù),helloworld
以便它運(yùn)行命令ping docker.com
而不是之前運(yùn)行的任何命令:
$ docker service update --args "ping docker.com" helloworld
當(dāng)您創(chuàng)建服務(wù)時(shí)未指定要使用的圖像版本的任何詳細(xì)信息時(shí),該服務(wù)將使用帶有latest
標(biāo)簽標(biāo)記的版本。您可以強(qiáng)制該服務(wù)以幾種不同的方式使用特定版本的圖像,具體取決于您想要的結(jié)果。
圖像版本可以用幾種不同的方式表達(dá):
如果您指定了一個(gè)標(biāo)簽,那么管理器(或Docker客戶端,如果您使用內(nèi)容信任)將該標(biāo)簽解析為摘要。當(dāng)在工作節(jié)點(diǎn)上接收到創(chuàng)建容器任務(wù)的請求時(shí),工作節(jié)點(diǎn)只會(huì)看到摘要,而不是標(biāo)簽。$ docker service create --name =“myservice”ubuntu:16.04一些標(biāo)簽代表離散版本,例如ubuntu:16.04
。像這樣的標(biāo)簽幾乎總是會(huì)隨著時(shí)間的推移逐漸形成穩(wěn)定的摘要。建議您盡可能使用這種標(biāo)簽。其他類型的標(biāo)簽(如latest
或nightly
)可能經(jīng)常會(huì)解析為新的摘要,具體取決于圖像作者更新標(biāo)簽的頻率。建議不要使用經(jīng)常更新的標(biāo)簽來運(yùn)行服務(wù),以防止使用不同映像版本的不同服務(wù)副本任務(wù)。
如果您完全不指定版本,則按照慣例,圖像的latest
標(biāo)記將被解析為摘要。創(chuàng)建服務(wù)任務(wù)時(shí),工作人員使用此摘要中的圖像。因此,以下兩個(gè)命令是等價(jià)的:$ docker service create --name =“myservice”ubuntu $ docker service create --name =“myservice”ubuntu:latest
如果直接指定摘要,則在創(chuàng)建服務(wù)任務(wù)時(shí)始終使用圖像的確切版本。$ docker service create \ --name =“myservice”\ ubuntu:16.04@sha256:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1
當(dāng)你創(chuàng)建一個(gè)服務(wù)時(shí),圖像的標(biāo)簽被解析為特定消化的標(biāo)記點(diǎn),在服務(wù)創(chuàng)建的時(shí)間。該服務(wù)的工作者節(jié)點(diǎn)將永久使用該特定的摘要,除非該服務(wù)被明確更新。如果您使用經(jīng)常更改的標(biāo)簽(例如,latest
),此功能尤其重要,因?yàn)樗纱_保所有服務(wù)任務(wù)使用相同版本的圖像。
注意:如果啟用了內(nèi)容信任,客戶端實(shí)際上會(huì)在聯(lián)系swarm管理器之前將圖像的標(biāo)簽解析為摘要,以驗(yàn)證圖像是否已簽名。因此,如果您使用內(nèi)容信任,swarm管理器會(huì)收到預(yù)先解決的請求。在這種情況下,如果客戶端無法將圖像解析為摘要,則請求失敗。
如果管理者無法將標(biāo)簽解析為摘要,則每個(gè)工作者節(jié)點(diǎn)負(fù)責(zé)將標(biāo)簽解析為摘要,并且不同節(jié)點(diǎn)可以使用不同版本的圖像。如果發(fā)生這種情況,將會(huì)記錄下面的警告,用占位符代替真實(shí)信息。
unable to pin image <IMAGE-NAME> to digest: <REASON>
要查看圖像的當(dāng)前摘要,請發(fā)出命令docker檢查<IMAGE>:<TAG>并查找RepoDigests行。 以下是Ubuntu的最新摘要:最新的內(nèi)容寫入時(shí)。 為了清晰起見,輸出被截?cái)唷?/p>
$ docker inspect ubuntu:latest
"RepoDigests": [ "ubuntu@sha256:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1"],
在創(chuàng)建服務(wù)之后,除非您使用--image標(biāo)志顯式運(yùn)行docker服務(wù)更新,否則其映像永遠(yuǎn)不會(huì)更新,如下所述。 其他更新操作(如擴(kuò)展服務(wù),添加或刪除網(wǎng)絡(luò)或體積,重命名服務(wù)或任何其他類型的更新操作)不會(huì)更新服務(wù)的映像。
每個(gè)標(biāo)簽代表一個(gè)摘要,類似于Git哈希。 一些標(biāo)簽,如最新的,經(jīng)常更新以指向新的摘要。 其他的,比如ubuntu:16.04,代表一個(gè)已發(fā)布的軟件版本,如果有的話,預(yù)計(jì)不會(huì)更新以指向新的摘要。 在Docker 1.13及更高版本中,當(dāng)您創(chuàng)建服務(wù)時(shí),它將被限制為使用圖像的特定摘要?jiǎng)?chuàng)建任務(wù),直到您使用帶有--image標(biāo)志的服務(wù)更新來更新服務(wù)。 如果您使用較舊版本的Docker Engine,則必須刪除并重新創(chuàng)建該服務(wù)以更新其映像。
當(dāng)您將service update
使用該--image
標(biāo)志運(yùn)行時(shí),swarm管理器會(huì)查詢Docker Hub或您的私人Docker注冊中心以獲取標(biāo)記當(dāng)前指向的摘要并更新服務(wù)任務(wù)以使用該摘要。
注意:如果您使用內(nèi)容信任,Docker客戶端解析圖像,swarm管理器接收圖像和摘要,而不是標(biāo)簽。
通常,管理員能夠?qū)?biāo)簽解析為新的摘要和服務(wù)更新,重新部署每個(gè)任務(wù)以使用新圖像。如果經(jīng)理無法解決標(biāo)簽或發(fā)生其他問題,則接下來的兩節(jié)概述了期望的內(nèi)容。
如果swarm manager可以將image標(biāo)簽解析為摘要,它會(huì)指示工作節(jié)點(diǎn)重新部署任務(wù)并使用該摘要中的圖像。
如果工作人員在該摘要中緩存了圖像,則會(huì)使用該圖像。
如果不是,它會(huì)嘗試從Docker Hub或私有注冊表中提取圖像。
- If it succeeds, the task is deployed using the new image.
- If the worker fails to pull the image, the service fails to deploy on that worker node. Docker tries again to deploy the task, possibly on a different worker node.
如果swarm manager無法將圖像解析為摘要,則全部不會(huì)丟失:
管理員指示工作節(jié)點(diǎn)使用該標(biāo)簽處的圖像重新部署任務(wù)。
如果工作人員擁有解析為該標(biāo)記的本地緩存圖像,則它會(huì)使用該圖像。
如果工作人員沒有解析為標(biāo)簽的本地高速緩存映像,則工作人員會(huì)嘗試連接到Docker Hub或私有注冊表以在該標(biāo)簽處拉取圖像。
- If this succeeds, the worker uses that image.
- If this fails, the task fails to deploy and the manager tries again to deploy the task, possibly on a different worker node.
在創(chuàng)建群集服務(wù)時(shí),可以通過兩種方式將該服務(wù)的端口發(fā)布到群集外的主機(jī):
你可以依靠路由網(wǎng)格。當(dāng)您發(fā)布服務(wù)端口時(shí),無論在該節(jié)點(diǎn)上運(yùn)行的服務(wù)是否有任務(wù),群集都可以在每個(gè)節(jié)點(diǎn)上的目標(biāo)端口上訪問該服務(wù)。這并不復(fù)雜,是許多類型服務(wù)的正確選擇。
您可以直接在運(yùn)行該服務(wù)的群集節(jié)點(diǎn)上發(fā)布服務(wù)任務(wù)的端口。此功能在Docker 1.13和更高版本中可用。這繞過了路由網(wǎng)格,并提供了最大的靈活性,包括您開發(fā)自己的路由框架的能力。但是,您有責(zé)任跟蹤每個(gè)任務(wù)的運(yùn)行位置,并將請求路由到任務(wù),并在各個(gè)節(jié)點(diǎn)之間進(jìn)行負(fù)載平衡。
請繼續(xù)閱讀以獲取更多信息和每種方法的用例。
要從外部向群發(fā)布服務(wù)的端口,請使用該--publish <TARGET-PORT>:<SERVICE-PORT>
標(biāo)志。群集使服務(wù)可以在每個(gè)群集節(jié)點(diǎn)的目標(biāo)端口上訪問。如果外部主機(jī)連接到任何群集節(jié)點(diǎn)上的該端口,則路由網(wǎng)格會(huì)將其路由到任務(wù)。外部主機(jī)不需要知道服務(wù)任務(wù)的IP地址或內(nèi)部使用端口與服務(wù)交互。當(dāng)用戶或進(jìn)程連接到服務(wù)時(shí),任何運(yùn)行服務(wù)任務(wù)的工作節(jié)點(diǎn)都可能會(huì)響應(yīng)。有關(guān)群集服務(wù)網(wǎng)絡(luò)的更多詳細(xì)信息,請參閱管理群集服務(wù)網(wǎng)絡(luò)。
假設(shè)您有一個(gè)10節(jié)點(diǎn)的群集,并且您部署了一個(gè)在10節(jié)點(diǎn)群集上運(yùn)行三個(gè)任務(wù)的Nginx服務(wù):
$ docker service create --name my_web \ --replicas 3 \ --publish 8080:80 \ nginx
三個(gè)任務(wù)將在最多三個(gè)節(jié)點(diǎn)上運(yùn)行。您不需要知道哪些節(jié)點(diǎn)正在運(yùn)行任務(wù); 在10個(gè)節(jié)點(diǎn)中的任何節(jié)點(diǎn)上連接到端口8080 都會(huì)將您連接到三項(xiàng)nginx
任務(wù)之一。你可以使用測試curl
。以下示例假定這localhost
是群集節(jié)點(diǎn)之一。如果情況并非如此,或者localhost
無法解析到主機(jī)上的IP地址,請使用主機(jī)的IP地址或可解析的主機(jī)名稱。
HTML輸出被截?cái)啵?/p>
$ curl localhost:8080<!DOCTYPE html><html><head><title>Welcome to nginx!</title>...truncated...</html>
后續(xù)連接可能會(huì)路由到同一個(gè)群集節(jié)點(diǎn)或不同的節(jié)點(diǎn)。
如果您需要根據(jù)應(yīng)用程序狀態(tài)做出路由決策,或者需要完全控制將請求路由到服務(wù)任務(wù)的流程,則使用路由網(wǎng)格可能不是您的應(yīng)用程序的正確選擇。 要直接在正在運(yùn)行的節(jié)點(diǎn)上發(fā)布服務(wù)的端口,請使用mode = host選項(xiàng)指定--publish標(biāo)志。
注意:如果您使用mode = host直接在群集節(jié)點(diǎn)上發(fā)布服務(wù)的端口,并設(shè)置published = <PORT>,則會(huì)創(chuàng)建隱式限制,您只能在給定群集節(jié)點(diǎn)上為該服務(wù)運(yùn)行一個(gè)任務(wù)。 另外,如果您使用mode = host,并且您在docker service create上不使用--mode = global標(biāo)志,則很難知道哪些節(jié)點(diǎn)正在運(yùn)行該服務(wù),以便將工作路由到它們。
nginx是一個(gè)開源的反向代理,負(fù)載均衡器,HTTP緩存和一個(gè)Web服務(wù)器。如果您使用路由網(wǎng)格將nginx作為服務(wù)運(yùn)行,則連接到任何swarm節(jié)點(diǎn)上的nginx端口將顯示(有效)運(yùn)行該服務(wù)的隨機(jī)群集節(jié)點(diǎn)的網(wǎng)頁。
以下示例在群集中的每個(gè)節(jié)點(diǎn)上運(yùn)行nginx作為服務(wù),并在每個(gè)群集節(jié)點(diǎn)上本地公開nginx端口。
$ docker service create \ --mode global \ --publish mode=host,target=80,published=8080 \ --name=nginx \ nginx:latest
您可以在每個(gè)群集節(jié)點(diǎn)的端口8080上訪問nginx服務(wù)器。如果您將一個(gè)節(jié)點(diǎn)添加到swarm中,則會(huì)啟動(dòng)一個(gè)nginx任務(wù)。您不能在任何綁定到端口8080的群集節(jié)點(diǎn)上啟動(dòng)另一個(gè)服務(wù)或容器。
注意:這是一個(gè)理想的例子。為多層服務(wù)創(chuàng)建應(yīng)用程序?qū)勇酚煽蚣芊浅?fù)雜,超出了本主題的范圍。
您可以使用覆蓋網(wǎng)絡(luò)連接群中的一個(gè)或多個(gè)服務(wù)。
首先,使用docker network create
帶有--driver overlay
標(biāo)志的命令在管理器節(jié)點(diǎn)上創(chuàng)建覆蓋網(wǎng)絡(luò)。
$ docker network create --driver overlay my-network
在群集模式下創(chuàng)建覆蓋網(wǎng)絡(luò)后,所有管理節(jié)點(diǎn)都可以訪問網(wǎng)絡(luò)。
您可以創(chuàng)建新服務(wù)并傳遞該--network
標(biāo)志以將服務(wù)附加到覆蓋網(wǎng)絡(luò):
$ docker service create \ --replicas 3 \ --network my-network \ --name my-web \ nginx
群體擴(kuò)展my-network
到運(yùn)行服務(wù)的每個(gè)節(jié)點(diǎn)。
您還可以使用該--network-add
標(biāo)志將現(xiàn)有服務(wù)連接到覆蓋網(wǎng)絡(luò)。
$ docker service update --network-add my-network my-web
要斷開正在運(yùn)行的服務(wù)與網(wǎng)絡(luò)的連接,請使用該--network-rm
標(biāo)志。
$ docker service update --network-rm my-network my-web
有關(guān)覆蓋網(wǎng)絡(luò)和服務(wù)發(fā)現(xiàn)的更多信息,請參閱將服務(wù)附加到覆蓋網(wǎng)絡(luò)和Docker群集模式覆蓋網(wǎng)絡(luò)安全模型。
要?jiǎng)?chuàng)建一個(gè)訪問Docker管理的機(jī)密的服務(wù),請使用該--secret
標(biāo)志。有關(guān)更多信息,請參閱管理Docker服務(wù)的敏感字符串(機(jī)密)
Swarm模式有兩種類型的服務(wù):復(fù)制和全局。對于復(fù)制服務(wù),您指定swarm管理器調(diào)度到可用節(jié)點(diǎn)的副本任務(wù)數(shù)。對于全局服務(wù),調(diào)度程序在每個(gè)可用節(jié)點(diǎn)上放置一個(gè)任務(wù)。
您可以使用--mode
標(biāo)志來控制服務(wù)的類型。如果您未指定模式,則該服務(wù)默認(rèn)為replicated
。對于復(fù)制服務(wù),您可以指定要使用該--replicas
標(biāo)志開始的副本任務(wù)數(shù)。例如,要使用3個(gè)副本任務(wù)啟動(dòng)復(fù)制的nginx服務(wù):
$ docker service create \ --name my_web \ --replicas 3 \ nginx
要在每個(gè)可用節(jié)點(diǎn)上啟動(dòng)全局服務(wù),請傳遞--mode global
給docker service create
。每當(dāng)新節(jié)點(diǎn)變?yōu)榭捎脮r(shí),調(diào)度程序就將全局服務(wù)的任務(wù)放置在新節(jié)點(diǎn)上。例如,要開始在群中每個(gè)節(jié)點(diǎn)上運(yùn)行阿爾派的服務(wù):
$ docker service create \ --name myservice \ --mode global \ alpine top
通過服務(wù)約束,您可以在調(diào)度程序?qū)⒎?wù)部署到節(jié)點(diǎn)之前設(shè)置節(jié)點(diǎn)的條件。您可以根據(jù)節(jié)點(diǎn)屬性和元數(shù)據(jù)或引擎元數(shù)據(jù)將約束應(yīng)用于服務(wù)。有關(guān)約束的更多信息,請參閱docker service create
CLI參考。
使用布置首選項(xiàng)將任務(wù)均勻分配到不同類別的節(jié)點(diǎn)上。一個(gè)可能有用的例子是在多個(gè)數(shù)據(jù)中心或可用區(qū)域之間平衡任務(wù)。在這種情況下,您可以使用展示位置首選項(xiàng)將任務(wù)分散到多個(gè)數(shù)據(jù)中心,并使面向本地中斷時(shí)的服務(wù)更具彈性。您可以使用其他布局偏好設(shè)置來進(jìn)一步將任務(wù)分成多組節(jié)點(diǎn)。例如,您可以在每個(gè)數(shù)據(jù)中心內(nèi)的多個(gè)機(jī)架上平衡它們。有關(guān)約束的更多信息,請參閱docker service create
CLI參考。
要為服務(wù)保留給定數(shù)量的內(nèi)存或CPU數(shù)量,請使用--reserve-memory
或--reserve-cpu
標(biāo)志。如果沒有可用的節(jié)點(diǎn)能夠滿足要求(例如,如果請求4個(gè)CPU并且群中沒有節(jié)點(diǎn)具有4個(gè)CPU),則服務(wù)保持掛起狀態(tài),直到節(jié)點(diǎn)可用于運(yùn)行其任務(wù)。
如果您的服務(wù)嘗試使用比swarm節(jié)點(diǎn)更多的內(nèi)存,則可能會(huì)遇到內(nèi)存異常(OOME),并且容器或Docker守護(hù)進(jìn)程可能會(huì)被內(nèi)核OOM殺手所殺。要防止發(fā)生這種情況,請確保您的應(yīng)用程序在具有足夠內(nèi)存的主機(jī)上運(yùn)行,并且請參閱了解耗盡內(nèi)存的風(fēng)險(xiǎn)。
Swarm服務(wù)允許您使用資源約束,布局首選項(xiàng)和標(biāo)簽來確保將您的服務(wù)部署到適當(dāng)?shù)娜杭?jié)點(diǎn)。
您可以設(shè)置服務(wù),將任務(wù)均勻分配到不同類別的節(jié)點(diǎn)上??梢杂杏玫囊粋€(gè)例子是在一組數(shù)據(jù)中心或可用區(qū)域上平衡任務(wù)。下面的例子說明了這一點(diǎn):
$ docker service create \ --replicas 9 \ --name redis_2 \ --placement-pref 'spread=node.labels.datacenter' \ redis:3.0.6
這使用帶有擴(kuò)展策略(當(dāng)前唯一支持的策略)的--placement-pref來將任務(wù)均勻分布在數(shù)據(jù)中心節(jié)點(diǎn)標(biāo)簽的值上。 在這個(gè)例子中,我們假設(shè)每個(gè)節(jié)點(diǎn)都附有一個(gè)數(shù)據(jù)中心節(jié)點(diǎn)標(biāo)簽。 如果群體中的節(jié)點(diǎn)之間存在三個(gè)不同的標(biāo)簽值,則三分之一的任務(wù)將被放置在與每個(gè)值相關(guān)的節(jié)點(diǎn)上。 即使有更多的節(jié)點(diǎn)具有一個(gè)值而不是另一個(gè)值,情況也是如此。 例如,請考慮以下一組節(jié)點(diǎn):
Three nodes with node.labels.datacenter=east
Two nodes with node.labels.datacenter=south
One node with node.labels.datacenter=west
由于我們正在傳播數(shù)據(jù)中心標(biāo)簽的值,并且該服務(wù)有9個(gè)副本,因此每個(gè)數(shù)據(jù)中心將有3個(gè)副本。 有三個(gè)節(jié)點(diǎn)與east的值相關(guān)聯(lián),所以每個(gè)節(jié)點(diǎn)都會(huì)為這個(gè)值保留三個(gè)副本中的一個(gè)。 有兩個(gè)值為南的節(jié)點(diǎn),這個(gè)值的三個(gè)副本將在它們之間分配,一個(gè)接收兩個(gè)副本,另一個(gè)接收一個(gè)副本。 最后,西部有一個(gè)節(jié)點(diǎn),它可以將所有三個(gè)副本保留給西部。
如果某個(gè)類別中的節(jié)點(diǎn)(例如那些帶有node.labels.datacenter=south
的節(jié)點(diǎn))由于約束或資源限制而無法處理其公平份額的任務(wù),則可能會(huì)將其他任務(wù)分配給其他節(jié)點(diǎn)。
布局首選項(xiàng)支持引擎標(biāo)簽和節(jié)點(diǎn)標(biāo)簽。上面的示例使用節(jié)點(diǎn)標(biāo)簽,因?yàn)闃?biāo)簽是以引用的node.labels.datacenter
。要分布引擎標(biāo)簽的值,請使用--placement-pref spread=engine.labels.<labelname>
。
可以向服務(wù)添加多個(gè)展示位置偏好設(shè)置。這建立了偏好的層次結(jié)構(gòu),因此任務(wù)首先被劃分為一個(gè)類別,然后進(jìn)一步劃分為其他類別。這可能有用的一個(gè)例子是在數(shù)據(jù)中心之間公平地分配任務(wù),然后將每個(gè)數(shù)據(jù)中心內(nèi)的任務(wù)分成多個(gè)機(jī)架。要添加多個(gè)展示位置首選項(xiàng),請--placement-pref
多次指定標(biāo)志。順序非常重要,布置首選項(xiàng)將按進(jìn)行排定決策時(shí)的順序應(yīng)用。
以下示例使用多個(gè)展示位置首選項(xiàng)設(shè)置服務(wù)。任務(wù)首先在各個(gè)數(shù)據(jù)中心上傳播,然后在機(jī)架上傳播(如各個(gè)標(biāo)簽所示):
$ 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服務(wù)更新更新服務(wù)時(shí),--placement-pref-add會(huì)在所有現(xiàn)有展示位置首選項(xiàng)之后附加新的展示位置首選項(xiàng)。 --placement-pref-rm刪除與參數(shù)匹配的現(xiàn)有展示位置偏好設(shè)置。
在創(chuàng)建服務(wù)時(shí),您可以指定滾動(dòng)更新行為,以便在運(yùn)行docker服務(wù)更新時(shí)swarm應(yīng)該如何將更改應(yīng)用于服務(wù)。 您也可以將這些標(biāo)志指定為更新的一部分,作為docker服務(wù)更新的參數(shù)。
該--update-delay
標(biāo)志配置更新服務(wù)任務(wù)或多組任務(wù)之間的時(shí)間延遲。您可以將時(shí)間描述T
為秒數(shù)Ts
,分鐘數(shù)Tm
或小時(shí)數(shù)的組合Th
。因此10m30s
表示延遲10分30秒。
默認(rèn)情況下,調(diào)度程序一次更新1個(gè)任務(wù)。 您可以傳遞--update-parallelism標(biāo)志來配置調(diào)度程序同時(shí)更新的最大服務(wù)任務(wù)數(shù)。
當(dāng)對單個(gè)任務(wù)的更新返回RUNNING狀態(tài)時(shí),調(diào)度程序通過繼續(xù)執(zhí)行另一個(gè)任務(wù)來繼續(xù)更新,直到更新所有任務(wù)。 如果在更新期間任何時(shí)候任務(wù)返回FAILED,則調(diào)度程序會(huì)暫停更新。 您可以使用docker service create或docker service update的--update-failure-action標(biāo)志來控制行為。
在下面的示例服務(wù)中,調(diào)度程序一次最多應(yīng)用2個(gè)副本。當(dāng)更新的任務(wù)返回RUNNING
或者FAILED
,調(diào)度程序在停止下一個(gè)任務(wù)更新之前等待10秒鐘:
$ docker service create \ --replicas 10 \ --name my_web \ --update-delay 10s \ --update-parallelism 2 \ --update-failure-action continue \ alpine
--update-max-failure-ratio標(biāo)志控制在更新之前更新的整個(gè)過程中可能失敗的部分任務(wù)可能失敗。 例如,使用--update-max-failure-ratio 0.1 --update-failure-action暫停,10%的任務(wù)更新失敗后,更新將暫停。
如果任務(wù)未啟動(dòng),或者在--update-monitor標(biāo)志指定的監(jiān)視時(shí)間段內(nèi)停止運(yùn)行,則認(rèn)為單個(gè)任務(wù)更新失敗。 --update-monitor的默認(rèn)值為30秒,這意味著任務(wù)在其開始后的前30秒內(nèi)失敗,將計(jì)入服務(wù)更新失敗閾值,并且在此之后的失敗將不計(jì)入。
如果更新版本的服務(wù)沒有按預(yù)期運(yùn)行,可以使用docker service update的 - 回滾標(biāo)志手動(dòng)回滾到服務(wù)的先前版本。 這會(huì)將服務(wù)恢復(fù)到最新的Docker服務(wù)更新命令之前的配置。
其他選項(xiàng)可以與--rollback; 例如,--update-delay 0s在任務(wù)之間執(zhí)行回滾而沒有延遲:
$ docker service update \ --rollback \ --update-delay 0s my_web
在Docker 17.04及更高版本中,如果服務(wù)更新未能部署,您可以將服務(wù)配置為自動(dòng)回滾。如果更新失敗,請參閱自動(dòng)回滾。
與新的自動(dòng)回滾功能相關(guān),在Docker 17.04及更高版本中,如果守護(hù)程序運(yùn)行Docker 17.04或更高版本,手動(dòng)回滾將在服務(wù)器端而不是客戶端進(jìn)行處理。這允許手動(dòng)啟動(dòng)的回滾來遵守新的回滾參數(shù)??蛻舳耸前姹靖兄模运匀粫?huì)使用舊的守護(hù)進(jìn)程的方法。
最后,在Docker 17.04及更高版本中, - rollback不能與其他標(biāo)志一起用于docker服務(wù)更新。
您可以通過以下方式來配置服務(wù):如果對服務(wù)的更新導(dǎo)致重新部署失敗,則該服務(wù)可以自動(dòng)回滾到以前的配置。這有助于保護(hù)服務(wù)可用性。您可以在創(chuàng)建或更新服務(wù)時(shí)設(shè)置以下一個(gè)或多個(gè)標(biāo)志。如果您未設(shè)置值,則使用默認(rèn)值。
旗 | 默認(rèn) | 描述 |
---|---|---|
--rollback延遲 | 0 | 在回滾下一個(gè)任務(wù)之前回滾任務(wù)之后要等待的時(shí)間量。值為0意味著在部署第一個(gè)回滾任務(wù)后立即回滾第二個(gè)任務(wù)。 |
--rollback故障影響的行動(dòng) | 暫停 | 當(dāng)任務(wù)無法回滾時(shí),是暫停還是繼續(xù)嘗試回滾其他任務(wù)。 |
--rollback-MAX-故障率 | 0 | 在回滾期間容忍的故障率,指定為介于0和1之間的浮點(diǎn)數(shù)。例如,給定5個(gè)任務(wù),故障率為0.2將允許一個(gè)任務(wù)無法回滾。值為0表示不允許失敗,值為1表示允許任意數(shù)量的失敗。 |
--rollback顯示器 | 5S | 每個(gè)任務(wù)回滾之后的持續(xù)時(shí)間以監(jiān)視失敗。如果任務(wù)在此時(shí)間段過去之前停止,則認(rèn)為回滾失敗。 |
--rollback并行性 | 1 | 并行回滾的最大任務(wù)數(shù)。默認(rèn)情況下,一次回滾一個(gè)任務(wù)。值為0將導(dǎo)致所有任務(wù)并行回滾。 |
以下示例將配置redis服務(wù),以在Docker服務(wù)更新未能部署時(shí)自動(dòng)回滾。 兩個(gè)任務(wù)可以并行回滾。 任務(wù)在回滾后監(jiān)視20秒,以確保它們不會(huì)退出,并且最大失敗率為20%是可以接受的。 默認(rèn)值用于--rollback-delay和--rollback-failure-action。
$ docker service create --name=my_redis \ --replicas=5 \ --rollback-parallelism=2 \ --rollback-monitor=20s \ --rollback-max-failure-ratio=.2 \ redis:latest
為了獲得最佳性能和可移植性,您應(yīng)避免將重要數(shù)據(jù)直接寫入容器的可寫層,而應(yīng)使用數(shù)據(jù)卷或綁定掛載。這一原則也適用于服務(wù)。
您可以為swarm中的服務(wù)創(chuàng)建兩種類型的掛載,卷掛載或綁定掛載。 無論使用哪種類型的掛載,在創(chuàng)建服務(wù)時(shí)使用--mount標(biāo)志進(jìn)行配置,或在更新現(xiàn)有服務(wù)時(shí)使用--mount-add或--mount-rm標(biāo)志進(jìn)行配置。如果你沒有指定類型,則默認(rèn)值是數(shù)據(jù)卷
數(shù)據(jù)卷是在刪除任務(wù)的容器后保持活動(dòng)的存儲。裝入卷的首選方法是利用現(xiàn)有卷:
$ docker service create \ --mount src=<VOLUME-NAME>,dst=<CONTAINER-PATH> \ --name myservice \ <IMAGE>
有關(guān)如何創(chuàng)建卷的更多信息,請參閱volume create
CLI參考。
以下方法在部署時(shí)在調(diào)度程序調(diào)度任務(wù)時(shí)創(chuàng)建卷,即在啟動(dòng)容器之前:
$ docker service create \ --mount type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=<DRIVER>,volume-opt=<KEY0>=<VALUE0>,volume-opt=<KEY1>=<VALUE1> --name myservice \ <IMAGE>
重要說明:如果您的卷驅(qū)動(dòng)程序接受逗號分隔列表作為選項(xiàng),則必須從外部CSV分析程序中轉(zhuǎn)義該值。 要轉(zhuǎn)義卷-opt,請用雙引號(“)括起來,并用單引號(')括住整個(gè)裝入?yún)?shù)。
例如,本地驅(qū)動(dòng)程序接受掛載選項(xiàng)作為o參數(shù)中的逗號分隔列表。 此示例顯示了轉(zhuǎn)義列表的正確方法。
$ docker service create \ --mount'type = volume,src = <VOLUME-NAME>,dst = <CONTAINER-PATH>,volume-driver = local,volume-opt = type = nfs,volume-opt = device = < nfs-server>:<nfs-path>,“volume-opt = o = addr = <nfs-address>,vers = 4,soft,timeo = 180,bg,tcp,rw”' - myservice \ <IMAGE>
綁定掛載是調(diào)度程序?yàn)樵撊蝿?wù)部署容器的主機(jī)的文件系統(tǒng)路徑。Docker將路徑安裝到容器中。文件系統(tǒng)路徑必須在swarm為任務(wù)初始化容器之前存在。
以下示例顯示了綁定掛載語法:
要掛載一個(gè)讀寫綁定:$ docker service create \ --mount type = bind,src = <HOST-PATH>,dst = <CONTAINER-PATH> \ --name myservice \ <IMAGE>
要裝入一個(gè)只讀綁定:$ docker service create \ --mount type = bind,src = <HOST-PATH>,dst = <CONTAINER-PATH>,只讀\ --name myservice \ <IMAGE>
重要提示:綁定安裝可能很有用,但它們也可能導(dǎo)致問題。在大多數(shù)情況下,建議您構(gòu)建應(yīng)用程序,以便不需要從主機(jī)安裝路徑。主要風(fēng)險(xiǎn)包括以下幾點(diǎn):
如果將主機(jī)路徑綁定到服務(wù)的容器中,則該路徑必須存在于每個(gè)群集節(jié)點(diǎn)上。Docker群模式調(diào)度程序可以在滿足資源可用性要求的任何機(jī)器上調(diào)度容器,并滿足您指定的所有約束和位置偏好。
如果Docker群模式調(diào)度程序變得不健康或無法訪問,Docker群模式調(diào)度程序可能會(huì)隨時(shí)重新安排正在運(yùn)行的服務(wù)容器。
主機(jī)綁定掛載是完全不可移植的。當(dāng)您使用綁定掛載時(shí),不能保證您的應(yīng)用程序在開發(fā)過程中的運(yùn)行方式與生產(chǎn)過程中的運(yùn)行方式相同。
您可以使用service create
Go的文本/模板軟件包提供的語法來為某些標(biāo)志使用模板。
支持以下標(biāo)志:
--hostname
--mount
--env
Go模板的有效占位符是:
占位符 | 描述 |
---|---|
.Service.ID | 服務(wù)ID |
.Service.Name | 服務(wù)名稱 |
.Service.Labels | 服務(wù)標(biāo)簽 |
.Node.ID | 節(jié)點(diǎn)ID |
.Task.Name | 任務(wù)名稱 |
.Task.Slot | 任務(wù)槽 |
本示例根據(jù)服務(wù)的名稱和容器運(yùn)行節(jié)點(diǎn)的ID來設(shè)置創(chuàng)建的容器的模板:
$ docker service create --name hosttempl \ --hostname="{{.Node.ID}}-{{.Service.Name}}"\ busybox top
要查看使用模板的結(jié)果,請使用docker service ps
和docker inspect
命令。
$ docker service ps va8ew30grofhjoychbr6iot8c ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS wo41w8hg8qan hosttempl.1 busybox:latest@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912 2e7a8a9c4da2 Running Running about a minute ago
$ docker inspect --format="{{.Config.Hostname}}" hosttempl.1.wo41w8hg8qanxwjwsg4kxpprj
群體管理指南
Docker引擎命令行參考
Swarm模式教程