Docker原生网络介绍

在云计算架构设计中,最复杂且最重要的组件就是网络,Docker作为云计算追捧的新宠儿也不会例外,尤其是当使用Docker容器构建分布式服务时,通信和网络变得非常重要。面向服务的架构严重依赖节点之间的网络架构。接下来,我们将从Docker原生网络架构出发,讨论目前活跃的多种针对Docker提出的网络优化方案。在一些简单情况下,采用Docker原生解决方案就可以满足要求,但针对更复杂的情况就需要考虑采用优化方案。

Docker的网络是基于Linux的网络命名空间和虚拟网络设备(特别是veth pair)来实现。在Docker中,网络接口默认都是虚拟的接口,可以充分发挥数据在不同Docker间或Docker与宿主机转发效率。这是因为Linux通过在内核中通过数据复制实现虚拟接口之间的数据转发,即发送接口的发送缓存中的数据包将被直接复制到接收接口的接收缓存中,而无需通过外部物理网络设备进行交换。

Docker容器创建网络时,会在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通,形成一对虚拟网络接口,这样的一对接口叫做veth pair。

20160819172445

当Docker进程启动之后,它会配置一个叫docker0的虚拟网桥在宿主机上。这个网桥接口允许Docker去分配虚拟的子网给即将启动的容器。这个网桥在容器内的网络和宿主机网络之间将作为网络接口的主节点呈现。

当Docker容器启动后,创建一对虚拟接口,分别放到本地主机和新容器的命名空间中。本地宿主机一端的虚拟接口连接到默认的docker0网桥或指定网桥上,并具有一个以veth开头的唯一名字。容器一端的虚拟接口将放到新创建的容器中,并修改名字作为eth0,这个接口只在容器的命名空间可见。

从网桥可用地址段中,分配一个网桥子网内的IP地址给容器的eth0。这个IP地址嵌在容器内网络中,用于提供容器网络到宿主机docker0网桥上的一个通道。并配置默认路由网关为docker0网卡的内部接口docker0的IP地址。Docker会自动配置iptables规则和配置NAT,便于连通宿主机上的docker0网桥。完成这些操作之后,容器就可以使用它所能看到的eth0虚拟网卡,来连接其他容器和访问外部网络。

Docker提供了一种容器间通信机制叫做Docker links。如果一个新容器链接到一个已有容器,新容器将会通过环境变量获得已有容器的链接信息。通过提供给信任容器有关已有容器的链接信息,实现容器间的通信。

20160819172452

同一宿主机上的容器可以相互通信并提供服务给相邻容器,而不需要额外的配置(端口暴露或发布),宿主系统会简单将路由请求从docker0传到目的地。

容器可以暴露它们的端口给宿主机,用于接收外部请求流量。暴露出的端口可以通过特定端口或由Docker来随机选择一个高位空闲端口映射到宿主机上。暴露端口意味着Docker将呈现该端口是暴露容器所使用,这可以被用于服务发现和links(新容器将会设置环境变量来对应原容器暴露的端口)。

容器可以发布它们的端口给宿主机,端口发布将映射端口到宿主接口,使得它可以与外界交互。暴露出的端口可选择映射宿主机上一个指定端口,或者Docker可以自动的随机选择一个高位空闲端口。

Libcontainer也需要重点关注下,它是Docker中用于容器管理模块(创建容器、实现容器生命周期管理),它基于Go语言实现,通过管理Namespaces、Cgroups以及文件系统来进行容器控制。在Docker中,对容器管理的模块为Execdriver,目前Docker支持的容器管理方式有两种,一种就是最初支持的LXC方式,另一种称为Native的Libcontainer进行容器管理。

20160819172458

Docker起初是采用LXC的开源容器管理引擎。把LXC复杂的容器创建与使用方式简化为Docker自己的一套命令体系。后来Docker将底层实现都抽象化到Libcontainer的接口。这样可以实现跨平台能力,无论是使用了Namespace、Cgroups技术或是使用Systemd等其他方案,只要实现了Libcontainer定义的一组标准接口,Docker都可以运行。

Docker原生网络模型在保证端口映射、链接正确的情况下,可实现同一宿主机上容器间的通信和宿主机之间的通信。但是,针对安全或者特殊功能要求特殊的网络环境,Docker这个原生的网络功能就会受限制。于是许多项目致力于扩展Docker网络生态。关于Docker网络优化的项目和方案,我们将在下一篇文章重点介绍。

原标题:Docker这么火,但你对它的原生网络知多少?

K8S中文社区微信公众号
分享到:更多 ()

评论 抢沙发

评论前必须登录!