Docker的容器特性和镜像特性已然为Docker实践者带来了诸多效益,然而Docker的网络特性却不能让用户满意。本文从Docker的网络模式入手,分析了Docker Daemon创建网络环境的详细流程,其中着重于分析Docker桥接模式的创建,为之后Docker Container创建网络环境做铺垫。
1. 前言
Docker作为一个开源的轻量级虚拟化容器引擎技术,已然给云计算领域带来了新的发展模式。Docker借助容器技术彻底释放了轻量级虚拟化技术的威力,让容器的伸缩、应用的运行都变得前所未有的方便与高效。同时,Docker借助强大的镜像技术,让应用的分发、部署与管理变得史无前例的便捷。然而,Docker毕竟是一项较为新颖的技术,在Docker的世界中,用户并非一劳永逸,其中最为典型的便是Docker的网络问题。
毋庸置疑,对于Docker管理者和开发者而言,如何有效、高效的管理Docker容器之间的交互以及Docker容器的网络一直是一个巨大的挑战。目前,云计算领域中,绝大多数系统都采取分布式技术来设计并实现。然而,在原生态的Docker世界中,Docker的网络却是不具备跨宿主机能力的,这也或多或少滞后了Docker在云计算领域的高速发展。
工业界中,Docker的网络问题的解决势在必行,在此环境下,很多IT企业都开发了各自的新产品来帮助完善Docker的网络。这些企业中不乏像Google一样的互联网翘楚企业,同时也有不少初创企业率先出击,在最前沿不懈探索。这些新产品中有,Google推出的容器管理和编排开源项目Kubernetes,Zett.io公司开发的通过虚拟网络连接跨宿主机容器的工具Weave,CoreOS团队针对Kubernetes设计的网络覆盖工具Flannel,Docker官方的工程师Jérôme Petazzoni自己设计的SDN网络解决方案Pipework,以及SocketPlane项目等。
对于Docker管理者与开发者而言,Docker的跨宿主机通信能力固然重要,但Docker自身的网络架构也同样重要。只有深入了解Docker自身的网络设计与实现,才能在这基础上扩展Docker的跨宿主机能力。
Docker自身的网络主要包含两部分:Docker Daemon的网络配置,Docker Container的网络配置。本文主要分析Docker Daemon的网络。
2. Docker Daemon网络分析内容安排
本文从源码的角度,分析Docker Daemon在启动过程中,为Docker配置的网络环境,章节安排如下:
- Docker Daemon网络配置;
- 运行Docker Daemon网络初始化任务;
- 创建Docker网桥。
本文为《Docker源码分析系列》第六篇——Docker Daemon网络篇,第七篇将安排Docker Container网络篇。
3. Docker Daemon网络配置
Docker环境中,Docker管理员完全有权限配置Docker Daemon运行过程中的网络模式。 关于Docker的网络模式,大家最熟知的应该就是“桥接”的模式。下图为桥接模式下,Docker的网络环境拓扑图(包括Docker Daemon网络环境和Docker Container网络环境):
3.1 Docker Daemon网络配置接口
Docker Daemon每次启动的过程中,都会初始化自身的网络环境,这样的网络环境最终为Docker Container提供网络通信服务。
Docker管理员配置Docker的网络环境,可以在Docker Daemon启动时,通过Docker提供的接口来完成。换言之,可以使用docker二进制可执行文件,运行docker -d并添加相应的flag参数来完成。
其中涉及的flag参数有EnableIptables、EnableIpForward、BridgeIface、BridgeIP以及InterContainerCommunication。该五个参数的定义位于./docker/daemon/config.go,具体代码如下:
flag.BoolVar(&config.EnableIptables, []string{"#iptables", "-iptables"}, true, "Enable Docker's addition of iptables rules") flag.BoolVar(&config.EnableIpForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward") flag.StringVar(&config.BridgeIP, []string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b") flag.StringVar(&config.BridgeIface, []string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge\nuse 'none' to disable container networking") flag.BoolVar(&config.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
以下介绍这5个flag的作用:
- EnableIptables:确保Docker对于宿主机上的iptables规则拥有添加权限;
- EnableIpForward:确保net.ipv4.ip_forward可以使用,使得多网络接口设备模式下,数据报可以在网络设备之间转发;
- BridgeIP:在Docker Daemon启动过程中,为网络环境中的网桥配置CIDR网络地址;
- BridgeIface:为Docker网络环境指定具体的通信网桥,若BridgeIface的值为”none”,则说明不需要为Docker Container创建网桥服务,关闭Docker Container的网络能力;
- InterContainerCommunication:确保Docker容器之间可以完成通信。
除了Docker会使用到的5个flag参数之外,Docker在创建网络环境时,还使用一个DefaultIP变量,如下:
opts.IPVar(&config.DefaultIp, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP address to use when binding container ports")
该变量的作用是:当绑定容器的端口时,将DefaultIp作为默认使用的IP地址。
具备了以上Docker Daemon的网络背景知识,以下着重举例分析使用BridgeIP和BridgeI