容器网络

在前面的博客中已经详细讲解了几种网络方案: none, host, bridge,user-defined。但是他们只是解决了单个主机间的容器的通信问题,并不能实现多个主机容器之间的通信。本篇博客将详细介绍如何实现该功能。

跨主机网络方案包括两大类:

  1. docker原生的:overlay和macvlan
  2. 第三方方案: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 中的容器呢?

答案是:

  1. 首先将主机加入到 weave 网络。
  2. 然后把主机当作访问 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。

最新文章

  1. C# 与数据库中字段类型 Int16(short), Int32(int), Int64(long)的取值范围、区别 。string长度
  2. CentOS 更改yum源与更新系统
  3. 【Unity3D游戏开发】之常用代码 (十二)
  4. 黑客入门之IP地址及常用命令
  5. AsyncTask的基础讲解
  6. noip2009 潜伏者
  7. open source e-business software - prestashop
  8. HDU 5726 GCD (RMQ + 二分)
  9. JavaScript学习心得(七)
  10. 开源项目AndroidUtil-采用Fragment实现TabHost
  11. A - Next_permutation
  12. mysql主从同步从库同步报错
  13. 安迪的第一个字典(Andy&#39;s First Dictionary,UVa 10815)
  14. 4层板的pcb创建
  15. 谈谈 ArrayList 和 LinkedList 的区别
  16. tomcat启动时卡住
  17. VirtualBox修改现有VDI虚拟磁盘大小
  18. A strange lift HDU - 1548
  19. 范围for循环(c++11)
  20. 【题解】 P1879 玉米田Corn Fields (动态规划,状态压缩)

热门文章

  1. pyttsx3 的使用教程
  2. docker入门4-docker stack
  3. 细讲前端设置cookie, 储存用户登录信息
  4. 个人项目WC.exe Node.js+electron实现
  5. 更改默认Xcode
  6. Linux环境下MySQL 5.6安装与配置----亲测有效----纯离线安装
  7. Clock()函数简单使用(C库函数)
  8. 【Flutter 实战】17篇动画系列文章带你走进自定义动画
  9. 超简单!基于Python搭建个人“云盘”
  10. WordCount(Java实现)