资讯专栏INFORMATION COLUMN

docker系列--网络模式解读

haitiancoder / 2972人阅读

摘要:网络主要是单机网络和多主机通信模式。下面分别介绍一下的各个网络模式。设计的网络模型。是以对定义的元数据。用户可以通过定义这样的元数据来自定义和驱动的行为。

前言

理解docker,主要从namesapce,cgroups,联合文件,运行时(runC),网络几个方面。接下来我们会花一些时间,分别介绍。

docker系列--namespace解读

docker系列--cgroups解读

docker系列--unionfs解读

docker系列--runC解读

docker系列--网络模式解读

namesapce主要是隔离作用,cgroups主要是资源限制,联合文件主要用于镜像分层存储和管理,runC是运行时,遵循了oci接口,一般来说基于libcontainer。网络主要是docker单机网络和多主机通信模式。

本机网络模式

我们在使用docker run创建Docker容器时,可以用--net选项指定容器的网络模式,Docker有以下4种网络模式:

host模式,使用--net=host指定。

container模式,使用--net=container:NAME_or_ID指定。

none模式,使用--net=none指定。

bridge模式,使用--net=bridge指定,默认设置。

下面分别介绍一下Docker的各个网络模式。

1)none:不为容器配置任何网络功能。
在该模式下,需要以--net=none参数启动容器:

$ docker run --net=none -ti ubuntu:latest ip addr show
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default
    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
    inet6 ::1/128 scope host
        valid_lft forever preferred_lft forever

可以看到Docker容器仅有一lo环回接口,用户使用--net=none启动容器之后,仍然可以手动为容器配置网络。

2)container:与另一个运行中的容器共享Network Namespace,共享相同的网络视图。
举个例子,首先以默认网络配置(bridge模式)启动一个容器,设置hostname为dockerNet,dns为8.8.4.4。

$ docker run -h dockerNet --dns 8.8.4.4 -tid ubuntu:latest bash
d25864df1a3bbdd40613552197bd1a965acaf7f3dcb2673d50c875d4a303a67f
$ docker exec -ti d25864df1a3b bash
root@dockerNet:/# ip addr show
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default
        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
        inet6 ::1/128 scope host
            valid_lft forever preferred_lft forever
1739: eth0:  mtu 1500 qdisc noqueue state UP group default
        link/ether 02:42:ac:11:00:01 brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 scope global eth0
            valid_lft forever preferred_lft forever
        inet6 fe80::42:acff:fe11:1/64 scope link
            valid_lft forever preferred_lft forever
root@dockerNet:/# cat /etc/resolv.conf
nameserver 8.8.4.4
root@dockerNet:/# exit
exit

然后以--net=container:d25864df1a3b方式启动另一个容器:

$ docker run --net=container:d25864df1a3b -ti ubuntu:latest bash
root@dockerNet:/# ip addr show
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default
        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
        inet6 ::1/128 scope host
            valid_lft forever preferred_lft forever
1739: eth0:  mtu 1500 qdisc noqueue state UP group default
        link/ether 02:42:ac:11:00:01 brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 scope global eth0
            valid_lft forever preferred_lft forever
        inet6 fe80::42:acff:fe11:1/64 scope link
            valid_lft forever preferred_lft forever
root@dockerNet:/# cat /etc/resolv.conf
nameserver 8.8.4.4

可以看到,使用--net=container:d25864df1a3b参数启动的容器,其IP地址、DNS、hostname都继承了容器d25864df1a3b。实质上两个容器是共享同一个Network Namespace的,自然网络配置也是完全相同。

3)host:与主机共享Root Network Namespace,容器有完整的权限可以操纵主机的协议栈、路由表和防火墙等,所以被认为是不安全的。
相应的,host模式启动时需要指定--net=host参数。举个例子:

$ docker run -ti --net=host ubuntu:latest bash
root@darcy-HP:/# ip addr show
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default
        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
        inet6 ::1/128 scope host
            valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc pfifo_fast state DOWN
group default qlen 1000
        link/ether 2c:41:38:9e:e4:d5 brd ff:ff:ff:ff:ff:ff
3: eth1:  mtu 1500 qdisc pfifo_fast state UP
group default qlen 1000
        link/ether 00:1b:21:cc:ee:6d brd ff:ff:ff:ff:ff:ff
        inet 10.110.52.38/22 brd 10.110.55.255 scope global eth1
            valid_lft forever preferred_lft forever
        inet6 fe80::21b:21ff:fecc:ee6d/64 scope link
            valid_lft forever preferred_lft forever
1642: docker0:  mtu 1500 qdisc noqueue state UP
group default
        link/ether 22:f2:f3:18:62:5d brd ff:ff:ff:ff:ff:ff
        inet 172.17.42.1/16 scope global docker0
            valid_lft forever preferred_lft forever
        inet6 fe80::348e:71ff:fe44:2d41/64 scope link
            valid_lft forever preferred_lft forever

host模式下,容器可以操纵主机的网络配置,这是危险的,除非万不得已,应该尽可能避免使用host模式。

4)bridge:Docker设计的NAT网络模型。
Docker daemon启动时会在主机创建一个Linux网桥(默认为docker0,可通过-b参数手动指定)。容器启动时,Docker会创建一对veth pair(虚拟网络接口)设备,veth设备的特点是成对存在,从一端进入的数据会同时出现在另一端。Docker会将一端挂载到docker0网桥上,另一端放入容器的Network Namespace内,从而实现容器与主机通信的目的。bridge模式下的网络拓扑图如下图所示。

在桥接模式下,Docker容器与Internet的通信,以及不同容器之间的通信,都是通过iptables规则控制的。
总之,Docker网络的初始化动作包括:创建docker0网桥、为docker0网桥新建子网及路由、创建相应的iptables规则等。

跨主机通信模式

docker在跨主机通信方面一直比较弱。目前主要有容器网络模型(CNM)和容器网络接口(CNI),下面我们分别介绍。当然k8s和docker之间通信采纳的是CNI。

CNM模式

CNM是一个被 Docker 提出的规范。现在已经被Cisco Contiv, Kuryr, Open Virtual Networking (OVN), Project Calico, VMware 和 Weave 这些公司和项目所采纳。

Libnetwork是CNM的原生实现。它为Docker daemon和网络驱动程序之间提供了接口。网络控制器负责将驱动和一个网络进行对接。每个驱动程序负责管理它所拥有的网络以及为该网络提供的各种服务,例如IPAM等等。由多个驱动支撑的多个网络可以同时并存。网络驱动可以按提供方被划分为原生驱动(libnetwork内置的或Docker支持的)或者远程驱动 (第三方插件)。原生驱动包括 none, bridge, overlay 以及 MACvlan。驱动也可以被按照适用范围被划分为本地(单主机)的和全局的 (多主机)。

『Network Sandbox』– 一个容器内部的网络栈。

『Endpoint』– 一个通常成对出现的网络接口。一端在网络容器内,另一端在网络内。 一个Endpoints可以加入一个网络。一个容器可以有多个endpoints。

『Network』– 一个endpoints的集合。该集合内的所有endpoints可以互联互通。

最后,CNM还支持标签(labels)。Lable是以key-value对定义的元数据。用户可以通过定义label这样的元数据来自定义libnetwork和驱动的行为。

API使用步骤

接着我们看下一般使用libnetwork的方法,具体的步骤一般是下面这样的:

(1)获取一个NetworkController对象用于进行下面的操作。获取对象的时候指定Driver。

(2)通过NetworkController对象的NewNetwork()建立一个网络。这里最简单的理解就是现在我们有了一个bridge了。

(3)通过网络的CreateEndpoint()在这个网络上建立Endpoint。这里最简单的理解就是每建立一个Endpoint,我们上面建立的bridge上就会多出一个VIF口等着虚拟机或者Sandbox连上来。假设这里使用的是veth,则veth的一头目前接在了bridge中,另一头还暴露在外面。

(4) 调用上面建立的Endpoint的Join方法,提供容器信息,于是libnetwork的代码就会建立一个Sandbox对象(一般这里的Sandbox就是容器的namespace,所以不会重复建立),然后将第三步建立的veth的一头接入到这个Sandbox中,也就是将其放到Sandbox的namespace中。

(5)当Sandbox的生命周期结束时,调用Endpoint的Leave方法使其从这个Network中解绑。简单的说就是将veth从Sandbox的namespace中拿出来回到物理机上。

(6)如果一个Endpoint无用了,则可以调用Delete方法删除。

(7)如果一个Network无用了,则可以调用Delete方法删除。

CNI模式

CNI(Conteinre Network Interface) 是 google 和 CoreOS 主导制定的容器网络标准,它 本身并不是实现或者代码,可以理解成一个协议。这个标准是在 rkt 网络提议 的基础上发展起来的,综合考虑了灵活性、扩展性、ip 分配、多网卡等因素。

这个协议连接了两个组件:容器管理系统和网络插件。它们之间通过 JSON 格式的文件进行通信,实现容器的网络功能。具体的事情都是插件来实现的,包括:创建容器网络空间(network namespace)、把网络接口(interface)放到对应的网络空间、给网络接口分配 IP 等等。

CNI本身实现了一些基本的插件(https://github.com/containern..., 比如bridge、ipvlan、macvlan、loopback、vlan等网络接口管理插件,还有dhcp、host-local等IP管理插件,并且主流的container网络解决方案都有对应CNI的支持能力,比如Flannel、Calico、Weave、Contiv、SR-IOV、Amazon ECS CNI Plugins等。

具体Flannel的分析可以阅读我之前的文章(k8s与网络--Flannel解读)。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/33058.html

相关文章

  • docker系列--网络模式解读

    摘要:网络主要是单机网络和多主机通信模式。下面分别介绍一下的各个网络模式。设计的网络模型。是以对定义的元数据。用户可以通过定义这样的元数据来自定义和驱动的行为。 前言 理解docker,主要从namesapce,cgroups,联合文件,运行时(runC),网络几个方面。接下来我们会花一些时间,分别介绍。 docker系列--namespace解读 docker系列--cgroups解读 ...

    zollero 评论0 收藏0
  • docker系列--网络模式解读

    摘要:网络主要是单机网络和多主机通信模式。下面分别介绍一下的各个网络模式。设计的网络模型。是以对定义的元数据。用户可以通过定义这样的元数据来自定义和驱动的行为。 前言 理解docker,主要从namesapce,cgroups,联合文件,运行时(runC),网络几个方面。接下来我们会花一些时间,分别介绍。 docker系列--namespace解读 docker系列--cgroups解读 ...

    xiaotianyi 评论0 收藏0
  • docker系列--cgroups解读

    摘要:系列解读系列解读系列解读系列解读系列网络模式解读主要是隔离作用,主要是资源限制,联合文件主要用于镜像分层存储和管理,是运行时,遵循了接口,一般来说基于。冻结暂停中的进程。配置时间都以微秒为单位,文件名中用表示。 前言 理解docker,主要从namesapce,cgroups,联合文件,运行时(runC),网络几个方面。接下来我们会花一些时间,分别介绍。 docker系列--name...

    岳光 评论0 收藏0
  • docker系列--cgroups解读

    摘要:系列解读系列解读系列解读系列解读系列网络模式解读主要是隔离作用,主要是资源限制,联合文件主要用于镜像分层存储和管理,是运行时,遵循了接口,一般来说基于。冻结暂停中的进程。配置时间都以微秒为单位,文件名中用表示。 前言 理解docker,主要从namesapce,cgroups,联合文件,运行时(runC),网络几个方面。接下来我们会花一些时间,分别介绍。 docker系列--name...

    cikenerd 评论0 收藏0
  • docker系列--cgroups解读

    摘要:系列解读系列解读系列解读系列解读系列网络模式解读主要是隔离作用,主要是资源限制,联合文件主要用于镜像分层存储和管理,是运行时,遵循了接口,一般来说基于。冻结暂停中的进程。配置时间都以微秒为单位,文件名中用表示。 前言 理解docker,主要从namesapce,cgroups,联合文件,运行时(runC),网络几个方面。接下来我们会花一些时间,分别介绍。 docker系列--name...

    alogy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<