目录
2.1 法(一)使用 run --link 进行容器互连(×)
我们之前通过端口映射实现过宿主机、外部主机对容器的访问。如果一个外部主机想要访问容器,那么访问宿主机的映射端口就好了!
那如果想要实现两个容器之间的通信怎么办?用已有的经验,是像图中蓝色的线那样走吗?
一、Docker0网络
我们运行一个容器,进入容器内部后发现容器也有自己的IP地址。
而且可以发现docker0的IP和容器的IP在同一个网段内(类似于路由器和连接到的路由器的终端),说明容器的IP是由docker0去分配的。
docker0的IP : 172.17.0.1
容器的IP :172.17.0.2
然后我们以Ctrl+p+q的方式,退出运行的容器, 让其在后台运行。此时在宿主机执行ip addr命令,发现容器的网卡在宿主机也能查到,但是抹去了其ip。
此时,我们会想,那宿主机能ping通容器吗?
发现是能ping通的!
这是通过什么技术实现的呢?
evth-pair技术!我们可以发现,容器的网卡是成对出现的,下图中网卡6和网卡7作为一对。
我们再看宿主机显示的网卡名,发现6和7的位置颠倒过来了。
evth-pair就是一对虚拟设备接口,他们都是成对出现的,一端连接着协议,一端连接着彼此。
evth-pair充当一个桥梁,通过虚拟网卡连接起各种虚拟网络设备,宿主机和docker容器就是通过evth-pair连接的,docker容器和docker容器之间也是这样连接的。
所以docker容器之间也是可以互相ping通的!
但是docker容器之间的通信并不是像下图这样直接通信的
而是通过docker0(可以直接看作路由器)和evth-pair技术。如果容器B要ping容器C,需要先发到docker0上,再由docker0发给容器C。
此外,通过研究docker网络我们还发现,docker0的IP是172.17.0.1/16,这就说明docker最多开65535个容器。
Docker中的网卡都是虚拟的,开始容器后出现一对虚拟网卡,rm掉这个容器以后,网卡也就没了。
二、容器互连
前面我们已经知道,容器和容器之间是可以ping通的,两个容器通过docker0可以通信,并且我们也做了UDP双人聊天项目进行两个容器之间通信的实战:
已经可以互连了,那为什么还要学习容器互连呢?因为上面这种联通方法有很多弊端。
弊端(一):所有容器之间的连接都要经过docker0,所有容器都被docker0分配到172.17.0.0/16这个网段上,所有容器都可以互相ping通,这是不安全的。如果我们想要定义下图这样一个与其他容器隔离的网络空间/集群,这个空间内部的容器相互连接,和外界保持隔离,这是做不到的。
弊端(二):我们容器之间连接的时候用的是172.17.0.3这样的IP地址,而不是名字,会出现这样的问题:比如我们我们访问百度用的不是www.baidu.com域名,而是记住百度搜索主页服务器提供的IP:39.156.66.10,那么倘若百度搜索主页换了一台服务器39.156.66.11,就必须“昭告天下”,是不是很麻烦?所以出现了IP地址:域名这一对名字映射。
同样地,我们也希望容器之间连接时不要再通过彼此的IP地址,而是提供一对IP地址:容器名的映射,直接通过彼此的容器名访问。
由此看来,名字目录Naming Directory的思想在计算机网络中随处可见!
2.1 法(一)使用 run --link 进行容器互连(×)
docker run --name tomcat03 --link tomcat02
这样,容器tomcat03去ping tomcat02的时候不需要查找tomcat02的IP地址,而是直接:
ping tomcat02
其底层原理是这样的,执行docker run --link命令之后,容器tomcat03(看作一台小型Linux虚拟机)便在/etc/hosts文件里写入了
172.17.0.x tomcat02
这样一条名字映射。 但是其弊端在于,此时tomcat02并不能通过tomcat03的容器名去pingtomcat03,必须得运行tomcat02时也加上--link tomcat03才行。
通过--link互连的方法已经淘汰了。
2.2 法(二)自定义网络(√)
分为两步,我们需要先用docker network create命令创建一个网络,然后在运行容器的时候用docker run --net命令把容器加入到这个网络中。
1. docker network create 创建一个网络
我们先用docker network ls命令看一下docker默认都有什么网络。
2. 把容器加入到自定义的网络当中
PS:之前在运行docker run命令时,自动跟着--net bridge参数(bridge代表docker network ls第1行名为bridge的网络),意思是容器桥接到docker0上。
现在我们用--net mynet将容器加入到自定义的网络中,就不直接桥接到docker0上了。 下图红框的部分就是我们的mynet。
用docker network inspect mynet 查看一下
看一下mynet的隔离性:是否能ping通docker0?(能)是否能ping通mynet外部的其他容器?(不能)
那如何实现让docker0网段里的tomcat03和mynet网段里的tomcat-mynet-01通呢?
很简单,只需要把tomcat03硬拉进mynet网络里。
也就是一个容器两个IP思想(一个主机两个网卡)。
docker network connect 网络名 容器名
验证(1): 然后我们再用tomcat-mynet-01 和 tomcat-03互相ping。
验证(2):我们用如下命令查看一下tomcat-03的IP地址
docker inspect tomcat-03
验证(3):我们用docker network inspect mynet 命令查看mynet里都有谁?
三、Redis集群部署实战
集群描述: 上面3个master,下面3个master的备份。ms死掉了,由s3顶上。
1. 在docker中创建网络 redis,规定网段为172.38.0.0/16
2. 用shell脚本在宿主机上配置redis的6个结点,作为docker容器的数据卷,稍后完后挂载。
查看宿主机数据卷上的redis节点配置信息cat /mydata/redis/node-1/conf/redis.conf:
3. docker run 开启6个redis服务。 --net redis --ip 172.38.0.11加入到redis网络中并手动分配ip。
PS:6379是redis默认的端口号
开启剩下5个redis服务。
PS:正常一台机器是带不起来6个redis服务的,但是用docker就可以。
然后我们在node-3上存储上一个key-value键值对,然后用docker stop redis-3把node-3停掉,这时候再去根据key查value发现依然能查到,说明master死后,备份的结点顶上来了。
PS: docker搭建集群分分钟完成