Docker核心原理——Docker网络管理


发布于 2016-06-25 / 19 阅读 / 0 评论 /
Docker 1.9版本引入了一整套的docker network子命令和跨主机网络支持。用户可根据应用的拓扑结构创建虚拟网络并将容器接入对应的网络。

Docker 1.9版本引入了一整套的docker network子命令和跨主机网络支持。用户可根据应用的拓扑结构创建虚拟网络并将容器接入对应的网络。

1.Docker网络架构

Docker在libnetwork中使用了CNM,架构图如下:

2.CNM

CNM有三个核心组件:

2.1.沙盒

一个沙盒包含容器网络栈信息。沙盒可以对容器的接口、路由和DNS设置等进行管理。沙盒的实现可以是Linux network namespace、FreeBSD Jail或者类似的机制。

2.2.断点

一个端点可以加入一个沙盒和一个网络。端点的实现可以是veth pair、Open vSwitch内部端口或相似的设备。

2.3.网络

一个网络是一组可以直接相互联通的端点。网络的实现可以是Linux bridge、VLAN等。

3.libnetwork内置驱动

libnetwork共支持五种内置驱动。

3.1.bridge驱动

Docker默认设置。libnetwork将创建的容器连接到Docker网桥。与外界通信使用NAT,增加了通信的复杂性。

3.2.host驱动

这种时候,libnetwork将不会为容器创建独立的network namespace。容器的进程处于宿主机的网络环境中,相当于Docker容器与宿主机共用一个network namespace,使用宿主机的网卡、IP、端口等信息。

3.3.overlay驱动

此驱动采用IETF标准的VXLAN方式。使用时需要额外的配置存储服务,如Consul、etcd或ZooKeeper,并在启动daemon时指定配置存储服务地址。

3.4.remote驱动

未做真正的网络服务实现,调用用户自行实现的网络驱动插件,使libnetwork实现了驱动的可插件化。

3.5.null驱动

使用这种驱动时,Docker容器拥有自己的network namespace,但并不为容器进行任何网络配置。除了network namespace自带的loopback网卡外,没有其他任何网卡、IP、路由等信息,需要用户为Docker容器添加网卡、配置IP等。

4.docker0网桥案例分析

案例如下图所示:

网桥等同于交换机,docker0网桥在daemon启动时自动创建,有三个相关启动参数:

(1)--bip=CIDR:设置docker0的IP地址和子网范围。

(2)--fix-cidr=CIDR:限制Docker容器获取IP得范围。默认为整个子网范围。

(3)--mtu=BYTES:指定最大传输单元。

也可将这些参数写入/etc/default/docker文件中的DOCKER_OPTS变量中,然后重启服务。

容器要访问外网服务的原理是宿主机进行iptables规则的设定。net表的POSTROUTING链有这么一条规则:-A POSTROUTONG -s 172.17.0.0/16 !-o docker0 -j MASQUERADE;也就是将Docker容器发出而不是从网卡发出的数据做SNAT,将IP包的源地址替换为相应网卡的地址。

外界想要访问Docker容器的服务怎么办?答案是端口映射。而端口映射的本质也是iptables规则。如运行5000:5000端口映射,则在宿主机可看到类似的两条iptables规则:

规则1-nat表:-A DOCKER ! docker0 -p tcp -m tcp --dport 5000 -j DNAT --to-destination 172.17.0.4:5000

规则2-filter表:-A DOCKER -d 172.17.0.4/32 ! docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT

Docker容器间通信也受iptables规则限制。首先,这些容器需属于同一个子网。然后,在Docker daemon启动时加参数配置“--icc=true”,此参数标志daemon会在FORWARD链的filter表中添加一条这样的规则“-A FORWARD -i docker0 -o docker0 -j ACCEPT”。或者在docker run命令中添加--link选项。

Docker容器与外界通信的过程中,还涉及多个网卡间数据包的转发(如从docker0到宿主机eth0网卡),这需要内核将ip-forward功能打开,即执行命令"echo 1 > /proc/sys/net/ipv4/ip_forward"。