docker-网络分析

413 阅读4分钟

docker 的网络类型

1: bridge 2: host 3: none 4: container

docker 四种网络类型的不同之处

从 net namespace 的角度来看, host 类型为 容器共享宿主机的 net namespace container 类型,则是两个容器共享一个 net namespace bridge类型 一个容器享有一个 net namespace none 类型,容器也会享有一个 net namespace ,但是容器无法连接外网。

bridge

docker 容器 网络类型 为bridge时 所具有的能力

在宿主机能访问外网的前提下 1: 容器 和外网进行通信 2: 外网能访问容器 (容器运行时 使用端口映射)

bridge 类型的背后实现

所启动的容器 网络类型是 bridge 类型时,容器启动时被分配一个网桥子网内的ip地址, 创建一对 veth pair 设备,一个作为容器的eth0网卡,一个被连接到网桥上。 iptables 会根据容器的启动参数,相应增加规则 概括地说:ip_forward + iptables + bridge + veth pair 使 容器能和外网互通。

自定义网络

自定义一个桥接类型的网络的实质是什么?

在宿主机上创建一个新的网桥,并为网桥分配一个子网地址, 在iptables nat 表 POSTROUTING链之中配置 snat 转换规则。

创建一个网络的使用例子

docker network create --driver bridge 网络名

将一个容器加入到某个网络之中

docker run 的 --network 参数,取值设置为网络名

ip forward

查看当前的宿主机 ip forward 功能 是否开启

  cat /proc/sys/net/ipv4/ip_forward
  如果输出值为1,那么表示开启,如果输出值为0,那么表示ip_forward并没有被开启。

注意:如果ip forward 功能并未开启,那么网络类型为 bridge 的 容器,就无法和外网进行通信了。

docker-proxy 介绍

作用

容器启动时,配置了端口映射参数,会启动一个docker-proxy 进程,来监听宿主机上容器映射的端口。有些情况下,访问容器的请求,并没有匹配到DNAT规则,那么由docker-proxy来处理,规避 docker0 并没有开启发夹模式而可能导致的问题。

docker 是否 默认开启 docker-proxy, 如何验证?

dockerd --help | grep proxy 

docker 是否可以关闭 docker-proxy 模式?

可以的。 /etc/docker/daemon.json 之中配置相应参数,重启docker 即可。 参数名为: dockerd --help | grep proxy 来获得 注意:如果关闭 docker-proxy 机制,那么docker0需要开启发夹模式,否则有些访问可能出现问题,例如(容器访问 宿主机ip+映射端口)

docker-proxy 机制带来的问题

搜索结果: 每启动一个 执行端口映射的容器,都会在机器上启动一个 docker-proxy 进程。 进程会占据一些内存,如果docker-proxy进程数过多,可能会占用大量的内存。 但是也有其他人实际测试:大量的docker-proxy进程,并不会占据大量的内存。

docker 容器内 向外网发送数据,数据的流转图

参与组件 iptables 网卡设备 行为: 在宿主机上的一个容器内 执行 curl 110.242.68.4, 对应的数据包的流转图示 验证方式 iptables -t 表明 -I 链名 -j LOG --log-prefix="相应的输出信息" dmesg | grep "相应的输出信息" 自己在 iptables 某个表的某个链之中增加相应的 打印规则,来判断数据的流向

容器向外网发送数据-输出步骤.png

容器向外网发送数据-输出步骤.png

注意:当容器使用端口映射的方式,向外暴露端口,外部主机访问本机容器时,数据流转和上面的一致。

在容器启动时 建立端口映射的前提下,在容器内 访问 宿主机ip+映射端口,数据流转图

数据包流转图.png

注意:这里的数据包并没有被docker 设置的 iptables DNAT规则所匹配,使数据包的流转走向了INPUT链,规避了 docker0网桥没有开启发夹模式 所可能导致的问题,数据包的处理由docker-proxy进程来执行。

docker 容器 端口映射 的 背后原理

启动容器时,配置端口映射,使外网能够访问此容器。背后的支撑是 iptables 的DNAT 以及 docker-proxy。

docker 网络调试 小技巧

如何进入docker容器进程的网络空间

   nsenter -n -t 容器进程id

注意: 这样可以解决容器内没有网络软件安装包的问题。

当容器无法连通外网的时候,如何调试?

1:首先排查 容器 与 docker0 之间是否连通 2:然后排查 docker0 与 eth0 之间的iptables 规则。

操作

1: 查看docker daemon 设置的默认网络类型

   自己未找到 寻找 docker daemon 设置的默认网络类型的方式,
   据搜索得知 docker daemon 设置的容器的默认网络类型为 bridge 

2: 查看 docker容器 的网络类型

 docker inspect -f {{.NetworkSettings.Networks}} 容器id