网络一直是Docker集群中的最令人头疼的问题,目前Docker已经收购了SocketPlane团队来解决相关问题,也发布了 libnetwork项目。该篇文章介绍了Docker生态中的网络解决方案,包括Docker原生网络功能,以及其它辅助项目。
简介
当使用Docker容器构建分布式服务时,通信和网络变得非常重要。面向服务的架构严重依赖节点之间的通信。
在这篇文章中,我们将讨论多种网络策略和工具用于容器所处的网络,并打造成他们所期待的状态。一些情况下可以采用Docker原生解决方案,其他情况就需要些备选方案。
Docker原生网络实现
为了实现容器到容器和容器到宿主机之间的通信,Docker本身就已经提供了几种解决方案。
当Docker进程启动之后,它会配置一个虚拟的网桥叫docker0在宿主机上。这个接口允许Docker去分配虚拟的子网给即将启动的容器们。这个网桥在容器内的网络和宿主机网络之间将作为接口的主节点。
Docker容器启动后,将创建一个新的虚拟接口并分配一个网桥子网内的IP地址。这个IP地址嵌在容器内网络中,用于提供容器网络到宿主机docker0网桥上的一个通道。Docker自动配置iptables规则来放行并配置NAT,连通宿主机上的docker0。
容器如何暴露服务给使用端
同一宿主机上的其他容器可以使用其他邻居提供的服务而不需要额外的配置。宿主系统会简单将路由请求从docker0传到目的地。
容器可以暴露它们的端口给宿主,这些端口用于接收外部请求流量。暴露出的端口映射到宿主机上,可以通过选择一个特定的端口或者由Docker来随机选择一个高位空闲端口。Docker谨慎的处理任何一个前向规则以及iptables配置来确保路由正确。
暴露端口和发布端口的区别是什么
当创建一个容器镜像或者运行一个容器,你可以选择暴露端口还是发布端口。这两者的区别是很重要的,但并不明显。
暴露一个端口意味着Docker将获悉该端口是此容器所使用。这可以被用于服务发现和链接。例如,注入一个容器将会返回暴露端口的信息。当容器被链接上,新容器将会设置环境变量来对应前一个容器暴露的端口。
默认情况下,无论是否暴露端口,容器对于宿主机都是可以访问的,并且对于同一个主机上其他容器也是可以访问的。暴露端口将简单的记录端口使用并在自动映射和链接中用于显示。
相对的,端口发布将映射端口到宿主接口,使得它可以与外界交互。容器端口可选择映射宿主机上一个指定端口,或者Docker可以自动的随机选择一个高位空闲端口。
Docker链接是什么
Docker提供了一种机制叫做Docker links用于配置容器间的通信。如果一个新容器链接到一个已有容器,新容器将会通过环境变量获得已有容器的链接信息。
这提供了一种简单的方法,通过提供给信容器关于已有容器的链接信息来实现容器间的通信。环境变量将会根据另一个容器暴露的端口进行设置。IP地址和其他信息将会有Docker自身补充。
那些扩展Docker网络功能的项目
上文讨论的网络模型提供了一个网络构建的良好起点。在端口被正确的映射并且链接信息被提供的情况下,同一宿主机上容器间的通信是非常简单的,宿主机之间的通信可以通过标准公共网络。
但是,许多应用为了安全或者特殊功能要求特殊的网络环境。Docker这个原生的网络功能在某些场景下会受限制。于是,许多项目致力于扩展Docker网络生态。
创建覆盖网络来抽象底层拓扑结构
许多项目都关注的一个功能性改进是实现覆盖网络。覆盖网络是一个虚拟网络,在现有网络链接上建立的。
实现覆盖网络使得你可以在宿主机间创建一个更加可预测、统一的网络环境。他们可以简单的在容器间互联而不需要考虑容器是否在运行。一个单一虚拟网可以跨多个宿主机或者特殊子网,可以指定每个主机在一个统一的网络。
覆盖网络的另一个用处是用于构建结构计算集群。在结构计算中,多个主机作为一个抽象主机被管理,这是一个更有计算能力的实体。一个结构计算层的实现使得终端用户来管理这个集群而不是单独的主机。网络在这个集群中起了关键的作用。
高级网络配置
另外一些项目扩展了Docker的网络功能使得它更灵活。
Docker默认的网络配置功能有用,但是功能单一。这些限制在应对跨宿主的网络时非常明显,但也避免了一个主机上更多定制的网络需求。
额外的功能通过管道功能来实现。这些项目不提供外部配置,但是他们使得你可以手工组合他们并创建一个复杂的网络场景。另外的一些功能可通过从特定主机之间实现私有网络获得,如配置网桥、vlan、定制化子网和网关。
还有一些其他的工具和项目,虽然它们不是为了Docker开发,但是在Docker的环境中经常使用。特别是,成熟的私有网络和隧道技术常用于提供主机之间、容器之间的安全通信。
有哪些项目用于改善Docker网络
有一些项目致力于为Docker宿主机提供覆盖网络。常见的有以下几个:
flannel:CoreOS团队开发,这个项目被开发的初衷是为每一个宿主系统提供一个共享网络的子网。虽然这是Google kubernetes的一个必要编排工具,但是它在其他场景下也有用处。
weave: Weave创建一个虚拟网络,使得每个宿主机互联。这简化了应用路由,因为它使得每个容器像被嵌入了一个网络交换机中。
对于高级网络功能,以下项目旨在通过提供额外的管道来填补这一空缺:
pipework:作为一个权宜之计的存在,直到Docker原生网络变得更高级,这个项目使得任意高级网络配置变得容易配置。
现有软件给Docker增加功能的例子是:
tinc:Tinc是一个轻量的VPN软件,它采用隧道和加密实现。Tinc是一个健壮的解决方案,它能够使私有网络对任何应用透明。
总结
虽然通过容器对内或者对外提供服务是一个非常有分量的模型,但是网络方面的考虑成为优先级较高的事情。Docker原生提供一些功能,通过虚拟接口的配置、子网、iptables、和NAT表管理,另外一些项目提供了更高级的配置。
在下一篇指南中,我们将讨论调度器和编排工具如何在这个基础上提供集群管理功能。
译者简介:
陈杰,北京理工大学计算机学院在读博士,研究方向是自然语言处理在企业网络信誉评价方面的应用,学习、使用和研究Docker。
转载自:http://dockone.io/article/372