docker的四种网络模式(Bridge、Host、Container、None 网络模式),自定义网络(创建自定义网桥、使两个不同网桥的容器通信、跨主机容器容器通讯等)

docker网络模式

docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分。
docker的四种网络模式(Bridge、Host、Container、None)

Docker 在启动时会开启一个虚拟网桥设备 docker0,默认地址为 172.17.1.1/16, 容器启动后都会被桥接到 docker0 上,并自动分配到一个 IP 地址。(我的虚拟机的docker0)

#要确保自己的docker服务已经开启
[root@docker1 ~]# ip a show docker0

在这里插入图片描述
同时每一个容器都会有一个独有的Pid:

[root@docker1 ~]# docker inspect registry | grep Pid

在这里插入图片描述
每一个独有的Pid都会在/proc目录下有一个相应的以Pid为名的目录,这个目录里面的ns目录有着关于这个Pid容器网络的文件:

[root@docker1 ~]# cd /proc/2033/
[root@docker1 2033]# ll ns/

在这里插入图片描述

  • 网桥
[root@docker1 2033]# brctl show docker0

在这里插入图片描述
容器桥接docker0后,自动分配ip地址(IP地址都会在172.17.0.1基础上递增 ,第一个容器它获取到的IP为172.17.0.2)
在这里插入图片描述
容器桥接docker0后,使用命令"ip a",会发现多了相应的虚拟网卡。
在这里插入图片描述
解释: veth设备是成双成对出现的,一端是容器内部命名为eth0,一端是加入到网桥并命名的veth*(通常命名为veth*),它们组成了一个数据传输通道,一端进一端出,veth设备连接了两个网络设备并实现了数据通信。

实验环境 :RHEL7.3

  • selinux与firewalld均为disabled
  • docker1 172.25.70.1
  • docker2 172.25.70.2

一、容器的四种网络模式

Docker在创建容器时有三种网络模式,bridge为默认不需要用–net去指定,其他三种模式需要在创建容器时使用–net去指定。

  • bridge 模式,使用–net=bridge指定,默认设置。
  • none 模式,使用–net=none指定。
  • host 模式,使用–net=host指定。
  • container 模式,使用–net=container:容器名称或ID指定
1、Bridge 桥接模式

在这里插入图片描述
Bridge 桥接模式的实现步骤主要如下:

Docker Daemon 利用 veth pair 技术,在宿主机上创建两个虚拟网络接口设备,假设为veth0 和 veth1。而 veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方。

Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0 网桥上。保证宿主机的网络报文可以发往 veth0;

Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并被改名为 eth0。如此一来,保证宿主机的网络报文若发往 veth0,则立即会被 eth0 接收,实现宿主机到Docker Container 网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性

Bridge桥接模式的缺陷:

最明显的是,该模式下 Docker Container 不具有一个公有 IP,即和宿主机的 eth0 不处于同一个网段。导致的结果是宿主机以外的世界不能直接和容器进行通信。

虽然 NAT 模式经过中间处理实现了这一点,但是 NAT 模式仍然存在问题与不便,如:容器均需要在宿主机上竞争端口,容器内部服务的访问者需要使用服务发现获知服务的外部端口等。

另外 NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率。

2、Host网络模式

host 模式是 bridge 桥接模式很好的补充。采用 host 模式的 Docker Container,可以直接使用宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。
在这里插入图片描述

Host 网络模式的缺陷:

当然,有这样的方便,肯定会损失部分其他的特性。

最明显的是 Docker Container 网络环境隔离性的弱化。即容器不再拥有隔离、独立的网络栈。

另外,使用 host 模式的 Docker Container 虽然可以让容器内部的服务和传统情况无差别、无改造的使用,但是由于网络隔离性的弱化,该容器会与宿主机共享竞争网络栈的使用;

另外,容器内部将不再拥有所有的端口资源,原因是部分端口资源已经被宿主机本身的服务占用,还有部分端口已经用以 bridge 网络模式容器的端口映射。

示例:创建一个host网络模式的容器vm2

[root@docker1 ~]# docker run -it --name vm2 --net host ubuntu
root@docker1:/# ip a

在这里插入图片描述
它将使用宿主机的IP地址,ip addr和宿主机查看到同样的结果:

[root@docker1 ~]# ip a

在这里插入图片描述

3、Container 模式

在这里插入图片描述
Container 网络模式的实现步骤主要如下:

1、查找 other container(即需要被共享网络环境的容器)的网络 namespace;

2、将新创建的 Docker Container(也是需要共享其他网络的容器)的 namespace,使用other container 的 namespace。

Docker Container 的 other container 网络模式,可以用来更好的服务于容器间的通信。
在这种模式下的 Docker Container 可以通过 localhost 来访问 namespace 下的其他容器,传输效率较高。虽然多个容器共享网络环境,但是多个容器形成的整体依然与宿主机以及其他容器形成网络隔离。另外,这种模式还节约了一定数量的网络资源。

Container网络模式的缺陷:

它并没有改善容器与宿主机以外世界通信的情况(和桥接模式一样,不能连接宿主机以外的其他设备)。

示例: 创建一个使用vm1容器网络的容器vm3

[root@docker1 ~]# docker run -it --name vm3 --net container:vm1 ubuntu
root@89e2b7c63ff1:/# ip a

在这里插入图片描述
由于vm3使用vm1的网络,,所以vm3使用 ip addr查看网络结果和vm1相同

4、None 网络模式

网络环境为 none,即不为 Docker Container 任何的网络环境。一旦 Docker Container 采用了none 网络模式,那么容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。可以说 none 模式为 Docker Container 做了极少的网络设定,但是俗话说得好“少即是多”,在没有网络配置的情况下,作为 Docker 开发者,才能在这基础做其他无限多可能的网络定制【开发。这也恰巧体现了 Docker 设计理念的开放。

示例:新建一个none网络模式的容器vm4

[root@docker1 ~]# docker run  -it --name vm4 --net none ubuntu
root@f611930f505f:/# ip a

在这里插入图片描述
link方法使容器之间相互通讯

root@f611930f505f:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
root@f611930f505f:/# ping vm1

二、高级网络配置

自定义网络模式,docker提供了三种自定义网络驱动:

  • bridge
  • overlay
  • macvlan
    bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,overlay和macvlan是用于创建跨主机网络。

建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。
1、添加docker的自定义网络
1.使用自动分配的ip地址和网关地址

添加bridge自定义网络(自动分配的ip地址和网关地址)之前的网络:bridge,host和none

[root@docker1 ~]# docker network ls

在这里插入图片描述
创建自定义网络模式

[root@server1 1675]# docker network create  my_net1
[root@docker1 ~]# docker network ls

在这里插入图片描述
查看bridge自定义网络(自动分配的ip地址和网关地址)的网关地址

[root@docker1 ~]# ip a

在这里插入图片描述
docker network inspect my_net1 查看bridge自定义网络(自动分配的ip地址和网关地址)的信息

[root@docker1 ~]# docker network inspect my_net1

在这里插入图片描述
在这里插入图片描述
使用自定义网络模式创建容器

[root@docker1 ~]# docker run -it --name vm1 --network=my_net1 ubuntu
root@6efb76be132d:/# ping vm1
[root@docker1 ~]# docker run -it --name vm2 --network=my_net1 ubuntu
root@b4396458a07b:/# ping vm1

在这里插入图片描述
在自定义网桥上(自定义的ip地址和网关地址),同一网桥上的容器是可以通信的。

2、使用–ip参数可以指定容器ip地址,但必须是在自定义网桥上(自定义的ip地址和网关地址),默认的bridge模式不支持,同一网桥上的容器是可以通信的

值的注意的是:

  • docker的bridge自定义网络之间默认是有域名解析的;
  • docker的bridge自定义网络与系统自带的网桥之间默认是有解析的;
  • 但是docker的系统自带的网桥之间默认是没有解析的。
[root@docker1 ~]# docker network create --subnet=172.25.0.0/24 --gateway=172.25.0.1 my_net2
[root@docker1 ~]# docker network ls

在这里插入图片描述
使用自定义网桥创建容器,,自定义ip地址:

[root@docker1 ~]# docker run -it --name vm3 --network=my_net2 --ip=172.18.0.6 ubuntu
[root@docker1 ~]# docker run -it --name vm3 --network=my_net2 --ip=172.25.0.6 ubuntu
root@ff7feb3ee20a:/# ping vm3

在这里插入图片描述
默认使用不同网桥的容器是不可以通讯的。

三、使两个不同网桥的容器通信

[root@docker1 ~]# docker attach vm1
root@6efb76be132d:/# ip a
root@6efb76be132d:/# ping vm3

在这里插入图片描述
我们现在的vm1使用的是my_net1网桥,vm3使用的是my_net2网桥,默认是不能通讯的。

使用 docker network connect命令为vm1添加一块my_net2 的网卡

[root@docker1 ~]# docker network connect my_net2 vm1
[root@docker1 ~]# docker attach vm1
root@6efb76be132d:/# ip a
root@6efb76be132d:/# ping vm3

在这里插入图片描述
可以成功通讯!!!

值的注意的是:

  • docker的bridge自定义网络之间:双方可以随便添加对方的网卡
  • docker的bridge自定义网络与系统自带的网桥之间:只能是,系统自带的网桥对应的容器添加bridge自定义网络对应的容器的网卡。而反过来会报错。
  • 但是docker的系统自带的网桥之间:是可以通信的,因为是在一个网络桥接上。

docker 1.10开始,内嵌了一个DNS server。dns解析功能必须在自定义网络中使用。

四、容器访问外网以及外网访问容器

在这里插入图片描述
在这里插入图片描述
示例:

查看当前iptable的nat表火墙策略
[root@docker1 ~]# iptables -t nat -nL

在这里插入图片描述

创建nginx的容器,配置端口映射

[root@docker1 ~]# docker run -d --name nginx -p 80:80 nginx
[root@docker1 ~]# docker port nginx
[root@docker1 ~]# netstat -antlp | grep 80
[root@docker1 ~]# iptables -t nat -nL

在这里插入图片描述
在这里插入图片描述

五、跨主机网络解决方案有哪些?

跨主机网络解决方案:

1、docker原生的macvlan和overlay;
2、第三方的flannel,weave和calico。

众多网络方案是如何与docker集成在一起的?

libnetwork docker容器网络库
CNM(Container Network Model)这个模型对容器网络进行了抽象

CNM分三类组件:

  • Sandbox:容器网络栈。包括容器接口,dns,路由表。(namespace)
  • Endpoint:作用是将sanbox接入network(veth pair)
  • Network:包含一组endpoint,同一network的endpoint可以通信。

在这里插入图片描述

macvlan 网络方案的实现
  • Linux kernel提供的一种网卡虚拟化技术。
  • 无需Linux bridge,直接使用 物理接口,性能极好。
1、跨主机的两台虚拟机都需要两个网卡,其中一个打开网卡的混杂模式
  • docker1:
[root@docker1 ~]# ip a | grep ens3
[root@docker1 ~]# ip a | grep eth0

在这里插入图片描述
在这里插入图片描述
添加网卡配置文件:

[root@docker1 ~]# cd /etc/sysconfig/network-scripts/
[root@docker1 network-scripts]# pwd
/etc/sysconfig/network-scripts
[root@docker1 network-scripts]# vim ifcfg-eth0
[root@docker1 network-scripts]# cat ifcfg-eth0 
BOOTPROTO=none
DEVICE=eth0
ONBOOT=yes
[root@docker1 network-scripts]# ifup eth0 #启动网卡

在这里插入图片描述

  • docker2:
[root@docker2 ~]# ip a | grep ens3
[root@docker2 ~]# ip a | grep eth0
==================================
[root@docker2 ~]# cd /etc/sysconfig/network-scripts/
[root@docker2 network-scripts]# vim ifcfg-eth0
[root@docker2 network-scripts]# cat ifcfg-eth0 
BOOTPROTO=none
DEVICE=eth0
ONBOOT=yes
[root@docker2 network-scripts]# ifup eth0

在这里插入图片描述
在这里插入图片描述

macvlan本身是linxu kernel的模块,本质上是一种网卡虚拟化技术。其功能是允许在同一个物理网卡上虚拟出多个网卡,通过不同的MAC地址在数据链路层进行网络数据的转发,一块网卡上配置多个 MAC 地址(即多个 interface),每个interface可以配置自己的IP,Docker的macvlan网络实际上就是使用了Linux提供的macvlan驱 动。

因为多个MAC地址的网络数据包都是从同一块网卡上传输,所以需要打开网卡的混杂模式ip link set eth0 promisc on。

  • 打开docker1和docker2的eth1网卡的混杂模式
#在server1上打开网卡eth0的混杂模式
[root@docker1 network-scripts]# ip link set ens3 promisc on
====================================================
[root@docker2 network-scripts]# ip link set ens3 promisc on

看到PROMISC,表示成功

[root@docker1 network-scripts]# ip a | grep eth0
===================================================
[root@docker2 network-scripts]# ip a | grep eth0

在这里插入图片描述
在这里插入图片描述
注意 : 如果不开启混杂模式,会导致macvlan网络无法访问外界,具体在不使用vlan时,表现为无法ping通路由,无法ping通同一网络内其他主机。

2、在两台主机上各创建macvlan网络

创建macvlan网络不同于桥接模式,需要指定网段和网关(因为要保证跨主机上网段和网关是相同的),并且都得是真实存在的,例如docker network create -d macvlan --subnet=172.183.1.0/24 --gateway=172.183.1.1 -o parent=eth0 mac_net1。

  • docker1:
[root@docker1 network-scripts]# docker network create -d macvlan --subnet=172.18.0.0/24 --gateway=172.18.0.1 -o parent=eth0 macvlan1
[root@docker1 network-scripts]# docker network ls

在这里插入图片描述

  • docker2
[root@docker2 network-scripts]# docker network create -d macvlan --subnet=172.18.0.0/24 --gateway=172.18.0.1 -o parent=eth0 macvlan1
[root@docker2 network-scripts]# docker network ls

在这里插入图片描述

3、在两台主机上分别使用创建的网络mac_net1运行一个容器
  • docker1
[root@docker1 network-scripts]# docker run -it --name vm1 --network=macvlan1 --ip=172.18.0.6 ubuntu
root@4b94fb778a1d:/# ip a

在这里插入图片描述

  • docker2
[root@docker2 ~]# docker run -it --name vm2 --network=macvlan1 --ip=172.18.0.10 ubuntu 
root@e9e0b8f58acb:/# ip a

在这里插入图片描述
访问测试:

  • docker1
root@4b94fb778a1d:/# ping 172.18.0.10

在这里插入图片描述
macvlan模式不依赖网桥,所以brctl show查看并没有创建新的bridge,但是查看容器的网络,会看到虚拟网卡对应了一个interface是8。

root@4b94fb778a1d:/# ip a

在这里插入图片描述
查看宿主机的网络,22正是虚机的eth1网卡

[root@docker1 ~]# ip a

在这里插入图片描述
可见,容器的 eth0 就是宿主机的eth0通过macvlan虚拟出来的interface。容器的interface直接与主机的网卡连接,这种方案使得容器无需通过NAT和端口映射就能与外网直接通信(只要有网关),在网络上看起来与其他独立主机没有区别。

macvlan会独占主机的网卡,也就是说一个网卡只能创建一个macvlan 网络,否则会报错,如果要创建多个macvlan网络,则需要添加多块网卡。

4、macvlan会独占主机的网卡的解决方案
  • macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络
  • vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,
  • vlan id取值为1~4094

我们只需要在创建容器时使用vlan子接口就可以i解决:

#创建vlan子接口
[root@docker1 ~]# docker network create -d macvlan --subnet=172.23.0.0/24 --gateway=172.23.0.1 -o parent=eth0.1 macvlan2
[root@docker1 ~]# docker network ls
[root@docker1 ~]# docker run -it --name vm3 --network=macvlan2 --ip=172.23.0.8 ubuntu
root@31fab2b09d9d:/# ip a

在这里插入图片描述
在这里插入图片描述
各个vlan子接口创建的容器之间的相互通讯
给容器添加vlan子接口

测试

[root@docker1 ~]# docker network connect macvlan1 vm3
[root@docker1 ~]# docker attach vm3
root@31fab2b09d9d:/# ip a
root@31fab2b09d9d:/# ping 172.18.0.6

在这里插入图片描述
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值