Docker跨主机通信(九)
容器网络
在前面的博客中已经详细讲解了几种网络方案: none, host, bridge,user-defined。但是他们只是解决了单个主机间的容器的通信问题,并不能实现多个主机容器之间的通信。本篇博客将详细介绍如何实现该功能。
跨主机网络方案包括两大类:
- docker原生的:overlay和macvlan
- 第三方方案:flannel、weave和calico
本篇博客将详细讲解overlay以及weave两种方案。
overlay
Docerk overlay 网络需要一个 key-value 数据库用于保存网络状态信息,包括 Network、Endpoint、IP 等。Consul、Etcd 和 ZooKeeper 都是 Docker 支持的 key-vlaue 软件,我们这里使用 Consul。
在 docker 主机 host1(172.20.10.2)和 host2(172.20.10.7)上实践各种跨主机网络方案,在 172.20.10.2 上部署支持的组件,比如 Consul。
第一步:启动路由转发功能
两台主机上面都需要开启
[root@ken3 ~]# echo "1" > /proc/sys/net/ipv4/ip_forward
第二步:运行consul
最简单的方式是以容器方式运行 Consul:
[root@ken1 ~]# docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap
第三步:浏览器访问
容器启动后,可以通过 http://172.20.10.2:8500 访问 Consul。
第四步:修改docker启动文件
接下来修改 host1 和 host2 的 docker daemon 的配置文件/usr/lib/systemd/system/docker.service
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H unix:// --cluster-store=consul://172.20.10.2:8500 --cluster-advertise=eth0:2376
...
--cluster-store
指定 consul 的地址。--cluster-advertise
告知 consul 自己的连接地址(eth0即为网卡名,固定格式)
重启 docker daemon。
[root@ken1 ~]# systemctl daemon-reload
[root@ken1 ~]# systemctl restart docker
重启consul
[root@ken1 ~]# docker rm $(docker ps -aq)
[root@ken1 ~]# docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap
第五步:浏览器查看
可以发现两个主机已经自动注册上去了
创建overlay网络
在host1中创建网络ov_ken
[root@ken1 ~]# docker network create -d overlay ov_ken
25979f1d44c12362f3866295995756984468060c10479288835d64588f27fa3b
[root@ken1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e36545bfeb92 bridge bridge local
43b0997b8ce5 host host local
36d9a3277b19 none null local
25979f1d44c1 ov_ken overlay global
注意到 ov_ken
的 SCOPE 为 global,而其他网络为 local。在 host2 上查看存在的网络:
host2 上也能看到 ov_ken。这是因为创建 ov_ken 时 host1 将 overlay 网络信息存入了 consul,host2 从 consul 读取到了新网络的数据。之后 ov_ken 的任何变化都会同步到 host1 和 host2。
docker network inspect
查看 ov_ken 的详细信息:
docker 自动为 ov_ken分配的 IP 空间为 10.0.0.0/24。
在overlay中运行容器
行一个 busybox 容器并连接到 ov_ken:
[root@ken1 ~]# docker run -itd --name b1 --network ov_ken busybox
fc6454145e12c1c1a494914e3c71d4a9c7c7da0d6ed888e4b6d2afe80379e000
访问外网测试
可以发现容器访问外网是没有问题的
外网想要访问主机可以通过端口映射
[root@ken1 ~]# docker exec b1 ping -c 2 www.baidu.com
PING www.baidu.com (61.135.169.125): 56 data bytes
64 bytes from 61.135.169.125: seq=0 ttl=54 time=25.144 ms
64 bytes from 61.135.169.125: seq=1 ttl=54 time=24.358 ms --- www.baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 24.358/24.751/25.144 ms
跨主机连通
在 host2 中运行容器 b2
[root@ken3 ~]# docker run -itd --name b2 --network ov_ken busybox
查看b2的网络
b2的ip为10.0.0.3
[root@ken3 ~]# docker exec b2 ip r
default via 172.18.0.1 dev eth1
10.0.0.0/24 dev eth0 scope link src 10.0.0.3
172.18.0.0/16 dev eth1 scope link src 172.18.0.2
测试b1能否ping通b2
[root@ken1 ~]# docker exec b1 ping -c 2 10.0.0.3
PING 10.0.0.3 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: seq=0 ttl=64 time=10.344 ms
64 bytes from 10.0.0.3: seq=1 ttl=64 time=1.694 ms --- 10.0.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 1.694/6.019/10.344 ms [root@ken1 ~]# docker exec b1 ping -c 2 b2
PING b2 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: seq=0 ttl=64 time=2.916 ms
64 bytes from 10.0.0.3: seq=1 ttl=64 time=1.950 ms --- b2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 1.950/2.433/2.916 ms
可见 overlay 网络中的容器可以直接通信,同时 docker 也实现了 DNS 服务。
overlay网络隔离
不同的 overlay 网络是相互隔离的。我们创建第二个 overlay 网络 ov_ken2 并运行容器 b
[root@ken1 ~]# docker network create -d overlay ov_ken2
2008b1f950566f105a567ea422ef2269b1db226de58b2d8d8350a91106542d27 [root@ken1 ~]# docker run -itd --name b3 --network ov_ken2 busybox
9f6b4166169ebe5993f8533c57dbf0089fe539a09607d94d3d9442990c8393ea
查看b3分配到的IP
可以发现是10.0.1.2
[root@ken1 ~]# docker exec b3 ip r
default via 172.18.0.1 dev eth1
10.0.1.0/24 dev eth0 scope link src 10.0.1.2
172.18.0.0/16 dev eth1 scope link src 172.18.0.3
现在尝试ping b2
[root@ken1 ~]# docker exec b3 ping -c 2 10.0.0.3
PING 10.0.0.3 (10.0.0.3): 56 data bytes --- 10.0.0.3 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
ping 失败,可见不同 overlay 网络之间是隔离的。
如果要实现 b3 与 b2 通信,可以将 b3 也连接到 ov_ken。
[root@ken1 ~]# docker network connect ov_ken b3 [root@ken1 ~]# docker exec b3 ip r
default via 172.18.0.1 dev eth1
10.0.0.0/24 dev eth2 scope link src 10.0.0.4
10.0.1.0/24 dev eth0 scope link src 10.0.1.2
172.18.0.0/16 dev eth1 scope link src 172.18.0.3
可以发现现在的b3有了一个eth2的网卡,ip地址为10.0.0.4
现在再来测试一下b3能否ping通b2
[root@ken1 ~]# docker exec b3 ping -c 2 10.0.0.3
PING 10.0.0.3 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: seq=0 ttl=64 time=7.145 ms
64 bytes from 10.0.0.3: seq=1 ttl=64 time=2.769 ms --- 10.0.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 2.769/4.957/7.145 ms
可以发现现在可以ping通了
weave网络
weave 不依赖分布式数据库(例如 etcd 和 consul)交换网络信息,每个主机上只需运行 weave 组件就能建立起跨主机容器网络。接下来在 host1 和 host2 上部署 weave 并实践 weave 的各项特性。
安装部署weave
weave 安装非常简单,在 host1 和 host2 上执行如下命令:
[root@ken1 ~]# curl -L git.io/weave -o /usr/local/bin/weave
[root@ken1 ~]# chmod a+x /usr/local/bin/weave
host1中启动weave
在 host1 中执行 weave launch
命令,启动 weave 相关服务。weave 的所有组件都是以容器方式运行的,weave 会从 docker hub 下载最新的 image 并启动容器。
[root@ken1 ~]# weave launch
查看启动的容器
[root@ken1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7a59dcccd908 weaveworks/weave:2.5.1 "/home/weave/weaver …" 37 seconds ago Restarting (1) 36 seconds ago weave
weave 运行了一个容器:
weave
是主程序,负责建立 weave 网络,收发数据 ,提供 DNS 服务等。
host1中启动容器
[root@ken ~]# eval $(weave env)
[root@ken ~]# docker run --name b1 --rm -itd busybox
e04f798321072542450ca800601e980d206e00e8850b1b1ce16f4cba8ce94a32
首先执行 eval $(weave env)
很重要,其作用是将后续的 docker 命令发给 weave proxy 处理。如果要恢复之前的环境,可执行 eval $(weave env --restore)
。
查看一下当前容器 bbox1 的网络配置:
b1 有两个网络接口 eth0 和 ethwe,其中 eth0 连接的是默认 bridge 网络,即网桥 docker0。
分配的 IP 10.32.0.1/12 ethwe 与 weave 相关
再运行一个容器 b2。
[root@ken ~]# docker run --name b2 --rm -itd busybox
abf55e9dead051e0e87afd524243fbb7c3a6985042d0d924a829a91399c76ade
测试b1与b2的连通性(相同主机host!)
可以发现b1与b2不仅可以互相ping通,还可以解析
[root@ken ~]# docker exec b1 ping -c 2 b2
PING b2 (10.32.0.2): 56 data bytes
64 bytes from 10.32.0.2: seq=0 ttl=64 time=0.141 ms
64 bytes from 10.32.0.2: seq=1 ttl=64 time=0.282 ms --- b2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.141/0.211/0.282 ms
weave跨主机通信
第一步:首先在host2 执行如下命令
[root@ken3 ~]# weave launch 172.20.10.2
e69a5bec56eb8d5471b139ce2c3080f2681e44c7bf582ef798c017d83107e3ac
这里必须指定 host1 的 IP 172.20.10.2,这样 host1 和 host2 才能加入到同一个 weave 网络。
第二步:开启路由转发功能
echo "1">/proc/sys/net/ipv4/ip_forward
第三步:启动容器
[root@ken3 ~]# eval $(weave env)
[root@ken3 ~]# docker run --name b3 --rm -itd busybox
4c86439dd59d545eb73e796709872cd51e4953503e63c2a0ff4549b2eb3ce8fa
第四步:测试容器连接性
可以发现主机host2上运行的b3容器可以与host1主机上面运行的b1和b2容器进行通信,而且可以解压主机名。
[root@ken3 ~]# docker exec b3 ping -c 2 b1
PING b1 (10.32.0.1): 56 data bytes
64 bytes from 10.32.0.1: seq=0 ttl=64 time=7.157 ms
64 bytes from 10.32.0.1: seq=1 ttl=64 time=1.021 ms --- b1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 1.021/4.089/7.157 ms
[root@ken3 ~]# docker exec b3 ping -c 2 b2
PING b2 (10.32.0.2): 56 data bytes
64 bytes from 10.32.0.2: seq=0 ttl=64 time=8.116 ms
64 bytes from 10.32.0.2: seq=1 ttl=64 time=1.960 ms --- b2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 1.960/5.038/8.116 ms
weave网络隔离
默认配置下,weave 使用一个大 subnet(例如 10.32.0.0/12),所有主机的容器都从这个地址空间中分配 IP,因为同属一个 subnet,容器可以直接通信。如果要实现网络隔离,可以通过环境变量 WEAVE_CIDR
为容器分配不同 subnet 的 IP,举例如下:
[root@ken3 ~]# docker run -e WEAVE_CIDR=net:10.32.2.0/24 --rm -itd busybox
98bc93412af210e08b4be7a9456e40749ca4a0672f3ebbc5a5f616ab0b4d3b50
这里 WEAVE_CIDR=net:10.32.2.0/24
的作用是使容器分配到 IP 10.32.2.2
。由于 10.32.0.0/12 与 10.32.2.0/24 位于不同的 subnet,所以无法 ping 到 b2。
[root@ken3 ~]# docker exec 98bc93412af ping -c 2 b2
PING b2 (10.32.0.2): 56 data bytes --- b2 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
除了 subnet,我们还可以直接为容器分配特定的 IP:
[root@ken3 ~]# docker run -e WEAVE_CIDR=ip:10.32.6.6/24 -it busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
36: eth0@if37: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
38: ethwe@if39: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1376 qdisc noqueue
link/ether ae:e0:cd:41:ac:f5 brd ff:ff:ff:ff:ff:ff
inet 10.32.6.6/24 brd 10.32.6.255 scope global ethwe
valid_lft forever preferred_lft forever
/ # ping -c 2 b2
PING b2 (10.32.0.2): 56 data bytes --- b2 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
weave与外网的连通性
weave 是一个私有的 VxLAN 网络(容器可以访问外网),默认与外部网络隔离。外部网络如何才能访问到 weave 中的容器呢?
答案是:
- 首先将主机加入到 weave 网络。
- 然后把主机当作访问 weave 网络的网关。
第一步:要将主机加入到 weave,执行 weave expose
。
[root@ken3 ~]# weave expose
10.32.2.129
第二步:查看IP
这个 IP 10.32.2.129
会被配置到 host2 的 weave 网桥上。
第三步:测试连通性
ping同一主机的b3
[root@ken3 ~]# ping -c 2 10.44.0.0
PING 10.44.0.0 (10.44.0.0) 56(84) bytes of data.
64 bytes from 10.44.0.0: icmp_seq=1 ttl=64 time=0.327 ms
64 bytes from 10.44.0.0: icmp_seq=2 ttl=64 time=0.068 ms --- 10.44.0.0 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.068/0.197/0.327/0.130 ms
ping host1中的b1
[root@ken3 ~]# ping -c 2 10.32.0.1
PING 10.32.0.1 (10.32.0.1) 56(84) bytes of data.
64 bytes from 10.32.0.1: icmp_seq=1 ttl=64 time=28.4 ms
64 bytes from 10.32.0.1: icmp_seq=2 ttl=64 time=0.975 ms --- 10.32.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.975/14.708/28.442/13.734 ms
接下来要让其他非 weave 主机访问到 bbox1 和 bbox3,只需将网关指向 host1。例如在 172.20.10.9上添加如下路由:
[root@host2 ~]# ip route add 10.32.0.0/12 via 172.20.10.2 [root@host2 ~]# ping -c 2 10.32.0.1
PING 10.32.0.1 (10.32.0.1) 56(84) bytes of data.
64 bytes from 10.32.0.1: icmp_seq=1 ttl=63 time=1.45 ms
64 bytes from 10.32.0.1: icmp_seq=2 ttl=63 time=2.25 ms --- 10.32.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 1.450/1.852/2.254/0.402 ms
10.32.0.0/12 是 weave 网络使用的默认 subnet,如果此地址空间与现有 IP 冲突,可以通过 --ipalloc-range
分配特定的 subnet。
weave launch –ipalloc-range 10.2.0.0/16
不过请确保所有 host 都使用相同的 subnet。
Docker跨主机通信(九)的更多相关文章
- Docker跨主机通信(九)--技术流ken
容器网络 在前面的博客中已经详细讲解了几种网络方案: 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,而是和宿主机共用一个. ...
- Docker容器跨主机通信
默认情况下Docker容器需要跨主机通信两个主机节点都需要在同一个网段下,这时只要两个Docker容器的宿主机能相互通信并且该容器使用net网络模式,改实现方式为网桥模式通信: 除此之外我们还可以通过 ...
随机推荐
- python去除 数据的 重复行
原文链接:https://www.cnblogs.com/loren880898/p/11303672.html
- 【Gin-API系列】Gin中间件之日志模块(四)
日志是程序开发中必不可少的模块,同时也是日常运维定位故障的最重要环节之一.一般日志类的操作包括日志采集,日志查询,日志监控.日志统计等等.本文,我们将介绍日志模块在Gin中的使用. Golang如何打 ...
- angular schametics 使用记录
什么是 schametics Schematics是Angular团队发布的一个代码生成工具.它提供了API,可以操作文件并在Angular项目中添加新的依赖项,ng cli 创建模板就是用它. 它也 ...
- 更换IntelliJ Idea的Terminal为git_home/bin/sh.exe命令端程序
idea中默认的terminal形式: 1.在IDEA中,打开settings,设置相应的bash路径 settings–>Tools–>Terminal–>Shell path:C ...
- 《java多线程——线程简介与其创建(1)》
Java 给多线程编程提供了内置的支持. 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. 多线程是多任务的一种特别的形式,但多线程使用了更小的资源开 ...
- python列表元素的基本操作
1.列表元素的增加 python提供三种方法增加元素,append,extend,insert. 区别:例 list3=[1,10,100,1000,10000] A. list3.append ...
- py_选择排序
# 选择排序 # 一趟排序记录最小值,放到第一个位置 #再一趟排序记录记录列表无序区最小的数,放到第二个位置 #.... # 关键点:有序区.无序区.无序区最小值 #方法一 def select_So ...
- Android开发之TextView中间设置横线,适用于电商项目,商品原价之类的功能。
textview.getPaint().setFlags(Paint. STRIKE_THRU_TEXT_FLAG ); //中间横线 textview.getPaint().setFlags(Pai ...
- lua 优化
彻底解析Android缓存机制——LruCache https://www.jianshu.com/p/b49a111147ee lua:部分常用操作的效率对比及代码优化建议(附测试代码) https ...
- c++ binding code generator based on clang
google it http://www.swig.org/Doc3.0/CSharp.html http://samanbarghi.com/blog/2016/12/06/generate-c-i ...