docker overlay网络详解

之前我们学习的网络是单台主机的网络通讯方案,这里我们学习的是跨主机方案。

我们原生的docker跨主机方案有macvlan和overlay,这里我们重点学习overlay

第三方网络插件有flannel,calico,weave网络。

docker网络之所以这么活跃,是因为网络部分的代码单独抽离出来成为docker的网络库,即libnetwork。

为了标准化网路驱动的开发步骤和支持各种网络驱动,libnetwork中使用了CNM(container network model),CNM定义了构建容器虚拟化网络的模型,同时还提供了可以用于开发多种网络驱动的标准化接口和组件。

现在我们有两台主机,里面的容器之间要进行通讯的话,要保持一个公式相等,即一个网段=一个广播域=一个VLAN。

下面介绍一下两个container的通讯构建过程,

首先会在我们的主机当中构建一个网络,这个网络叫做sanbox,这个是网络容器内的协议栈。

在每个容器里面都会这样的一个设备叫做endpoint,它的作用就是把容器(sandbox)接入到network中去,endpoint最典型的案例就是veth pair

network包含的是一组endpoint,同一个network下的endpoint可以通信,network实现的方法就是桥接加VLAN的方式。

什么叫做overlay网络?

字面意思就是叠加的网络,指的就是在物理网络层上再搭建一层网络,通过某种技术再构建一张相同的网络,这张称为逻辑网。也就是说我们想要两台主机的容器进行通讯,首先这两台主机自己要可以通讯,然后在这个物理机的基础之上部署一张逻辑层的网络,他具有物理网络的所有特性,跟物理网络一模一样。

VLAN是什么,我们想要划分网络就叫做VLAN,VLAN只是单纯的对物理网络进行划分,隔离ip,Mac。VLAN是划分广播域的最基础概念。

vxlan是在物理网络基础之上构建出来的网络,这个网络可以通过 vxlan进行划分,ip,Mac只需要在一个vxlan中就可以进行通讯。

我们overlay网络的需求就是需要一个非关系型的数据库,这里以consul为例

[root@master1~]# docker pull progrium/consul

这里将要存放的是network,endpont,sandbox,ip等信息。

两台主机名必须不一样,然后启动我们的consul镜像

[root@master1 ~]# docker run -d --restart always -p 8400:8400 -p 8500:8500 -p 8600:53/udp -h consul progrium/consul -server -bootstrap -ui-dir /ui c1f0022ecfdb494a3ecc86384ef132479fe251a0c53e35146e120bba3d955987 [root@master1 ~]#

这个时候我们可以通过浏览器访问到我们的consul

启动完成之后,这个时候我们需要把测试的两个主机加入到我们的consul中来

在docker.service这个文件中加即可

加入第一台主机:

增加参数如下:

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --cluster-store=consul://192.168.64.150:8500 --cluster-advertise=ens33:2376

分析:

  1. --cluster-store 表示存储在哪里
  2. --cluster-advertise 本机网卡地址,2376为默认端口

第二台机器加入同样的参数即可。

然后先重启consul所在主机的docker,然后重启第二台主机。

然后看一下consul的web端

这个时候,我们的试验环境就已经准备好了

此时查看宿主机的network

[root@master1 ~]# docker network ls

NETWORK ID NAME DRIVER SCOPE

2238d0cf60dc bridge bridge local

3b93f4bad0a9 host host local

6b6f0e006e46 none null local

这个时候我们需要创建一个网络,创建之前先看一下物理网卡支不支持vxlan,这里不支持,按照如下方式修改即可:

[root@master1 ~]# ifconfig ens33 promisc

promisc:混杂模式

Linux下网卡的混杂模式浅谈 - 云+社区 - 腾讯云

在第二台主机相同的操作。。。

补充:删除的命令 ifconfig ens33 -promisc

这个时候我们就可以创建overlay的网络驱动器了

[root@master1 ~]# docker network create --driver overlay --attachable ov_net1 5473d38fd5fd0b4a1d432c60af2d8a9fef942b72b8333b41cbf210c86a451d69

[root@master1 ~]# docker network ls

NETWORK ID NAME DRIVER SCOPE

2238d0cf60dc bridge bridge local

3b93f4bad0a9 host host local

6b6f0e006e46 none null local

5473d38fd5fd ov_net1 overlay global //这个global表示全局生效

attachable的作用是:默认情况下。overlay生效的返回是在dockerswarm集群中,如果想要单独拿出来用的话,没有在这个集群中创建的话,就需要加这个单词。

这个时候我们去我们另外一台主机上看,发现也会自动同步一个overlay网络

[root@master2 ~]# docker network ls

NETWORK ID NAME DRIVER SCOPE

d0b01765b18e bridge bridge local

822ef830c4f7 host host local

ff5394e0cfc8 none null local

5473d38fd5fd ov_net1 overlay global

[root@master2 ~]#

我们观察一下这个网络的特点

根据我们之前的经验,网关地址可能是桥接卡的地址,我们ip a看一下宿主机网络,发现没有

这个时候猜想可能在另外的一个namespace网络空间,因为我们的overlay网络是在一层物理机网络之上,在铺设一层网络。

我先使用一下这个overlay网络

发现overlay网络有两个网卡,12的那个是overlay的网段的网卡,15的那个172.18的网段,现在看看这两块网卡分别连到宿主机的哪块网卡。。

(容器里面12号网卡连接容器外边的13号,没有在宿主机找到,这个其实在ip netns网络空间里面,这个我们后边会讲到,暂时先不解释这个连接,即先不管10.0这个网段,下面的先讲15连16的情况)

我们发现在主机当中多了14号的那块网卡,docker_gwbridge,刚好也是172.18的网段。

根据名字可以猜到这个是块网关桥接卡

[root@master1 ~]# brctl show

bridge name bridge id STP enabled interfaces

docker0 8000.02428ec5c553 no vetha5eebba

docker_gwbridge 8000.02423841ce9a no veth78af435

[root@master1 ~]#

新增了一个名为docker_gwbridge的桥接卡

docker network ls查看一下docker的网络,也多了一块网卡

[root@master1 ~]# docker network ls

NETWORK ID NAME DRIVER SCOPE

2238d0cf60dc bridge bridge local

09575e4ff9dc docker_gwbridge bridge local

3b93f4bad0a9 host host local

6b6f0e006e46 none null local

5473d38fd5fd ov_net1 overlay global

[root@master1 ~]#

我们大概画一下这个关系

那么这个网络能不能对外通讯呢?

其实整个对外通讯走的都是docker_gwbridge这个桥接卡,因为物理机上没有10网段的路由转发

[root@master1 ~]# ip r

default via 192.168.64.2 dev ens33 proto static metric 100

172.17.0.0/16 dev docker0 proto kernel scope link src

172.17.0.1 172.18.0.0/16 dev docker_gwbridge proto kernel scope link src

172.18.0.1 192.168.64.0/24 dev ens33 proto kernel scope link src 192.168.64.150 metric 100

即容器想要通过物理机对外进行通讯的话,一定要依赖这个docker_gwbridge的网卡。

测试一下

使用network ls命令查看,也没有增加额外的网卡信息。。。

查看网桥信息,可以发现多了veth19bab1f连接到docker_gwbridge这个桥接卡上了。

所以这个docker_gwbridge其实是用来跟外网进行通讯的。。。

这里还没有到我们的overlay网络的讲解,因为上面的讲解是容器如何实现对外网通讯的,这来我们刚开始可能有个疑问,明明最开始创建容器(bbox1或者web1)的时候我们--network选择式是overlay网络。。。我们想想啊,选择的是overlay,能实现跨主机通讯,但是总要跟外网通讯的呀,而且刚开始的是,创建bbox1的时候,我们进入容器里面Ip a看到的是有两块网卡信息,上面解释了能够在物理机使用ip a命令看到的那一块。。。

下面我们才真正开始解释,为啥物理机看不到另外的一块信息。

我们在另外一台主机上创建一个bbox2,让它来连接开始的那台主机的bbox1

[root@master2 ~]# docker run -itd --name bbox2 --network ov_net1 busybox 6087d1baca4499f68dfabc65486177b6d2814b4ff33e9f561dcae16a0ed87f4a [root@master2 ~]# docker exec -it bbox2 sh

/ # 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

6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue link/ether 02:42:0a:00:00:04 brd ff:ff:ff:ff:ff:ff inet 10.0.0.4/24 brd 10.0.0.255 scope global eth0 valid_lft forever preferred_lft forever

9: eth1@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1 valid_lft forever preferred_lft forever

/ # ping bbox1

PING bbox1 (10.0.0.2): 56 data bytes

64 bytes from 10.0.0.2: seq=0 ttl=64 time=8.489 ms

64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.765 ms

^C

--- bbox1 ping statistics ---

2 packets transmitted, 2 packets received, 0% packet loss

round-trip min/avg/max = 0.765/4.627/8.489 ms

/ # ping 10.0.0.1

PING 10.0.0.1 (10.0.0.1): 56 data bytes

64 bytes from 10.0.0.1: seq=0 ttl=64 time=0.085 ms

64 bytes from 10.0.0.1: seq=1 ttl=64 time=0.054 ms

^C

--- 10.0.0.1 ping statistics ---

2 packets transmitted, 2 packets received, 0% packet loss

round-trip min/avg/max = 0.054/0.069/0.085 ms

/ #

/ # ping 10.0.0.2

PING 10.0.0.2 (10.0.0.2): 56 data bytes

64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.280 ms

64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.256 ms

^C

--- 10.0.0.2 ping statistics ---

2 packets transmitted, 2 packets received, 0% packet loss

round-trip min/avg/max = 0.256/0.268/0.280 ms

/ #

/ # ping 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=0.504 ms

64 bytes from 10.0.0.3: seq=1 ttl=64 time=0.671 ms

^C

--- 10.0.0.3 ping statistics ---

2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.504/0.587/0.671 ms

/ #

如上试验,我们也支持DNS通讯,overlay实现了跨主机通讯的同时,docker也实现了DNS的解析,docker会为我们创建一个独立的网络空间,因为10网段不在物理机上,即我们使用ip a无法看到某个网卡是10网段的。

((docker inspect 403784c26c7e |grep -i sand 查看某个容器属于哪个netns))

使用ip netns 查看宿主机的网络空间,发现没有看到,此时我们需要去docker的文件系统目录下看

[root@master1 ~]# cd /var/run/docker/

[root@master1 docker]# ls

containerd libnetwork metrics.sock netns plugins runtime-runc swarm

[root@master1 docker]# ls netns/

1-5473d38fd5 51fc6a02edce 604c7fb0bdfb 74c2063136cd

[root@master1 docker]#

里面有个netns目录,我们把它连接到我们常规查看的网络空间的目录下,然后再次查看

[root@master1 ~]# ln -s /var/run/docker/netns/ /var/run/netns

[root@master1 ~]# ip netns

604c7fb0bdfb (id: 3)

74c2063136cd (id: 2)

1-5473d38fd5 (id: 1)

51fc6a02edce (id: 0)

[root@master1 ~]#

同理我们在第二台主机上也软连接一下

[root@master2 ~]# ln -s /var/run/docker/netns/ /var/run/netns

[root@master2 ~]#

[root@master2 ~]#

[root@master2 ~]#

[root@master2 ~]# ip netns

5eebc027694b (id: 1)

1-5473d38fd5 (id: 0)

[root@master2 ~]#

我们发现两台主机都有一个1-5473d38fd5的空间名字,查看一下这个网络空间,我们发现了13号网卡了,之前不是讲过我们创建的bbox1容器里面,有12号网卡连接到13号网卡,但是宿主机找不到13号网卡,在这里面可以找到。(18号网卡是连接到我们的web1容器里的17号)

[root@master1 ~]# ip netns exec 1-5473d38fd5 brctl show

bridge name bridge id STP enabled interfaces br0 8000.723a3c527d07 no veth0 veth1 vxlan0

[root@master1 ~]#

发现在1-5473d38fd5这个网络空间内br0这块网卡才是10.0网段的,13那块网卡并没有10.0网段地址,其实我们的13号网卡,也就是veth0桥接到br0上了。

在主机当中有另外的一个空间的存在,这里就是1-5473d38fd5,这个空间里面有如上的桥接关系。

(复习一个知识点,不同空间的网卡数据转发方式是veth pair,同一个空间是桥接)

我们发现br0上有vxlan0的接口,vxlan0的作用是跟对端主机进行通讯的,也就是我们这里的第二台主机。对端主机的网络也是这样的形式,如下:

两台主机的容器进行通讯依靠的是vxlan在相同的网络里面,此时查看一下vxlan0的ID号

VXLAN ID相同,大家在同一个广播域里面,地址又是同一个网段的,既可以通讯。

通讯的话,就是上面的介绍。

下面介绍一下如何实现隔离的

先创建一个overlay网络

[root@master1 ~]# docker network create --driver overlay --attachable ov_net2 aafcf8d932c847d3f520a1b350cb36c63ceacd18cbf96ca01d75e09881179d59

[root@master1 ~]#

[root@master1 ~]# docker network ls

NETWORK ID NAME DRIVER SCOPE

2238d0cf60dc bridge bridge local

09575e4ff9dc docker_gwbridge bridge local

3b93f4bad0a9 host host local

6b6f0e006e46 none null local

5473d38fd5fd ov_net1 overlay global

aafcf8d932c8 ov_net2 overlay global

[root@master1 ~]#

新创建的ov_net2的网段是10.0.1.0

此时创建一个容器,是无法跟之前ov_net1的容器进行通讯的

若我们想要让ov_net2创建的容器跟ov_net1的容器进行通讯的话,操作如下:

把我们的ov_net2的容器跟ov_net1网络连接起来,此时我们的ov_net2的容器里面多了一块ov_net1的网段的网卡。

补充:自己手动创建网络的网关,网段的命令

参考资料:《Docker 容器与容器云(第2版)》

说明


--------------------------------------------------------我是分割线----------------------------------------------------------

这里所有的资料都是自己平时学习之中的笔记,拿出来分享一下,这其中难免有些不到之处,所以仅供参考哈

  • 10
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值