Docker网络详解

Docker 专栏收录该内容
42 篇文章 0 订阅


一、Docker网络间通信

启动一个测试容器

docker run -d --name test busybox sleep 36000

查看容器的IP地址

docker exec -it test ip a s

在这里插入图片描述
网卡eth0@if11和172.17.0.2/16的IP是docker自动分配给容器的

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

1.4.容器ping另外一个容器

再启动一个容器test1

docker run -d --name test1 busybox sleep 36000

查看容器test1的IP
在这里插入图片描述
ping测试
在这里插入图片描述
容器之间是可以正常通信的

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

二、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设备对
在这里插入图片描述

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

veth1已经查看不到了
在这里插入图片描述

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

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

14: veth1@if15解释

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

在这里插入图片描述

注意:我们在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地址后可以正常通信,这也就实现了不同网络命名空间的通信
在这里插入图片描述

常用操作

Veth设备查看对端

ip netns exec ns1 ethtool -S veth1

在这里插入图片描述

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
在这里插入图片描述

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

在这里插入图片描述

删除网桥

ip link set dev docker1 down
brctl delbr docker1

三、理解docker0

在这里插入图片描述

Docker启动后会自动创建一块网卡——docker0,默认地址为172.17.0.1/16
在这里插入图片描述
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

在这里插入图片描述

netstat -rn或route -n

在这里插入图片描述
标志是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的包是允许的

  • 1
    点赞
  • 5
    评论
  • 6
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值