使用 Docker Stack 部署多服务集群

前言


单机模式下,我们可以使用 Docker Compose 来编排多个服务,而在 上一篇文章 中介绍的 Docker Swarm 只能实现对单个服务的简单部署。于是就引出了本文的主角 Docker Stack ,通过 Docker Stack 我们只需对已有的 docker-compose.yml 配置文件稍加改造就可以完成 Docker 集群环境下的多服务编排。

正文


  • 首先创建一个 docker-compose.yml 文件,使用 Docker Compose v3 语法

    内容比较简单,一个有四个实例的 nginx 服务,两个只部署在 manager 节点上的单实例监控工具服务: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
  • 在浏览器中访问监控工具,对应端口如下:
portainer  ——→ ip:9000
visualizer ——→ ip:9001

注意:如果有多个 manager 节点,portainer 和 visualizer 可能分别部署在两台机器上,所以ip可能会不一样。

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

关于负载均衡


评论区有小伙伴提到,容器间通过服务名 ( 比如文中的 nginx ) 通讯时,对应的 IP 却和容器的实际 IP 对不上。出现这个情况是因为负载均衡( 对外表现为一个服务,内部为多个服务 )。下面是我做的试验,希望能帮助大家理解。

  1. 按上面的配置启动集群 ( 由两台服务器构成 )

  2. manager 节点服务器中看下运行的服务

    $ 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
    

    发现容器中绑了3个网卡 eth0eth1eth2 ,我猜想分别对应 整个 Swarm 集群的局域网当前 Stack 集群的局域网当前主机下 Compose 服务的局域网 三个网络。

  4. 查看当前主机下的 docker 网络

    $ 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 的网络,进去看下具体信息

    $ 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",
        }
    }
    

    内容太多就省略其他无关内容了,从上面的信息已经可以证明第三步的猜想了 ( ingress 对应 Swarm 集群 , stack-demo_default 对应 Stack 集群 ) ,要进一步确认可以再看下另一台服务器上的网络。

  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
    

    发现 IP10.0.6.5 ,属于 stack-demo_default 网络,但是在两台服务器的 docker 网络详情里面都找不到这个实例。

  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 网络中一个名为 lb- 开头的实例,它就是这个负载均衡的入口。

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

    发现并没有访问记录,说明这个负载均衡仅限于 当前服务器相同服务多个实例,不会跨服务器负载均衡。

  10. 在另一台服务器上再重复 7 & 8 两个步骤

    发现另一台服务器上不存在名为 lb- 开头的实例,而负载均衡的入口是其中一个普通的 nginx 实例。

总结下:

整个请求的调用流程应该就是:通过服务名 nginx 访问 -- 指向 --> stack 集群网关 ( 10.0.6.5 ) -- 转发 --> stack 集群中,位于当前服务器的负载均衡实例 ( 10.0.6.4 ) -- 分发 --> 最终的应用

相关命令


命令 描述
docker stack deploy 部署新的堆栈或更新现有堆栈
docker stack ls 列出现有堆栈
docker stack ps 列出堆栈中的任务
docker stack rm 删除一个或多个堆栈
docker stack services 列出堆栈中的服务

参考文章



系列文章


Docker 学习总结

Docker 常用指令详解

使用 Dockerfile 构建镜像

使用 Docker Compose 构建容器

Docker Daemon 连接方式详解

Docker 下的网络模式


转载请注明出处:https://www.jianshu.com/p/1db6f0150fdb

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容