日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

如果了解Docker Compose,就會發(fā)現(xiàn)Docker Stack非常簡單。事實上在許多方面,Stack一直是期望的Compose——完全集成到Docker中,并能夠管理應(yīng)用的整個生命周期。

從體系結(jié)構(gòu)上來講,Stack位于Docker應(yīng)用層級的最頂端。Stack基于服務(wù)進行構(gòu)建,而服務(wù)又基于容器,如圖14.1所示。

使用Docker Stack部署應(yīng)用

 

圖14.1 AtSea商店架構(gòu)圖

接下來的章節(jié)分為如下幾部分。

  • 簡單應(yīng)用。
  • 深入分析Stack文件。
  • 部署應(yīng)用。
  • 管理應(yīng)用。

14.2.1 簡單應(yīng)用

本章后續(xù)的內(nèi)容會一直使用示例應(yīng)用AtSea Shop。該示例托管在Github的dockersamples/atsea-sample-shop-App庫中,基于Apache 2.0許可證開源。

使用該應(yīng)用是因為其復(fù)雜度適中,不會因為太復(fù)雜而難以完整解釋。除此之外,該應(yīng)用還是個多服務(wù)應(yīng)用,并且利用了認(rèn)證和安全相關(guān)的技術(shù)。應(yīng)用架構(gòu)如圖14.2所示。

如圖所示,該應(yīng)用由5個服務(wù)、3個網(wǎng)絡(luò)、4個密鑰以及3組端口映射構(gòu)成。具體細(xì)節(jié)將會結(jié)合Stack文件進行分析。

注:

 

在本章中用到服務(wù)一詞時,指的是Docker服務(wù)(由若干容器組成的集合,作為一個整體進行統(tǒng)一管理,并且在Docker API中存在對應(yīng)的服務(wù)對象)。

使用Docker Stack部署應(yīng)用

 

圖14.2 AtSea商店架構(gòu)圖

復(fù)制Github倉庫,以獲取全部源代碼文件。

$ git clone https://github.com/dockersamples/atsea-sample-shop-app.git Cloning
into 'atsea-sample-shop-app'...
remote: Counting objects: 636, done.
remote: Total 636 (delta 0), reused 0 (delta 0), pack-reused 636
Receiving objects: 100% (636/636), 7.23 MiB | 28.25 MiB/s, done.
Resolving deltas: 100% (197/197), done.

該應(yīng)用的代碼由若干目錄和源碼文件組成。讀者可以隨意瀏覽這些文件。但是接下來,重點關(guān)注的文件是docker-stack.yml。該文件通常被稱為Stack文件,在該文件中定義了應(yīng)用及其依賴。

在該文件整體結(jié)構(gòu)中,定義了4種頂級關(guān)鍵字。

version:
services:
networks:
secrets:

version代表了Compose文件格式的版本號。為了應(yīng)用于Stack,需要3.0或者更高的版本。services中定義了組成當(dāng)前應(yīng)用的服務(wù)都有哪些。networks列出了必需的網(wǎng)絡(luò),secrets定義了應(yīng)用用到的密鑰。

如果展開頂級的關(guān)鍵字,可以看到類似圖14.2中的結(jié)構(gòu)。Stack文件由5個服務(wù)構(gòu)成,分別為“reverse_proxy”“database”“appserver”“visualizer”“payment_gateway”。Stack文件中包含3個網(wǎng)絡(luò),分別為“front-tier”“back-tier”“payment”。最后,Stack文件中有4個密鑰,分別為“postgres_password”“staging_token”“revprox_key”“revprox_cert”。

version: "3.2"
services:
    reverse_proxy:
    database:
    appserver:
    visualizer:
    payment_gateway:
networks:
    front-tier:
    back-tier:
    payment:
secrets:
    postgres_password:
    staging_token:
    revprox_key:
    revprox_cert:

Stack文件定義了應(yīng)用的很多依賴要素,理解這一點很重要。因此,Stack文件是應(yīng)用的一個自描述文件,并且作為一個很好的工具彌合了開發(fā)和運維之間的隔閡。

接下來一起深入分析Stack文件的細(xì)節(jié)。

14.2.2 深入分析Stack文件

Stack文件就是Docker Compose文件。唯一的要求就是version:一項需要是“3.0”或者更高的值。具體可以關(guān)注Docker文檔中關(guān)于Compose文件的最新版本信息。

在Docker根據(jù)某個Stack文件部署應(yīng)用的時候,首先會檢查并創(chuàng)建networks:關(guān)鍵字對應(yīng)的網(wǎng)絡(luò)。如果對應(yīng)網(wǎng)絡(luò)不存在,Docker會進行創(chuàng)建。

一起看一下Stack文件中的網(wǎng)絡(luò)定義。

1.網(wǎng)絡(luò)

networks:
  front-tier:
  back-tier:
  payment:
    driver: overlay
    driver_opts:
      encrypted: 'yes'

該文件中定義了3個網(wǎng)絡(luò):front-tier、back-tier以及payment。默認(rèn)情況下,這些網(wǎng)絡(luò)都會采用overlay驅(qū)動,新建對應(yīng)的覆蓋類型的網(wǎng)絡(luò)。但是payment網(wǎng)絡(luò)比較特殊,需要數(shù)據(jù)層加密。

默認(rèn)情況下,覆蓋網(wǎng)絡(luò)的所有控制層都是加密的。如果需要加密數(shù)據(jù)層,有兩種選擇。

  • 在docker network create命令中指定-o encrypted參數(shù)。
  • 在Stack文件中的driver_opts之下指定encrypted:'yes'。

數(shù)據(jù)層加密會導(dǎo)致額外開銷,而影響額外開銷大小的因素有很多,比如流量的類型和流量的多少。但是,通常額外開銷會在10%的范圍之內(nèi)。

正如前面提到的,全部的3個網(wǎng)絡(luò)均會先于密鑰和服務(wù)被創(chuàng)建。

2.密鑰

密鑰屬于頂級對象,在當(dāng)前Stack文件中定義了4個。

secrets:
  postgres_password:
    external: true
  staging_token:
    external: true
  revprox_key:
    external: true
  revprox_cert:
    external: true

注意,4個密鑰都被定義為external。這意味著在Stack部署之前,這些密鑰必須存在。

當(dāng)然在應(yīng)用部署時按需創(chuàng)建密鑰也是可以的,只需要將file: <filename>替換為external: true。但該方式生效的前提是,需要在主機文件系統(tǒng)的對應(yīng)路徑下有一個文本文件,其中包含密鑰所需的值,并且是未加密的。這種方式存在明顯的安全隱患。

稍后會展示在部署的時候究竟是如何創(chuàng)建這些密鑰的?,F(xiàn)在,讀者只需知道應(yīng)用定義了4個密鑰,并且需要提前創(chuàng)建即可。

下面對服務(wù)逐一進行分析。

3.服務(wù)

部署中的主要操作都在服務(wù)這個環(huán)節(jié)。

每個服務(wù)都是一個JSON集合(字典),其中包含了一系列關(guān)鍵字。本書會依次介紹每個關(guān)鍵字,并解釋操作的具體內(nèi)容。

(1)reverse_proxy服務(wù)

正如讀者所見,reverse_proxy服務(wù)定義了鏡像、端口、密鑰以及網(wǎng)絡(luò)。

reverse_proxy:
  image: dockersamples/atseasampleshopapp_reverse_proxy
  ports:
    - "80:80"
    - "443:443"
  secrets:
    - source: revprox_cert
      target: revprox_cert
    - source: revprox_key
      target: revprox_key
networks:
  - front-tier

image關(guān)鍵字是服務(wù)對象中唯一的必填項。顧名思義,該關(guān)鍵字定義了將要用于構(gòu)建服務(wù)副本的Docker鏡像。

Docker是可選項,除非指定其他值,否則鏡像會從Docker Hub拉取。讀者可以通過在鏡像前添加對應(yīng)第三方鏡像倉庫服務(wù)API的DNS名稱的方式,來指定某個鏡像從第三方服務(wù)拉取。例如google的容器服務(wù)的DNS名稱為gcr.io。

Docker Stack和Docker Compose的一個區(qū)別是,Stack不支持構(gòu)建。這意味著在部署Stack之前,所有鏡像必須提前構(gòu)建完成。

ports關(guān)鍵字定義了兩個映射。

  • 80:80將Swarm節(jié)點的80端口映射到每個服務(wù)副本的80端口。
  • 443:443將Swarm節(jié)點的443端口映射到每個服務(wù)副本的443端口。

默認(rèn)情況下,所有端口映射都采用Ingress模式。這意味著Swarm集群中每個節(jié)點的對應(yīng)端口都會映射并且是可訪問的,即使是那些沒有運行副本的節(jié)點。另一種方式是Host模式,端口只映射到了運行副本的Swarm節(jié)點上。但是,Host模式需要使用完整格式的配置。例如,在Host模式下將端口映射到80端口的語法如下所示。

ports:
  - target: 80
    published: 80
    mode: host

推薦使用完整語法格式,這樣可以提高易讀性,并且更靈活(完整語法格式支持Ingress模式和Host模式)。但是,完整格式要求Compose文件格式的版本至少是3.2。

secret關(guān)鍵字中定義了兩個密鑰:revprox_cert以及revprox_key。這兩個密鑰必須在頂級關(guān)鍵字secrets下定義,并且必須在系統(tǒng)上已經(jīng)存在。

密鑰以普通文件的形式被掛載到服務(wù)副本當(dāng)中。文件的名稱就是stack文件中定義的target屬性的值,其在linux下的路徑為/run/secrets,在windows下的路徑為C:ProgramDataDockersecrets。Linux將/run/secrets作為內(nèi)存文件系統(tǒng)掛載,但是Windows并不會這樣。

本服務(wù)密鑰中定義的內(nèi)容會在每個服務(wù)副本中被掛載,具體路徑為/run/secrets/revprox_cert和/run/secrets/revprox_key。若將其中之一掛載為/run/secrets/uber_secret,需要在stack文件中定義如下內(nèi)容。

secrets:
  - source: revprox_cert
    target: uber_secret

networks關(guān)鍵字確保服務(wù)所有副本都會連接到front-tier網(wǎng)絡(luò)。網(wǎng)絡(luò)相關(guān)定義必須位于頂級關(guān)鍵字networks之下,如果定義的網(wǎng)絡(luò)不存在,Docker會以O(shè)verlay網(wǎng)絡(luò)方式新建一個網(wǎng)絡(luò)。

(2)database服務(wù)

數(shù)據(jù)庫服務(wù)也在Stack文件中定義了,包括鏡像、網(wǎng)絡(luò)以及密鑰。除上述內(nèi)容之外,數(shù)據(jù)庫服務(wù)還引入了環(huán)境變量和部署約束。

database:
  image: dockersamples/atsea_db
  environment:
    POSTGRES_USER: gordonuser
    POSTGRES_DB_PASSWORD_FILE: /run/secrets/postgres_password
    POSTGRES_DB: atsea
  networks:
    - back-tier
  secrets:
    - postgres_password
  deploy:
    placement:
      constraints:
        - 'node.role == worker'

environment關(guān)鍵字允許在服務(wù)副本中注入環(huán)境變量。在該服務(wù)中,使用了3個環(huán)境變量來定義數(shù)據(jù)庫用戶、數(shù)據(jù)庫密碼的位置(掛載到每個服務(wù)副本中的密鑰)以及數(shù)據(jù)庫服務(wù)的名稱。

environment:
  POSTGRES_USER: gordonuser
  POSTGRES_DB_PASSWORD_FILE: /run/secrets/postgres_password
  POSTGRES_DB: atsea

注:

 

將三者作為密鑰傳遞會更安全,因為這樣可以避免將數(shù)據(jù)庫名稱和數(shù)據(jù)庫用戶以明文變量的方式記錄在文件當(dāng)中。

該服務(wù)還在deploy關(guān)鍵字下定義了部署約束。這樣保證了當(dāng)前服務(wù)只會運行在Swarm集群的worker節(jié)點之上。

deploy:
  placement:
    constraints:
      - 'node.role == worker'

部署約束是一種拓?fù)涓兄〞r任務(wù),是一種很好的優(yōu)化調(diào)度選擇的方式。Swarm目前允許通過如下幾種方式進行調(diào)度。

  • 節(jié)點ID,如node.id==o2p4kw2uuw2a。
  • 節(jié)點名稱,如node.hostname==wrk-12。
  • 節(jié)點角色,如node.role!=manager。
  • 節(jié)點引擎標(biāo)簽,如engine.labels.operatingsystem==ubuntu16.04。
  • 節(jié)點自定義標(biāo)簽,如node.labels.zone==prod1。

注意==和!=操作符均支持。

(3)appserver服務(wù)

appserver服務(wù)使用了一個鏡像,連接到3個網(wǎng)絡(luò),并且掛載了一個密鑰。此外appserver服務(wù)還在deploy關(guān)鍵字下引入了一些額外的特性。

appserver:
  image: dockersamples/atsea_app
  networks:
    - front-tier
    - back-tier
    - payment
  deploy:
    replicas: 2
    update_config:
      parallelism: 2
    failure_action: rollback
    placement:
      constraints:
      - 'node.role == worker'
  restart_policy:
    condition: on-failure
    delay: 5s
    max_attempts: 3
    window: 120s
secrets:
  - postgres_password

接下來進一步了解deploy關(guān)鍵字中新增的內(nèi)容。

首先,services.appserver.deploy.replicas = 2設(shè)置期望服務(wù)的副本數(shù)量為2。缺省情況下,默認(rèn)值為1。如果服務(wù)正在運行,并且需要修改副本數(shù),則讀者需要顯示聲明該值。這意味著需要更新stack文件中的services.appserver.deploy.replicas,設(shè)置一個新值,然后重新部署當(dāng)前stack。后面會進行具體展示,但是重新部署stack并不會影響那些沒有改動的服務(wù)。

services.appserver.deploy.update_config定義了Docker在服務(wù)滾動升級的時候具體如何操作。對于當(dāng)前服務(wù),Docker每次會更新兩個副本(parallelism),并且在升級失敗后自動回滾?;貪L會基于之前的服務(wù)定義啟動新的副本。failure_action的默認(rèn)操作是pause,會在服務(wù)升級失敗后阻止其他副本的升級。failure_action還支持continue。

update_config:
  parallelism: 2
  failure_action: rollback

services.appserver.deploy.restart-policy定義了Swarm針對容器異常退出的重啟策略。當(dāng)前服務(wù)的重啟策略是,如果某個副本以非0返回值退出(condition: onfailure),會立即重啟當(dāng)前副本。重啟最多重試3次,每次都會等待至多120s來檢測是否啟動成功。每次重啟的間隔是5s。

restart_policy:
  condition: on-failure
  delay: 5s
  max_attempts: 3
  window: 120s

(4)visualizer服務(wù)

visualizer服務(wù)中指定了鏡像,定義了端口映射規(guī)則、更新配置以及部署約束。此外還掛載了一個指定卷,并且定義了容器的優(yōu)雅停止方式。

visualizer:
  image: dockersamples/visualizer:stable
  ports:
    - "8001:8080"
  stop_grace_period: 1m30s
  volumes:
    - "/var/run/docker.sock:/var/run/docker.sock"
  deploy:
    update_config:
      failure_action: rollback
    placement:
      constraints:
        - 'node.role == manager'

當(dāng)Docker停止某個容器的時候,會給容器內(nèi)部PID為1的進程發(fā)送SIGTERM信號。容器內(nèi)PID為1的進程會有10s的優(yōu)雅停止時間來執(zhí)行一些清理操作。如果進程沒有處理該信號,則10s后就會被SIGKILL信號強制結(jié)束。stop_grace_period屬性可以調(diào)整默認(rèn)為10s的優(yōu)雅停止時長。

volumes關(guān)鍵字用于掛載提前創(chuàng)建的卷或者主機目錄到某個服務(wù)副本當(dāng)中。在本例中,會掛載Docker主機的/var/run/docker.sock目錄到每個服務(wù)副本的/var/run/docker.sock路徑。這意味著在服務(wù)副本中任何對/var/run/docker.sock的讀寫操作都會實際指向Docker主機的對應(yīng)目錄中。

/var/run/docker.sock恰巧是Docker提供的IPC套接字,Docker daemon通過該套接字對其他進程暴露其API終端。這意味著如果給某個容器訪問該文件的權(quán)限,就是允許該容器接收全部的API終端,即等價于給予了容器查詢和管理Docker daemon的能力。在大部分場景下這是決不允許的。但是,這是一個實驗室環(huán)境中的示例應(yīng)用。

該服務(wù)需要Docker套接字訪問權(quán)限的原因是需要以圖形化方式展示當(dāng)前Swarm中服務(wù)。為了實現(xiàn)這個目標(biāo),當(dāng)前服務(wù)需要能訪問管理節(jié)點的Docker daemon。為了確保能訪問管理節(jié)點Docker daemon,當(dāng)前服務(wù)通過部署約束的方式,強制服務(wù)副本只能部署在管理節(jié)點之上,同時將Docker套接字綁定掛載到每個服務(wù)副本中。綁定掛載如圖14.3所示。

使用Docker Stack部署應(yīng)用

 

圖14.3 綁定掛載

(5)payment_gateway服務(wù)

payment_gateway服務(wù)中指定了鏡像,掛載了一個密鑰,連接到網(wǎng)絡(luò),定義了部分部署策略,并且使用了兩個部署約束。

payment_gateway:
  image: dockersamples/atseasampleshopapp_payment_gateway
  secrets:
    - source: staging_token
      target: payment_token
  networks:
    - payment
  deploy:
    update_config:
      failure_action: rollback
    placement:
      constraints:
        - 'node.role == worker'
        - 'node.labels.pcidss == yes'

除了部署約束node.label之外,其余配置項在前面都已經(jīng)出現(xiàn)過了。通過docker node update命令可以自定義節(jié)點標(biāo)簽,并添加到Swarm集群的指定節(jié)點。因此,node.label配置只適用于Swarm集群中指定的節(jié)點上(不能用于單獨的容器或者不屬于Swarm集群的容器之上)。

在本例中,payment_gateway服務(wù)被要求只能運行在符合PCI DSS(支付卡行業(yè)標(biāo)準(zhǔn),譯者注)標(biāo)準(zhǔn)的節(jié)點之上。為了使其生效,讀者可以將某個自定義節(jié)點標(biāo)簽應(yīng)用到Swarm集群中符合要求的節(jié)點之上。本書在搭建應(yīng)用部署實驗環(huán)境的時候完成了該操作。

因為當(dāng)前服務(wù)定義了兩個部署約束,所以服務(wù)副本只會部署在兩個約束條件均滿足的節(jié)點之上,即具備pcidss=yes節(jié)點標(biāo)簽的worker節(jié)點。

關(guān)于Stack文件的分析到這里就結(jié)束了,目前對于應(yīng)用需求應(yīng)該有了較好的理解。前文中提到,Stack文件是應(yīng)用文檔化的重要部分之一。讀者已經(jīng)了解該應(yīng)用包含5個服務(wù)、3個網(wǎng)絡(luò)以及4個密鑰。此外讀者還知道了每個服務(wù)都會連接到哪個網(wǎng)絡(luò)、有哪些端口需要發(fā)布、應(yīng)用會使用到哪些鏡像以及哪些服務(wù)需要在特定的節(jié)點上發(fā)布。

下面開始部署。

14.2.3 部署應(yīng)用

在部署應(yīng)用之前,有幾個前置處理需要完成。

  • Swarm模式:應(yīng)用將采用Docker Stack部署,而Stack依賴Swarm模式。
  • 標(biāo)簽:某個Swarm worker節(jié)點需要自定義標(biāo)簽。
  • 密鑰:應(yīng)用所需的密鑰需要在部署前創(chuàng)建完成。

1.搭建應(yīng)用實驗環(huán)境

在本節(jié)中會完成基于Linux的三節(jié)點Swarm集群搭建,同時能滿足上面應(yīng)用的全部前置依賴。完成之后,實驗環(huán)境如圖14.4所示。

使用Docker Stack部署應(yīng)用

 

圖14.4 示例環(huán)境

接下來內(nèi)容分為3個步驟。

(1)創(chuàng)建新的Swarm。

(2)添加節(jié)點標(biāo)簽。

(3)創(chuàng)建密鑰。

首先創(chuàng)建新的三節(jié)點Swarm集群。

(1)初始化Swarm。

在讀者期望成為Swarm管理節(jié)點的機器上,運行下面的命令。

$ docker swarm init
Swarm initialized: current node (lhma...w4nn) is now a manager.
<Snip>

(2)添加工作節(jié)點。

復(fù)制前面輸出中出現(xiàn)的docker swarm join命令。將復(fù)制內(nèi)容粘貼到工作節(jié)點上并運行。

//Worker 1 (wrk-1)
wrk-1$ docker swarm join --token SWMTKN-1-2hl6...-...3lqg 172.31.40.192:2377
This node joined a swarm as a worker.

//Worker 2 (wrk-2)
wrk-2$ docker swarm join --token SWMTKN-1-2hl6...-...3lqg 172.31.40.192:2377
This node joined a swarm as a worker.

(3)確認(rèn)當(dāng)前Swarm由一個管理節(jié)點和兩個工作節(jié)點構(gòu)成。在管理節(jié)點中運行下面的命令。

$ docker node ls
ID            HOSTNAME  STATUS    AVAILABILITY   MANAGER STATUS
lhm...4nn *   mgr-1     Ready     Active         Leader
b74...gz3     wrk-1     Ready     Active
o9x...um8     wrk-2     Ready     Active

Swarm集群目前就緒。

payment_gateway服務(wù)配置了部署約束,限制該服務(wù)只能運行在有pcidss=yes標(biāo)簽的工作節(jié)點之上。本步驟中將在wrk-1上添加該節(jié)點標(biāo)簽。

在現(xiàn)實世界中,添加該標(biāo)簽之前必須將某個Docker節(jié)點按PCI規(guī)范進行標(biāo)準(zhǔn)化。但是,這只是一個實驗環(huán)境,所以就暫且跳過這一過程,直接將標(biāo)簽添加到wrk-1節(jié)點。

在Swarm管理節(jié)點運行下面的命令。

(1)添加節(jié)點標(biāo)簽到wrk-1。

$ docker node update --label-add pcidss=yes wrk-1

Node標(biāo)簽只在Swarm集群之內(nèi)生效。

(2)確認(rèn)節(jié)點標(biāo)簽。

$ docker node inspect wrk-1
[
{
    "ID": "b74rzajmrimfv7hood6l4lgz3",
    "Version": {
        "Index": 27
    },
    "CreatedAt": "2018-01-25T10:35:18.146831621Z",
    "UpdatedAt": "2018-01-25T10:47:57.189021202Z",
    "Spec": {
        "Labels": {
            "pcidss": "yes"

        },
        <Snip>

wrk-1工作節(jié)點現(xiàn)在已經(jīng)配置完成,所以該節(jié)點可以運行payment_gateway服務(wù)副本了。

應(yīng)用定義了4個密鑰,這些都需要在應(yīng)用部署前創(chuàng)建。

  • postgress_password。
  • staging_token。
  • revprox_cert。
  • revprox_key。

在管理節(jié)點運行下面的命令,來創(chuàng)建這些密鑰。

(1)創(chuàng)建新的鍵值對。

密鑰中有3個是需要加密key的。在本步驟中會創(chuàng)建加密key,下一步會將加密key放到Docker密鑰文件當(dāng)中。

$ openssl req -newkey rsa:4096 -nodes -sha256 
  -keyout domain.key -x509 -days 365 -out domain.crt

(2)創(chuàng)建revprox_cert、revprox_key以及postgress_password密鑰。

$ docker secret create revprox_cert domain.crt
cqblzfpyv5cxb5wbvtrbpvrrj

$ docker secret create revprox_key domain.key
jqd1ramk2x7g0s2e9ynhdyl4p

$ docker secret create postgres_password domain.key
njpdklhjcg8noy64aileyod6l

(3)創(chuàng)建stage_token密鑰。

$ echo staging | docker secret create staging_token -
sqy21qep9w17h04k3600o6qsj

(4)列出所有密鑰。

$ docker secret ls
ID          NAME                CREATED             UPDATED
njp...d6l   postgres_password   47 seconds ago      47 seconds ago
cqb...rrj   revprox_cert        About a minute ago  About a minute ago
jqd...l4p   revprox_key         About a minute ago  About a minute ago
sqy...qsj   staging_token       23 seconds ago      23 seconds ago

上面已經(jīng)完成了全部的前置準(zhǔn)備。是時候開始部署應(yīng)用了!

2.部署示例應(yīng)用

如果還沒有代碼,請先復(fù)制應(yīng)用的GitHub倉庫到Swarm管理節(jié)點。

$ git clone https://github.com/dockersamples/atsea-sample-shop-app.git
Cloning into 'atsea-sample-shop-app'...
remote: Counting objects: 636, done.
Receiving objects: 100% (636/636), 7.23 MiB | 3.30 MiB/s, done. remote:
Total 636 (delta 0), reused 0 (delta 0), pack-reused 636 Resolving
deltas: 100% (197/197), done.
Checking connectivity... done.

$ cd atsea-sample-shop-app

現(xiàn)在已經(jīng)擁有了源碼,可以開始部署應(yīng)用了。

Stack通過docker stack deploy命令完成部署?;A(chǔ)格式下,該命令允許傳入兩個參數(shù)。

  • Stack文件的名稱。
  • Stack的名稱。

應(yīng)用的GitHub倉庫中包含一個名為docker-stack.yml的Stack文件。這里會使用該文件。本書中為Stack起名seastack,如果讀者不喜歡,也可以選擇其他名稱。

在Swarm管理節(jié)點的atsea-sample-shop-app目錄下運行下面的命令。

部署Stack(應(yīng)用)。

$ docker stack deploy -c docker-stack.yml seastack
Creating network seastack_default
Creating network seastack_back-tier
Creating network seastack_front-tier
Creating network seastack_payment
Creating service seastack_database
Creating service seastack_appserver
Creating service seastack_visualizer
Creating service seastack_payment_gateway
Creating service seastack_reverse_proxy

讀者可以運行docker network ls以及docker service ls命令來查看應(yīng)用的網(wǎng)絡(luò)和服務(wù)情況。

下面是命令輸出中幾個需要注意的地方。

網(wǎng)絡(luò)是先于服務(wù)創(chuàng)建的。這是因為服務(wù)依賴于網(wǎng)絡(luò),所以網(wǎng)絡(luò)需要在服務(wù)啟動前創(chuàng)建。

Docker將Stack名稱附加到由他創(chuàng)建的任何資源名稱前作為前綴。在本例中,Stack名為seastack,所以所有資源名稱的格式都如:seastack_<resource>。例如,payment網(wǎng)絡(luò)的名稱是seastack_payment。而在部署之前創(chuàng)建的資源則沒有被重命名,比如密鑰。

另一個需要注意的點是出現(xiàn)了新的名為seastack_default的網(wǎng)絡(luò)。該網(wǎng)絡(luò)并未在Stack文件中定義,那為什么會創(chuàng)建呢?每個服務(wù)都需要連接到網(wǎng)絡(luò),但是visualizer服務(wù)并沒有指定具體的網(wǎng)絡(luò)。因此,Docker創(chuàng)建了名為seastack_default的網(wǎng)絡(luò),并將visualizer連接到該網(wǎng)絡(luò)。

讀者可以通過兩個命令來確認(rèn)當(dāng)前Stack的狀態(tài)。docker stack ls列出了系統(tǒng)中全部Stack,包括每個Stack下面包含多少服務(wù)。docker stack ps <stack-name>針對某個指定Stack展示了更詳細(xì)的信息,例如期望狀態(tài)以及當(dāng)前狀態(tài)。下面一起來了解下這兩條命令。

$ docker stack ls
NAME                SERVICES
Seastack            5

$ docker stack ps seastack
NAME                         NODE    DESIRED STATE   CURRENT STATE
seastack_reverse_proxy.1     wrk-2   Running         Running 7 minutes ago
seastack_payment_gateway.1   wrk-1   Running         Running 7 minutes ago
seastack_visualizer.1        mgr-1   Running         Running 7 minutes ago
seastack_appserver.1         wrk-2   Running         Running 7 minutes ago
seastack_database.1          wrk-2   Running         Running 7 minutes ago
seastack_appserver.2         wrk-1   Running         Running 7 minutes ago

在服務(wù)啟動失敗時,docker stack ps命令是首選的問題定位方式。該命令展示了Stack中每個服務(wù)的概況,包括服務(wù)副本所在節(jié)點、當(dāng)前狀態(tài)、期望狀態(tài)以及異常信息。從下面的輸出信息中能看出reverse_proxy服務(wù)在wrk-2節(jié)點上兩次嘗試啟動副本失敗。

$ docker stack ps seastack
NAME                NODE      DESIRED    CURRENT ERROR
                              STATE      STATE
reverse_proxy.1     wrk-2     Shutdown   Failed  "task: non-zero exit (1)"
_reverse_proxy.1   wrk-2     Shutdown   Failed  "task: non-zero exit (1)"

如果想查看具體某個服務(wù)的詳細(xì)信息,可以使用docker service logs命令。讀者需要將服務(wù)名稱/ID或者副本ID作為參數(shù)傳入。如果傳入服務(wù)名稱或ID,讀者可以看到所有服務(wù)副本的日志信息。如果傳入的是副本ID,讀者只會看到對應(yīng)副本的日志信息。

下面的docker service logs命令展示了seastack_reverse_proxy服務(wù)的全部副本日志,其中包含了前面輸出中的兩次副本啟動失敗的日志。

$ docker service logs seastack_reverse_proxy
seastack_reverse_proxy.1.zhc3cjeti9d4@wrk-2 | [emerg] 1#1: host not found...
seastack_reverse_proxy.1.6m1nmbzmwh2d@wrk-2 | [emerg] 1#1: host not found...
seastack_reverse_proxy.1.6m1nmbzmwh2d@wrk-2 | Nginx: [emerg] host not found..
seastack_reverse_proxy.1.zhc3cjeti9d4@wrk-2 | nginx: [emerg] host not found..
seastack_reverse_proxy.1.1tmya243m5um@mgr-1 | 10.255.0.2 "GET / HTTP/1.1" 302

輸出內(nèi)容為了適應(yīng)頁面展示,已經(jīng)經(jīng)過裁剪,但是讀者還是可以看到全部3個服務(wù)副本的日志(兩個啟動失敗,1個正在運行)。每行的開始都是副本的名稱,包括服務(wù)名稱、副本序號、副本ID以及副本所在主機的名稱。接下來是具體的日志輸出。

注:

 

讀者可能已經(jīng)注意到前面日志中全部副本的序號都是1。這是因為Docker每次只創(chuàng)建一個副本,并且只有當(dāng)前面的副本啟動失敗時才會創(chuàng)建新的。

因為輸出內(nèi)容經(jīng)過裁剪,所以具體原因很難明確,但看起來前兩次副本啟動失敗原因是其依賴的某個服務(wù)仍然在啟動中(一種啟動時服務(wù)間依賴導(dǎo)致的競爭條件)。

讀者可以繼續(xù)跟蹤日志(--follow),查看日志尾部內(nèi)容(--tail),或者獲取額外的詳細(xì)信息(--details)。

現(xiàn)在Stack已經(jīng)啟動并且處于運行中,看一下如何管理stack。

14.2.4 管理應(yīng)用

Stack是一組相關(guān)聯(lián)的服務(wù)和基礎(chǔ)設(shè)施,需要進行統(tǒng)一的部署和管理。雖然這句話里充斥著術(shù)語,但仍提醒我們Stack是由普通的Docker資源構(gòu)建而來:網(wǎng)絡(luò)、卷、密鑰、服務(wù)等。這意味著可以通過普通的Docker命令對其進行查看和重新配置,例如docker network、docker volume、docker secret、docker service等。

在此前提之下,通過docker service命令來管理Stack中某個服務(wù)是可行的。一個簡單的例子是通過docker service scale命令來擴充appserver服務(wù)的副本數(shù)。但是,這并不是推薦的方式!

推薦方式是通過聲明式方式修改,即將Stack文件作為配置的唯一聲明。這樣,所有Stack相關(guān)的改動都需要體現(xiàn)在Stack文件中,然后更新重新部署應(yīng)用所需的Stack文件。

下面是一個簡單例子,闡述了為什么通過命令修改的方式不好(通過CLI進行變更)。

假設(shè)讀者已經(jīng)部署了一個Stack,采用的Stack文件是前面章節(jié)中從GitHub復(fù)制的倉庫中的docker-stack.yml。這意味著目前appserver服務(wù)有兩個副本。如果通過docker service scale命令將副本修改為4個,當(dāng)前運行的集群會有4個副本,但是Stack文件中仍然是兩個。得承認(rèn)目前看起來還不是特別糟糕。但是,假設(shè)讀者又通過修改Stack文件對Stack做了某些改動,然后通過docker stack deploy命令進行滾動部署。這會導(dǎo)致appserver服務(wù)副本數(shù)被回滾到兩個,因為Stack文件就是這么定義的。因此,推薦對Stack所有的變更都通過修改Stack文件來進行,并且將該文件放到一個合適的版本控制系統(tǒng)當(dāng)中。

一起來回顧對Stack進行兩個聲明式修改的過程。目標(biāo)是進行如下改動。

  • 增加appserver副本數(shù),數(shù)量為2~10。
  • 將visualizer服務(wù)的優(yōu)雅停止時間增加到2min。

修改docker-stack.yml文件,更新兩個值:services.appserver.deploy.replicas=10和services.visualizer.stop_grace_period=2m。

目前,Stack文件中的內(nèi)容如下。

<Snip>
appserver:
  image: dockersamples/atsea_app
  networks:
    - front-tier
    - back-tier
    - payment
  deploy:
    replicas: 10             <<Updated value
<Snip>
visualizer:
  image: dockersamples/visualizer:stable
  ports:
    - "8001:8080"
stop_grace_period: 2m        <<Updated value
<Snip

保存文件并重新部署應(yīng)用。

$ docker stack deploy -c docker-stack.yml seastack
Updating service seastack_reverse_proxy (id: z4crmmrz7zi83o0721heohsku)
Updating service seastack_database (id: 3vvpkgunetxaatbvyqxfic115)
Updating service seastack_appserver (id: ljht639w33dhv0dmht1q6mueh)
Updating service seastack_visualizer (id: rbwoyuciglre01hsm5fviabjf)
Updating service seastack_payment_gateway (id: w4gsdxfnb5Gofwtvmdiooqvxs)

以上重新部署應(yīng)用的方式,只會更新存在變更的部分。

運行docker stack ps命令來確認(rèn)appserver副本數(shù)量確實增加。

$ docker stack ps seastack
NAME                    NODE  DESIRED STATE CURRENT STATE
seastack_visualizer.1   mgr-1 Running       Running 1 second ago
seastack_visualizer.1   mgr-1 Shutdown      Shutdown 3 seconds ago
seastack_appserver.1    wrk-2 Running       Running 24 minutes ago
seastack_appserver.2    wrk-1 Running       Running 24 minutes ago
seastack_appserver.3    wrk-2 Running       Running 1 second ago
seastack_appserver.4    wrk-1 Running       Running 1 second ago
seastack_appserver.5    wrk-2 Running       Running 1 second ago
seastack_appserver.6    wrk-1 Running       Starting 7 seconds ago
seastack_appserver.7    wrk-2 Running       Running 1 second ago
seastack_appserver.8    wrk-1 Running       Starting 7 seconds ago
seastack_appserver.9    wrk-2 Running       Running 1 second ago
seastack_appserver.10   wrk-1 Running       Starting 7 seconds ago

為了本書的排版效果,輸出內(nèi)容有所裁剪,只展示了受變更影響的服務(wù)。

注意關(guān)于visualizer服務(wù)有兩行內(nèi)容。其中一行表示某個副本在3s前停止,另一行表示新副本已經(jīng)運行了1s。這是因為剛才對visualizer服務(wù)作了修改,所以Swarm集群終止了正在運行的副本,并且啟動了新的副本,新副本中更新了stop_grace_period的值。

還需要注意的是,appserver服務(wù)目前擁有10個副本,但不同副本的“CURRENT STATE”一列狀態(tài)并不相同:有些處于running狀態(tài),而有些仍在starting狀態(tài)。

經(jīng)過足夠的時間,集群的狀態(tài)會完成收斂,期望狀態(tài)和當(dāng)前狀態(tài)就會保持一致。在那時,集群中實際部署和觀察到的狀態(tài),就會跟Stack文件中定義的內(nèi)容完全一致。這真是讓人開心的事情。

所有應(yīng)用/Stack都應(yīng)采用該方式進行更新。所有的變更都應(yīng)該通過Stack文件進行聲明,然后通過docker stack deploy進行部署。

正確的刪除某個Stack方式是通過docker stack rm命令。一定要謹(jǐn)慎!刪除Stack不會進行二次確認(rèn)。

$ docker stack rm seastack
Removing service seastack_appserver
Removing service seastack_database
Removing service seastack_payment_gateway
Removing service seastack_reverse_proxy
Removing service seastack_visualizer
Removing network seastack_front-tier
Removing network seastack_payment
Removing network seastack_default
Removing network seastack_back-tier

注意,網(wǎng)絡(luò)和服務(wù)已經(jīng)刪除,但是密鑰并沒有。這是因為密鑰是在Stack部署前就創(chuàng)建并存在了。在Stack最上層結(jié)構(gòu)中定義的卷同樣不會被docker stack rm命令刪除。這是因為卷的設(shè)計初衷是保存持久化數(shù)據(jù),其生命周期獨立于容器、服務(wù)以及Stack之外。

本文摘自《深入淺出Docker》

分享到:
標(biāo)簽:Docker Stack
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運動步數(shù)有氧達(dá)人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定