一、背景

在前一篇文章彻底搞懂Docker网络原理之单机通信中,列举了在单主机场景下docker容器之间的通信方式。这篇文章主要介绍跨主机的docker容器之间的通信方式。

二、准备

虚拟机

笔者在笔记本上通过docker-machine创建了3个虚拟机,前提是已经安装好docker engine、docker machine、visualbox,如果已经有现成的服务器可以跳过这步

$ docker-machine create --driver virtualbox myvm1
$ docker-machine create --driver virtualbox myvm2
$ docker-machine create --driver virtualbox myvm3

安装完成后,查看各主机的连接情况

$ docker-machine ls
NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER     ERRORS
myvm1   -        virtualbox   Running   tcp://192.168.99.100:2376           v18.09.5
myvm2   -        virtualbox   Running   tcp://192.168.99.101:2376           v18.09.5
myvm3   -        virtualbox   Running   tcp://192.168.99.102:2376           v18.09.5

如果是初学或者喜欢各种倒腾的,强烈推荐使用docker-machine创建虚拟机来体验docker的分布式功能。不用担心这样创建多个虚拟机而消耗过多电脑资源,因为docker-machine使用virtualbox创建的虚拟机是使用的boot2docker.iso这个专门的精简版linux镜像仅47M大小,同时镜像也是自动下载的,创建一个running的虚拟机不到1分钟,安装完后的目录如下
在这里插入图片描述
在visualbox上也能看到虚拟机的情况,这些虚拟机已经默认安装好了docker环境
在这里插入图片描述
点击显示可以直接登录上虚拟机,然后试试docker info命令

swarm环境

swarm是官方的docker集群解决方案,即实现对多台服务器中docker的互联互通、统一管理和部署。通过一个或多个manage node关联一个或多个worker node,组成一个docker的集群环境。

对集群中的docker操作,只需要在manage node完成就可以了,更多swarm的介绍查看官网
首先我们选择myvm1为manage node,作为发号施令的地方
1、通过docker-machine ssh进入myvm1的终端环境

$ docker-machine ssh myvm1
   ( '>')
  /) TC (\   Core is distributed with ABSOLUTELY NO WARRANTY.
 (/-_--_-\)           www.tinycorelinux.net

docker@myvm1:~$ docker swarm init --advertise-addr 192.168.99.100

2、sawrm初始化成功后,会输出join命令

Swarm initialized: current node (qlei0052c6v128ywfapvjlmjr) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-206zssashmvv1q2yk8bvl0xxtrua18bhdyldcujs5n3sh6jib2-6swf5yoxonv22kc3rlgu7qazz 192.168.99.103:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

3、其中docker swarm join复制到myvm2和myvm3执行,即让2和3加入1

$ docker-machine ssh myvm2
docker@myvm2:~$ docker swarm join --token SWMTKN-1-206zssashmvv1q2yk8bvl0xxtrua18bhdyldcujs5n3sh6jib2-6swf5yoxonv22kc3rlgu7qazz 192.168.99.100:2377

$ docker-machine ssh myvm3
docker@myvm3:~$ docker swarm join --token SWMTKN-1-206zssashmvv1q2yk8bvl0xxtrua18bhdyldcujs5n3sh6jib2-6swf5yoxonv22kc3rlgu7qazz 192.168.99.100:2377

4、回到myvm1查看各node情况

docker@myvm1:~$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
t0xsww8xjlmbrar80g3f4z7oc *   myvm1               Ready               Active              Leader              18.09.5
h3za191ue2fjlajgoiwoj5rc3     myvm2               Ready               Active                                  18.09.5
yl5uytcu6d3iwwrkdvhpq6t2z     myvm3               Ready               Active                                  18.09.5

5、为了方便后续演示和更直观的查看运行情况,我们使用portainer作为docker的界面管理工具,portainer的安装很简单,在manage node(myvm1)上部署portainer

docker@myvm1:~$ curl -L https://downloads.portainer.io/portainer-agent-stack.yml -o portainer-agent-stack.yml
docker@myvm1:~$ docker stack deploy --compose-file=portainer-agent-stack.yml portainer

部署完成后打开http://192.168.99.100:9000,首次登录会要求设置账号密码,因为我已经设置过了,这里就不截图了。

6、登录后会看到一个总览页面
在这里插入图片描述
点击primary进入Dashborad
在这里插入图片描述
再点击Go to cluster visualizer查看node情况,是不是一目了然
在这里插入图片描述
到这里一个分布式的docker环境就准备好了。

三、多机环境

需求:需要在myvm1(192.168.99.100)上访问myvm2(192.168.99.101)部署的redis容器
Portainer-containers
在这里插入图片描述
Portainer-Swarm
在这里插入图片描述

使用IP

这是最直接普通的方式,使用容器所在宿主机的IP直接访问

root@myvm1:~# docker run -it --rm --network my-bridge  bitnami/redis:5.0 redis-cli -h 192.168.99.101
192.168.99.101:6379>

可以看到,能正常访问,但这样存在的问题是,容器需要通过参数指定目标IP才行

swarm模式

swarm环境已经在环境准备中搭建好了,只需要以下三步

  1. 选择一台服务器执行docker swarm init使之成为manage node角色
  2. 选择其他服务器执行docker swarm join使之成为workder node
  3. 在manage node上执行docker node ls查看swarm集群服务器情况,或者通过portainer的swarm查看可视化的界面

在swarm模式下部署的应用称作service,一个service只能包含一个镜像,但可以启动运行任意多个容器实例,多个service可以通过stack来归类管理,如下图
在这里插入图片描述
例如可能存在这样的stack结构

在这里插入图片描述
deploy是swarm特有的,因为当前swarm环境存在多台服务器,需要指定容器部署的目标node,匹配的模式有多种,后期专题再讲,这里先只部署一个实例

  1. 打开Stacks菜单,点击Add stack
    在这里插入图片描述
  2. 输入stack名称和docker-compose,可以在线编辑也可以上传文件,或者指定git地址
    在这里插入图片描述
    docker-compose
version: '3'
services:
  redis:
    image: 'bitnami/redis:5.0'
    ports:
      - "6379:6379"
    environment:
      - ALLOW_EMPTY_PASSWORD=yes
    deploy:
      replicas: 1
  1. 点击页面下方的Depoly the stack
    在这里插入图片描述
  2. 稍等片刻,即可看到部署好的stack
    在这里插入图片描述
  3. 点击stack名称进入到service列表,可以看到redis被自动部署到了myvm1,且是一个实例
    在这里插入图片描述
Ingress网络

Ingress是swarm集群中每个node都默认存在的一种网络类型,它的作用是可以确保部署在集群中某个端口的服务始终保留该端口,不管实际运行容器的是哪个节点。

尝试在myvm2连接myvm1的redis,这次我们还是使用IP的方式,但使用myvm2的IP

docker@myvm2:~$ docker run -it --rm bitnami/redis:5.0 redis-cli -h 192.168.99.101
192.168.99.101:6379>

redis明明部署在myvm1(192.168.99.100),为什么使用myvm2(192.168.99.101)能访问呢,这就是Ingress网络在启作用了,用一张官网的图说明
在这里插入图片描述
从图中可以看到无论通过哪个node访问服务,都会由swarm loan balancer做一次转发,所以就算当前node未部署相应服务,也能访问的到,只要当前swarm集群中存在该服务。至于访问哪个node的服务,则由swarm轮询控制。

Overlay网络

Overlay网络可以将多个Docker守护进程连接在一起,使集群服务能够彼此通信。
创建Overlay网络有以下几种方式:

  1. 在docker-compose.xml中通过network属性创建。如果不指定network,则会创建一个名为服务名_default的默认overlay网络,并且所以service都加入该overlay网络
  2. 使用docker network create手动创建,在创建service时手动指定network并加入

为了更好的演示,这里新增一个名为rebrow的容器,通过rebrow演示overlay网络的特性。
rebrow是一个web版的查看redis运行情况的工具。

  1. 打开之前创建的redis_stack,点击Editor填写一下内容
    在这里插入图片描述
version: '3'
services:
  redis:
    image: 'bitnami/redis:5.0'
    ports:
      - "6379:6379"
    environment:
      - ALLOW_EMPTY_PASSWORD=yes
    deploy:
      replicas: 1
  rebrow:
    image: 'marian/rebrow'
    ports:
      - "5001:5001"
    deploy:
      replicas: 1
  1. 再点击Update the stack
    在这里插入图片描述
  2. 稍等片刻可看到新增的rebrow服务被创建,此时redis位于myvm1,rebrow位于myvm3
    在这里插入图片描述
  3. 打开http://192.168.99.100:5001/,将Host改为redis,点击Connect
    在这里插入图片描述
  4. 可以看到登录成功,说明位于myvm3的rebrow通过redis这个host就访问到了位于myvm1的redis,且这中间没有任何IP出现,这就是overlay网络的作用。它横跨了myvm1和myvm3,将使用该网络的访问都管理了起来,实现跨主机的互联互通
    在这里插入图片描述
  5. 打开Networks可以看到有两个名为redis_default的网络,位于myvm1和myvm3,分别服务于redis和rebrow
    在这里插入图片描述
  6. 查看其详情可以看到两个redis_default的ID是一样的,这是由swarm自动创建的,将处于同一个overlay网络的服务实例根据其部署的主机而创建,使同一个overlay网络的服务之间能够通过服务名称相互访问。
    在这里插入图片描述

总结

本文简单介绍了跨主机的docker容器之间的通信方式,包括以下3种

  1. 通过容器所在宿主机IP访问
  2. 使用Ingress网络访问
  3. 使用Overlay网络访问
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐