Docker扁平化网络设计与实现

简介:

研发背景

众所周知,Docker容器跨主机互访一直是一个问题,Docker官方为了避免网络上带来的诸多麻烦,故将跨主机网络开了比较大的口子,而由用户自己去实现。目前Docker跨主机的网络实现方案也有很多种,主要包括端口映射、ovs、 fannel等。

但是这些方案都无法满足我们的需求:端口映射服务内的内网IP会映射成外网的IP,这样会给开发带来困惑,因为他们往往在跨网络交互时是不需要内网IP的;而ovs与fannel则是在基础网络协议上又包装了一层自定义协议,这样当网络流量大时,却又无端的增加了网络负载。最后我们采取了自主研发扁平化网络插件,也就是说让所有的容器统统在大二层上互通。

Docker原生四种网络模式

目前,基于Docker的网络模式有很多种,接下来就简单的对Bridge、Host、Container、None模式进行介绍。

A. Bridge模式该模式为Docker的默认网络模式,Docker daemon 会在宿主机上建立一个默认的网桥docker0, 相信大家对docker0非常熟悉,但是在跨容器通信当中它却没有派上用场,因为默认的docker0的地址都是内网地址,而且启动后容器虽然也桥接在docker0上,但是容器的默认网关却依然无法设置,这就是docker原生默认网络的一个弊端。当然了,他却实现了在当先宿主机的网络隔离,拥有自己的namespace, 网卡和IP,具体的桥接原理我将在后面继续说明。

B. Host模式

该模式其实就是和当前宿主机共享网络空间,而Docker本身并没有进行网络隔离,说的通俗点,也就是说容器其实都是和宿主机拥有相同的IP, 而如何具体区分各个容器的呢?那就是通过端口映射,在启动Docker容器的时候来指定-p参数来进行设置端口映射。虽然这种方式在某种程度上也可以达到跨宿主机容器访问的目的,但是,却丧失了Docker网络隔离的意义,而且端口映射同样给微服务迁移带来一些麻烦,无法像非虚拟环境那样的平滑迁移,而是要考虑到很多端口转换的问题。

C. Container模式

顾名思义,此模式会共享另一个容器的网络命名空间,但是会限制在一台宿主机上,依然无法实现容器间跨主机通信的功能。

D. None模式

该模式是容器拥有自己的网络命名空间,自己的网路栈,自己的网卡,不和外界有任何瓜葛,容器网络完全独立,换句话说就是容器不需要网络功能,这种模式适用于容器包含写数据到磁盘卷的一些任务。这种模式依然无法实现我们的跨宿主机容器网络通信的功能。

自研Docker Overlay网络模式

目前Overlay网络模式主要是由隧道和路由两种方式实现,一种是对基础网络协议进行封包,另一种是配置更复杂的路由配置实现容器间跨主机的网络通信。其实,以上两种或多或少的都会给我们网络的实现带来了复杂性以及性能上的损耗,因为当我们拥有庞大的业务集群以后,这些复杂度和性能损耗都是不能忽视的。

插件原理如下:

2.png

  1.创建Docker自定义网络

docker network create --opt=com.docker.network.bridge.enable_icc=true--opt=com.docker.network.bridge.enable_ip_masquerade=false--opt=com.docker.network.bridge.host_binding_ipv4=0.0.0.0--opt=com.docker.network.bridge.name=br0--opt=com.docker.network.driver.mtu=1500--ipam-driver=talkingdata

--subnet=容器IP的子网范围, 例:172.18.0.0/17

--gateway=br0网桥使用的IP,也就是宿主机的地址, 例:172.18.0.5

--aux-address=DefaultGatewayIPv4=容器使用的网关地址mynet

我们首先需要创建一个br0自定义网桥,这个网桥并不是通过系统命令手动建立的原始Linux网桥,而是通过Docker的create network命令来建立的自定义网桥,这样避免了一个很重要的问题就是我们可以通过设置DefaultGatewayIPv4参数来设置容器的默认路由,这个解决了原始Linux自建网桥不能解决的问题. 用Docker创建网络时我们可以通过设置subnet参数来设置子网IP范围,默认我们可以把整个网段给这个子网,后面可以用ipam driver(地址管理插件)来进行控制。还有一个参数gateway是用来设置br0自定义网桥地址的,其实也就是你这台宿主机的地址啦。

2.IPAM

这个驱动是专门管理Docker 容器IP的, Docker 每次启停与删除容器都会调用这个驱动提供的IP管理接口,然后IP接口会对存储IP地址的Etcd有一个增删改查的操作。此插件运行时会起一个Unix Socket, 然后会在docker/run/plugins 目录下生成一个.sock文件,Docker daemon之后会和这个sock 文件进行沟通去调用我们之前实现好的几个接口进行IP管理,以此来达到IP管理的目的,防止IP冲突。

3.桥接

通过Docker命令去创建一个自定义的网络起名为“mynet”,同时会产生一个网桥br0,之后通过更改网络配置文件(在/etc/sysconfig/network-scripts/下ifcfg-br0、ifcfg-默认网络接口名)将默认网络接口桥接到br0上,重启网络后,桥接网络就会生效。Docker默认在每次启动容器时都会将容器内的默认网卡桥接到br0上,而且宿主机的物理网卡也同样桥接到了br0上了。其实桥接的原理就好像是一台交换机,Docker 容器和宿主机物理网络接口都是服务器,通过veth pair这个网络设备像一根网线插到交换机上。至此,所有的容器网络已经在同一个网络上可以通信了,每一个Docker容器就好比是一台独立的虚拟机,拥有和宿主机同一网段的IP,可以实现跨主机访问了。

4.etcd

我们可以设置1,3,5,7个节点为Etcd集群去集中管理Docker集群的IP,而且我们也将宿主机的地址进行了统一的管理,这样做同样也是为了避免IP的使用冲突导致线上资源不可用。我们会通过自己开发的工具进行IP初始化,也就是说会传进来一个IP范围,然后工具会将所有的IP存进etcd中,每一个网络ID就是一个etcd目录,目录下就会分成已分配与未分配的IP地址池。etcd本身会提供Go语言的API来访问etcd, 目前etcd还是相当稳定的,没有出现过什么问题。

结语

我们的Docker集群是采用Swarm进行管理的,Swarm相对K8S来说要简单的很多,但是在编排功能上也会有所欠缺,不过目前等新版本的dokcer 1.12发布以后,Swarm集成到Docker内部,而且增加了许多的功能后,我想这个问题就会迎刃而解。管理Swarm的是采用第三方的管理图形界面软件shipyard,这款软件本身并不会兼容自定义网络,而且在设置每个容器使用的Cpu核数时又会有BUG,我们对此开源软件进行了二次开发,解决了这些问题。现如今我们已经成功的在上面运行了YARN集群,网络性能也是没有什么问题的。

参考

https://docs.docker.com/engine/extend/plugins

https://github.com/docker/libnetwork/blob/master/docs/ipam.md

https://github.com/docker/go-plugins-helpers

该Docker插件的开源地址: 
https://github.com/TalkingData/Shrike

关于作者

马超,TalkingData运维部研发工程师,精通Golang和Python,五年技术工作经历,曾从事手机游戏服务端研发, 技术运营研发工程师。关注 平台稳定性(监控,问题发现及响应)和资源充分利用(虚拟化,容器)。

本文转自d1net(转载)

目录
相关文章
|
29天前
|
缓存 网络协议 网络架构
Docker 网络 IP 地址冲突,就该这么处理!
Docker 网络 IP 地址冲突,就该这么处理!
|
19天前
|
Kubernetes Devops 持续交付
DevOps实践:使用Docker和Kubernetes实现持续集成和部署网络安全的守护盾:加密技术与安全意识的重要性
【8月更文挑战第27天】本文将引导读者理解并应用DevOps的核心理念,通过Docker和Kubernetes的实战案例,深入探讨如何在现代软件开发中实现自动化的持续集成和部署。文章不仅提供理论知识,还结合真实示例,旨在帮助开发者提升效率,优化工作流程。
|
24天前
|
应用服务中间件 nginx Docker
【与时俱进】网络工程师必备技能:Docker基础入门指南,助你轻松应对新时代挑战!
【8月更文挑战第22天】随着容器技术的发展,Docker已成为开发与运维的关键工具。本文简要介绍Docker——一种开源容器化平台,能让应用程序及依赖项被打包成轻量级容器,在任何Linux或Windows机器上运行。文中涵盖Docker的安装步骤、基础命令操作如启动服务、查看版本、拉取与运行容器等。并通过实例演示了如何运行Nginx服务器和基于Dockerfile构建Python Flask应用镜像的过程。这些基础知识将助力网络工程师理解Docker的核心功能,并为实际应用提供指导。
44 2
|
26天前
|
Ubuntu Shell 网络架构
网络工程师的秘密武器:为何他们必须掌握Docker的基础知识?
【8月更文挑战第20天】在IT领域,Docker作为主流容器化平台,简化了应用部署与管理。网络工程师虽不必精通Docker,但需了解其基本概念如镜像、容器等,及如何创建、运行容器,还需掌握Docker网络模式如bridge、overlay等。这有助于与开发团队协作,设计高效网络架构。例如,通过`docker pull ubuntu`和`docker run -it ubuntu /bin/bash`即可拉取并启动Ubuntu容器。了解这些基础知识能促进跨团队沟通,适应快速发展的IT行业需求。
28 0
|
12天前
|
Shell Linux Docker
自定义Docker网络
这篇文章介绍了如何使用Docker命令自定义网络,并通过创建和配置网络来实现容器间的通信。
19 6
自定义Docker网络
|
12天前
|
NoSQL 应用服务中间件 Redis
Docker跨宿主机容器通信-通过网络跨宿主机互联
这篇文章介绍了Docker容器跨宿主机通信的实现方法,包括Docker的四种网络模式(host、none、container、bridge)以及如何通过修改网络配置和添加路由规则来实现不同宿主机上的容器之间的互联。
39 0
Docker跨宿主机容器通信-通过网络跨宿主机互联
|
6天前
|
Kubernetes 安全 Docker
|
24天前
|
Kubernetes 网络安全 网络架构
Docker不同宿主机网络打通
【8月更文挑战第20天】在不同宿主机上打通Docker网络可通过多种方法:1) 使用Docker原生的Overlay或Macvlan网络驱动实现跨主机通信,如Overlay网络利用VXLAN技术连接多台宿主机,Macvlan则让容器直接接入物理网络;2) 利用第三方工具如Weave Net或Flannel构建虚拟网络,Weave Net简化网络配置,Flannel则适用于Kubernetes环境并通过UDP封装数据包实现通信。实施前需确保宿主机间网络畅通且防火墙设置适当。
|
27天前
|
网络协议 Linux 网络安全
遇到Docker容器网络隔断?揭秘六种超级实用解决方案,轻松让Docker容器畅游互联网!
【8月更文挑战第18天】Docker容器内网络不通是开发者常遇问题,可能因网络配置错、Docker服务异常或防火墙阻碍等原因引起。本文提供六种解决策略:确认Docker服务运行状态、重启Docker服务、检查与自定义Docker网络设置、验证宿主机网络连接、临时禁用宿主机IPv6及检查防火墙规则。通过这些步骤,多数网络问题可得以解决,确保容器正常联网。
46 1
|
1月前
|
监控 安全 虚拟化
Docker技术概论(5):Docker网络
Docker技术概论(5):Docker网络
252 6