下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

聊聊 Ulti-Network Ns 在Underlay下的应用:本手篇

作者:匿名     来源: 互联网点击数:740发布时间: 2022-06-08 21:32:50

标签: HostnameNetwork容器

  对容器而言,multiple namespace 这个技术的重要性怎么强调都不过分。因为 namespace 的出现,使得容器所用到的诸如 Hostname、Network、Mount Points 等资源被隔离起来,由公用变成独享。

  大家好,我是二哥。

  对容器而言,multiple namespace 这个技术的重要性怎么强调都不过分。因为 namespace 的出现,使得容器所用到的诸如 Hostname、Network、Mount Points 等资源被隔离起来,由公用变成独享。

  技术的进步是一把双刃剑,基于 multi namespace 的容器在几乎重塑了云计算市场的形态和云计算机基础设施栈的同时,也给我们带来了陡峭的学习曲线。

  Network namespace 就是这样一个例子。

  今年全国新高考 Ⅰ 卷的作文题看了吧?“本手、妙手、俗手”是围棋的三个术语。本手是指合乎棋理的正规下法;妙手是指出人意料的精妙下法;俗手是指貌似合理,而从全局看通常会受损的下法。对于初学者而言,应该从本手开始,本手的功夫扎实了,棋力才会提高。一些初学者热衷于追求妙手,而忽视更为常用的本手。本手是基础,妙手是创造。一般来说,对本手理解深刻,才可能出现妙手;否则,难免下出俗手,水平也不易提升。

  来吧,这篇让我们从“本手”开始。下篇我们看“妙手”部分:将本文所聊内容稍作变形看看 multi network namespace 在 Underlay 下面是如何玩的。

  multi network namespace

  我们先就着下图来看看 multi network namespace 的典型使用方式。后文统一将 network namespace 写成 network ns 。

  这是一个包含 multi network ns 的环境。分为三大部分:最上层为 OS ,中间是一个网卡(物理的或者虚拟的),最下面是网卡所连接的外部(物理)网络。

  OS 部分包含了 root network ns 以及被 Pod 使用的其它 network ns 。

  OS 部分还包含了 eth 和 bridge 这样的网络设备(struct net_device)。虽然图中不同的 network ns 中的 eth 都叫 eth0 ,但 root network ns 中的 eth0 和其它网络设备有着本质的区别:

  root network ns 中的 eth0 是对网卡的软件抽象,也就是说它对应的是一个外部设备,如果这个网卡是物理的话,eth0 还包含控制该设备的一系列函数。

  而图中其它的 eth0 和 bridge 都是对根本不存在的虚拟网络设备的抽象,说白了它们就只是一些不会与外部设备打交道的数据结构,这些数据结构存在的意义是为了可以最大程度上复用现有的代码逻辑和功能。它们可以作为媒介用来在同一个 OS 内进行进程间通信、用户态和内核态数据交换,但无法被用于外部通信。比如我们熟知的 loopback 设备,通过它可以使本机上两个进程间的 socket 通信完整地走完 TCP/IP 协议栈。

  network namespace

  我们说 network ns 用来隔离包括网卡(Network Interface)、回环设备(Loopback Device)、网络栈、IP 地址、端口等等在内的网络资源。它的特点是由可配置的数据组成。对于一个进程来说,这些要素,其实就构成了它发起和响应网络请求的基本环境。这里所谓“网络栈(Networking stack)”,包括了:路由表(Routing Table), network filter,iptables 规则等。

  无论是一个 Linux 容器还是宿主机的进程所能看见的“网络栈”,实际上是被隔离在它们各自的 network ns 当中的,通信双方的网卡(如典型的 veth pair )也自然被隔离到相应的 namespace 中。

  另外还有一个栈也会被经常提起:TCP/IP 协议栈。我们可以将 TCP/IP 协议栈看成是程序的代码部分,而网络栈看成是程序的数据部分。很显然 TCP/IP 栈应该是被这个 OS 上所有人共享的,无论是进程还是容器,甚至是基于 qemu-kvm 的虚拟机都共享着宿主机的协议栈,但网络栈却是各个 network ns 独享的。

  二哥知道,上面的描述还是太抽象。所以我画了下面一张图。图 2 把内核中负责描述进程的数据结构 task_struct 和 network ns 之间的结构关系画出来了。进程 1 和进程 2 共享宿主机 root network ns,它包含网卡 eth0 。Pod 内的容器自然位于 Pod 自己的 network ns 中。但容器本质上也是进程而已,虽然在图中看起来 Pod 隔离了一个完全属于自己的 eth1,但在内核看来,一样也是用相同的数据结构来描述它和 network ns 之间的关系。

  看完这个数据结构示意图,对于 TCP/IP 协议栈而言,希望下面两点描述没有让你感到困惑:

  网络包无论是从容器内的网卡流出,还是离开容器后再与其它网络设备打交道,必然都会经过内核 TCP/IP 协议栈。

  无论网络包是属于容器的还是属于宿主机 native process 的,对于内核 TCP/IP 协议栈而言,这些网络包只是属于不同的 network ns 而已。

  网络设备

  你一定看到了图 1 的 OS 部分包含网络设备 eth0 和 bridge。

  其中 eth0 用来描述物理网卡,它在内核中用数据结构 net_device 来表示。一个 net_device 里面都包含些什么呢?我将其中一些重要的部分画在了图 3 里面。简单来说就是包含了用来操作这个物理网卡的 netdev_ops (如 set _mac / ioctl 之类),与 BSP 相关的诸如总线地址、IRQ等设置,与具体网卡型号相关的收/发环形队列,还有 IP 地址设置等等。

  因为 eth0 是属于一个 network ns 的,这就意味着如果有多个 network ns ,就可能会出现多个 eth0(如果都重命名为 eth0 的话)。

  bridge 又名网桥,是一个虚拟的二层交互机。用它来搭配虚拟网络设备 veth / tap 可以模拟物理交换机以及插入其上的 RJ-45 网络插头。

  在图 4 所示的这个环境里,一个网桥可以组成一个简单子局域网,插在网桥上的设备之间可以如物理局域网络那样相互通过二层交流。这样的交流不需要离开 bridge ,这通常发生在位于同一个 Work Node 上面的不同 Pod 之间相互通信的场景。

  而如果网络包的目的 MAC 地址为网桥本身,并且网桥设置了 IP 地址的话,那么 bridge 就认为该网络包应该是发往创建该网桥的那台主机,于是这个数据包将不会转发到任何设备,而是直接交给上层(三层)协议栈去处理。处理的过程会涉及到基于本机路由表的路由查询。

  上述过程可以结合图 5 来理解。例如当 Pod 想要访问百度的时候,请求就会沿着图中红色的线流动。如果我们将红线看成一个管道的话,那么 Pod 的请求从管道一端流入。而管道的流出端接进了宿主机协议栈的 IP 层。在这里经过 iptables 和路由表的处理后,最终通过宿主机的 eth0 离开这台机器。

  这种情况下,如果我说宿主机的 eth0 可以看成 bridge 的 gateway,你同意吗?

  如果你对这个细节感兴趣的话,可以阅读《当从Pod访问百度时会用到VTEP吗》。

  让我们把图 5 再放大一些。把图 5 中 network ns 里的路由表、 iptables 、eth0 、bridge 拎出来看看。看看当 bridge 处理 Pod 访问百度的请求时,是如何把流量先送进 root network ns 又是如何以宿主机为 gateway 将流量送至外部网络的。

  来源: 二哥聊云原生

    >>>>>>点击进入计算专题

赞(12)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程