Docker跨主机网络通信方案

在微服务架构中,多个服务是通过服务注册中心进行管理的,服务需要将自己的IP地址和端口发送给注册中心,这样该服务才能被其它服务感知并调用。但是当服务在docker容器内运行时,服务获取到的自身IP是宿主机分配的内部IP(默认情况下会在172.17.0.0/16子网下),如172.17.0.1, 这个地址只能在宿主机内部使用(通过docker0网桥转发),其它机器是无法ping通的。我们就以服务注册的场景讨论docker容器跨主机通信方案。

端口映射

启动容器时通过 -p 参数将容器内服务监听的端口映射到主机端口中。例如容器运行的web服务监听8080端口,那么当指定-v 8080:80时,外部就可以通过访问宿主机的80端口访问到这个web服务了。这种方式有一个很大的缺点:服务器端口是一种稀缺资源,一台机器往往会运行多个容器,它们之间有可能会出现端口冲突的情况。而且就服务注册这个场景而言,容器内的web服务是无法主动得到宿主机的ip地址的,因此需要我们在启动容器时通过Dockerfile将宿主机IP通过环境变量注入到容器中,然后配置web项目使用我们指定的IP来注册自身。这种方式显然无法应用于大规模集群部署。

性能损失:20%

不进行网络隔离,直接使用宿主机网络配置

通过–net=host参数可指定使用该模式。在这种模式下,容器的网络环境并没有通过Linux内核的Network Namespace进行隔离,在容器内可以自由修改宿主机的网络参数,因此是不安全的,但优点是网络性能损失可以忽略不计。对于我们的场景来说,微服务能够像直接部署一样正常获取到主机IP。

性能损失:几乎没有

组建overlay网络

Overlay网络其实就是隧道技术,即将一种网络协议包装在另一种协议中传输的技术。Docker常见的overlay网络实现有flannel, swarm overlay, Open vSwitch等。它们的工作流程基本都是一样的:先通过某种方式保证所有docker容器都有全局唯一的ip, 然后把docker容器的ip和其所在宿主机ip的对应关系存放到第三方存储服务中(如etcd, consul),之后通过在宿主机上修改路由表、创建虚拟网卡的方式,将数据包转发到目标容器所在的宿主机上,最后再由目标宿主机的docker0网桥转发给容器。对于flannel来说,它的工作原理如下图:
这里写图片描述

10.76.98.1和10.76.98.2是局域网内的两台物理机,它们各运行着容器A(172.17.0.1)和容器B(172.17.0.2)。当容器A要访问容器B时:

  • 数据包首先到达docker0, 由于flannel修改了路由表,docker0会将其转发给flannel0
  • flannel的守护进程flanneld会持续监听flannel0转出的数据包, 它首先会到 etcd 中查询172.17.0.2所在宿主机的ip(10.76.98.2),然后将原数据包进行封装(可以使用UDP或vxlan封装),把目的ip地址改为对方宿主机ip并交由eth0
  • eth0将新数据包通过网络发到10.76.98.2
  • 10.76.98.2的eth0收到数据包后转发给flannel0, 由守护进程flanneld进行解包,取出原数据包,得到容器ip地址172.17.0.2, 然后转发给docker0
  • docker0将数据包转发至容器进程对应端口

到此容器A就实现了跨主机访问容器B。

overlay网络的性能损耗取决于其实现方式,经老外测试,flannel(vxlan模式), swarm overlay实现的损耗几乎与端口映射持平,但是 docker 1.12版本新加入的 swarm overlay 实现性能损耗高达60%(swarm overlay代码实现质量不高)。因此,在产生环境下不建议使用swarm overlay方案。

Calico和Weave

这两种实现的方式跟overlay不太一样,它会把每台宿主机都当成一个路由器使用,数据包在各个主机之间流动最终被投递到目标主机。为了让主机支持路由功能,它们会向路由表中写入大量记录,因些如果集群中的节点太多,路由表记录数过高(超过1万)时会出现性能问题。

虽然实现原理一样,但它们的性能区别还是很大的。Calico因为使用的是内核特性,能做到在内核态完成路由,因此性能与原生网络非常接近(90%以上),而Weave则是在用户态转发数据包,性能较差,损耗高达70%以上。

总结

overlay方案和Calico, Weave由于可以实现容器IP的直接通信,因此在服务注册的场景下都可以正常运行,但是需要付出一定的性能代价。而端口映射方式则需要强行配置我们的应用使用指定IP,灵活性极差,只适用于小规模的集群部署。而host模式则是通过牺牲隔离性来换取最大化网络性能。在实际应用中我们应该根据业务特点来选择最适合的网络方案。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Docker是一种基于容器的虚拟化技术,它提供了一种轻量级的容器化解决方案,可以将应用程序及其依赖项打包到一个可移植的容器中,以便在任何地方运行。在Docker中,容器之间的通信是通过网络实现的,在本文中,我们将详细介绍Docker中的网络通信Docker中的网络类型 Docker提供了四种不同类型的网络,分别是: 1. 桥接网络(Bridge Network):桥接网络Docker的默认网络,它允许容器之间相互通信,并且可以与主机通信。在桥接网络中,每个容器都有一个独立的IP地址,并且可以通过容器名称或IP地址进行访问。 2. 主机网络(Host Network):主机网络将容器直接连接到主机网络上,容器与主机共享同一个网络接口和IP地址,因此可以与主机网络上的其他设备进行通信。 3. 网络绑定(None Network):网络绑定不为容器配置任何网络,这意味着容器无法通过网络与外界进行通信。通常,这种网络类型用于测试和调试容器应用程序。 4. Overlay网络(Overlay Network):Overlay网络用于主机容器之间的通信。它允许在多个主机上运行分布式应用程序,并提供了自动发现和负载均衡的功能。 Docker网络配置 在Docker中,可以使用docker network命令来管理网络。可以使用以下命令创建一个新的桥接网络: ``` docker network create my-network ``` 可以通过以下命令将容器添加到网络中: ``` docker run --name my-container --network my-network my-image ``` 在此命令中,--network选项指定要将容器添加到的网络名称。 可以使用以下命令列出所有可用的网络: ``` docker network ls ``` 可以使用以下命令查看特定网络的详细信息: ``` docker network inspect my-network ``` 在Docker中,还可以使用--link选项将一个容器链接到另一个容器。这将创建一个虚拟网络接口,允许容器之间进行通信。以下命令将容器my-container链接到容器my-other-container: ``` docker run --name my-container --link my-other-container my-image ``` 在此命令中,--link选项指定要链接的容器名称。 总结 在Docker中,容器之间的通信是通过网络实现的。Docker提供了四种不同类型的网络,包括桥接网络主机网络网络绑定和Overlay网络。可以使用docker network命令来管理网络,可以使用--link选项将一个容器链接到另一个容器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值