Docker 网络理论基础
要了解docker网络,先了解如下基础概念。
Network Namespace
简介
Namespace连接案例
通过手工方式创建两个 Network Namespace,并最终让它们相互连通,即可以通过 ping 命令测试成功。通过案例更好地去理解 Docker 网络的底层原理。
前置条件:在虚拟机中准备好linux环境。
创建两个命名空间
分别创建两个命名空间netns(Network Namespace) ns1 与 ns2,查看是否创建成功
ip netns add ns1
ip netns add ns2
ip netns list
因为每个网络空间都是独立的,所以每个 Network Namespace 都具有一个回环网络适配器 lo。查看刚刚创建的两个netns的ip信息。
ip netns exec ns1 ip addr
ip netns exec ns2 ip addr
创建网络接口 veth pair
如果要让两个命名空间连通,则需要用到虚拟设备接口技术 veth pair。该技术需要一对网络接口分别置于两个命名空间中。
以下命令用于创建一对网络接口 veth-ns1 与 veth-ns2。
ip link add veth-ns1 type veth peer name veth-ns2
此时通过 ip link 查看当前的网络地址情况,可以看到新增了两个相互连通的 veth pair,它们都具有 MAC 地址,但它们的状态都是 DOWN,且都不具有 IP。
命名空间分配网络接口
通过 ip link set 命令,将这两个网络接口分别分配给两个命名空间。
ip link set veth-ns1 netns ns1
ip link set veth-ns2 netns ns2
此时分别在两个命名空间中执行 ip link 命令,可以查看到,它们中分别新增了前面指定的一个网络接口。
此时再在主机中查看 ip link,发现原来的那两个网络接口已经消失了。
为网络接口分配 IP
前面创建的两个网络接口是没有 IP 的。下面要通过 ip netns exec 命令,为每个指定的命名空间执行 IP 添加命令 ip addr add [ip] dev [网络接口]。
ip netns exec ns1 ip addr add 192.168.1.1/24 dev veth-ns1
ip netns exec ns2 ip addr add 192.168.1.2/24 dev veth-ns2
分别查看两个ns的ip信息。
ip netns exec ns1 ip addr
ip netns exec ns2 ip addr
启动接口
上图可以看到两个接口虽然分配了IP,但是状态依旧是DOWN。下面要通过 ip link set dev [接口] up 来启动指定的网络接口。
[root@localhost ~]# ip netns exec ns1 ip link set dev veth-ns1 up
[root@localhost ~]# ip netns exec ns2 ip link set dev veth-ns2 up
再查看两接口的状态,已经变为了 UP。
测试ping
ip netns exec ns1 ping 192.168.1.2
ip netns exec ns2 ping 192.168.1.1
总结
通过上述内容,应该可以更好的理解Network Namespace。个人认为可以理解从网络上讲,一个Network Namespace就是一个独立主机。
CNM
Docker 网络架构由三个主要部分构成:CNM、Libnetwork 与 Driver。
CNM,Container Network Model,容器网络模型,其是一种网络连接的解决方案,是一种设计规范、设计标准,其规定了 Docker 网络的基础组成要素。
CNM 中定义了三个基本要素:沙盒 Sandbox,终端 Endpoint 与网络 Network。
- 沙盒:一个独立的网络栈,其中包括以太网接口、端口号、路由表、DNS 配置等。Linux Network Namespace 是沙盒的标准实现。
- 终端:虚拟网络接口,主要负责创建连接,即将沙盒连接到网络上。一个终端只能接入某一个网络。
- 网络:802.1d 网桥的软件实现,是需要交互的终端的集合。
Libnetwork
CNM 是设计规范,而 Libnetwork 是开源的、由 Go 语言编写的、跨平台的 CNM 的标准实现。
Libnetwork 除了实现了 CNM 的三个组件,还实现了本地服务发现、容器负载均衡,以及网络控制层与管理层功能。
Driver
每种不同的网络类型都有对应的不同的底层 Driver,这些 Driver 负责在主机上真正实现需要的网络功能,例如创建 veth pair 设备等。
不过,无论哪种网络类型,其工作方式都是类似的。通过调用 Docker 引擎的 API 发出请求,然后由 Libnetwork 做出框架性的处理,然后将请求转发给相应的 Driver。
通过 docker network ls 命令可以查看当前主机所连接的网络及网络类型。
可以看到docker中有如下driver: