我们在使用docker run创建Docker容器时,可以用--net选项指定容器的网络模式,Docker有以下4种网络模式:
1.host模式,使用--net=host指定。
2.container模式,使用--net=container:NAME_or_ID指定。
3.none模式,使用--net=none指定。
4.bridge模式,使用--net=bridge指定,默认设置
5.overlay模式:使用--net=overlay(覆盖网络,跨主机通信)
一、host模式
Docker使用的网络实际上和宿主机一样,在容器内看到的网卡ip是宿主机上的ip。
众所周知,Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的Network Namespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口
docker run -it --net=host centos /bin/bash
可以看到容器内网卡直接复用宿主机网络,该模式将禁用Docker容器的网络隔离
二、container模式
多个容器使用共同的网络看到的ip是一样的。
在理解了host模式后,这个模式也就好理解了。这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信
例子:
docker run -it --net=container:169c875f4ba0 centos /bin/bash (复用169c875f4ba0容器的网络)
可以看出和容器169c875f4ba0的网络环境一样
三、none模式
这种模式下不会配置任何网络。
这个模式和前两个不同。在这种模式下,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
例子:
docker run -it --net=none centos /bin/bash
可以看出,并没有配置网卡信息,需要自己手动配置
四、bridge模式
bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。
同一个宿主机上的所有容器会在同一个网段下,相互之间是可以通信的
例子:
docker run -it --net=bridge centos /bin/bash
对比宿主机网桥,发现容器内网卡和宿主机网桥在同一网段.
通过网桥和外界通信
五、overlay neetwork模式(跨主机通信)
容器在两个跨主机进行通信的时候,是使用overlay network这个网络模式进行通信,如果使用host也可以实现跨主机进行通信,直接使用这个物理的ip地址就可以进行通信。overlay它会虚拟出一个网络,在这个overlay网络模式里面,有一个类似于服务网关的地址,然后把这个包转发到物理服务器这个地址,最终通过路由和交换,到达另一个服务器的ip地址
在docker容器里面overlay 是怎么实现的呢
例子:
宿主机:172.16.1.56,172.16.1.57 修改
vim /lib/systemd/system/docker.service
修改启动参数
--cluster-store 指定 consul 的地址。
--cluster-advertise 告知 consul 自己的连接地址。
之后重启docker
systemctl daemon-reload
systemctl restart docker.service
使用docker部署服务发现工具consul
docker run -d -p 8400:8400 -p 8500:8500 -p 8600:53/udp -h consul progrium/consul -server -bootstrap -ui-dir /ui
http://172.16.1.57:8500/
可以看到已经存在的服务
查看目前的网络模式
创建overlay网络
-d overlay: 指定driver为overlay
可以注意到ov_net1的scope为global
在另一台机器傻女查看网络模式
发现也存在ov_net1网络
查看网络详细信息
创建容器
docker run -it --net=ov_net1 centos /bin/bash
发现两个不同主机的容器可以ping通
恢复netns命名空间
执行下面的命令来获取容器进程号
docker inspect adaea943f075|grep Pid
ln -s /proc/26398/ns/net /var/run/netns/adaea943f075(容器id) #netns目录不存在则创建
查看网络空间
恢复docker容器netns
ln -s /var/run/docker/netns /var/run/netns
查看指定网络命名空间的网络
ip netns exec 1-46663fb66b ip addr
查看网络网卡
ip netns exec 1-46663fb66b brctl show
实现步骤
从这个通信过程中来看,跨主机通信过程中的步骤如下:
容器的网络命名空间与overlay网络的网络命名空间通过一对veth pair连接起来,当容器对外通信时,veth pair起到网线的作用,将流量发送到overlay网络的网络命名空间中。
容器的veth pair对端eth3与vxlan设备通过br0这个Linux bridge桥接在一起,br0在同一宿主机上起到虚拟机交换机的作用,如果目标地址在同一宿主机上,则直接通信,如果不再则通过设置在vxlan1这个vxlan设备进行跨主机通信。
vxlan1设备上会在创建时,由docker daemon为其分配vxlan隧道ID,起到网络隔离的作用。
docker主机集群通过key/value存储共享数据,在7946端口上,相互之间通过gossip协议学习各个宿主机上运行了哪些容器。守护进程根据这些数据来在vxlan1设备上生成静态MAC转发表。
根据静态MAC转发表的设置,通过UDP端口4789,将流量转发到对端宿主机的网卡上。
根据流量包中的vxlan隧道ID,将流量转发到对端宿主机的overlay网络的网络命名空间中。
对端宿主机的overlay网络的网络命名空间中br0网桥,起到虚拟交换机的作用,将流量根据MAC地址转发到对应容器内部。
虽然上面的网络通信模型可以实现容器的跨主机通信,但还是有一些缺陷,造成实际使用上的不便,例如:
由于vxlan网络与宿主机网络默认不再同一网络环境下,为了解决宿主机与容器的通信问题,docker为overlay网络中的容器额外增加了网卡eth2作为宿主机与容器通信的通道。这样在使用容器服务时,就必须根据访问性质的不同,选择不同的网卡地址,造成使用上的不便。
容器对外暴露服务仍然只能使用端口绑定的方式,外界无法简单地直接使用容器IP访问容器服务。
从上面的通信过程中来看,原生的overlay网络通信必须依赖docker守护进程及key/value存储来实现网络通信,约束较多,容器在启动后的一段时间内可能无法跨主机通信,这对一些比较敏感的应用来说是不可靠的。
不通overlay network网络空间的容器如何通信
使用连接网络
docker network connect ov_net1 containId(容器名或者ID) (该容器位于另一个网络空间)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。