zoukankan      html  css  js  c++  java
  • Docker Bridge 网络原理

    Docker 的网络子系统是可插拔驱动式的,默认情况下存在或支持多种网络接口,如 bridge、host、overlay、macvlan 以及 none 类型的网络接口。

    bridge 是 docker 默认的网络模式,如果在创建容器时不指定网络类型,则默认时 bridge 模式,会为每个容器分配一个 Network Namespace、IP 等,并将容器的网络连接到一个网桥(docker0)上。
    这种模式的特点是:同一个网桥下的容器间可以相互通信,不同网桥间的容器网络会被隔离。

    Linux 网桥

    bridge 模式是基于 Linux 的网桥(一同通过软件实现的虚拟设备)实现的,网桥可以将 Linux 内部多个网络接口连接在一起,如下图:

    通过网桥将网络接口连接起来可以实现:一个网络接口接收到网络数据包后,会复制到其他网络接口中,如下图所示:

    如上图所示,当网络接口A收到数据包后,网桥会将数据包复制发送给连接到网桥的其他接口(如上图中的网卡B和网卡C)。

    docker0

    Docker 通过 Linux 的网桥实现了 bridge模式,原理如下图:

    Docker 在启动时,会创建一个名为docker0网桥,并把其IP地址设为172.17.0.1/16(私有IP地址)。

    $ brctl show
    bridge name	bridge id		STP enabled	interfaces
    docker0		8000.0242526953be	no		
    

    注:brclt 一个用来管理网桥的命令行工具。详见

    $ ip addr
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 00:0c:29:9c:30:76 brd ff:ff:ff:ff:ff:ff
        inet 192.168.59.128/24 brd 192.168.59.255 scope global noprefixroute dynamic ens33
           valid_lft 1512sec preferred_lft 1512sec
        inet6 fe80::b356:f4d:f6ea:25aa/64 scope link noprefixroute 
           valid_lft forever preferred_lft forever
    3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:52:69:53:be brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
           valid_lft forever preferred_lft forever
        inet6 fe80::42:52ff:fe69:53be/64 scope link 
           valid_lft forever preferred_lft forever
    

    然后 Docker 在创建容器时,会通过虚拟设备对veth-pair来将容器与docker0 连接起来。对于172.17.0.0/16网段的数据包, Docker 会定义一条iptables NAT的规则来讲这些数据包的 IP 地址转换成公网 IP 地址,然后通过真实的网络接口(如上图 ens160 接口)发送出去。
    启动一个容器,默认使用 bridge 模式

    $ docker run -d --name redis -p6379:6379 redis:4
    5bd019a047ce
    

    查看网桥状态,已有 veth 连接

    $ brctl show
    bridge name	bridge id		STP enabled	interfaces
    docker0		8000.0242526953be	no		vethed2a70d
    

    查看容器的netns

    当容器启动时,Docker 内部会自动为这个容器创建一个netns用于网络隔离,但当我们使用ip netns list查看时却看不到数据,是因为 Docker 把netns创建到了其他地方,而ip netns list命令只能读目录/var/run/netns下面的数据。

    我们可以通过以下命令来解决这个问题,方便我们学习docker网络。

    # 得到容器对应的进程
    pid=`docker inspect -f '{{.State.Pid}}' $container_id`
    # 手动创建防止文件夹不存在
    mkdir -p /var/run/netns/
    # 建立软连接
    ln -s /proc/$pid/ns/net /var/run/netns/$container_id
    

    将上面的命令修改为和当前环境一致并验证netns中的网卡。

    $ pid=`docker inspect -f '{{.State.Pid}}' 5bd019a047ce`
    $ mkdir -p /var/run/netns/
    $ ln -s /proc/$pid/ns/net /var/run/netns/5bd019a047ce
    $ ip netns list
    5bd019a047ce (id: 0)
    
    $ ip netns exec 5bd019a047ce ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    

    可以看到我们成功输出了netns中的网卡信息,并且此信息和从docker容器中看到的一致。

  • 相关阅读:
    asp.net Core 中AuthorizationHandler 实现自定义授权
    Android 动态获取ListView的高度
    artDialog是一个基于javascript编写的对话框组件,它拥有精致的界面与友好的接口
    Java日期时间思维导图整理
    《领域驱动设计》第二部分:模型驱动设计的构造块 第四章:分离领域 阅读笔记
    《领域驱动设计》第一部分:让领域模型发挥作用 第三章:绑定模型和实现 阅读笔记
    《领域驱动设计》干货整理
    简单的服务熔断方案
    框架设计注意事项——生命周期
    【翻译】 Guice 动机——依赖注入的动机
  • 原文地址:https://www.cnblogs.com/Zioyi/p/15389230.html
Copyright © 2011-2022 走看看