docker swarm英文文檔學習-8-在集羣中部署服務

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

集羣服務使用聲明式模型,這意味着你須要定義服務的所需狀態,並依賴Docker來維護該狀態。該狀態包括如下信息(但不限於):

應該運行服務容器的鏡像名稱和標記
有多少容器參與服務
是否有任何端口暴露給集羣以外的客戶端
當Docker啓動時,服務是否應該自動啓動
重啓服務時發生的特定行爲(例如是否使用滾動重啓)
服務能夠運行的節點的特徵(例如資源約束和位置首選項)
有關羣模式的概述,請參見 Swarm mode key concepts。有關服務如何工做的概述,請參見How services workhtml

 

Create a service建立服務

要建立沒有額外配置的單副本服務,只須要提供鏡像名稱。該命令使用隨機生成的名稱啓動Nginx服務,沒有發佈端口。這是一個簡單的示例,由於你沒法與Nginx服務交互。node

$ docker service create nginx

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

$ docker service ls

ID                  NAME                MODE                REPLICAS            IMAGE                                                                                             PORTS
a3iixnklxuem        quizzical_lamarr    replicated          1/1                 docker.io/library/nginx@sha256:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268

建立的服務並不老是當即運行。若是服務的鏡像不可用,若是沒有節點知足你爲服務配置的需求,或者其餘緣由,則該服務可能處於pending掛起狀態。有關更多信息,請參見 Pending services

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

$ docker service create --name my_web nginx

與獨立容器同樣,你能夠經過在鏡像名稱以後添加命令來指定服務容器應該運行的命令。這個例子啓動了一個名爲helloworld的服務,它使用alpine的鏡像並運行命令ping docker.com:redis

$ 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

$ docker login registry.example.com

$ docker service  create \
  --with-registry-auth \
  --name my_service \
  registry.example.com/acme/my_image:latest

這將使用加密的WAL日誌將登陸令牌從本地客戶機傳遞到部署服務的集羣節點。有了這些信息,節點就能夠登陸到註冊中心並拉出鏡像。json

 

Update a service更新服務

你可使用docker service update命令更改現有服務的幾乎全部內容。更新服務時,Docker將中止其容器並使用新配置從新啓動它們。

因爲Nginx是一個web服務,若是你將端口80發佈到集羣以外的客戶端,那麼它的工做效果會更好。你能夠在建立服務時使用-p或--publish標誌指定這一點。更新現有服務時,標誌爲--publish-add。還有一個--publish-rm標誌,用於刪除先前發佈的端口。

假設上一節中的my_web服務仍然存在,使用如下命令更新它以發佈端口80。ubuntu

$ 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": [
  "ubuntu@sha256: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:latest@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912  2e7a8a9c4da2  Running        Running about a minute ago

 

$ docker inspect --format="{{.Config.Hostname}}" hosttempl.1.wo41w8hg8qanxwjwsg4kxpprj
相關文章
相關標籤/搜索