【docker】2.docker网络

 

每一个docker容器拥有自己的网络命名空间,那么容器之间是如何通信的呢?

docker容器有4种通信方式:

  • bridge模式(默认)
  • host模式
  • container模式
  • none模式

1. bridge桥接模式

(1) 原理

我们局域网中的两台物理设备,彼此也是网络命名空间隔离的,它们是如何通信的呢?

物理设备的通信需要:

  • 交换机:维护、学习MAC地址,做寻址、转发
  • 网线两端的网口:两个网口组成一对,一端接入交换机,一端接入PC设备
  • 传输介质:网线
linux上如何查看网桥:
[root@k8s-master ~]# yum install -y bridge-utils
[root@k8s-master ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02428c27984c       no              veth0db5e12
                                                        veth8369b2f
                                                        vethb632024

与物理设备类似,docker桥接模式也是通过这种原理实现的:

容器的通信也同样需要:

  • 虚拟网桥docker0:
  • 网卡对:veth0 veth1,一端接入虚拟网桥,一端接入容器内
  • 传输介质:虚拟的,通过网卡对传输

docker 创建一个容器的时候,会执行如下操作:

  • 创建一对虚拟接口/网卡,也就是veth pair
  • 将网卡对的本地主机一端接到docker网桥上,并具有一个唯一的名字,如 veth0db5e12(主机上的网卡)
  • 将网卡对的容器一端接到容器内部,并修改名字为 eth0(这个网卡只在容器内可见)
  • 从网桥的可用地址段中(也就是与该bridge对应的network)获取一个空闲地址分配给容器的eth0
  • 配置默认路由到网桥

这样就模拟了二层交换机,创建好了通信桥梁。

(2) 上手操作一下

先清空所有容器:
#清空
docker rm -f `docker ps -aq`

#查看
docker ps
brctl show

创建两个测试容器test1,test2:

#运行容器test1
docker run -d --name test1 nginx:alpine

#查看docker0上的网卡变化
brctl show

#查看网卡信息
ip a |grep veth

# 查看容器中的网卡
docker exec -ti test1 ifconfig

#运行容器test2
docker run -d --name test2 nginx:alpine

#进入容器
docker exec -ti test2 sh

#curl到test1容器
sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
apk add curl
curl 172.18.0.2

(3) 容器的通信过程

在 test2 容器内查看路由表:
$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0
0.0.0.0         172.18.0.1      0.0.0.0         UG    0      0        0 eth0

- eth0 网卡

是这个容器里的默认路由设备

- 第1条路由规则

所有对 172.18.0.0/16 这个网段的请求,都会被交给 eth0 来处理,这条路由规则的网关(Gateway)是 0.0.0.0。这就意味着这是一条直连规则,即:凡是匹配到这条规则的 IP 包,应该经过本机的 eth0 网卡,通过二层网络(数据链路层)直接发往目的主机。

- test2发送ARP广播请求

test2容器通过 eth0 网卡发送一个 ARP 广播,来通过目的 IP 地址(172.18.0.2)查找对应的 MAC 地址。

- 网桥转发ARP广播请求

eth0 的另一端插宿主机的 docker0 网桥上,通过另一端vethx,把请求交给网桥处理,由网桥转发ARP的广播请求。

- test1对ARP做出响应

docker0将ARP请求广播出去,test1收到之后返回响应,这样docker0就维护了一份MAC地址映射表,后续对于test2的eth0对test1的请求,都由docker0网桥负责转发。

查看MAC映射表:

[root@k8s-master ~]# brctl showmacs docker0
port no mac addr                is local?       ageing timer
  2     72:b5:69:87:9c:20       yes                0.00
  2     72:b5:69:87:9c:20       yes                0.00
  1     f2:da:d9:3d:99:4a       yes                0.00
  1     f2:da:d9:3d:99:4a       yes                0.00

查看容器的网卡eth0与主机的哪个虚拟网卡相对应:

#查看容器内网卡eth0的索引序号
[root@k8s-master ~]# docker exec -it test1 cat /sys/class/net/eth0/ifindex
48

#查看所有网卡对
[root@k8s-master ~]# ip a|grep @if
49: veth32652ea@if48: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
51: veth96900b0@if50: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default

2. Host模式

(1) 使用

docker不会为容器创建网络命名空间,容器直接共享宿主机的网络空间。那么在容器内的所有网络操作,都是走的宿主机网络,容器也没有自己独立的IP地址。

这种方式由于不需要进行NAT转换,网络性能较好。

启动一个容器,并使用 --net host 参数指定 host 模式:

docker run --net host -d --name mysql mysql:5.7

可以查看主机网络接口与容器的网络接口,结果应该是一致的:

#查看主机网络接口
ifconfig

#查看容器网络接口
docker exec -it mysql ifconfig

(2) 场景

适用于需要容器与宿主机共享网络资源的场景。

例如,网络监控、日志收集等,需要直接访问宿主机的网络接口和IP地址。

3. Container模式

(1) 使用

指定新创建的容器和已经存在的某个容器共享一个网络命名空间,而不是和宿主机共享。

新创建的容器不会创建自己的网卡,配置自己的 IP,而是和指定的容器共享 IP、端口。两个容器的进程可以通过 lo 网卡设备通信。

这种模式可以直接访问 localhost 来访问 namespace下的其他容器,可以降低容器间的通信难度,同时节约网络资源

启动一个容器,并使用 --net container:{target container} 参数指定 container 模式:

docker run -d --name test1 nginx:alpine
docker run -d --name test2 --net container:test1 nginx:alpine

可以查看两个容器的网络接口,结果应该是一致的:

docker exec -it test1 ifconfig
docker exec -it test2 ifconfig

在test1容器内可以使用localhost访问test2的接口:

wget -O- localhost

(2) 场景

适用于需要多个容器之间共享网络配置的场景。

比如 k8s 的一个 pod 内不同容器间的通信方式,使用的就是这种模式。k8s 会在 pod 中创建一个名为 pause 的默认容器,pause 会创建一个命名空间,其他容器加入到 puase 容器中共享 pause 的网络,多个容器之间通过 localhost 相互通信。

4. None模式

docker 会将容器与宿主机隔离开来,但容器不提供任何网络能力。在这种模式下,容器内部没有网卡、IP地址、路由等信息,只有一个回环网络(loopback)接口。这意味着容器不能访问外部网络,也不能被外部网络访问。

这种模式会用于一些特殊场景,比如需要在容器内部运行一些独立的、与网络无关的应用程序,或者需要进行一些网络调试。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值