使用 Docker Stack 部署多服務集群

前言


單機模式下,我們可以使用 Docker Compose 來編排多個服務,而在 上一篇文章 中介紹的 Docker Swarm 只能實現(xiàn)對單個服務的簡單部署。于是就引出了本文的主角 Docker Stack ,通過 Docker Stack 我們只需對已有的 docker-compose.yml 配置文件稍加改造就可以完成 Docker 集群環(huán)境下的多服務編排。

正文


  • 首先創(chuàng)建一個 docker-compose.yml 文件,使用 Docker Compose v3 語法

    內容比較簡單,一個有四個實例的 nginx 服務,兩個只部署在 manager 節(jié)點上的單實例監(jiān)控工具服務:portainervisualizer

version: "3"

services:
  nginx:
    image: nginx:alpine
    ports:
      - 80:80
    deploy:
      mode: replicated
      replicas: 4

  visualizer:
    image: dockersamples/visualizer
    ports:
      - "9001:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]

  portainer:
    image: portainer/portainer
    ports:
      - "9000:9000"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
  • 部署服務
$ docker stack deploy -c docker-compose.yml stack-demo
  • 部署成功之后查看詳情
$ docker stack services stack-demo 
ID                  NAME                    MODE                REPLICAS            IMAGE                             PORTS
4yb35ywqvo49        stack-demo_portainer    replicated          1/1                 portainer/portainer:latest        *:9000->9000/tcp
mzd2volqug28        stack-demo_nginx        replicated          4/4                 nginx:alpine                      *:80->80/tcp
r0zlzpp3wujg        stack-demo_visualizer   replicated          1/1                 dockersamples/visualizer:latest   *:9001->8080/tcp
  • 在瀏覽器中訪問監(jiān)控工具,對應端口如下:
portainer  ——→ ip:9000
visualizer ——→ ip:9001

注意:如果有多個 manager 節(jié)點,portainer 和 visualizer 可能分別部署在兩臺機器上,所以ip可能會不一樣。

  • 修改 docker-compose.yml 文件后重新部署即可完成對修改內容的更新
$ docker stack deploy -c docker-compose.yml stack-demo

關于負載均衡


評論區(qū)有小伙伴提到,容器間通過服務名 ( 比如文中的 nginx ) 通訊時,對應的 IP 卻和容器的實際 IP 對不上。出現(xiàn)這個情況是因為負載均衡( 對外表現(xiàn)為一個服務,內部為多個服務 )。下面是我做的試驗,希望能幫助大家理解。

  1. 按上面的配置啟動集群 ( 由兩臺服務器構成 )

  2. manager 節(jié)點服務器中看下運行的服務

    $ docker ps
    CONTAINER ID IMAGE NAMES
    9b96f07bbb91 dockersamples/visualizer:latest stack-demo_visualizer.1.p5hy7gsc50vbm0wkxm1c17rl6
    942dd34d024e nginx:alpine stack-demo_nginx.4.tp6u05jmg9iuookqc9i9e11kz
    706ae42e0089 nginx:alpine stack-demo_nginx.2.vnlmlky5m5qy7l8qxq6k5nllk
    6dba55dd7d63 portainer/portainer:latest stack-demo_portainer.1.yv76gf0i7gou2awen44kshm1j
    
  3. 在這臺服務器上啟動了兩個 nginx 容器實例,隨便進一個實例看下 IP

    $ docker exec -it stack-demo_nginx.2.vnlmlky5m5qy7l8qxq6k5nllk ifconfig
    eth0 Link encap:Ethernet HWaddr 02:42:0A:FF:00:3E
    inet addr:10.255.0.62 Bcast:10.255.255.255 Mask:255.255.0.0
    eth1 Link encap:Ethernet HWaddr 02:42:0A:00:06:07
    inet addr:10.0.6.7 Bcast:10.0.6.255 Mask:255.255.255.0
    eth2 Link encap:Ethernet HWaddr 02:42:AC:13:00:04
    inet addr:172.19.0.4 Bcast:172.19.255.255 Mask:255.255.0.0
    lo Link encap:Local Loopback
    inet addr:127.0.0.1 Mask:255.0.0.0
    

    發(fā)現(xiàn)容器中綁了3個網(wǎng)卡 eth0 、eth1 、eth2 ,我猜想分別對應 整個 Swarm 集群的局域網(wǎng)當前 Stack 集群的局域網(wǎng) 、當前主機下 Compose 服務的局域網(wǎng) 三個網(wǎng)絡。

  4. 查看當前主機下的 docker 網(wǎng)絡

    $ docker network ls
    NETWORK ID NAME DRIVER SCOPE
    bd4fa8219483 bridge bridge local
    e51735fef0d6 docker_gwbridge bridge local
    26360437865a host host local
    yvupj4ex3odl ingress overlay swarm
    f0a0190c3b1f none null local
    oft930l7jpdn stack-demo_default overlay swarm
    
  5. 上一步看到有兩個 swarm 的網(wǎng)絡,進去看下具體信息

    $ docker network inspect ingress
    "IPAM": {
        "Config": [
            {
                "Subnet": "10.255.0.0/16",
                "Gateway": "10.255.0.1"
            }
        ]
    },
    "Containers": {
        "6dba55dd7d63f7166e2e0ee3afed8e427089b7140d62f39a835d3145a058b868": {
            "Name": "stack-demo_portainer.1.yv76gf0i7gou2awen44kshm1j",
            "IPv4Address": "10.255.0.59/16",
        },
        "706ae42e00890444087aa6d51ccb966b76b5ad4c985b48fdf5215c192bcf0836": {
            "Name": "stack-demo_nginx.2.vnlmlky5m5qy7l8qxq6k5nllk",
            "IPv4Address": "10.255.0.62/16",
        },
        "942dd34d024e218aad4e5034e1194a2cfa1d9be81a839ec86403cf237d41368b": {
            "Name": "stack-demo_nginx.4.tp6u05jmg9iuookqc9i9e11kz",
            "IPv4Address": "10.255.0.64/16",
        },
        "9b96f07bbb91a570bb8d26945996d77151c5633c0a6057361ab4474b393da364": {
            "Name": "stack-demo_visualizer.1.p5hy7gsc50vbm0wkxm1c17rl6",
            "IPv4Address": "10.255.0.66/16",
        },
        "ingress-sbox": {
            "Name": "ingress-endpoint",
            "IPv4Address": "10.255.0.2/16",
        }
    }
    

    內容太多就省略其他無關內容了,從上面的信息已經(jīng)可以證明第三步的猜想了 ( ingress 對應 Swarm 集群 , stack-demo_default 對應 Stack 集群 ) ,要進一步確認可以再看下另一臺服務器上的網(wǎng)絡。

  6. 通過容器 nginx.4 使用服務名的方式 ping 一下 nginx

    $ docker exec -it stack-demo_nginx.4.tp6u05jmg9iuookqc9i9e11kz ping nginx
    PING nginx (10.0.6.5): 56 data bytes
    64 bytes from 10.0.6.5: seq=0 ttl=64 time=0.121 ms
    

    發(fā)現(xiàn) IP10.0.6.5 ,屬于 stack-demo_default 網(wǎng)絡,但是在兩臺服務器的 docker 網(wǎng)絡詳情里面都找不到這個實例。

  7. 在容器 nginx.4 中安裝 curl 然后再訪問 nginx 看下效果

    $ docker exec -it stack-demo_nginx.4.tp6u05jmg9iuookqc9i9e11kz sh -c 'echo -e "https://mirrors.ustc.edu.cn/alpine/latest-stable/main\nhttps://mirrors.ustc.edu.cn/alpine/latest-stable/community" > /etc/apk/repositories && apk --update add curl'
    $ docker exec -it stack-demo_nginx.4.tp6u05jmg9iuookqc9i9e11kz curl nginx
    

    可以看到訪問成功,再多調用幾次。

  8. 打印 nginx 容器的日志 ( 可以多開幾個終端打印日志,再訪問 nginx 看下實時日志的效果,這樣更直觀 )

    $ docker logs stack-demo_nginx.2.vnlmlky5m5qy7l8qxq6k5nllk && echo "---分界線---" && docker logs stack-demo_nginx.4.tp6u05jmg9iuookqc9i9e11kz
    10.0.6.4 - - [06/Dec/2018:10:15:18 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.60.0" "-"
    ---分界線---
    10.0.6.4 - - [06/Dec/2018:10:13:16 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.60.0" "-"
    10.0.6.4 - - [06/Dec/2018:10:15:19 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.60.0" "-"
    

    可以看到明顯的負載均衡的效果,請求都來自 10.0.6.4,它就是 stack-demo_default 網(wǎng)絡中一個名為 lb- 開頭的實例,它就是這個負載均衡的入口。

    "lb-stack-demo_default": {
     "Name": "stack-demo_default-endpoint",
     "IPv4Address": "10.0.6.4/24",
    }
    
  9. 再去另一臺服務器看下 nginx 的日志

    發(fā)現(xiàn)并沒有訪問記錄,說明這個負載均衡僅限于 當前服務器相同服務多個實例,不會跨服務器負載均衡。

  10. 在另一臺服務器上再重復 7 & 8 兩個步驟

    發(fā)現(xiàn)另一臺服務器上不存在名為 lb- 開頭的實例,而負載均衡的入口是其中一個普通的 nginx 實例。

總結下:

整個請求的調用流程應該就是:通過服務名 nginx 訪問 -- 指向 --> stack 集群網(wǎng)關 ( 10.0.6.5 ) -- 轉發(fā) --> stack 集群中,位于當前服務器的負載均衡實例 ( 10.0.6.4 ) -- 分發(fā) --> 最終的應用 。

相關命令


命令 描述
docker stack deploy 部署新的堆?;蚋卢F(xiàn)有堆棧
docker stack ls 列出現(xiàn)有堆棧
docker stack ps 列出堆棧中的任務
docker stack rm 刪除一個或多個堆棧
docker stack services 列出堆棧中的服務

參考文章



系列文章


Docker 學習總結

Docker 常用指令詳解

使用 Dockerfile 構建鏡像

使用 Docker Compose 構建容器

Docker Daemon 連接方式詳解

Docker 下的網(wǎng)絡模式


轉載請注明出處:http://www.itdecent.cn/p/1db6f0150fdb

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容