• 网络虚拟化之Docker的网络模式


    一、概述

    接上篇网络虚拟化之副本网卡技术MACVLAN,基础的虚拟网络技术基本都认识到,本文来看看Docker中是怎么用的。网络虚拟化的运用才是真正开始解决问题。

     几个核心点:

    1.Docker开箱即用的网络模式只有3种

    2.允许自己定制网络,制定给Docker容器

    3.底层技术并没有脱离之前介绍的基础技术范畴

    4.虽然当前是K8S的天下,但Docker也是发布了第一个容器网络的业界标准

    二、核心原理

    相对Kubernetes,Docker的网络模型要相对简单很多。但也最适合我们来充分理解前面介绍的各类网络虚拟化的基础技术。

    Docker 提供的三种开箱即用的网络方案:

    1. 桥接模式

    为每个容器创建veth pair,同时主机上有一个Linux bridge,同一个主机上容器二层网络联通bridge,但不解决主机间网络通信,Linux bridge可以设置IP充当路由器角色,所以可以配置做到容器访问主机设备和外部网络,详细参见:网络虚拟化之虚拟交换机技术Linux Bridge

    2. 主机模式

    该模式下,Docker 不会为新容器创建独立的网络名称空间,这样容器一切的网络设施,如网卡、网络栈等都直接使用宿主机上的真实设施,容器也就不会拥有自己独立的 IP 地址。此模式下与外界通信无须进行 NAT 转换,没有性能损耗,但缺点也十分明显,没有隔离就无法避免网络资源的冲突,譬如端口号不允许重复。

    说白了,这种模式容器直接复用的主机网卡、主机网络,性能损耗最低,但达不到容器隔离的目的。

    3. 空模式

    Docker 会给新容器创建独立的网络名称空间,但是不会创建任何虚拟的网络设备,此时容器能看到的只有一个回环设备(Loopback Device)而已。提供这种方式是为了方便用户去做自定义的网络配置,如自己增加网络设备、自己管理 IP 地址,等等。

    由此,一般可以定制网络模式。有如下几种:

    1. 容器模式

    多个容器共享一个容器网络,本质上是加入同一个网络空间,共享网络资源。该网络空间下的网络设备就自行定义了。

    2. MACVLAN模式

    先创建一个副本网卡,为容器指定这个副本网卡,容器通过副本网卡的 MAC 地址使用宿主机上的物理设备。在追求通信性能的场合,这种网络是最好的选择。

    Docker 的 MACVLAN 只支持 Bridge 通信模式,因此在功能表现上与桥接模式相类似。

    3.Overlay 模式

    使用 docker network create -d overlay 创建,Docker 说的 Overlay 网络实际上就是特指 VXLAN,主要用于 Docker Swarm 服务之间进行通信。然而由于 Docker Swarm 败于Kubernetes,在一些简化场景使用Docker Swarm时会用到,并未成为主流。

    三、使用示例

    安装好Docker后,使用docker network ls 可以看到Docker支持的三种网络模式。

    NETWORK ID          NAME                DRIVER              SCOPE
    6cd2e38e5103        bridge              bridge              local
    401779e10c7e        host                host                local
    a6700b7c7b97        none                null                local

    创建一个测试容器:

    1. docker create --name mnginx \
    2. --network bridge \
    3. --publish 27777:80 \
    4. nginx:latest

     创建后,执行

    docker start mnginx

    再执行,查看刚启动的容器

    docker ps
    1. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    2. b2246463d5ae nginx:latest "/docker-entrypoin..." 27 seconds ago Up 2 seconds 0.0.0.0:27777->80/tcp mnginx

    此时查看主机的网络设备,会增加如下两个:

    docker0: flags=4163  mtu 1500
            inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
            inet6 fe80::42:c0ff:fe93:b9c5  prefixlen 64  scopeid 0x20
            ether 02:42:c0:93:b9:c5  txqueuelen 0  (Ethernet)
            RX packets 96234  bytes 5256444 (5.0 MiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 102552  bytes 1673521274 (1.5 GiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

    veth8edc141: flags=4163  mtu 1500
            inet6 fe80::8449:40ff:fee2:5680  prefixlen 64  scopeid 0x20
            ether 86:49:40:e2:56:80  txqueuelen 0  (Ethernet)
            RX packets 8  bytes 656 (656.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 8  bytes 656 (656.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

    docker0即为一个Linux Bridge,带有IP地址,可以将发往该地址的请求转发给主机网络栈,充当容器的路由器。

    veth8edc141是指派给容器veth pair中的一端,连接在网桥docker0上,通过bridge link可以看到:

    30: veth8edc141 state UP @(null): mtu 1500 master docker0 state forwarding priority 32 cost 2

    veth的另一端如何查看呢?你会发现通过常规方法

    ip netns list
    

    查不到容器定义的网络命名空间。

    在 docker 中,默认情况下不会将容器network namespace 添加到 linux 运行时数据中(从 /run 挂载到 /var/run)。

    怎么办呢?请参考:docker(Kubernetes)环境如何查看network namespace

    可以查看到如下容器内的网络设备信息:

    1: lo: 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
    29: eth0@if30: 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 scope global eth0
           valid_lft forever preferred_lft forever
        inet6 fe80::42:acff:fe11:2/64 scope link
           valid_lft forever preferred_lft forever

    在容器内veth pair另一端被命名为eth0@if30,ip地址是172.17.0.2。

    在容器内ping主机IP和docker0 IP,看下结果:

     nsenter -t 4227 -n ping 172.17.0.1

    上述命令参数含义请参阅docker(Kubernetes)环境如何查看network namespace

    Docker的主机模式跟上述示例中的端口映射的效果一样,其他网络定制模式可以试验一下,底层还是在VXLAN、MacVlan的技术应用或者多种网络技术的组合。

  • 相关阅读:
    linux 环境下安装docker 以及docker-compose
    前端面试话术集锦第 14 篇:高频考点(React常考基础知识点)
    【TcaplusDB知识库】Tmonitor单机安装指引介绍(一)
    lmbench----lmbench性能测试工具迁移至openEuler操作系统实践
    数据中台开发流程
    c++ 11 多线程支持 条件变量 (condition_variable_any)(三)
    python+selenium实现UI自动化(入门篇)
    mysql not in 怎么优化
    TensorFlow Lite 是什么?用 TensorFlow Lite 来转换模型(附代码)
    Spring Security
  • 原文地址:https://blog.csdn.net/feng_zi0yhv/article/details/125975250