Docker网络虚拟化

一、Docker网络虚拟化原理

Docker 的网络实现其实就是利用了 Linux 上的网络命名空间和虚拟网络设备(特别是 veth pair).

首先,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包;此外,如果不同子网之间要进行通信,需要路由机制。

Docker 中的网络接口默认都是虚拟的接口。虚拟接口的优势之一是转发效率较高。 Linux 通过在内核中进行数据复制来实现虚拟接口之间的数据转发,发送接口的发送缓存中的数据包被直接复制到接收接口的接收缓存中。对于本地系统和容器内系统看来就像是一个正常的以太网卡,只是它不需要真正同外部网络设备通信,速度要快很多。

Docker 容器网络就利用了这项技术。它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做 veth pair)。

netns 是在 linux 中提供网络虚拟化的一个项目,使用 netns 网络空间虚拟化可以在本地虚拟化出多个网络环境,目前 netns 在 lxc 容器中被用来为容器提供网络。
使用 netns 创建的网络空间独立于当前系统的网络空间,其中的网络设备以及 iptables 规则等都是独立的,就好像进入了另外一个网络一样。

Docker 创建一个容器的时候,会执行如下操作:
  • 创建一对虚拟接口,分别放到本地主机和新容器中;
  • 本地主机一端桥接到默认的 docker0 或指定网桥上,并具有一个唯一的名字,如 veth0;
  • 容器一端放到新容器中,并修改名字作为 eth0,这个接口只在容器的命名空间可见;
  • 从网桥可用地址段中获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡 veth0。

完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。

通过 –net 参数来指定容器的网络配置,有4个可选值:
  • –net=bridge 这个是默认值,连接到默认的网桥。
  • –net=host 告诉 Docker 不要将容器网络放到隔离的命名空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其它 root 进程一样可以打开低范围的端口,可以访问本地网络服务比如 D-bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。因此使用这个选项的时候要非常小心。如果进一步的使用 –privileged=true,容器会被允许直接配置主机的网络堆栈。
  • –net=container:NAME_or_ID 让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过 lo 环回接口通信。
  • –net=none 让 Docker 将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自己进行配置。

二、网络虚拟化部署

1、启动一个 /bin/bash 容器,指定 –net=none 参数
[root@foundation51 ~]# docker run -it --name vm1 --net none ubuntu

Docker网络虚拟化_第1张图片
在这里插入图片描述

2、在本地主机查找容器的进程 id,并为它创建网络命名空间。
[root@foundation51 ~]# docker inspect vm1 | grep Pid
            "Pid": 5597,                 ##Pid为5597
            "PidMode": "",
            "PidsLimit": 0,
[root@foundation51 ~]# ln -s /proc/5597/ns/net /var/run/netns/5597
3、创建一对 “veth pair” 接口 veth0 和 veth1,绑定 veth0 到网桥 docker0,并启用它
[root@foundation51 ~]# ip link add name veth0 type veth peer name veth1
[root@foundation51 ~]# brctl addif docker0 veth0    ##绑定 veth0 到网桥 docker0
[root@foundation51 ~]# ip link set up dev veth0  
  • 创建接口veth0 和 veth1
    在这里插入图片描述

  • 绑定 veth0 到网桥 docker0
    Docker网络虚拟化_第2张图片

  • 开启veth0接口
    在这里插入图片描述

4、将veth1放到容器的网络命名空间,命名为 eth0,启动它并配置一个可用 IP(桥接网段)和默认网关。
[root@foundation51 ~]# ip link set veth1 netns 5597   #将veth1加到namespace “5597” 
[root@foundation51 ~]# ip netns exec 5597 ip link set veth1 name eth0
[root@foundation51 ~]# ip netns exec 5597 ip link set up dev eth0
[root@foundation51 ~]# ip netns exec 5597 ip addr add 172.17.0.51/24 dev eth0
[root@foundation51 ~]# ip netns exec 5597 ip route add default via 172.17.0.1
  • 开启端口前,eth0端口为DOWN
    Docker网络虚拟化_第3张图片
  • 开启端口后,eth0端口为UP
    Docker网络虚拟化_第4张图片
  • 配置ip
    在这里插入图片描述
  • 配置网关
    在这里插入图片描述
以上,就是 Docker 配置网络的具体过程。

当容器结束后,Docker 会清空容器,容器内的 eth0 会随网络命名空间一起被清除,veth0 接口也被自动从 docker0 卸载。

此外,用户可以使用 ip netns exec 命令来在指定网络命名空间中进行配置,从而配置容器内的网络。

你可能感兴趣的:(Linux)