libnetwork

本文详细介绍了Docker的libnetwork库,包括sandbox、endpoint、network和CNM对象的概念。讨论了如何通过NetworkController创建和管理网络,以及Driver如何实现不同网络模式,如bridge、overlay和host等。还涵盖了endpoint的加入、离开和删除过程,以及Docker的网络命令,如docker network create、connect、disconnect和rm。最后提到了CNI和CNM的区别,CNI专注于将容器添加到网络和从网络中删除容器的接口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CNM模型定义了libnetwork的工作原理
原来docker的网络相关的代码是直接在docker中的,网络功能也比较简单,对网络的诟病也是比较多,随着docker越来越向平台化发展,将功能组件逐渐从docker中解耦, docker从1.7把网络相关的代码从docker的代码中剥离出来新建了一个libnetwork项目,引入了CNM的网络模型。
CNM网络模型主要引入三个概念: sandbox, endpoint和network。 Sandbox代表的是一个独立的网络栈,有自己的网络接口,路由表等,每个容器有一个sandbox,也就是有个独立的网络栈。在不同的系统下,sandbox的实现不一样,在linux系统下是通过network namespace来实现的,在FreeBSD下是Jail。 Endpoint是sandbox连接到network的端点,也就是一个网络接口,我们容器里面看到的eth0 eth1这样的网口,一个sandbox可以加入到多个网络中,也就有多个endpoint,也就是有多个网口,endpoint的实现也有很多,用得最多的就是veth设备对。 Network用来连接不同的sandbox,实现容器间的通信,是一系列endpoint的集合。Network的实现有很多种,如linux bridge, ovs, vxlan等

sandbox:独立的网络栈

endpoint:连接网络的网口

network:容器互联通信

CNM对象
NetworkController: libnetwork网络管理器,提供API
Driver:  network的具体底层实现,提供api给network
Network:  cnm中network的具体实现,networkcontroller提供了api来创建/删除network
Endpoint:cnm中endpoint的具体实现,是容器内网口的抽象描述
Sandbox: cnm中sandbox的具体实现,代表了容器网络的配置如路由表,网络接口等。每个Sandbox有一个olssandbox。

networkController  比如docker启动的时候就会新建一个network controller, docker通过调用network controller的api来完成网络的管理。
Driver   不同的网络模式对应不同的driver, 我们常见的网络模式如果host模式,对应的driver是host
Network     一个network底层有具体的driver来实现,调用driver提供的api

Endpoint   实现容器与network的连接,一个endpoint只能连接到一个network。


1.  Drivers registers with NetworkController
2.  NetworkController object is created using libnetwork.New() 
3. Network is created using the controller's NewNetwork() API by providing a name and networkType
4. sandbox is created using the NewSandbox() API of controller
5. network.CreateEndpoint() can be called to create a new Endpoint in a given network.
6. endpoint.Join() can be used to attach a container to an Endpoint.
7. endpoint.Leave() can be invoked when a container is stopped.
8. endpoint.Delete() is used to delete an endpoint from a network. 
9. network.Delete() is used to delete a network.  

在系统启动的时候网络驱动注册到NetworkController
调用者(docker)通过libnetwork.New()新建一个NetworkController的对象
调用者使用NetworkController的NewNetwork的API创建一个网络,创建的时候指定网络的名字和驱动。
启动容器时,调用NetworkController的NewSandbox新建一个新的sandbox,这个时候新建的sandbox是一个空的,不连接到任何网络
调用network.CreateEndpoint创建网络上的个endpoint,给这个endpoint分配一个ip
调用endpoint.Join把这个endpoint加入到容器里,使容器连接到网络上
容器退出或者调用了docker netwrok disconnect时,调用endpoint.Leave()使容器从网络上断开
当删除一个容器时,该容器的所有endpoint都会删除,此时调用endpoint.Delete()把endpoint从网络中删除

当这网络不再需要的时候,调用network.Delete()删除网络


driver的API:
driver.CreateNetwork
driver.DeleteNetwork
driver.CreateEndpoint
driver.DeleteEndpoint
driver.Join

driver.Leave

目前支持的driver:
 null
 bridge  
 overlay
 remote
 host
 macvlan

 ipvlan


前面讲过每个network都有个对应的driver,network通过调用driver的API来实现network的管理,driver的api跟network提供的api都是一一对应的。Networkcontroller调用CreateNetwork创建network, network就要调用driver.CreateNetwork创建驱动层的网络。

一个driver要加到libnetwork中,就要实现这些api,这些api抽象出了对网络的操作。




Remote 模式是用来支持第三方的网络插件,可以使用户灵活的定义自己的网络模式,而不需要将网络的相关代码推动社区,合入到libnetwork里面。
MACVLAN是一种将一块以太网卡虚拟成多块以太网卡的的方案

IPVLAN和MACVLAN的区别在于它在IP层进行流量分离而不是基于MAC地址




Docker启动的时候会默认创建一个bridge网络,驱动就是bridge,如果在启动容器的时候没有指定容器的网络模式,则默认就是bridge模式。veth驱动是类似通道的技术,并且成对出现,一端连接到docker0网桥,一端连接到容器内,当一端收到报文后,直接通过另外一端设备发送出去,中间不做额外的处理。
SNAT就是在iptables中加入一条masquerade规则,将来自容器的数据包的源ip地址都改成主机的ip地址。
Port mapping 就是把主机上的端口通过iptables规则映射到容器内部


在bridge模式下可以通过配置docker daemon的启动参数-b、--bip、--fixed-cidr可以实现更复杂的网络功能来实现一些复杂的功能,使用flannel来实现多主机间容器的通信就是通过配置—bip来实现的




这个模式有什么用呢?
可以创建两个点对点连接的容器,
有时候想让两个特别的容器能够直接通信,不用绑定到主机的以太网桥上,
我们就可以net=none模式创建容器,之后再操作创建一个对等接口,将这个对等接口的两端分别
放到两个容器的net namespace内,这样这两个容器就是经典的点对点连接。
$ sudo ip link add A type veth peer name B 
$ sudo ip link set A netns 2989
$ sudo ip netns exec 2989 ip addr add 10.1.1.1/32 dev A 
$ sudo ip netns exec 2989 ip link set A up 
$ sudo ip netns exec 2989 ip route add 10.1.1.2/32 dev A 
$ sudo ip link set B netns 3004
$ sudo ip netns exec 3004 ip addr add 10.1.1.2/32 dev B
$ sudo ip netns exec 3004 ip link set B up 

$ sudo ip netns exec 3004 ip route add 10.1.1.1/32 dev B



创建容器和删除容器时,网络的操作都比较简单,这里主要讲启动容器时网络的流程
allocateNetwork读取该容器配置的网络,需要连接到哪些网络,然后依次调用connectToNetwork
CreateEndpoint创建对应网络上的endpoint,分配ip地址,在对应的driver上创建对应的endpoint,每种不同的网络操作都不一样                     以bridge网络为例,在drivers上创建endpoint时,在host上创建一个veth设备对,并把其中一端连接到docker0网桥上,另外一端在后续                        的操作中连接到network namespace中
NewSandbox创建一个sandbox实例,会创建一个network namespace,创建network namespace的过程跟ip netns add的原理一样,在fork进程的时候加上NEWNET的标志位,这样新创建的进程就有一个新的network namespace,然后将这个进程的
netns (这个netns目录在/proc/pid/ns/net)通过bind mount的方式mount到docker统一管理的network namespace下
5. ep.Join将endpoint加入到sandbox中

6. 到这里看起来容器的网络的初始化就完成了,在1.9版本之前,网络到这一步确实就结束了,只要把创建好的network namespace给容器就可以了,容器在fork进程的时候加入到这个network namespace就可以了。但是在1.9版本后,加入了usernamespace的支持,这样的做法就有冲突了,因为有user namespace后,容器的内的进程并不是真正的root,只是一个普通进程,所以调用setns把自己加到一个root的net ns会失败,

docker network create
创建网络,-d指定创建网络的driver
docker network connect
将容器连接到一个网络上
docker network disconnect
将容器从一个网络上断开
docker network inspect
查询网络的数据
docker network ls
列举网络
docker network rm

删除网络


CNI和CNM的区别

CNI只定义了两个概念container和network
两个接口Add container to network和Delete container from network
CNI的接口更加简洁,把更多的工作托管给容器的网络管理者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值