1. 程式人生 > >docker swarm英文文件學習-8-在叢集中部署服務

docker swarm英文文件學習-8-在叢集中部署服務

Deploy services to a swarm在叢集中部署服務

叢集服務使用宣告式模型,這意味著你需要定義服務的所需狀態,並依賴Docker來維護該狀態。該狀態包括以下資訊(但不限於):

應該執行服務容器的映象名稱和標記
有多少容器參與服務
是否有任何埠暴露給叢集之外的客戶端
當Docker啟動時,服務是否應該自動啟動
重啟服務時發生的特定行為(例如是否使用滾動重啟)
服務可以執行的節點的特徵(例如資源約束和位置首選項)
有關群模式的概述,請參見 Swarm mode key concepts。有關服務如何工作的概述,請參見How services work

 

Create a service建立服務

要建立沒有額外配置的單副本服務,只需要提供映象名稱。該命令使用隨機生成的名稱啟動Nginx服務,沒有釋出埠。這是一個簡單的示例,因為你無法與Nginx服務互動。

$ docker service create nginx

服務被安排在一個可用的節點上。要確認服務已建立併成功啟動,請使用docker service ls命令:

$ docker service ls

ID                  NAME                MODE                REPLICAS            IMAGE                                                                                             PORTS
a3iixnklxuem        quizzical_lamarr    replicated          
1/1 docker.io/library/[email protected]:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268

建立的服務並不總是立即執行。如果服務的映象不可用,如果沒有節點滿足你為服務配置的需求,或者其他原因,則該服務可能處於pending掛起狀態。有關更多資訊,請參見 Pending services

要為你的服務提供名稱,請使用--name標誌:

$ docker service create --name my_web nginx

與獨立容器一樣,你可以通過在映象名稱之後新增命令來指定服務容器應該執行的命令。這個例子啟動了一個名為helloworld的服務,它使用alpine的映象並執行命令ping docker.com:

$ docker service create --name helloworld alpine ping docker.com

你還可以為要使用的服務指定一個映象標記。這個例子修改了前面的例子,使用alpine:3.6標記:

$ docker service create --name helloworld alpine:3.6 ping docker.com

 

Create a service using an image on a private registry使用私有登錄檔上的映象建立服務

如果你的映象在需要登入的私有註冊中心上可用,請在登入後使用docker service create的--with-registry-auth標誌。如果你的映象儲存在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日誌將登入令牌從本地客戶機傳遞到部署服務的叢集節點。有了這些資訊,節點就可以登入到註冊中心並拉出映象。

 

Update a service更新服務

你可以使用docker service update命令更改現有服務的幾乎所有內容。更新服務時,Docker將停止其容器並使用新配置重新啟動它們。

由於Nginx是一個web服務,如果你將埠80釋出到叢集之外的客戶端,那麼它的工作效果會更好。你可以在建立服務時使用-p或--publish標誌指定這一點。更新現有服務時,標誌為--publish-add。還有一個--publish-rm標誌,用於刪除先前釋出的埠。

假設上一節中的my_web服務仍然存在,使用以下命令更新它以釋出埠80。

$ docker service update --publish-add 80 my_web

檢查其是否工作,使用:

docker service ls

有關釋出埠如何工作的更多資訊,請參見publish ports

你幾乎可以更新關於現有服務的所有配置細節,包括它執行的映象名稱和標記。參見Update a service’s image after creation

 

Remove a service移除服務

要刪除服務,請使用docker service remove命令。你可以通過其ID或名稱刪除服務,如docker service ls命令的輸出所示。下面的命令刪除my_web服務。

$ docker service remove my_web

 

Service configuration details服務配置細節

下面幾節提供關於服務配置的詳細資訊。本主題並不涵蓋每個標誌或場景。在幾乎所有可以在服務建立時定義配置的例項中,你還可以以類似的方式更新現有服務的配置。

請參閱docker service createdocker service update的命令列引用,或使用--help標誌執行這些命令之一。

Configure the runtime environment配置執行環境

你可以為容器中的執行時環境配置以下選項:

  • 使用--env標誌表示的環境變數
  • 容器內使用--workdir標誌表示的工作目錄
  • 使用--user標誌表示的使用者名稱或UID

以下服務的容器將環境變數$MYVAR設定為myvalue,從/tmp/目錄執行,並作為my_user使用者執行。

$ docker service create --name helloworld \
  --env MYVAR=myvalue \
  --workdir /tmp \
  --user my_user \
  alpine ping docker.com

 

Update the command an existing service runs更新存在的服務執行的命令

要更新現有服務執行的命令,可以使用--args標誌。下面的示例更新一個名為helloworld的現有服務,使其執行ping docker.com命令,而不是以前執行的任何命令:

$ docker service update --args "ping docker.com" helloworld

 

 

Specify the image version a service should use指定服務應該使用的映象版本

當你建立一個服務而沒有指定要使用的映象版本的任何細節時,該服務將使用使用latest標記來標記的版本。根據期望的結果,你可以強制服務以幾種不同的方式使用映象的特定版本。
一個映象版本可以用幾種不同的方式表達:
1.如果指定一個標記,則管理器(如果使用content trust,則為Docker客戶機)將該標記解析為摘要。當在工作節點上接收到建立容器任務的請求時,工作節點只會看到摘要,而不會看到標記。

注意:

標記即ubuntu:16.04

摘要即對應的sha256:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1

$ docker service create --name="myservice" ubuntu:16.04

一些標籤表示獨立的版本,比如ubuntu:16.04。隨著時間的推移,這樣的標記幾乎總是解析為一個穩定的摘要。如果可能的話,建議你使用這種標記。
其他型別的標記,如latest或nightly,可能經常解析為新的摘要,這取決於映象的作者更新標記的頻率。不建議使用頻繁更新的標記執行服務,以防止不同的服務複製任務使用不同的映象版本。


2.如果根本不指定版本,則按照約定將映象的latest標記解析為摘要。工作人員在建立服務任務時使用此摘要中的映象。
因此,以下兩個命令是等價的:

$ docker service create --name="myservice" ubuntu

$ docker service create --name="myservice" ubuntu:latest

 

3.如果直接指定摘要,則在建立服務任務時總是使用映象的準確版本。

$ docker service create \
    --name="myservice" \
    ubuntu:16.04@sha256:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1

在建立服務時,映象的標記被解析為服務建立時標記所指向的特定摘要。除非服務被顯式更新,否則該服務的工作節點將永遠使用該特定摘要。如果你確實使用經常更改的標記(如最新),則此功能尤其重要,因為它確保所有服務任務使用相同版本的映象。

注意:如果啟用了內容可信(content trust),客戶端實際上會在聯絡叢集管理器之前將映象的標記解析為摘要,以驗證映象是否已簽名。因此,如果你使用內容可信,叢集管理器將接收預先解析的請求。在這種情況下,如果客戶機無法將映象解析為摘要,則請求將失敗。

如果管理器不能將標記解析為摘要,則每個工作節點負責將標記解析為摘要,不同的節點可能使用不同版本的映象。如果發生這種情況,將記錄如下所示的警告,用佔位符替換實際資訊。

unable to pin image <IMAGE-NAME> to digest: <REASON>

要檢視影象的當前摘要,發出命令docker inspect <IMAGE>:<TAG>並查詢RepoDigests行。以下是ubuntu:latest當前的摘要,在編寫此內容時是最新的。為了清晰起見,輸出被截斷。

$ docker inspect ubuntu:latest
...
"RepoDigests": [
  "[email protected]:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1"
],
...

建立服務之後,除非你使用--image標記顯式地執行docker service update,否則它的映象永遠不會更新,如下所述。其他更新操作(如擴充套件服務、新增或刪除網路或卷、重新命名服務或任何其他型別的更新操作)不更新服務的映象。

 

Update a service’s image after creation建立後更新服務的映象

每個標記表示一個摘要,類似於Git雜湊。有些標記(如latest)經常更新以指向新的摘要。其他的,比如ubuntu:16.04,代表了一個已經發布的軟體版本,不需要經常更新以指向一個新的摘要。在Docker 1.13及更高版本中,當你建立服務時,它被限制為使用映象的特定摘要來建立任務,直到你使用--image標誌的service update來更新服務為止。如果使用舊版本的Docker引擎,則必須刪除並重新建立服務以更新其映象。

當你使用--image標誌執行service update時,swarm manager查詢Docker Hub或你的私有Docker登錄檔,以獲取標記當前指向的摘要,並更新服務任務以使用該摘要。

注意:如果使用內容可信content trust,Docker客戶機解析映象,swarm manager接收映象和摘要,而不是標記。
通常,管理器可以將標記解析為新的摘要和服務更新,重新部署每個任務以使用新映象。如果管理器無法解決標記或出現其他問題,則接下來的兩個部分將概述將會發生的情況。

IF THE MANAGER RESOLVES THE TAG如果管理器解析標記

如果叢集管理器可以將映象標記解析為摘要,它將指示工作節點重新部署任務並在摘要中使用映象。

  • 如果工作人員在該摘要中快取了映象,則使用它。
  • 如果不是,則嘗試從Docker Hub或私有註冊中心提取映象:
  1. 如果成功,則使用新映象部署任務。
  2. 如果worker無法拉出映象,則服務無法在該worker節點上部署。Docker再次嘗試部署任務,可能是在不同的工作節點上。

IF THE MANAGER CANNOT RESOLVE THE TAG如果管理器不能解析標記

如果叢集管理器不能將映象解析為摘要,那麼一切都不會丟失:

  • 管理器指示工作節點使用標記處的映象重新部署任務。
  • 如果worker有一個本地快取的映象,該映象將解析到該標記,那麼它將使用該映象。
  • 如果worker沒有解析到標記的本地快取映象,則該worker將嘗試連線到Docker Hub或私有註冊中心以從該標記提取映象。
  1. 如果成功,工作人員將使用該映象。
  2. 如果失敗,任務將無法部署,管理員將再次嘗試部署任務,可能是在不同的工作節點上。

 

Publish ports釋出埠

在建立叢集服務時,可以通過兩種方式將該服務的埠釋出到叢集之外的主機:

  • 你可以依賴路由網格。當你釋出一個服務埠時,叢集使服務在每個節點上的目標埠都可以訪問,而不管在該節點上執行的服務是否有任務。這並不複雜,而且對於許多型別的服務來說都是正確的選擇。
  • 你可以將服務任務的埠直接釋出到執行該服務的叢集節點上。該特性在Docker 1.13及更高版本中可用。這繞過了路由網格,並提供了最大的靈活性,包括開發自己的路由框架的能力。但是,你負責跟蹤每個任務的執行位置,並將請求路由到任務,以及跨節點的負載平衡。

1.PUBLISH A SERVICE’S PORTS USING THE ROUTING MESH使用路由網格釋出服務埠

要向叢集外部發布服務的埠,使用--publish <PUBLISHED-PORT>:<SERVICE-PORT>。叢集使得服務可以在每個叢集節點上的已釋出埠上訪問。如果外部主機連線到任何叢集節點上的該埠,則路由網格將其路由到一個任務。外部主機不需要知道與服務互動的服務任務的IP地址或內部使用的埠。當用戶或流程連線到服務時,執行服務任務的任何工作節點都可能響應。有關叢集服務網路的詳細資訊,請參見Manage swarm service networks

Example: Run a three-task Nginx service on 10-node swarm 例子:在10個節點叢集中執行三個任務的Ngnix服務

想象你有10個節點的叢集,然後你部署了一個Ngnix服務在10個節點上執行三個任務:

$ docker service create --name my_web \
                        --replicas 3 \
                        --publish published=8080,target=80 \
                        nginx

三個任務最多在三個節點上執行。你不需要知道哪些節點正在執行任務;在這10個節點中,連線到埠8080可以將你連線到三個nginx任務之一。你可以用curl來測試。下面的示例假設localhost是叢集節點之一。如果不是這種情況,或者本地主機沒有解析到你的主機上的IP地址,則替換主機的IP地址或可解析的主機名。

HTML輸出被截斷:

$ curl localhost:8080

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...truncated...
</html>

後續連線可以路由到相同或不同的群集節點。

 

PUBLISH A SERVICE’S PORTS DIRECTLY ON THE SWARM NODE直接在叢集節點中釋出服務埠

如果需要根據應用程式的狀態進行路由決策,或者需要完全控制將請求路由到服務任務的流程,那麼使用路由網格可能不是應用程式的正確選擇。要將服務的埠直接釋出到其執行的節點上,請使用--publish標誌的mode=host選項。

注意:如果你使用mode=host在swarm節點上直接釋出一個服務的埠,並且還設定published=<PORT>,這就造成了一個隱含的限制,即你只能在給定的swarm節點上為該服務執行一個任務。你可以通過在沒有埠定義的情況下指定published來解決這個問題,這會導致Docker為每個任務分配一個隨機埠。

此外,如果你使用mode=host而不使用docker service create上的--mode=global標誌,那麼很難知道哪些節點正在執行服務來將工作路由到它們。

 

Example: Run an nginx web server service on every swarm node 例子:在每個叢集節點上執行nginx web伺服器服務

nginx是一個開源的反向代理、負載平衡器、HTTP快取和web伺服器。如果你使用路由網格將nginx作為服務執行,那麼連線到任何叢集節點上的nginx埠都會顯示(有效地)執行該服務的隨機叢集節點的web頁面。

下面的示例將nginx作為服務在叢集中的每個節點上執行,並在每個叢集節點上本地公開nginx埠。

$ docker service create \
  --mode global \
  --publish mode=host,target=80,published=8080 \
  --name=nginx \
  nginx:latest

你可以在每個叢集節點的埠8080上訪問nginx伺服器。如果向叢集中新增一個節點,就會啟動nginx任務。你不能在任何繫結到埠8080的叢集節點上啟動另一個服務或容器。

注意:這是一個簡單的例子。為多層服務建立應用層路由框架非常複雜,超出了本主題的範圍。

 

Connect the service to an overlay network連線服務到覆蓋網路

你可以使用覆蓋網路來連線群中的一個或多個服務。
首先,使用docker network create命令和--driver overlay標記在管理器節點上建立覆蓋網路。

$ docker network create --driver overlay my-network

在叢集模式下建立覆蓋網路之後,所有管理器節點都可以訪問該網路。
你可以建立一個新的服務,並傳遞--network標誌,將服務附加到覆蓋網路:

$ docker service create \
  --replicas 3 \
  --network my-network \
  --name my-web \
  nginx

該叢集將my-network擴充套件到執行服務的每個節點。
你還可以使用--network-add標誌將現有服務連線到覆蓋網路。

$ docker service update --network-add my-network my-web

要從網路斷開正在執行的服務,請使用--network-rm標誌。

$ docker service update --network-rm my-network my-web

 

Grant a service access to secrets授予服務對機密的訪問權

要建立對docker管理的機密內容有訪問許可權的服務,請使用--secret標誌。有關更多資訊,請參見Manage sensitive strings (secrets) for Docker services

Customize a service’s isolation mode自定義服務的隔離模式

Docker 17.12 CE及更高版本允許你指定叢集服務的隔離模式。此設定僅適用於Windows主機,對於Linux主機則忽略此設定。隔離模式可以是以下模式之一:

  • default:使用為Docker主機配置的預設隔離模式,如daemon.json中的-exec-opt標誌或exec-opts陣列所配置的那樣。如果守護程序沒有指定隔離技術,則process是Windows伺服器的預設設定,而hyperv是Windows 10的預設(且唯一)選擇。
  • process:將服務任務作為獨立的程序在主機上執行。

    注意:process隔離模式僅在Windows伺服器上受支援。Windows 10只支援hyperv隔離模式。

  • hyperv:將服務任務作為獨立的hyperv任務執行。這增加了開銷,但提供了更多的隔離。

在使用--isolation標誌建立或更新新服務時,可以指定隔離模式。

 

Control service placement控制服務位置

群服務為你提供了幾種不同的方法來控制不同節點上服務的規模和位置。

  • 你可以指定服務需要執行特定數量的副本,還是應該在每個工作節點上全域性執行。參見Replicated or global services
  • 你可以配置服務的CPU或記憶體需求,並且服務只在滿足這些需求的節點上執行。
  • 位置約束允許你將服務配置為僅在具有特定(任意)元資料集的節點上執行,如果不存在適當的節點,則會導致部署失敗。例如,你可以指定你的服務只能在任意標籤pci_compatible設定為true的節點上執行。
  • 位置首選項讓你可以對每個節點應用具有一系列值的任意標籤,並使用演算法將服務的任務分散到這些節點上。目前,唯一受支援的演算法是spread,它試圖將它們平均放置。例如,如果你標記每個節點帶著一個值從1到10的標籤rack,然後指定一個位置首選項值標籤rack,然後在其他位置限制,位置偏好,和其他特定於節點的限制後,服務任務將盡可能均勻地放置在所有帶著標籤rack的節點,。

與約束不同,位置首選項是最有效的,如果沒有節點能夠滿足首選項,服務不會失敗部署。如果你指定了服務的位置首選項,那麼當叢集管理器決定哪些節點應該執行服務任務時,與該首選項匹配的節點的排名會更高。其他因素,如服務的高可用性,也會影響到計劃在其中執行服務任務的節點。舉個例子,如果你有N個節點帶著標籤(還有一些其他人),和你的服務配置是要執行N + 1副本,首先將會降N個任務放置到帶有rack標籤的節點上,然後+ 1將排程到一個並沒有服務在上面的節點,如果這個節點存在,無論該節點帶有rack標籤或不帶有。

 

REPLICATED OR GLOBAL SERVICES複製或全域性服務

叢集模式有兩種服務型別:複製replicated服務和全域性global服務。對於複製的服務,你可以為swarm manager指定要排程到可用節點上的複製任務的數量。對於全域性服務,排程器在滿足服務的位置約束和資源需求的每個可用節點上放置一個任務。
使用--mode標誌控制服務的型別。如果不指定模式,則服務預設為複製。對於複製的服務,指定要開始使用--replicas標誌的複製任務的數量。例如,使用3個複製任務啟動一個複製的nginx服務:

$ docker service create \
  --name my_web \
  --replicas 3 \
  nginx

要在每個可用節點上啟動全域性服務,請將--mode global傳遞給docker service create。每當新節點可用時,排程器將全域性服務的任務放置在新節點上。例如,啟動一個在群中的每個節點上執行alpine的服務:

$ docker service create \
  --name myservice \
  --mode global \
  alpine top

服務約束允許你在排程程式將服務部署到節點之前為節點設定要滿足的條件。你可以基於節點屬性和元資料或引擎元資料對服務應用約束。有關約束的更多資訊,請參閱docker service create CLI reference

 

RESERVE MEMORY OR CPUS FOR A SERVICE為服務保留記憶體或cpu

若要為服務保留給定的記憶體或cpu數量,請使--reserve-memory或--reserve-cpu標誌。如果沒有可用的節點可以滿足需求(例如,如果你請求4個cpu,而叢集中沒有節點有4個cpu),則服務將保持掛起狀態,直到有合適的節點可以執行其任務為止。

Out Of Memory Exceptions (OOME)

如果你的服務試圖使用比群集節點可用的記憶體更多的記憶體,那麼你可能會遇到記憶體不足異常(OOME),核心OOM殺手可能會殺死容器或Docker守護程序。要防止這種情況發生,請確保你的應用程式在具有足夠記憶體的主機上執行,檢視 Understand the risks of running out of memory.
Swarm服務允許你使用資源約束、位置首選項和標籤來確保你的服務被部署到適當的Swarm節點。

 

PLACEMENT CONSTRAINTS位置約束

使用位置約束來控制可以分配給服務的節點。在下面的示例中,服務僅在標籤region設定為east的節點上執行。如果沒有適當標記的節點可用,任務將在Pending中等待,直到它們可用為止。--constraint標誌使用一個等式運算子(== or !=)。對於複製的服務,可能所有服務都執行在相同的節點上,或者每個節點只執行一個副本,或者一些節點不執行任何副本。對於全域性服務,服務在滿足位置約束和任何資源需求的每個節點上執行。

$ docker service create \
  --name my-nginx \
  --replicas 5 \
  --constraint node.labels.region==east \
  nginx

你還可以在docker-compose.yml檔案中使用constraint服務級別鍵。
如果指定多個放置約束,則服務只部署到所有節點都滿足的節點上。下面的示例將服務限制為在所有節點上執行,其中region設定為east, type設定為devel:

$ docker service create \
  --name my-nginx \
  --mode global \
  --constraint node.labels.region==east \
  --constraint node.labels.type!=devel \
  nginx

還可以將位置約束與位置首選項和CPU/記憶體約束結合使用。注意不要使用不可能完成的設定。
有關約束的更多資訊,請參閱docker service create CLI reference

 

PLACEMENT PREFERENCES位置首選項

雖然位置約束限制了服務可以在其上執行的節點,但是位置首選項嘗試以演算法的方式將服務放置在適當的節點上(目前,僅平均分佈)。例如,如果你為每個節點分配一個rack標籤,那麼你可以設定一個位置首選項,通過值將服務均勻地分佈到帶有rack標籤的節點上。這樣,如果你丟失了一個rack,服務仍然在其他rack上的節點上執行。
位置首選項不嚴格執行。如果沒有節點具有你在首選項中指定的標籤,則會像未設定首選項一樣部署服務。
全域性服務忽略位置首選項。
下面的示例設定了一個首選項,根據datacenter標籤的值將部署分散到節點上。如果某些節點具有datacenter=us-east,而其他節點具有datacenter=us-west,則服務在這兩組節點之間儘可能均勻地部署。

$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref 'spread=node.labels.datacenter' \
  redis:3.0.6

⚠️Missing or null labels

缺少用於擴充套件的標籤的節點仍然接收任務分配。作為一個組,這些節點接收任務的比例與由特定標籤值標識的任何其他組相同。從某種意義上說,缺失的標籤等同於標籤上附加了一個空null值。如果服務應該只在使用spread首選項的標籤的節點上執行,則應該將首選項與約束結合起來。

你可以指定多個位置首選項,並按照遇到的順序處理它們。下面的示例設定具有多個位置首選項的服務。任務首先分佈在各個datacenters,然後分佈在rack上(如各自的標籤所示):

$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref 'spread=node.labels.datacenter' \
  --placement-pref 'spread=node.labels.rack' \
  redis:3.0.6

還可以將位置首選項與位置約束或CPU/記憶體約束結合使用。注意不要使用不可能完成的設定。
這個圖表說明瞭如何放置首選項工作:

當使用docker service update更新服務時,--placater -pref-add在所有現有的放置首選項之後追加一個新的放置首選項。--placater-pref-rm刪除與引數匹配的現有位置首選項。

 

Configure a service’s update behavior配置服務的更新行為

在建立服務時,可以指定一個滾動更新行為,說明在執行docker service update時叢集應該如何將更改應用於服務。你還可以將這些標誌指定為更新的一部分,作為docker service update的引數。
--update-delay標誌配置服務任務或任務集更新之間的時間延遲。你可以將時間T描述為Ts秒數、Tm分鐘數或Th小時數的組合。所以10m30s表示10分30秒的延遲。
預設情況下,排程程式每次更新一個任務。你可以傳遞--update-parallelism標誌來配置排程程式同時更新的服務任務的最大數量。

當對單個任務的更新返回RUNNING的狀態時,排程器將繼續更新,方法是繼續到另一個任務,直到所有任務都被更新。如果在更新期間某個任務返回FAILED,排程程式將暫停更新。你可以使用docker service create或docker service update的--update-failure-action標誌來控制行為。

在下面的示例服務中,排程器每次最多應用兩個副本的更新。當更新後的任務返回RUNNING或FAILED時,排程器將等待10秒後停止下一個任務更新:

$ docker service create \
  --replicas 10 \
  --name my_web \
  --update-delay 10s \
  --update-parallelism 2 \
  --update-failure-action continue \
  alpine

--update-max-failure-ratio標誌控制在整個更新被認為失敗之前的更新過程中有多少任務會失敗。例如,使用--update-max-failure-ratio 0.1 --update-failure-action pause,在更新的任務中有10%失敗後,更新將暫停。

如果任務沒有啟動,或者在--update-monitor標誌指定的監視週期內停止執行,則認為單個任務更新失敗。--update-monitor的預設值是30秒,這意味著在任務啟動後的前30秒內失敗的任務將計入服務更新失敗閾值,而啟動後的失敗則不計入。

 

Roll back to the previous version of a service回滾到服務的上一個版本

如果服務的更新版本沒有如預期那樣發揮作用,可以使用docker service update的--rollback標誌手動回滾到服務的前一個版本。這將服務恢復到docker service update命令之前的配置。

其他選項可以與--rollback結合使用;例如--update-delay 0s執行回滾,任務之間不存在延遲:

$ docker service update \
  --rollback \
  --update-delay 0s
  my_web

在Docker 17.04及更高版本中,可以配置服務,以便在服務更新部署失敗時自動回滾。參見Automatically roll back if an update fails
與新的自動回滾特性相關的是,在Docker 17.04及更高版本中,如果守護程序執行Docker 17.04或更高版本,則手動回滾將在伺服器端處理,而不是在客戶端處理。這允許手動啟動的回滾尊重新的回滾引數。客戶機是版本敏感的,因此它仍然對較舊的守護程序使用舊方法。
最後,在Docker 17.04及更高版本中,--rollback不能與Docker服務更新的其他標誌一起使用。

 

Automatically roll back if an update fails如果更新失敗則自動回滾

你可以這樣配置服務:如果對服務的更新導致重新部署失敗,服務可以自動回滾到上一個配置。這有助於保護服務可用性。你可以在服務建立或更新時設定以下一個或多個標誌。如果沒有設定值,則使用預設值。

Flag Default Description
--rollback-delay 0s 指定在回滾一個任務之後等待的時間,然後再回滾下一個任務。值0表示在第一個回滾任務部署之後立即回滾第二個任務。
--rollback-failure-action pause 當一個任務無法回滾時,是暫停還是繼續嘗試回滾其他任務。
--rollback-max-failure-ratio 0 回滾期間容忍的失敗率,指定為0到1之間的浮點數。例如,給定5個任務,.2的失敗率將允許一個任務(0.2*5=1)不能回滾。值為0表示不允許出現故障,值為1表示允許出現任意數量的故障。
--rollback-monitor 5s 每個任務回滾後的持續時間,以監視失敗情況。如果任務在此時間段結束之前停止,則認為回滾失敗。
--rollback-parallelism 1 並行回滾的最大任務數。預設情況下,一次回滾一個任務。值0將導致並行回滾所有任務。

下面的示例將redis服務配置為在docker service update部署失敗時自動回滾。兩個任務可以並行回滾。在回滾之後,將對任務進行20秒的監視,以確保它們不退出,並且允許最大失敗率為20%。預設值用於--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

 

Give a service access to volumes or bind mounts授予服務訪問卷或繫結掛載的許可權

為了獲得最佳的效能和可移植性,應該避免將重要資料直接寫入容器的可寫層,而是使用資料量或繫結掛載。這個原則也適用於服務。

你可以為群集中的服務建立兩種型別的掛載,volume掛載或bind掛載。無論使用哪種型別的掛載,在建立服務時使用--mount標誌配置它,在更新現有服務時使用--mount-add或--mount-rm標誌配置它。如果不指定型別,預設值是一個數據卷。

DATA VOLUMES資料卷

資料卷是獨立於容器存在的儲存。叢集服務下的資料量的生命週期類似於容器下的生命週期。卷的壽命比任務和服務長,因此它們的刪除必須單獨管理。可以在部署服務之前建立卷,或者在部署任務時,如果在特定主機上不存在卷,則根據服務上的卷規範自動建立卷。
要將現有資料卷與服務一起使用,請使用--mount標誌:

$ docker service create \
  --mount src=<VOLUME-NAME>,dst=<CONTAINER-PATH> \
  --name myservice \
  <IMAGE>

如果在將任務排程到特定主機時,不存在具有相同<VOLUME-NAME>的卷,則建立一個。預設的卷驅動程式是local的。要使用具有這種按需建立模式的不同卷驅動程式,請使用--mount標誌指定驅動程式及其選項:

$ 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>

有關如何建立資料卷和使用卷驅動程式的更多資訊,請參見 Use volumes.

 

BIND MOUNTS繫結掛載

繫結掛載是來自排程程式為任務部署容器的主機的檔案系統路徑。Docker將路徑裝載到容器中。在叢集初始化任務的容器之前,檔案系統路徑必須存在
下面的例子展示了繫結掛載語法:

  • 要掛載讀寫繫結:
$ docker service create \
  --mount type=bind,src=<HOST-PATH>,dst=<CONTAINER-PATH> \
  --name myservice \
  <IMAGE>
  • 掛載只讀繫結:
$ docker service create \
  --mount type=bind,src=<HOST-PATH>,dst=<CONTAINER-PATH>,readonly \
  --name myservice \
  <IMAGE>

重要提示:繫結掛載可能有用,但也可能導致問題。在大多數情況下,建議你對應用程式進行架構設計,以避免從主機掛載路徑。主要風險包括:

  • 如果將主機路徑繫結到服務容器中,則該路徑必須存在於每個群集節點上。Docker群模式排程程式可以在任何滿足資源可用性要求並滿足你指定的所有約束和位置首選項的機器上排程容器。
  • 如果執行中的服務容器變得不健康或無法訪問,Docker群模式排程程式可能會在任何時候重新排程它們。
  • 主機繫結安裝是不可移植的。在使用繫結掛載時,不能保證應用程式在開發中以與在生產中相同的方式執行。

 

Create services using templates使用模版建立服務

你可以使用Go的文字/模板包提供的語法,為service create的一些標誌使用模板。
支援以下標誌:

  • --hostname
  • --mount
  • --env

Go模板的有效佔位符如下:

Placeholder Description
.Service.ID Service ID
.Service.Name Service name
.Service.Labels Service labels
.Node.ID Node ID
.Node.Hostname Node hostname
.Task.Name Task name
.Task.Slot Task slot

TEMPLATE EXAMPLE模版例子

這個示例根據服務的名稱和執行容器的節點的ID設定建立的容器的模板:

$ docker service create --name hosttempl \
                        --hostname="{{.Node.ID}}-{{.Service.Name}}"\
                         busybox top

要檢視使用模板的結果,請使用docker service ps和docker inspect命令。

$ docker service ps va8ew30grofhjoychbr6iot8c

ID            NAME         IMAGE                                                                                   NODE          DESIRED STATE  CURRENT STATE               ERROR  PORTS
wo41w8hg8qan  hosttempl.1  busybox:[email protected]:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912  2e7a8a9c4da2  Running        Running about a minute ago

 

$ docker inspect --format="{{.Config.Hostname}}" hosttempl.1.wo41w8hg8qanxwjwsg4kxpprj