介绍
在构建分布式系统以服务于 Docker 容器时,通信和网络变得极其重要。 不可否认,面向服务的架构在很大程度上依赖于组件之间的通信才能正常运行。
在本指南中,我们将讨论用于将容器使用的网络塑造成所需状态的各种网络策略和工具。 有些情况可以利用 Docker 原生解决方案,而另一些情况则必须使用替代项目。
本地 Docker 网络实现
Docker 本身提供了容器到容器和容器到主机通信所需的许多网络基础。
当 Docker 进程本身启动时,它会在主机系统上配置一个名为 docker0
的新虚拟桥接接口。 该接口允许 Docker 分配一个虚拟子网,以供在它将运行的容器之间使用。 网桥将作为容器内网络和主机网络之间的主要接口点。
当 Docker 启动容器时,会创建一个新的虚拟接口,并在网桥的子网范围内为其分配一个地址。 IP 地址连接到容器的内部网络,为容器的网络提供到主机系统上的 docker0
网桥的路径。 Docker 自动配置 iptables
规则以允许转发,并为源自 docker0
并发往外部世界的流量配置 NAT 伪装。
容器如何向消费者公开服务?
同一主机上的其他容器无需任何额外配置即可访问其邻居提供的服务。 主机系统将简单地将源自 docker0
接口的请求路由到适当的位置。
容器可以将它们的端口暴露给主机,在那里它们可以接收从外部世界转发的流量。 暴露的端口可以映射到主机系统,要么选择一个特定的端口,要么让 Docker 选择一个随机的、高的、未使用的端口。 Docker 负责任何转发规则和 iptables
配置,以在这些情况下正确路由数据包。
公开和发布端口有什么区别?
创建容器镜像或运行容器时,您可以选择公开端口或发布端口。 两者之间的差异很大,但可能无法立即辨别。
暴露一个端口仅仅意味着 Docker 会注意到该端口被容器使用。 然后可以将其用于发现目的和链接。 例如,检查容器将为您提供有关暴露端口的信息。 链接容器时,将在新容器中设置环境变量,指示原始容器上暴露的端口。
默认情况下,无论端口是否暴露,主机系统和主机上的任何其他容器都可以访问容器。 公开端口只是记录端口的使用,并使该信息可用于自动映射和链接。
相反,发布端口会将其映射到主机接口,使其可供外界使用。 容器端口可以映射到主机上的特定端口,或者 Docker 可以自动随机选择一个高的、未使用的端口。
什么是 Docker 链接?
Docker 提供了一种称为“Docker 链接”的机制来配置容器之间的通信。 如果新容器链接到现有容器,则新容器将通过环境变量获得现有容器的连接信息。
通过为新容器提供有关如何访问其伙伴的显式信息,这提供了一种在两个容器之间建立通信的简单方法。 环境变量是根据其他容器暴露的端口来设置的。 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 表管理本机提供了其中的一些功能,但已经创建了其他项目来提供更高级的配置。
在 下一篇指南 中,我们将讨论调度程序和编排工具如何在此基础上构建以提供集群容器管理功能。