容器网络

在前面的博客中已经详细讲解了几种网络方案: 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 "" > /proc/sys/net/ipv4/ip_forward

第二步:运行consul

最简单的方式是以容器方式运行 Consul:

[root@ken1 ~]# docker run -d -p : -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 : -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  www.baidu.com
PING www.baidu.com (61.135.169.125): data bytes
bytes from 61.135.169.125: seq= ttl= time=25.144 ms
bytes from 61.135.169.125: seq= ttl= time=24.358 ms --- www.baidu.com ping statistics ---
packets transmitted, packets received, % 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/ dev eth0 scope link src 10.0.0.3
172.18.0.0/ dev eth1 scope link src 172.18.0.2

测试b1能否ping通b2

[root@ken1 ~]# docker exec b1 ping -c  10.0.0.3
PING 10.0.0.3 (10.0.0.3): data bytes
bytes from 10.0.0.3: seq= ttl= time=10.344 ms
bytes from 10.0.0.3: seq= ttl= time=1.694 ms --- 10.0.0.3 ping statistics ---
packets transmitted, packets received, % packet loss
round-trip min/avg/max = 1.694/6.019/10.344 ms [root@ken1 ~]# docker exec b1 ping -c b2
PING b2 (10.0.0.3): data bytes
bytes from 10.0.0.3: seq= ttl= time=2.916 ms
bytes from 10.0.0.3: seq= ttl= time=1.950 ms --- b2 ping statistics ---
packets transmitted, packets received, % 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/ dev eth0 scope link src 10.0.1.2
172.18.0.0/ dev eth1 scope link src 172.18.0.3

现在尝试ping b2

[root@ken1 ~]# docker exec b3 ping -c  10.0.0.3
PING 10.0.0.3 (10.0.0.3): data bytes --- 10.0.0.3 ping statistics ---
packets transmitted, packets received, % 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/ dev eth2 scope link src 10.0.0.4
10.0.1.0/ dev eth0 scope link src 10.0.1.2
172.18.0.0/ 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  10.0.0.3
PING 10.0.0.3 (10.0.0.3): data bytes
bytes from 10.0.0.3: seq= ttl= time=7.145 ms
bytes from 10.0.0.3: seq= ttl= time=2.769 ms --- 10.0.0.3 ping statistics ---
packets transmitted, packets received, % 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. "/home/weave/weaver …" seconds ago Restarting () 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  b2
PING b2 (10.32.0.2): data bytes
bytes from 10.32.0.2: seq= ttl= time=0.141 ms
bytes from 10.32.0.2: seq= ttl= time=0.282 ms --- b2 ping statistics ---
packets transmitted, packets received, % 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 "">/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  b1
PING b1 (10.32.0.1): data bytes
bytes from 10.32.0.1: seq= ttl= time=7.157 ms
bytes from 10.32.0.1: seq= ttl= time=1.021 ms --- b1 ping statistics ---
packets transmitted, packets received, % packet loss
round-trip min/avg/max = 1.021/4.089/7.157 ms
[root@ken3 ~]# docker exec b3 ping -c b2
PING b2 (10.32.0.2): data bytes
bytes from 10.32.0.2: seq= ttl= time=8.116 ms
bytes from 10.32.0.2: seq= ttl= time=1.960 ms --- b2 ping statistics ---
packets transmitted, packets received, % 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/ --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  b2
PING b2 (10.32.0.2): data bytes --- b2 ping statistics ---
packets transmitted, packets received, % packet loss

除了 subnet,我们还可以直接为容器分配特定的 IP:

[root@ken3 ~]# docker run -e WEAVE_CIDR=ip:10.32.6.6/ -it busybox
/ # ip a
: lo: <LOOPBACK,UP,LOWER_UP> mtu qdisc noqueue qlen
link/loopback ::::: brd :::::
inet 127.0.0.1/ scope host lo
valid_lft forever preferred_lft forever
: eth0@if37: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu qdisc noqueue
link/ether ::ac::: brd ff:ff:ff:ff:ff:ff
inet 172.17.0.4/ brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
: ethwe@if39: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu qdisc noqueue
link/ether ae:e0:cd::ac:f5 brd ff:ff:ff:ff:ff:ff
inet 10.32.6.6/ brd 10.32.6.255 scope global ethwe
valid_lft forever preferred_lft forever
/ # ping -c b2
PING b2 (10.32.0.2): data bytes --- b2 ping statistics ---
packets transmitted, packets received, % 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  10.44.0.0
PING 10.44.0.0 (10.44.0.0) () bytes of data.
bytes from 10.44.0.0: icmp_seq= ttl= time=0.327 ms
bytes from 10.44.0.0: icmp_seq= ttl= time=0.068 ms --- 10.44.0.0 ping statistics ---
packets transmitted, received, % 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  10.32.0.1
PING 10.32.0.1 (10.32.0.1) () bytes of data.
bytes from 10.32.0.1: icmp_seq= ttl= time=28.4 ms
bytes from 10.32.0.1: icmp_seq= ttl= time=0.975 ms --- 10.32.0.1 ping statistics ---
packets transmitted, received, % 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/ via 172.20.10.2

[root@host2 ~]# ping -c  10.32.0.1
PING 10.32.0.1 (10.32.0.1) () bytes of data.
bytes from 10.32.0.1: icmp_seq= ttl= time=1.45 ms
bytes from 10.32.0.1: icmp_seq= ttl= time=2.25 ms --- 10.32.0.1 ping statistics ---
packets transmitted, received, % 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跨主机通信(九)--技术流ken的更多相关文章

  1. Docker跨主机通信(九)

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

  2. Docker网络(五)--技术流ken

    本章内容 1.dokcer默认自带的几种网络介绍 2. 自定义网络 3. 容器间通信 4. 容器与外界交互 docker网络分为单个主机上的容器网络和多个主机上的哇网络,本文主要讲解单个主机上的容器网 ...

  3. Docker容器监控(十)--技术流ken

    docker自带的监控命令 docker自带了三个监控命令即ps, top, stats ps docker ps 可以帮助我们很快的了解当前正在运行的容器 -a:会显示已经停掉的容器 [root@h ...

  4. docker跨主机通信扁平化网络的设计与实现

    端口映射.ovs. fannel,weave 1.使用网桥实现跨主机容器连接 使用Open vSwitch实现跨主机容器连接

  5. Docker跨主机通信之路由

    一.实验环境: 主机名 主机IP Docker0_IP Docker1 192.168.88.130 172.17.0.1 Docker2 192.168.88.131 172.18.0.1 二.实验 ...

  6. docker跨主机通信-overlay

    使用consul 1,让两个网络环境下的容器互通,那么必然涉及到网络信息的同步,所以需要先配置一下consul. 直接运行下面命令.启动consul. docker run -d -p 8500:85 ...

  7. Docker跨主机网络——overlay

    前言 在Docker网络--单host网络一文中,我为大家总结了Docker的单机网络相关知识和操作,单机网络比较容易.本文我为大家总结Docker跨主机通信相关知识.同样本文大部分内容以CloudM ...

  8. k8s集群监控(十一)--技术流ken

    Weave Scope   在我之前的docker监控中<Docker容器监控(十)--技术流ken>就已经提到了weave scope. Weave Scope 是 Docker 和 K ...

  9. Docker跨主机网络实践

    Docker使用中网络管理是最麻烦的,在项目初始化前期就需要进行合理的规划,如果在比较理想的单主机的网络通信是比较简单的,但如果涉及到跨主机的网络就需要使用docker自带的overlay netwo ...

随机推荐

  1. mysql数据库内容相关操作

    第一:介绍 mysql数据内容的操作主要是: INSERT实现数据的插入 UPDATE实现数据的更新 DLETE实现数据的删除 SELECT实现数据的查询. 第二:增(insert) 1.插入完整的数 ...

  2. DP-01背包

    题目传送门 题目类似01背包,但存在一个选取先后不同价值会有损耗,所有对物品按易损耗的程度从大到小排个序来顺序选取. #include<bits/stdc++.h> using names ...

  3. [LeetCode] Possible Bipartition 可能的二分图

    Given a set of N people (numbered 1, 2, ..., N), we would like to split everyone into two groups of  ...

  4. Spring Cloud 组件 —— eureka

    官方文档,Spring Cloud 对其封装,Spring Cloud eureka 文档

  5. DCOS实践分享(2):基于Docker Compose和Swarm的Docker化之路

    2016 年1 月 23 日,北京史上气温最低的一天. 在下午 1 点半的时候,由 DaoCloud 赞助的 2016 年度首次 Docker Meetup 准时开始. 在这次Meetup中,我分享了 ...

  6. XML如何添加注释?

    注释以 <!-- 开始并以 --> 结束, 例如 <!--注释内容-->. 注释可以出现在文档序言中,包括文档类型定义 (DTD):文档之后:或文本内容中. 注释不能出现在属性 ...

  7. linux运维架构师职业规划

    1.假如你从来未接触过Linux的话,首先要做的就找一本指导书来学习.现在公认的Linux的入门书籍是“鸟哥的私房菜”,讲的很全面,鸟哥的私房菜一共分为两部,一部是基础篇,一部是服务器篇.“鸟哥的私房 ...

  8. 当初要是看了这篇,React高阶组件早会了

    当初要是看了这篇,React高阶组件早会了. 概况: 什么是高阶组件? 高阶部件是一种用于复用组件逻辑的高级技术,它并不是 React API的一部分,而是从React 演化而来的一种模式. 具体地说 ...

  9. ThinkPHP 数据库操作(七) : 视图查询、子查询、原生查询

    视图查询 视图查询可以实现不依赖数据库视图的多表查询,并不需要数据库支持视图,例如: Db::view('User','id,name') ->view('Profile','truename, ...

  10. Spark中SQL列和并为一行

    在使用数据库的时候,需要将查询出来的一列按照逗号合并成一行. 原表名字为 TABLE ,表中的部分原始数据为: +---------+------------------------+ | BASIC ...