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容器中看到的一致。

  • 相关阅读:
    Best Time to Buy and Sell Stock
    Remove Nth Node From End of List
    Unique Paths
    Swap Nodes in Pairs
    Convert Sorted Array to Binary Search Tree
    Populating Next Right Pointers in Each Node
    Maximum Subarray
    Climbing Stairs
    Unique Binary Search Trees
    Remove Duplicates from Sorted Array
  • 原文地址:https://www.cnblogs.com/Zioyi/p/15389230.html
Copyright © 2011-2022 走看看