docker系列四之网络

基础材料

CentOS7.6 minimal  关闭selinux 关闭swap分区 关闭NetworkManager 关闭firewalld

Docker-ce 18.09.0

Docker支持的网络类型

前面已经介绍过,docker支持的网络驱动类型有5类,分别是bridge、host、overlay、macvlan、none

bridge为默认模式(也是k8s管理的模式),docker启动后如果不指定网络则生成默认的docker0网桥,每个容器有独立的network namespace,容器和网桥之间通过veth pair虚拟网卡对进行通信。

host模式最为简单,直接使用主机网络,由于所用容器共享宿主机端口,不需要经过转换,性能高,相对的容易引起端口冲突,使得容器直接暴露在宿主机之外。

overlay模式称为覆盖网络层,用于连接多台宿主机上的docker进行通信。例如k8s下常用的flannel是overlay网络的一种实现,其在所有docker0网桥之上建立一个上层网络用于转发所有docker0网桥上的数据包。

macvlan模式使用macvlan网络驱动程序为每个容器的虚拟网络接口分配MAC地址,使其看起来像是直接连接到物理网络的物理设备,Docker守护程序通过其MAC地址将流量路由到容器

none模式禁用所有网络。通常与自定义网络驱动程序一起使用,否则容器无法对外进行通信。

由于目前环境上docker通常结合k8s使用,在k8s下管理模式为bridge类型,在k8s中overlay层一般又由第三方插件实现,如flannel等在k8s系列中再进行详细说明,所以本篇主要对bridge类型进行说明。

Docker bridge

docker在结合K8S使用时,使用birdge网桥类型,这样每个容器进程就可以使用自己的network namespace,拥有自己的网络栈(网络栈包括网卡,环回设备,iptables规则,路由表),IP地址和端口,更加接近一台虚拟机的网络。本地使用docker0网桥的容器之间是可以任意通信的。如果要对外发布服务需要使用docker run -p命令进行容器到宿主机之间的端口映射。

当然自定义网桥和默认网桥还是有一定区别的,详细区别请参见官方文档https://docs.docker.com/network/bridge/,由于大多数情况下都是结合k8s进行使用的,使用默认网桥即可。

本地主机不同容器拥有不同的network namespace,彼此看不到对方的网络栈情况,也没有相关的路由,他们之间又是如何通信的呢?

上图是两个本地容器通信的示意图,由于每创建一个容器都会生成veth pair,且是成对出现,如同物理网线一般,一端插在docker0网桥(veth),另一端插在容器上(eth0),而容器端的eth0发出的数据包会直接出现在对应的veth设备上(反之亦然,即使他们处于不用的namespace中),从而到达docker0网桥,而docker0网桥的作用可以看作是一个物理交换机,掌握着本地所有容器的地址信息,会把数据包转发到正确的veth端口,然后直接到达容器的eth0网卡上。

通过brctl show命令查看我的本地环境已经有三个veth设备插在docker0网桥之上

如何确定这些veth设备与容器之间的对应关系呢?这里提供一个方法,可以自行编写成脚本执行

通过如下两条命令可以找出veth设备及容器eth0设备的编号,通过该编号将两者联系起来。

[root@k8sregistry ~]# ip link

[root@k8sregistry ~]# docker exec 0a7b19cb468c /bin/bash -c "cat /sys/class/net/eth0/iflink"

了解本地docker容器的通信方法后,再来看看两台宿主机之间的容器是如何通信的。

上图为两台宿主机容器间通信示意图,以及宿主机A的路由表

从图上所示,容器1到宿主机B的eth0网卡之间是可以通信的,数据包通过docker0网桥转发至宿主机A的eth0网卡,两个宿主机之间通过eth0网卡是可以正常通信的。

容器1到容器3之间是不能通信的,数据包流向分为两种情况:

1、两台宿主机之间的docker0网桥使用同一网段,根据宿主机A的路由表会匹配172.17.0.0这条路由,会在本地查找172.17.0.6这个容器ip,这种情况下数据包在本地docker0网桥上就被丢弃了,根本不会向外发送。

2、两台宿主机之间的docker0网桥使用不同网段(如172.16.0.0),这种情况下无法匹配本地路由表的任何策略,会将数据包发送到默认网关,而网关只掌握两台宿主机的网络信息,并不知道宿主机B上的docker0(172.16.0.1)的存在,所以数据包会在路由器上被丢弃。

由此看来单靠docker0网桥是无法实现两台宿主机容器间的通信,这就需要使用overlay类型在所有docker0网桥之上建立一个上层网络,用于跨主机容器的通信。(当然在宿主机上指定静态路由也是可以的,但这不是好办法)

上图所示是以flannel作为overlay层的实现跨主机容器通信的方式

此时docker0网桥的地址通过其网络参数的控制,读取并设置为Flannel.1的同网段,而flannel.1的ip地址分配又由etcd数据库进行控制,保证加入到集群的每台宿主机分配网段的唯一性。当容器1向容器2发送数据包时,会先将数据包通过docker0网桥发送至flannel.1之上,此时flannel会获得目标地址的网段信息为172.30.67.0,根据该信息去etcd数据库中查找对应网段所在的宿主机ip,然后将包进行封装,由本机的eth0发出去,宿主机B的eth0网卡接收到该包,再将其解包转发至其flannel.1上,从而到达容器2.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于网络排障,你可以使用一些常用的工具和技术来诊断和解决问题。下面是一些可以使用的方法和docker镜像: 1. 检查容器网络设置:使用`docker inspect`命令查看容器的网络配置,确保容器的网络设置正确。 2. 检查网络连接:使用`ping`命令检查容器是否能够与其他主机或容器建立网络连接。你可以通过在容器中运行`ping`命令来测试网络连通性。 3. 检查端口访问:使用`telnet`或`nc`命令检查容器的端口是否能够被访问。例如,`telnet <容器IP> <端口号>`。 4. 检查网络配置:确保容器的网络配置正确,并且与主机网络配置相匹配。可以使用`ifconfig`或`ip addr`命令查看容器和主机的网络配置。 5. 使用网络诊断工具:像Wireshark这样的网络抓包工具可以帮助你分析网络流量,定位问题所在。 6. 使用专门的网络排障工具:有一些专门用于容器网络排障的工具,例如Weave Scope、Cilium等。你可以尝试使用这些工具来帮助诊断和解决问题。 对于docker镜像,你可以使用一些预先构建好的镜像来进行网络排障,例如: - `nicolaka/netshoot`镜像:这个镜像包含了许多常用的网络工具,如ping、telnet、dig、curl等,非常适合用于网络排障。 - `praqma/network-multitool`镜像:这个镜像也包含了一系列网络工具,可以帮助你进行网络排障和诊断。 以上是一些常见的方法和docker镜像,希望对你有所帮助。如果你有更具体的问题,请提供更多细节,我将尽力回答。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值