0
点赞
收藏
分享

微信扫一扫

Docker网络详解


文章目录

  • ​​一、Docker网络间通信​​
  • ​​`1.1.宿主机ping容器,可以正常通信`​​
  • ​​`1.2.容器ping宿主机,可以正常通信`​​
  • ​​`1.3.容器ping外网,可以正常通信(前提条件是宿主机能访问外网)`​​
  • ​​`1.4.容器ping另外一个容器`​​
  • ​​二、Docker网络常用技术​​
  • ​​`2.1.网络命名空间`​​
  • ​​网络命名空间的操作​​
  • ​​`2.2.Veth设备对`​​
  • ​​创建veth设备对​​
  • ​​实现veth设备对之间的通信​​
  • ​​常用操作​​
  • ​​`2.3.网桥`​​
  • ​​把veth0连接到网桥docker1​​
  • ​​删除网桥​​

  • ​​三、理解docker0​​
  • ​​`3.1.iptables和Netfilter`​​
  • ​​`3.2.路由`​​
  • ​​路由表的创建​​
  • ​​路由表的查看​​

  • ​​四、Docker的网络实现​​
  • ​​`4.1.Docker启动后`​​
  • ​​NAT表​​
  • ​​filter表​​
  • ​​`4.2.运行不映射端口的容器`​​
  • ​​`4.3.运行映射了端口(80:80)的容器`​​
  • ​​NAT表​​
  • ​​filter表​​


一、Docker网络间通信

启动一个测试容器

docker run -d --name test busybox sleep 36000

查看容器的IP地址

docker exec -it test ip a s

Docker网络详解_veth设备对
网卡eth0@if11和172.17.0.2/16的IP是docker自动分配给容器的

​1.1.宿主机ping容器,可以正常通信​

Docker网络详解_网络命名空间_02

​1.2.容器ping宿主机,可以正常通信​

Docker网络详解_网络命名空间_03

​1.3.容器ping外网,可以正常通信(前提条件是宿主机能访问外网)​

Docker网络详解_docker_04

​1.4.容器ping另外一个容器​

再启动一个容器test1

docker run -d --name test1 busybox sleep 36000

查看容器test1的IP
Docker网络详解_docker0_05
ping测试
Docker网络详解_网络命名空间_06
容器之间是可以正常通信的

问题:那么它们之间是如何实现通信的呢?

二、Docker网络常用技术

查看Docker容器在哪个网络命名空间

​2.1.网络命名空间​

  • 为了支持网络协议栈的多个实例,Linux在网络栈中引入了网络命名空间。
  • 处于不同命名空间中的网络栈是​​完全隔离​​的,彼此之间无法通信,就好像两个“平行宇宙”
  • 通过对网络资源的隔离,就能在一个宿主机上虚拟多个不同的网络环境

网络命名空间的操作

ip netns add ns1    #创建命名空间ns1
ip netns list #列出命名空间
ip netns exec ns1 ifconfig #在命名空间中执行命名,此时没有任何网络设备
ip netns exec ns1 bash #进入到命名空间
exit #退出到外面的命名空间
ip link set br0 netns ns1 #把br0设备转移到ns1命名空间中
ethtool -k br0 | grep netns #如果netns-local的值是on,说明不可以转移,否则可以转移
ip netns del ns1 #删除网络命名空间

​2.2.Veth设备对​

通过Veth设备对可以直接将两个网络命名空间连接起来,实现不同网络命名空间之间的通信

创建veth设备对

ip link add veth0 type veth peer name veth1    #创建Veth设备对
ip link show

在当前网络命名空间出现了一对veth设备对
Docker网络详解_docker0_07

ip netns add ns1          #创建命名空间ns1
ip link set veth1 netns ns1 #把veth1转移到ns1命名空间中
ip link show

veth1已经查看不到了
Docker网络详解_veth设备对_08

ip netns exec ns1 ip link show    #在ns1中查看网络设备

veth1已经移动到ns1网络命名空间了

14: veth1@if15解释

14表示设备的编号
veth1表示设备名
if15表示该设备的peer设备编号为15

Docker网络详解_veth设备对_09

注意:我们在Docker容器中看到的网络设备是eth0,这是因为Docker在将Veth设备放入容器后改名为eth0,简直以假乱真

实现veth设备对之间的通信

ip netns exec ns1 ip addr add 10.1.1.11/24 dev veth1
ip netns exec ns1 ip link set dev veth1 up
ip addr add 10.1.1.10/24 dev veth0
ip link set dev veth0 up
ping 10.1.1.11

设置IP地址后可以正常通信,这也就实现了不同网络命名空间的通信
Docker网络详解_docker0_10

常用操作

Veth设备查看对端

ip netns exec ns1 ethtool -S veth1

Docker网络详解_docker0_11

​2.3.网桥​

把veth0连接到网桥docker1

brctl addbr docker1           #新增网桥docker1
brctl addif docker1 veth0 #将veth0连接到网桥docker1
ifconfig veth0 0.0.0.0 #veth0工作在链路层,因此不再需要IP地址
ifconfig docker1 10.1.1.1/24 #给网桥配置IP地址
brctl show #查看网桥信息

网桥docker1下连接了veth0
Docker网络详解_网络命名空间_12

bridge link        #显示哪些设备连接到网桥中

Docker网络详解_Docker网络详解_13

删除网桥

ip link set dev docker1 down
brctl delbr docker1

三、理解docker0

Docker网络详解_网络命名空间_14

Docker启动后会自动创建一块网卡——docker0,默认地址为172.17.0.1/16
Docker网络详解_网络命名空间_15
docker0相当于一个可以配置IP的网桥,类似于三层交换机,所有容器均连接到docker0上,由docker0来实现MAC寻址和路由转发

每启动一个容器,就会分配一个IP地址

默认使用桥接(bridge)模式,通过​​Veth设备对​​技术来实现通信

​3.1.iptables和Netfilter​

​Netfilter​​​负责在内核中执行各种挂接的规则,运行在​​内核模式​​中

而​​iptables​​​是在​​用户模式​​下运行的进程,负责协助和维护内核中Netfilter的各种规则表。

iptables 命令介绍

​3.2.路由​

路由表的创建

Linux的路由表至少包括两个表,一个是​​LOCAL表​​​,另一个是​​MAIN表​​。

LOCAL表包含所有本地设备地址,LOCAL路由表是在配置网络设备地址时自动创建的,用于供Linux协议栈识别本地地址,以及进行本地各个不同网络接口之间的数据转发

通过如下命令查看LOCAL表的内容:

ip route show table local type local

MAIN表用于各类网络IP地址的转发。

路由表的查看

ip route list

Docker网络详解_网络命名空间_16

netstat -rn或route -n

Docker网络详解_veth设备对_17
标志是U,说明是可达路由
标志是G,说明这个网络接口连接的是网关,否则说明这个接口是直连主机

四、Docker的网络实现

详细介绍Docker启动后、运行不映射端口的容器、运行映射了端口的容器时iptables的区别(使用​​iptables-save​​查看)

​4.1.Docker启动后​

NAT表

-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

前两条匹配生效后,都会执行DOCKER链,而此时DOCKER链为空,所以前两条只是做了一个框架,并没有实际效果

若本地出发的数据包不是发往docker0的,则需要进行动态地址修改(MASQUERADE),将源地址从容器的地址(172段)修改为宿主机网卡的IP地址,之后就可以发送给外面的网络了,即SNAT

filter表

-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT

第1条:如果接收到的数据包属于以前已经建立好的连接,那么允许直接通过。这样接收到的数据表又走回docker0,并中转到相应的容器

第2条是框架,发往docker0的包都会走DOCKER链

第3条:来自docker0的包,如果Forward到非docker0的本地IP地址设备,是允许的。这样,docker0设备的包就可以根据路由规则中转到宿主机的网卡设备,​​从而访问外面的网络​

第4条:docker0的包还可以被中转给docker0本身,即连接在docker0网桥上的​​不同容器之间的通信​​也是允许的

​4.2.运行不映射端口的容器​

iptable与Docker启动后一样

​4.3.运行映射了端口(80:80)的容器​

共增加了如下三条规则

NAT表

-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80

第1条:作用是将原地址和目标地址为容器IP 172.17.0.2/32, 且目标端口为80,MASQUERADE动态地转换为可用的宿主机IP地址—​​没搞懂为什么要这么做​

第2条:其作用是将访问宿主机80端口请求的流量转发到容器172.17.0.2的80端口上,所以,外界访问Docker容器是通过iptables做DNAT实现的。

filter表

-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT

从非docker0发往docker0且目的地址为172.17.0.2/32,端口是tcp 8443的包是允许的


举报

相关推荐

0 条评论