跨主机容器通信¶
备注
host 网络驱动程序仅适用于 Linux 主机,在 Docker Desktop for Mac、Docker Desktop for Windows 或 Docker EE for Windows Server 上不受支持。
早期的跨主机通信方案¶
容器使用host模式:
容器直接使用宿主机的网络,这样天生就可以支持跨主机通信。 虽然可以解决跨主机通信问题,但这种方式应用场景很有限,容易出现端口冲突,也无法做到隔离网络环境 一个容器崩溃很可能引起整个宿主机的崩溃
端口绑定:
通过绑定容器端口到宿主机端口 跨主机通信时,使用主机IP+端口的方式访问容器中的服务 显而易见,这种方式仅能支持网络栈的四层及以上的应用 并且容器与宿主机紧耦合很难灵活的处理,可扩展性不佳
docker外定制容器网络:
在容器通过docker创建完成后,然后再通过修改容器的网络命名空间来定义容器网络 典型的就是很久以前的pipework,容器以none模式创建, pipework通过进入容器的网络命名空间为容器重新配置网络 这样容器网络可以是静态IP、vxlan网络等各种方式,非常灵活 容器启动的一段时间内会没有IP,明显无法在大规模场景下使用,只能在实验室中测试使用
第三方SDN定义容器网络:
使用Open vSwitch或Flannel等第三方SDN工具,为容器构建可以跨主机通信的网络环境。 这些方案要求各个主机上的docker0网桥的cidr不同 以避免出现IP冲突的问题限制了容器在宿主机上的可获取IP范围 并且在容器需要对集群外提供服务时,需要比较复杂的配置,对部署实施人员的网络技能要求比较高
备注
上面这些方案有各种各样的缺陷,同时也因为跨主机通信的迫切需求,docker 1.9版本时,官方提出了基于vxlan的overlay网络实现,原生支持容器的跨主机通信。同时,还支持通过libnetwork的plugin机制扩展各种第三方实现,从而以不同的方式实现跨主机通信。
流行的方案¶
基于隧道的overlay网络:
按隧道类型来说,不同的公司或者组织有不同的实现方案。 a. docker原生的overlay网络就是基于vxlan隧道实现的。 b. ovn则需要通过geneve或者stt隧道来实现的。 c. flannel最新版本也开始默认基于vxlan实现overlay网络。
基于包封装的overlay网络:
基于UDP封装等数据包包装方式,在docker集群上实现跨主机网络。 典型实现方案有Weave、Flannel的早期版本。
基于三层实现SDN网络:
基于三层协议和路由,直接在三层上实现跨主机网络,并且通过iptables实现网络的安全隔离。 典型的方案为 Calico。 同时对不支持三层路由的环境,Calico还提供了基于IP封装的跨主机网络实现
操作命令¶
Docker通过使用Linux桥接提供容器之间的通信,docker0桥接接口的目的就是方便Docker管理。当Docker daemon启动时需要做以下操作:
-> 如果docker0不存在则创建
-> 搜索一个与当前路由不冲突的ip段
-> 在确定的范围中选择 ip
-> 绑定ip到 docker0
列出当前主机网桥:
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02426f15541e no vethe833b02
查看当前 docker0 ip:
[root@localhost ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:6fff:fe15:541e prefixlen 64 scopeid 0x20<link>
ether 02:42:6f:15:54:1e txqueuelen 0 (Ethernet)
RX packets 120315 bytes 828868638 (790.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 132565 bytes 100884398 (96.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
................
在容器运行时,每个容器都会分配一个特定的虚拟机口并桥接到docker0。每个容器都会配置同docker0 ip相同网段的专用ip 地址,docker0的IP地址被用于所有容器的默认网关:
// 一般启动的容器中ip默认是172.17.0.1/24网段
[root@linux-node2 ~]# docker run -t -i --name my-test centos /bin/bash
[root@c5217f7bd44c /]#
[root@linux-node2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c5217f7bd44c centos "/bin/bash" 10 seconds ago Up 10 seconds my-test
[root@linux-node2 ~]# docker inspect c5217f7bd44c|grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
注意:宿主机的ip路由转发功能一定要打开,否则所创建的容器无法联网:
[root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward
1
[root@localhost ~]#
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e64eade06d1 docker.io/centos "/bin/bash" 10 seconds Up 9 seconds my-centos
[root@localhost ~]# docker run -itd --net=none --name=container1 docker.io/centos
5e5bdbc4d9977e6bcfa40e0a9c3be10806323c9bf5a60569775903d345869b09
[root@localhost ~]# docker attach container1
[root@5e5bdbc4d997 /]# ping www.baidu.com
PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data.
64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=1 ttl=53 time=2.09 ms
64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=2 ttl=53 time=2.09 ms
关闭ip路由转发功能,容器即不能联网
[root@localhost ~]# echo 0 > /proc/sys/net/ipv4/ip_forward
[root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward
0
[root@5e5bdbc4d997 /]# ping www.baidu.com //ping不通~