一、什么是容器网络栈

所谓容器能看见的“网络栈”,被隔离在自己的Network Namespace当中

  1. 网卡(network interface)
  2. 回环设备(loopback device)
  3. 路由表(Routing Table)
  4. iptables规则

    当然 ,容器可以直接声明使用宿主机的网络栈:-net=host(不开启Network Namespace),这样可以为容器提供良好的网络性能,但是也引入了共享网络资源的问题,比如端口冲突。

    大多数情况下,我们希望容器能使用自己的网络栈,拥有属于自己的IP和端口

二、容器如何和其他不同Network Namespace的容器交互 ?

  1. 将容器看做一台主机,两台主机通信直接的办法,就是用一根网线连接,如果是多台主机之间通信,就需要用网络将它们连接到一台交换机上
  2. 在linux中,能够起到虚拟交换机作用的设备是网桥(Bridge)

    网桥是一个工作在数据链路层的设备,功能是根据MAC地址学习来将数据包转发到网桥不同端口上,为了实现上述上的,Docker项目默认在宿主机上创建了一个docker0的网桥,连接在上面的容器,可以通过它来通信

三、如何把容器连接到docker0网络上

需要一种叫Veth Pair的虚拟设备。当Veth Pair被创建出来后,总是以两张虚拟网卡(Veth Peer)的形式成对出现 ,而且从其中一个网卡出的数据包,可以直接出现在它对应的另一张网卡上,即使两张卡在不同的Network Namespace里

这就使Veth Pair常常被用作连接不同的Network Namspace的网线

四、示例演示

下面将在宿主机启动两个容器,分别是nginx-1和nginx-2演示,nginx-1容器访问nginx-2是如何通信的

1. 运行一个nginx-1容器

 docker run -d --name=nginx-1 nginx

2.查看nginx-1的网络设备

root@d5bfaab9222e:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.18.0.2 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:ac:12:00:02 txqueuelen 0 (Ethernet)
RX packets 3520 bytes 8701343 (8.2 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3010 bytes 210777 (205.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

eth0的网卡,是Veth Pari设备的其中一端

3.查看nginx-1的路由表,通过route命令查看

root@d5bfaab9222e:/# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 172.18.0.1 0.0.0.0 UG 0 0 0 eth0
172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0

所有172.18.0.0/16网段的请求,都交给eth0处理,这是Veth Pair设备的一端,另一端在宿主机上

4.查看宿主机的网桥

通过brctl show查看

root@VM-0-8-ubuntu:/home/ubuntu# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242c635ddb8 no veth4d1c130

可以看到,docker0上插入上veth4d1c130网卡

5.再运行一个nginx-2

 docker run -d --name=nginx-2 nginx

6.再查看宿主机网桥

root@VM-0-8-ubuntu:/home/ubuntu# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242c635ddb8 no veth4d1c130
vetha9356e9

可以看到,docker0插上了两张网卡veth4d1c130、 vetha9356e9

此时,当容器nginx-1(172.18.0.2)ping容器nginx-2(172.18.0.3)的时候,就会发现两个容器是可以连通的

五、nginx-1能访问nginx-2的原理是什么?

被限制在Network Namespace的容器进程,是通过Veth Pair设备+宿主机网桥的方式,实现跟其它容器的数据交换

1.nginx-1访问nginx-2时,IP地址会匹配到nginx-1容器的每二条路由规则

172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0

凡是匹配这条规则 的IP包,应该经过本机的eth0网卡,通过二层网络发往目的主机

2.要通过二层网络到达nginx-2 ,需要有172.18.0.3的MAC地址,找到

nginx-1容器需要通过eth0网卡发送一个ARP广播,通过IP来查看对应的MAC地址

这个eth0网卡,是一个Veth Pair,它的一端在nginx-1容器的Network Namespace,另一端位于宿主机上(Host Namespace),并且插入在了宿主机的docker0网桥上

一旦虚假网卡(veth4d1c130)被插在网桥(docker0)上,调用网络的数据包会被转发给对应的网桥,所以ARC请求会被发给docker0

3.docker0转发数据到到相应的nginx-2

docker0会继续扮演二层交换机的角色,根据数据包的上的MAC地址(nginx-2的MAC地址),在它的CAM表里查对应的端口,会找到vetha9356e9,然后将数据包发往这个端口,这样数据包就到了nginx-2容器的Network Namespace里

nginx-2看到它自己的eth0网卡上出现了流入的数据包,然后对请求进行处理,再返回响应给nginx-1

可以打开iptables的TRACE功能查看数据包的传输过程,通过tail -f /var/log/syslog

# iptables -t raw -A OUTPUT -p icmp -j TRACE
# iptables -t raw -A PREROUTING -p icmp -j TRACE

原理图如下

为什么不同命名空间的docker容器可以相互通信?的更多相关文章

  1. Docker容器跨主机通信之:直接路由方式

    一.Docker网络基本原理 直观上看,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)与外界相通,并可以收发数据包:此外,如果不同子网之间要进行通信,需要额外的路由机制. Docker ...

  2. Docker容器跨主机通信

    默认情况下Docker容器需要跨主机通信两个主机节点都需要在同一个网段下,这时只要两个Docker容器的宿主机能相互通信并且该容器使用net网络模式,改实现方式为网桥模式通信: 除此之外我们还可以通过 ...

  3. docker容器内外相互拷贝数据

    从宿主机上拷贝文件到容器内 注意:一下红色字体为宿主机文件 docker cp 文件 容器名:目录 # docker cp httpd-2.4.34.tar.gz node4:/opt/ 从宿主机上拷 ...

  4. Docker容器跨主机通信--overlay网络

    一.Docker主机间容器通信的解决方案 Docker网络驱动 Overlay: 基于VXLAN封装实现Docker原生Overlay网络 Macvlan: Docker主机网卡接口逻辑上分为多个子接 ...

  5. Docker容器跨主机通信之:OVS+GRE

    一.概述 由于docker自身还未支持跨主机容器通信,需要借助docker网络开源解决方案 OVS OpenVSwich即开放式虚拟交换机实现,简称OVS,OVS在云计算领域应用广泛,值得我们去学习使 ...

  6. docker容器之间的通信

    容器之间互通 新建两个容器 docker run -d --name box1 busybox /bin/sh -c "while true;do sleep 3600;done" ...

  7. docker images之间相互通信 link

    同一个host上的两个container 首先启动一个nginx. container起名叫netease_nginx docker run --detach --name netease_nginx ...

  8. Docker: Docker容器之间互相通信

    最简单的方法,关闭防火墙(只建议用于开发环境) systemctl stop firewalld

  9. Docker容器学习梳理 - 容器间网络通信设置(Pipework和Open vSwitch)

    自从Docker容器出现以来,容器的网络通信就一直是被关注的焦点,也是生产环境的迫切需求.容器的网络通信又可以分为两大方面:单主机容器上的相互通信,和跨主机的容器相互通信.下面将分别针对这两方面,对容 ...

随机推荐

  1. [币严区块链]ETH搭建节点区块数据同步的三种模式:full、fast、light

    ETH  全节点Archive(归档)模式数据量增长图 上述图表可通过链接查看:https://etherscan.io/chartsync/chainarchive 通过上表,可以看到截止2019年 ...

  2. jvm内存溢出问题的定位方法

    jvm内存溢出问题的定位方法 今天给大家带来JVM体验之内存溢出问题的定位方法. 废话不多说直接开始: 一.Java堆溢出 测试代码如下: import java.util.*; public cla ...

  3. 浅谈DanmakuView

      今天简单介绍一下开源的弹幕引擎---danmakuView   使用之前在build.gradle里面添加下面这一条(目前我使用的工具是AndroidStudio 3.1.2)   impleme ...

  4. git windows 安装 - Github同步 / Vscode源代码管理:Git 安装操作

    github上创建立一个项目 登录github网站,在github首页,点击页面右下角"New Repository" 最后点击"Create Repository&qu ...

  5. SQL手工注入进阶篇

    0.前言 上一篇我们介绍了SQL手工注入的流程以及步骤,但在实际的安全问题以及CTF题目中,查询语句多种多样,而且是肯定会对用户的输入进行一个安全过滤的,而这些过滤并不一定是百分百安全的,如何利用一些 ...

  6. Nginx缓存原理及机制

    文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 上篇文章介绍了Nginx一个较为重要的知识点:Nginx实现接口限流.本篇文章将介绍Nginx另一个重要知识点 ...

  7. Java门面模式

    一.简介 隐藏系统的复杂性,对外提供统一的访问入口,外部系统访问只通过此暴露出的统一接口访问.是一种结构型模式.封装子系统接口的复杂性,提供统一的对外接口,能够使子系统更加简单的被使用. 二.结构及使 ...

  8. 【深度学习】Focal Loss 与 GHM——解决样本不平衡问题

    Focal Loss 与 GHM Focal Loss Focal Loss 的提出主要是为了解决难易样本数量不平衡(注意:这有别于正负样本数量不均衡问题)问题.下面以目标检测应用场景来说明. 一些 ...

  9. CocosCreator实现动物同化

    获取源码 关注微信公众号『一枚小工 』,发送『动物同化 』获取完整游戏源码. 游戏玩法 游戏目标是将游戏区域的动物全部同化成同一种动物.游戏从左上角开始,从右边点击需要变成的目标动物头像,如果被同化动 ...

  10. python爬虫入门新手向实战 - 爬取猫眼电影Top100排行榜

    本次主要爬取Top100电影榜单的电影名.主演和上映时间, 同时保存为excel表个形式, 其他相似榜单也都可以依葫芦画瓢 首先打开要爬取的网址https://maoyan.com/board/4, ...