docker swarm和compose 的使用(阿里)

基本的docker使用參考:Docker 入門 到部署Web 程序- (阿里面試經常使用的docker命令和優勢)html

昨天去阿里面試 問我若是給你5臺服務器 如何部署docker,我說一個個拷貝,面試官聽了臉都綠了,node

說有沒有據說過用swarm和compose 部署docker集羣,我說沒用過,nginx

後來回來一看本身的項目,我暈,天天用的yaml文件 就是 compose。git

趕忙作一下總結:阿里的人喜歡讓你寫命令,好比 你是否記得 docker的部署命令啓動命令之類的: github

5. 部署與維護

docker stack

部署命令:web

docker stack deploy -c docker-compose.yml --with-registry-auth youclk,

私有倉庫必須加 --with-registry-auth 才能下載鏡像。除此以外經常使用的以下:面試

# network volume service secret 用法都相似,同出一系嘛...
docker stack ls
docker stack ps youclk
docker stack rm youclk

docker serviceredis

我使用 Compose 的場景通常都結合 Swarm,所以不多去記手動建立或者更改配置的命令了,意義也不大。除了查看移除等與上文類似之外,此處還應記兩個:docker

docker service logs --tail 10  youclk_proxy
docker service update --force youclk_proxy

分別是查看日誌和服務異常後強制重啓。    shell

這是個人項目中用到的compose部署文件:manifest.yaml

 

version: v1
common:
  tools:
    oracle-jdk: 8
build: 
  tools:
    maven: 3.3.3
  run:
    workDir: ./
    cmd: 
      - sh deploy/compile.sh
  target: 
    distDir: ./target/
    files: 
      - ./*.jar
      - ../deploy
autodeploy:
    targetDir: /opt/meituan/com.sankuai.qcs.regulation.nanjingnew/
    env:
    run: sh deploy/run.sh
    check: sh deploy/check.sh
    checkRetry: 3 #後面下掉,加默認值爲1
    CheckInterval: 20s #後面下掉

 

 

 

任何相對完整的應用服務都不多是由單一的程序來完成支持,計劃使用 Docker 來部署的服務更是如此。大型服務須要進行拆分,造成微服務集羣方能加強其穩定性和可維護性。本篇隨筆將對 Docker Compose 和 Docker Swarm 的原理和配置作整理概括,並分享其使用經驗。

總結一下,這張圖很形象:Docker 能夠看作集裝箱把雜亂的貨物一個個整理歸類, Compose 則是用於編排這些集裝箱,最後 Swarm 就是多提供幾條船,掛掉一兩條還能繼續走,提升穩定性。

1. YAML 簡介

Docker Compose 的配置文件採用 YAML 格式,所以有必要在正文以前簡要說明下。YAML 是一門專門用來寫配置文件的語言,設計目標就是方便讀寫,其實質上是一種通用的數據串行化格式,基本語法規則以下:

  • 大小寫敏感。
  • # 表示註釋。
  • 使用縮進表示層級關係。
  • 縮進時不容許使用 Tab 鍵,只容許使用空格。
  • 縮進的空格數目不重要,只要相同層級的元素左側對齊便可。

YAML 支持的數據結構有三種:

  • 對象:animal:cat
  • 數組:一組中劃線開頭的行,例如:
# ex1
  - cat
  - dog
  - bird
  
# ex2
  -
    - cat
    - dog
    - bird
    
# ex3
  animal: [cat, dog, bird]
  • 值類型和字符串。

2. Docker Compose

2.1 安裝與簡介

Docker 能夠極爲方便地部署單個服務,但這時候咱們須要一個工具來整合 Docker 的功能,使之可以更便捷地去管理整個微服務集羣的部署和遷移,Docker Compose 正是應此而生。他是由 Python 編寫的程序,可以根據指令結合配置文件轉換成對應的 Docker API 的操做,並直接體現到 Docker Daemon 中,這就代替咱們完成了重複輸入複雜指令的過程,主要功能可分爲如下兩點:

  • Service:表明的是運行同種應用程序的一個或多個相同容器的抽象定義,也是咱們在Docker Compose 中配置的主要對象。在每一個 Docker Compose 的配置文件中,咱們能夠定義多個服務,並定義服務的配置,以及服務於服務之間的以來關係。
  • Project:表明的是由多個服務所組成的一個相對完整的業務單元。

安裝命令:

curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose

 

2.2 配置參數

Docker Compose 的核心就是其配置文件,採用 YAML 格式,默認爲 docker-compose.yml ,參數詳解可查閱「官方文檔」,如下只作一個常規摘要。

services

全部服務的根節點。

image

指定服務的鏡像名,若本地不存在,則 Compose 會去倉庫拉取這個鏡像:

services:
  web:
    image: nginx

ports

端口映射,例:

ports:
  - "80:80"
  - "81:81"

volumes

掛載主機目錄,其中 ro 表示只讀,例:

volumes:
  - "/etc/nginx/www:/www"
  - "/var/run/docker.sock:/tmp/docker.sock:ro"

 

大多數狀況下集羣中部署的應該都是無狀態服務,服務可複製且不固定在某一臺宿主機,因此掛載的數據卷最好應當與宿主機脫離關係,例:

  web:
  services:
    image: nginx
    volumes:
      - type: volume
        source: logs
        target: /mnt
        volume:
          nocopy: true
          
volumes:
  logs:
    driver_opts:
      type: nfs
      o: addr=***.cn-hangzhou.nas.aliyuncs.com,rw
      device: ":/"

 

固然,這種狀況下最好是優先建立數據卷,後在配置文件中引用,例:

docker volume create --driver local \
    --opt type=nfs \
    --opt o=addr=***.cn-hangzhou.nas.aliyuncs.com,rw \
    --opt device=:/ \
    logs
volumes:
  logs:
    external: true

 

若必須掛載集羣中一臺宿主機的目錄做爲數據卷,則要安裝一個 docker 插件:

docker plugin install vieux/sshfs

# 若配置了密鑰對則可省略 password 參數
docker volume create \
  -d vieux/sshfs \
  --name sshvolume \
  -o "sshcmd=user@1.2.3.4:/remote" \
  -o "password=$(cat file_containing_password_for_remote_host)\ 
sshvolume

networks

配置服務間的網路互通與隔離,例:

services:
  web:
    image: nginx
    networks:
      - proxy
      - youclk
networks:
  youclk:
    external: true
  proxy:
    external: true

secrets

配置服務密碼訪問,例:

services:
  redis:
    image: redis:latest
    deploy:
      replicas: 1
    secrets:
      - my_secret
      - my_other_secret
secrets:
  my_secret:
    file: "./my_secret.txt"
  my_other_secret:
    external: true
docker secret create [OPTIONS] SECRET [file|-]
echo "admin:password" | docker secret create my_secret -
docker secret create my_secret ./secret.json

 

healthcheck

健康檢查,這個很是有必要,等服務準備好之後再上線,避免更新過程當中出現短暫的沒法訪問。

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost/alive"]
  interval: 5s
  timeout: 3s

 

其實大多數狀況下健康檢查的規則都會寫在 Dockerfile 中:

FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost/alive || exit 1

 

depends_on

依賴的服務,優先啓動,例:

depends_on:
  - redis

environment & env_file

設置環境變量和指定環境變量的文件,例:

environment:
  - VIRTUAL_HOST=test.youclk.com
env_file:
  - ./common.env

deploy

部署相關的配置都在這個節點下,例:

deploy:
  mode: replicated
  replicas: 2
  restart_policy:
    condition: on-failure
    max_attempts: 3
  update_config:
    delay: 5s
    order: start-first # 默認爲 stop-first,推薦設置先啓動新服務再終止舊的
  resources:
    limits:
      cpus: "0.50"
      memory: 1g
deploy:
  mode: global # 不推薦全局模式(僅我的意見)。
  placement:
    constraints: [node.role == manager]

 

若非特殊服務,以上各節點的配置可以知足大部分部署場景了。

3. Swarm

Docker 默認包含了 Swarm,所以能夠直接使用,初始化命令:

docker swarm init

此時將會默認當前節點爲 Leader,如下命令爲查看 token:docker swarm join-token (worker|manager),其餘節點能夠用 manager 或者 worker 的身份加入到當前集羣,例:

docker swarm join --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx 172.17.0.2:2377

 

執行 docker swarm leave 脫離集羣。

如下各節點常規操做命令,比較簡單,就不解釋了:

docker node demote [NODE]
docker node inspect [NODE]
docker node ls
docker node promote [NODE]
docker node ps [NODE]
docker node rm [NODE]
docker node update [OPTIONS] NODE

 

4. 應用案例

集羣最擅長的就是解決多服務問題,只要在同一 network 之下,服務之間默承認以直接經過 service_name 互通有無。但爲了不混亂,各服務與外部的通訊最好統一交給一個反向代理服務轉發。因對 nginx 比較熟悉,因此我最初選擇的代理是「jwilder/nginx-proxy」

server
{
    listen 80;
    server_name localhost;
    location /alive {
        return 200;
    }
}

server {
    listen  81;
    return  301 https://$host$request_uri;
}
FROM jwilder/nginx-proxy
ADD ./src /etc/nginx/conf.d
ADD https://gitee.com/youclk/entry/raw/master/debian/sources-vpc.list /etc/apt/sources.list
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost/alive || exit 1
version: "3.5"

services:

  proxy:
    image: $REGISTRY/proxy
    ports:
      - "80:80"
      - "81:81"
    volumes:
      - "/var/run/docker.sock:/tmp/docker.sock:ro"
    deploy:
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: on-failure
        max_attempts: 3
      update_config:
        delay: 5s
        order: start-first 
      resources:
        limits:
          cpus: "0.50"
          memory: 1g

 

負載均衡使用的是阿里雲的 SLB,監聽 80 -> 81, 443 -> 80,這樣一個服務就實現了節點檢查、代理和 https 重定向爲一身。拖 nginx 的福,反正用起來就是爽,點擊「Nginx 原理解析和配置摘要」進一步瞭解。

正所謂樂極生悲,某一次我在擴展 Swarm 集羣的時候提高了部分 work 節點爲 manager, 而且擴展了代理的數量,這讓不少服務頻繁出現 503,找來找去我發現問題出在 nginx-proxy 代理上。當服務在各節點分佈不均的時候,非 leader 節點上的那個代理沒法找到服務,廢了老大的勁兒也沒找到合理的解決方案。

最後我決定選擇「Docker Flow Proxy」做爲新的代理(好傢伙,這一看文檔嚇我一跳,我仍是第一次看到私人的開源項目能把參考文檔寫得這麼詳細,做者的細膩程度「使人髮指」,小弟頂禮膜拜之),如下是個人案例:

version: "3.5"

services:

  proxy:
    image: vfarcic/docker-flow-proxy
    ports:
      - "80:80"
    networks:
      - proxy
    environment:
      - LISTENER_ADDRESS=swarm-listener
      - MODE=swarm
    secrets:
      - dfp_users_admin
    deploy:
      replicas: 2
      labels:
        - com.df.notify=true
        - com.df.port=8080
        - com.df.serviceDomain=localhost
        - com.df.reqPathSearchReplace=/alive,/v1/docker-flow-proxy/ping

  swarm-listener:
    image: vfarcic/docker-flow-swarm-listener
    networks:
      - proxy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DF_NOTIFY_CREATE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/reconfigure
      - DF_NOTIFY_REMOVE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/remove
    deploy:
      placement:
        constraints: [node.role == manager]

networks:
  proxy:
    external: true
secrets:
  dfp_users_admin:
    external: true

 

更換代理的過程也並不是一路順風,我在 https 重定向這個問題浪費了好多時間,最後也沒在代理中解決。做者固然是考慮到了這個問題,經典的解決方案應以下:

services:
  proxy:
    image: vfarcic/docker-flow-proxy
    ports:
      - "80:80"
      - "443:443"
    networks:
      - proxy
    environment:
      - LISTENER_ADDRESS=swarm-listener
      - MODE=swarm
    deploy:
      replicas: 2
      labels:
        - com.df.notify=true
        - com.df.httpsOnly=true
        - com.df.httpsRedirectCode=301

 

但奈何哥哥「非經典」呀,個人 https 證書和負載均衡都委託給阿里雲的 SLB 了,SLB 代理的後端請求只能限定 http。個人想法仍是監聽全部請求 443 端口的域名並返回 301,但如下方案並無成功:

labels:
  - com.df.notify=true
  - com.df.httpsRedirectCode=301
  - com.df.serviceDomainAlgo=hdr_dom(host)
    
  - com.df.srcPort.1=80
  - com.df.port.1=8080
  - com.df.serviceDomain.1=localhost
  - com.df.reqPathSearchReplace.1=/alive,/v1/docker-flow-proxy/ping
    
  - com.df.srcPort.2=443
  - com.df.port.2=8080
  - com.df.serviceDomain.2=youclk.com,localhost
  - com.df.httpsOnly.2=true

 

固然重定向能夠在各服務內部實現,但我不認爲這是個好的解決方案。最後的最後,我想反正早晚都要上 CND,因而就在 CND 中加了 https 重定向(哎,就是帶寬的費用要 double 咯...):

除了代理,最好再加一個監控服務,我選擇了官方案例中的 visualizer ,配合 proxy 示例:

services:
  visualizer:
    image: dockersamples/visualizer
    networks:
      - proxy
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]
      labels:
        - com.df.notify=true
        - com.df.serviceDomain=visualizer.youclk.com
        - com.df.port=8080
        - com.df.usersSecret=admin

 

visualizer 算是敏感服務了,通常須要用密碼保護,這裏經過 com.df.usersSecret 指定了密碼文件,密碼已寫入 secrets dfp_users_admin 中。注意,com.df.usersSecret 的值與 dfp_users_* 必須相同,示例已在上文。部署後顯示以下:

docker-flow-proxy 還有一個默認的監控服務,顯示以下:

不過數據沒有統一收集,所以意義不大,看看就好。除此以外就是真正須要部署的應用了,只要服務器性能足夠,隨便想來幾個來幾個。

 


 


在以前使用Docker的過程當中,一直是用 Docker run 命令單獨啓動container後再加入Overlay網絡的方式實現部署工做的. 這種方式看似直接,可是隨着服務所包含的container的個數愈來愈多(docker 命令)也就愈來愈多,由此帶來許多重複工做。。。

 

在官網上看到了經過 docker-compose 能夠執行container的編排,尤爲是compose files -- V3版本,加入的許多功能能夠方便咱們將服務中的contain部署在單獨的docker host 或者多個 hosts (swarm 節點) 上,因而考慮到目前對於 docker 的使用狀況,確實也到了進行高級特性的嘗試階段,因而乎,走起!

 

分享一個示例:https://hackernoon.com/deploy-docker-compose-v3-to-swarm-mode-cluster-4159e9cca712#.lyx2e8fd9

上面的說的是如何使用compose V3 + swarm 構建一個貓狗投票系統,官方的例子,描述的很詳細,有興趣的童鞋能夠研究一下。。。我在這裏部署的方式也是使用了相似的方法,區別之處在與:實例中運用了「docker stack deploy」命令在多個host上面部署,而我使用的是「docker-compose up」 分別在兩個host上面啓動與部署服務。 

 

準備工做

首先是經過 Swarm 建立 nodes,而且建立Overlay網絡模式. 我在這裏就不在贅述,你們能夠參看我以前的隨筆或者利用萬能的互聯網找到答案。

我這裏使用的Docker engine 和 Docker-compose 版本以下:

 

Docker-compose

衆所周知,compose 就是 docker提供給咱們用來進行編排的利器,那麼咱們應該如何使用她呢?

在解析docker-compose.yml以前,我想先說明一下個人業務,在熟悉業務以後,咱們再來看看具體的"code".

業務需求:咱們要在兩個host (swarm node)上面分別創建一組服務,爲了簡單起見,我將nodes命名爲nodeDB和nodeService;顧名思義,咱們就是要在nodeDB上面創建database的服務(我這裏是部署oracle server),在nodeService上面部署咱們的程序(containers). 而 containers 之間的通訊就是經過Swarm的Overlay網絡來完成的。

 

NodeDB的docker-compose.yml 

version: '3'

services:

  frs_orasvr:
    build:
      context: ./frsDB
      dockerfile: Dockerfile
    image: frs_orasvr_img:v1
    container_name: frs_orasvr
    hostname: frs_orasvr
    ports:
      - "1521:1521"
    volumes:
      - /DATA/compose_frs/frsDB/cafisFRSDB/:/frs
    networks:
      - qrtSwamComposeNet
    

networks:
  qrtSwamComposeNet:
    driver: overlay

 

這裏請注意幾個內容:

1. networks: 在 compose file V3中, 容許咱們經過networks關鍵字定義一個基於 Docker0 網絡的 subnet。 而後將咱們的服務添加到這個subnet中。這樣作的好處實現了服務之間的隔離,一旦咱們不須要這組服務了,咱們能夠經過命令「docker-compose down」 卸載服務和對應的subnet,他不會對其餘的服務形成影響。

 

2. build: 咱們能夠經過build命令來指定加載那個Dockerfile。 Dockerfile 提供給咱們一種方式將通用的dockr image 定製化成爲本身的image,這些定製化的步驟就能夠以Dockerfile的方式記錄下來。例如,我以前從docker 倉庫裏pull 下來一個image, 咱們叫他baseImage,以後在此基礎上進行了個人定製化生成myImage,若是須要在其餘機器上面使用myImage,以前的作法吧myImage提交到私有倉庫,在須要的時候pull下來,可是若是不一樣的地方須要不一樣的myImage (v1,v2,v3...),就有可能形成Image氾濫。如今咱們經過Dockerfile的方式記錄本身的定製過程,就會方便許多。

 

OK,囉嗦了一大堆。。。如今咱們再來看看咱們的Dockerfile長得如何:

 

FROM 172.100.1.15:5000/oracle11g_server_v3
RUN mkdir /frs/
COPY /cafisFRSDB/ /frs/
COPY /cafisFRSDB/listener.ora /app/oracle/11.2.0/network/admin/
CMD ["/bin/bash", "/frs/startup.sh"]

Dockerfile的內容很簡單,就是copy文件;

CMD -- 就是咱們須要在啓動container的時候執行的shell腳本,經過她啓動oracle服務和實例(業務邏輯需求)。 

 

如今咱們cd到docker-compose.yml文件所在的目錄,輸入命令 「docker-compose up」,命令執行完成後咱們能夠看到

1. 創建網絡 composefrs_qrtSwarmComposeNet 

 

2. 經過 Dockerfile 生成 imge

 

3. compose運行image,生成container而且調用shell腳本

 

 

到此,咱們在nodeDB上面的工做就完成了。。。

 

NodeService的docker-compose.yml

 咱們要在這個host (swarm node) 部署服務,服務中的container須要與以前node上面oracle服務通訊。。。

 直接上code (簡單起見,只列出了services 中的一個 container) 

version: '3'
services:

  frs_ftsoft:
    build:
      context: ./ftsoft
      dockerfile: Dockerfile
    image: frs_ftsoft_img:v1
    networks:
      - composefrs_qrtSwamComposeNet
    container_name: frs_ftsoft
    hostname: frs_ftsoft
    mac_address: xx:xx:xx:xx:xx:xx
    volumes:
     - /data/CabisSvr/DockerFrs/ftsoft:/frs

networks:
  composefrs_qrtSwamComposeNet:
    external: true

 

Compose文件中使用的 Dockerfile 的內容和以前差很少,就不在這裏多說了。

 

注意:

1. 因爲以前咱們在nodeDB的compose file 裏面已經建立過了網絡,這裏須要指定爲external:true (不須要在建立了),在container裏面加入便可。

2. 咱們直接運行"docker-compose up"會報錯,內容大體爲找不到指定的網絡。。。這是因爲咱們以前在nodeDB上面建立的network不會自動再新的node上面顯示(官方說法),因此咱們須要先在 nodeService 上面運行一個container讓其加入網絡 「composefrs_qrtSwamComposeNet「

 

例如 「docker run -itd --name=mybusybox --network=composefrs_qrtSwamComposeNet busybox /bin/sh」

 

以後咱們即可以在nodeService上面可以查看到 composefrs_qrtSwamComposeNet 網絡,此時再運行「docker-compose up」就OK了。這點仍是有點坑的

 

結論

OK,經過在nodeDB和nodeService上運行兩次 " docker-compose up ",命令,咱們實現了在不一樣的hosts節點上運行containers,最終將他們以service的方式展示給外部用戶。

 

PS,我還嘗試過用docker stack deploy的方式進行部署,使用它最大的好處就是能夠再一臺機器上完成部署(傳說中的一鍵部署),可是因爲其中的種種限制(例如必須保證須要部署的service中使用的image必須提早存在於指定機器或者私有倉庫,且不能使用Dockerfile臨時編譯; 不能指定conainer的IP,Mac 等等。。。),最終未能如願,但願在 docker 以後的版本里可以改善吧。

 

本文只是一種實際部署方案的例子,涉及到的技術有(除Docker/Docker Swarm外):

Docker overlay network

Fluentd

Prometheus stack

vegasbrianc的Prometheus監控方案

步驟大綱:

 

部署Docker machine

基本配置

配置網絡

啓動Fluentd日誌服務

 

 

部署Docker swarm集羣

配置網絡

添加Node

 

 

部署Prometheus stack

給Node打Label

建立監控網絡

啓動service

 

 

部署應用

識別stateless與stateful

建立應用網絡

給Node打Label

啓動service

 

1 部署Docker machine 1.1 基本配置

準備若干Linux服務器(本例使用Ubuntu 16.04),參照Docker CE 鏡像源站提到的步驟安裝Docker CE。

參照Docker Daemon生產環境配置。

1.2 配置bridge網絡

參照Docker Daemon生產環境配置中的mtu和子網章節。

1.3 啓動Fluentd日誌服務

參考使用Fluentd收集Docker容器日誌。

2 部署Docker swarm集羣

到一臺機器上執行docker swarm init,這個機器將做爲manager node。

執行docker node ls會看到相似下面的結果:

$ docker node ls

ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
dxn1zf6l61qsb1josjja83ngz *  manager1  Ready   Active        Leader

若是你計劃不會把工做負載跑在manager node上,那麼使用docker drain

docker node update --availability drain <node-id>

可參考Docker Swarm基本命令清單。

2.1 配置網絡MTU和子網

參考Docker Overlay網絡的MTU。

特別注意

觀察docker_gwbridgeingress的子網是否與已有網絡衝突:

$ docker network inspect -f '{{json .IPAM}}' docker_gwbridge
{"Driver":"default","Options":null,"Config":[{"Subnet":"172.18.0.0/16","Gateway":"172.18.0.1"}]}

$ docker network inspect -f '{{json .IPAM}}' ingress
{"Driver":"default","Options":null,"Config":[{"Subnet":"10.255.0.0/16","Gateway":"10.255.0.1"}]}

若是有衝突則參考Docker Overlay網絡的MTU中的方法修改子網。

2.2 添加Node

參考Docker Swarm基本命令清單。

3 部署Prometheus stack

使用的是vegasbrianc的Prometheus監控方案。

整個監控方案包含一下幾個組件:

Prometheus

Node-exporter,運行在每一個node上

Alertmanager

cAdvisor,運行在每一個node上

Grafana

3.1 給Node打Label

挑選一臺Node做爲運行監控服務的機器。給這個node打上label:

$ docker node update --label-add for-monitor-stack=1 <node-id>

3.2 建立監控網絡

$ docker network create -d overlay --attachable monitor-net

參考參考Docker Overlay網絡的MTU檢查子網與MTU是否配置正確。

3.3 啓動service

clone vegasbrianc的Prometheus監控方案 項目代碼。

使用我修改過的docker-stack.yml

啓動service:

$ docker stack deploy \
  --with-registry-auth \
  --prune \
  -c docker-stack.yml \
  p8s-monitor-stack

訪問地址:

Prometheus:http://<任意swarm node ip>:9000

Node-exporter:http://<任意swarm node ip>:9010

Alertmanager:http://<任意swarm node ip>:9020

cAdvisor:http://<任意swarm node ip>:9030

Grafana:http://<任意swarm node ip>:9040,用戶名admin,密碼foobar

4 部署應用 4.1 識別stateless與stateful

若是你的應用由多個組件(service)組成,那麼在部署它們以前你得識別出哪些是stateless service哪些是stateful service。

針對每一個service你自問如下三個問題:

這個service崩潰以後,是否是隻須要重啓它就能夠了,而不須要關心數據恢復?

這個service是否能夠在node之間任意遷移,且不須要分佈式存儲?

這個service是否無需固定IP?

若是上述回答都是Yes,那麼這個service就是stateless的,只要有一個是No,則這個service是stateful的。

對於stateless service,你能夠:

docker stack deploy部署

docker service create部署

對於stateful service,你能夠:

docker run部署

docker-compose up部署

若是沒有固定IP的要求,那麼你也能夠用docker stack deploy/docker service create部署,前提是你得保證這個service只會固定在一臺機器上運行。

有時候你的應用既有stateless service又有stateful service,這時須要把他們掛載到同一個overlay網絡裏,這樣它們之間就可以互相通訊了。

4.2 建立應用網絡

建立app-net(你也能夠改爲本身的名字)

$ docker network create -d overlay --attachable app-net

參考Docker Overlay網絡的MTU檢查子網與MTU是否配置正確。

4.3 給Node打Label

若是你對於Service部署在哪一個Node上有要求,那麼你得給Node打上Label:

$ docker node update --label-add <your-label>=1 <node-id>

而後在docker-compose.yaml裏添加約束條件:

version: "3.7"
services:
  busybox:
    image: busybox
    deploy:
      placement:
        constraints:
          - node.labels.<your-label> == 1

4.4 啓動service

對於stateless service,編寫docker-compose.yaml,裏面寫了同時掛載app-netmonitor-net,好比:

version: "3.7"
services:
  busybox:
    image: busybox
    networks:
      app-net:
      monitor-net:
        aliases:
          - busybox
...
networks:
  app-net:
    external: true
  monitor-net:
    external: true

注意上面設置了busybox service在monitor-net中的別名,這是由於若是你用docker stack deploy部署,那麼busybox的名字默認是<stack-name>_busybox,這樣對於prometheus而言此名字不穩定,不便於配置詳見Prometehus監控Docker Swarm Overlay網絡中的容器。

而後用docker stack deploy部署:

$ docker stack deploy   --with-registry-auth   --prune   -c docker-compose.yaml   <stack-name>

若是用docker service create則:

$ docker service create \
 --network app-net \
 --network monitor-net \
 --name <name> \
 ... 其餘參數
 <image>

下面舉例docker run啓動stateful service的方法:

$ docker run -d \
  --name <name> \
  --network app-net \
  ... 其餘參數 \
  <image>
  
# 而後再掛載到monitor-net上
$ docker network connect monitor-net <name>

 

參考:Docker 小記 — Compose & Swarm

參考:Docker - 使用Swarm和compose部署服務(containers)

相關文章
相關標籤/搜索