【06】循序渐进学 docker:跨主机通信
写在前面的话
目前解决容器跨主机通信的方案有很多种,这里给出的只是其中的一种,而且还不是最好的方案,不过归根结底,大同小异。在学习 docker swarm 之前,大家可以先看看这种。
啥是 overlay 和 etcd
从这里开始正式引入 overlay 网络这个概念,那啥是 overlay 呢?
可以这样理解,在原本主机通信之上开通的通信隧道,覆盖于原本的主机网络之上,所以叫 overlay。
那 etcd 又是啥?它源于 zookeeper,一个用于分享配置和服务发现的分布式一致性 KV 存储系统。
为啥将这两个东西放在一起?我们的目的就是为了搭建一个能够静态发现,并且能够实现配置共享的容器网络~
etcd 下载地址:
https://github.com/etcd-io/etcd/tags
多主机多容器实践
这里以实例的形式来实现这个功能,需要准备两台安装了 docker 的虚拟机,我这里分别是:
docker-node1:192.168.100.100(之后统称 node1)运行 redis 容器
docker-node2:192.168.100.101(之后统称 node2)运行 flask 容器
具体的拓扑图如下所示,项目就是之前的 flask + redis 项目:

在开始之前,有几点要特别说明:
1. 由于中间会涉及几个端口,建议关闭防火墙,可以省掉很多麻烦。
2. 一定要让两台机器的主机名有意义且不一样,否则莫名其妙的 BUG 调哭你。
3. 为了直接安装 etcd 建议安装 epel 源。
# 修改主机名 hostnamectl set-hostname docker-node1 hostnamectl set-hostname docker-node2 # 关闭防火墙 systemctl stop firewalld.service systemctl disable firewalld.service # 安装 epel 源 yum -y install epel-release
截至我写文之前,GITHUB 上面 etcd 最新 TAG 为 3.3.12,而 epel 里面的版本为:3.3.11,所以推荐 epel 源直接 yum 安装。
【1】在 node1 上安装配置 etcd:
yum -y install etcd cd /etc/etcd/ mv etcd.conf etcd.conf_bak vim etcd.conf
内容如下:
#[Member] ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380" ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001" ETCD_NAME="docker-node1" #[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.100.100:2380" ETCD_ADVERTISE_CLIENT_URLS="http://192.168.100.100:2379,http://192.168.100.100:4001" ETCD_INITIAL_CLUSTER="docker-node1=http://192.168.100.100:2380,docker-node2=http://192.168.100.101:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="new"
说明:有几个值得注意的地方需要说明:
ETCD_NAME:必须唯一,而且在之后的 ETCD_INITIAL_CLUSTER 参数也会用到。
Clustering 下面的配置除了 ETCD_INITIAL_CLUSTER 里面指定其他节点需要用到其他的 IP,否则都使用本机的 IP。
ETCD_INITIAL_CLUSTER_TOKEN:所有的节点都必须配置一样的值,相当于密钥
【2】在 node2 上面也安装 etcd 和配置 etcd:
yum -y install etcd cd /etc/etcd/ mv etcd.conf etcd.conf_bak vim etcd.conf
内容如下:
#[Member] ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380" ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001" ETCD_NAME="docker-node2" #[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.100.101:2380" ETCD_ADVERTISE_CLIENT_URLS="http://192.168.100.101:2379,http://192.168.100.101:4001" ETCD_INITIAL_CLUSTER="docker-node1=http://192.168.100.100:2380,docker-node2=http://192.168.100.101:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="new"
同 node1 的配置,只是需要注意有些标识性的配置改为自己的就行。
简单的做个参数说明:
| 关键字 | 说明 |
|---|---|
| ETCD_DATA_DIR | 数据存储目录 |
| ETCD_LISTEN_PEER_URLS | 与其他节点通信时的监听地址列表,通信协议可以是http、https |
| ETCD_LISTEN_CLIENT_URLS | 与客户端通信时的监听地址列表 |
| ETCD_NAME | 节点名称,在也就是后面配置的那个 名字=地址 |
| ETCD_INITIAL_ADVERTISE_PEER_URLS | 节点在整个集群中的通信地址列表,可以理解为能与外部通信的ip端口 |
| ETCD_ADVERTISE_CLIENT_URLS | 告知集群中其他成员自己名下的客户端的地址列表 |
| ETCD_INITIAL_CLUSTER | 集群内所有成员的地址,这就是为什么称之为静态发现,因为所有成员的地址都必须配置 |
| ETCD_INITIAL_CLUSTER_TOKEN | 初始化集群口令,用于标识不同集群 |
| ETCD_INITIAL_CLUSTER_STATE | 初始化集群状态,new表示新建 |
【3】在两个节点都启动 etcd 并查看:
systemctl start etcd systemctl enable etcd # 查看节点 etcdctl member list # 监控检查 etcdctl cluster-health
结果如图:

如果发现不通报错,一般都是防火墙问题。
【4】修改两个 docker 的启动配置:
node1:
systemctl stop docker vim /etc/systemd/system/multi-user.target.wants/docker.service
将 ExecStart= 项改成如下内容:如果文件不存在,记得:systemctl enable docker.service
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.100.100:2379 --cluster-advertise=192.168.100.100:2375
启动 docker:
systemctl daemon-reload systemctl start docker
node2:
systemctl stop docker vim /etc/systemd/system/multi-user.target.wants/docker.service
将 ExecStart= 项改成如下内容:
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.100.101:2379 --cluster-advertise=192.168.100.101:2375
启动 docker:
systemctl daemon-reload systemctl start docker
【5】 在 node1 上面我们创建一个 overlay 网络:
# 创建网络 docker network create -d overlay demo # 查看 docker network ls
结果如图:

此时在 node2 上面查看网络应该也是存在的~
如果你发现 node2 没有同步或者在 node1 上面直接创建就报 docker swarm 错误,建议重启两个机器的 etcd 服务和 docker 服务,一般就能解决。
【6】我们此时可以创建两个测试容器测试网络的连通性:
node1:
docker run -d --name b1 --net demo busybox sh -c "while true; do sleep 3600; done"
node2:
docker run -d --name b2 --net demo busybox sh -c "while true; do sleep 3600; done"
node1 上测试连通性:
docker container exec b1 ping b2
可以发现已经可以正常通信了。
【7】导出和导入镜像:
这里专门提供了一种导出和导入镜像的方法,因为在 node2 上面没有 Flask 项目的镜像,可以在 node1 上的镜像导出,再到 node2 上面导入,可以节省我们下载的时间。
node1:
docker save python:2.7 dylan/flask-demo:v1.0 -o image.tar
将镜像传到 node2 上面,然后在 node2 执行:
docker load -i image.tar
完成以后在 node2 上面就有了这些镜像。
【8】运行项目:
node1:运行 redis 容器
docker run -d --name redis --network demo redis
node2:运行 flask 容器
docker run -d --name flask-demo --network demo -it -e REDIS_HOST="redis" -p 8080:5000 dylan/flask-demo:v1.0
【9】访问测试:

值得我们注意得是,在这里也没有指定 --link 参数。
小结
总的来说,这种方法还是很复杂的,而且由于是静态发现,每一次增加减少节点都会去修改配置重启 etcd,非常不方便。
【06】循序渐进学 docker:跨主机通信的更多相关文章
- Docker跨主机通信(九)--技术流ken
容器网络 在前面的博客中已经详细讲解了几种网络方案: none, host, bridge,user-defined.但是他们只是解决了单个主机间的容器的通信问题,并不能实现多个主机容器之间的通信.本 ...
- Docker跨主机通信(九)
容器网络 在前面的博客中已经详细讲解了几种网络方案: none, host, bridge,user-defined.但是他们只是解决了单个主机间的容器的通信问题,并不能实现多个主机容器之间的通信.本 ...
- docker跨主机通信扁平化网络的设计与实现
端口映射.ovs. fannel,weave 1.使用网桥实现跨主机容器连接 使用Open vSwitch实现跨主机容器连接
- Docker跨主机通信之路由
一.实验环境: 主机名 主机IP Docker0_IP Docker1 192.168.88.130 172.17.0.1 Docker2 192.168.88.131 172.18.0.1 二.实验 ...
- docker跨主机通信-overlay
使用consul 1,让两个网络环境下的容器互通,那么必然涉及到网络信息的同步,所以需要先配置一下consul. 直接运行下面命令.启动consul. docker run -d -p 8500:85 ...
- Docker跨主机网络——overlay
前言 在Docker网络--单host网络一文中,我为大家总结了Docker的单机网络相关知识和操作,单机网络比较容易.本文我为大家总结Docker跨主机通信相关知识.同样本文大部分内容以CloudM ...
- Docker跨主机网络实践
Docker使用中网络管理是最麻烦的,在项目初始化前期就需要进行合理的规划,如果在比较理想的单主机的网络通信是比较简单的,但如果涉及到跨主机的网络就需要使用docker自带的overlay netwo ...
- overlay 如何实现跨主机通信?- 每天5分钟玩转 Docker 容器技术(52)
上一节我们在 host1 中运行了容器 bbox1,今天将详细讨论 overlay 网络跨主机通信的原理. 在 host2 中运行容器 bbox2: bbox2 IP 为 10.0.0.3,可以直接 ...
- Docker 网络管理及容器跨主机通信
1.网络模式 docker支持四种网络模式,使用--net选项指定: host,--net=host,如果指定此模式,容器将不会获得一个独立的network namespace,而是和宿主机共用一个. ...
随机推荐
- Linux运维基础入门(一)网络基础知识梳理01
一,计算机网络参考模型 1.1 OSI七层模型 1)物理层 主要功能是完成相邻节点之间原始比特流的传输.(网卡等) 物理层协议关心的典型问题是使用什么样的物理信号来表示数据1和0:持续的时间有多长:数 ...
- TCP与UDP与HTTP协议
http:是用于www浏览的一个协议.tcp:是机器之间建立连接用的到的一个协议. 1.TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层.在网络层有IP协议.ICMP协议.ARP协议.R ...
- 导入txt文件到SQL SERVER 2008
最近在学习数据库,想要试处理大量数据.大量的数据手动输入是不可能的了,所以需要导入.本人上网看了不少的教程,然后下载了txt格式的一万条彩票开奖记录数据.但是把这些数据导入到SQL Server 20 ...
- 9-queue
在C++中只要#include<queue>即可使用队列类,其中在面试或笔试中常用的成员函数如下(按照最常用到不常用的顺序) 1. push 2. pop 3. size 4. empty ...
- SpringBoot的配置属性文件*.properties值如何映射到类中使用
想要在JAVA Bean中读取配置文件中的内容有两种方式,可以进行获取到 第一种方式: 1.在默认的配置文件application.properties 中进行设置 Key-Value键值对 com. ...
- orcle clob字段查询
select utl_raw.cast_to_varchar2(DBMS_LOB.SUBSTR(column,2000,1)) from t
- 修改apache的默认访问路径
- 如何将.crt的ssl证书文件转换成.pem格式
如何将.crt的ssl证书文件转换成.pem格式 摘自:https://www.landui.com/help/show-8127 2018-07-04 14:55:41 2158次 准备:有一台安装 ...
- JVM内存模型以及堆分配参数
程序计数器: 存放下一条要运行的指令:每个线程都必须用一个独立的程序计数器,用于记录下一条要运行的指令.程序计数器是一块线程私有的内存空间. JAVA虚拟机栈: 线程私有的内存空间,它保存方法的局部变 ...
- ACM暑假培训宣讲稿
(鞠躬)感谢大家的掌声! 我上台来作这次的宣讲,首先要感谢大家的捧场(当然,这是一句玩笑话),其实吧,我要感谢一下我们ACM班老大(班长),hjh队友,是他指派我来的,给了我这个宝贵的机会.最要感谢的 ...