7-docker容器的网络通信
一 容器网络的类型
Docker 网络从覆盖范围可分为单个 host 上的容器网络和跨多个 host 的网络,多host网络又分为原生网络和第三方网络,如下:
- 原生单机网络
- None:不为容器配置任何网络功能,–net=none
- Host:与主机共享Network Namespace,–net=host
- Container:与另一个运行中的容器共享网络名称空间,–net=container:ID
- Bridge:Docker设计的,默认的NAT网络模型,–net=bridge
- 原生多机网络
- overlay:基于vxlan的隧道网络
- macvlan:基于网卡虚拟化的大局域网
- 第三方多机网络[本章不讨论]
- flannel
- weave
- calico
原生网络和单机网络都是通过不同的driver来实现的,未来可能还会有更多的开源driver
二 原生单机网络
docker安装好后,默认会创建三个网络,分别是none,host和bridge,用docker network ls命令查看如下
1 | [root@docker01 ~]# docker network ls |
A. none网络
none 网络就是什么都没有的网络。挂在这个网络下的容器除了 lo,没有其他任何网卡。容器创建时,可以通过 --network=none 指定使用 none 网络。
1 | docker run -it --rm --network=none centos:6.9 |
封闭意味着隔离,一些对安全性要求高并且不需要联网的应用可以使用 none 网络。
比如某个容器的唯一用途是生成随机密码,就可以放到 none 网络中避免密码被窃取。
B. host网络
连接到 host 网络的容器共享 Docker host 的网络栈,容器的网络配置与 host 完全一样。可以通过 --network=host
指定使用 host 网络。
在容器中可以看到 host 的所有网卡,并且连 hostname 也是 host 的。
1 | docker run -it --rm --network=host busybox |
Docker host 的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,可以选择 host 网络,但要考虑端口冲突问题
另一个用途是让容器可以直接配置 host 网路。如某些跨 host 的网络解决方案,本身也是以容器方式运行的,需要对网络进行配置,比如管理 iptables
C. Container网络
container网络严格来说并不是一种网络类型,因为它只是让一个容器使用主容器的网络名称空间,主容器的网络是什么类型都不影响
- 创建主容器并查看网卡信息
1 | docker run -d --name bbx --rm busybox sleep 900 |
- 创建新容器并使用主容器网络
1 | [root@docker01 ~]# docker run --network=container:bbx busybox ip a|grep eth0|awk '{print $1,$2}' |
- 用途说明
可以明显看出来,上诉两个容器使用的是同一个网卡,其他整个网络名称空间用的都是一个,用这种方式组织的容器,容器间通信十分便捷,效率也很高
三 bridge 网络
A. bridge网络入门解释
如果不指定--network
,创建的容器默认都会挂到 docker0
上,docker0是安装时创建的linux bridge网络(可以理解为NAT),可以用linux管理bridge的命令进行查看和管理
1 | yum install bridge-utils |
可以看到网桥docker0的信息,可以把docker0理解为一个虚拟交换机,现在这个交换机上没有接设备,我们启动一个容器看看结果
1 | docker run -d --name bbx --rm busybox sleep 900 |
交换机docker0已近连接了虚拟接口对(veth pair)的接口veth0652c67,该虚拟接口对的另一个接口连接到了刚刚新建的容器bbx中
veth pair 是一种成对出现的特殊网络设备,可以想象成由一根虚拟网线连接起来的一对网卡,网卡的一头在容器中,另一头挂在网桥 docker0 上
1 | [root@docker01 ~]# ip a|grep veth0652c67|awk '{print $1,$2}' |
上面代码解释说明:
- docker主机中多了一块网卡,编号33,名称veth0652c67,对端网卡编号if32
- bbx容器中有一个网卡,编号32,名称eth0,对端网卡边哈if33,正好是一对
- 默认分配的IP地址段是172.17.0.0/16,网关IP就是docker0的IP
B. bridge网络自定义
默认的bridge网络是自动创建的,已有的信息不能修改,但docker支持自定义新的bridge网络,子网段、网关、是否自动分配等都可以自定义
- 创建简单的自定义bridge网络
1 | docker network create --driver bridge noah_net |
- 创建自定义网段的bridge网络
1 | docker network create --driver bridge \ |
- 使用自定义网络创建容器
以上两个自定义网络创建好以后,创建容器时只要指定–network=xxx,就可以使用新的bridge网络了.
使用--subnet
创建的网络,还可以通过–ip手动分配IP,非--subnet
参数创建的网络不能手动分配IP,会报错
1 | [root@docker01 ~]# docker run -it --rm --network=noah_net busybox ip addr|grep "172" |
C. bridge网络之间通信
先说结论:
- 相同bridge网络下的容器互相之间可以通过IP通信
- 不同bridge网络下的容器互相之间不能通过IP通信
- 不同bridge网络之间不能通过添加路由解决通信问题
- iptables DROP 掉了不同bridge网络间的通信
基于以上原因,要解决不同bridge网络之间的通信问题,常用的解决办法就是为容器配置多个bridge的网卡,通过docker network connect 命令实现。
1 | docker run -d --name bbx1 --network=noah_net busybox sleep 900 |
四 macvlan网络
A. 什么是macvlan:
macvlan 本质上是一种网卡虚拟化技术
macvlan 本身是 linux kernel 模块,允许在同一个物理网卡上配置多个 MAC 地址,即多个 interface,每个 interface 可以配置自己的 IP。
使用macvlan可以实现容器跨主机通信:
B. 创建macvlan:
首先需要再开一台虚拟机,创建好docker环境,然后两台机器都执行下列命令
1 | docker network create --driver macvlan |
说明:docker不会为macvlan创建网关,所以这里的网关要事先存在
macvlan最好自己手动管理IP地址,不要自动分配,容易IP冲突
两台docker主机上分别创建容器测试:
- docker01:
1 | docker run -it --network macvlan_1 --ip=10.0.0.111 busybox:latest /bin/sh |
- docker02:
1 | docker run -it --network macvlan_1 --ip=10.0.0.112 busybox:latest /bin/sh |
五 overlay网络
overlay网络是基于 VxLAN 的 隧道网络,VxLAN 可将二层数据封装到 UDP 进行传输,VxLAN 提供与 VLAN 相同的以太网二层服务,但是拥有更强的扩展性和灵活性。
不同overlay网络是互相隔离的,要相互通信的话,也是需要把容器加入多个网络才行.
Docerk overlay 网络需要一个 key-value 数据库用于保存网络状态信息,包括 Network、Endpoint、IP 等。Consul、Etcd 和 ZooKeeper 都支持,这里使用 Consul。
A. 环境准备工作
- 分别修改docker配置文件
docker01、02上都增加如下配置在daemon.json文件中
1 | vim /etc/docker/daemon.json |
- docker01上运行consul
1 | docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap |
运行成功后,可以访问consul的web页:http://10.0.0.11:8500/ui/#/dc1/kv/
B. overlay网络功能测试
- 创建overlay网络(任意主机)
由于overlay信息会写入数据库,所以在docker02上创建overlay网络,docker01上是可以看到的
1 | [root@docker02 ~]# docker network create -d overlay olay-1 |
- 启动容器测试
1 | [root@docker01 ~]# docker run --rm --network olay-1 busybox ip a s|grep inet |
- 测试结果说明
上面的结果中,每个容器都分别有eth0和eth1两个网卡,其中eth0属于overlay网络,用于跨主机通信,eth1用于与宿主机通信
overlay网络支持docker dns server,支持使用容器名进行通信
C. overlay IPAM
docker 默认为 overlay 网络分配 24 位掩码的子网(10.0.X.0/24),所有主机共享这个 subnet,容器启动时会顺序从此空间分配 IP。当然我们也可以通过--subnet
指定 IP 空间。
1 | docker network create -d overlay --subnet 10.22.1.0/24 ov_net3 |