深入剖析Kubernetes之容器网络(一)

2023-11-11

单机容器网络

  • 一个 Network Namespace 的网络栈包括:网卡(Network Interface)、回环设备(Loopback Device)、路由表(Routing Table)和 iptables 规则。对于一个进程来说,这些要素,其实就构成了它发起和响应网络请求的基本环境。
  • 在大多数情况下,我们都希望容器进程能使用自己 Network Namespace 里的网络栈,即:拥有属于自己的 IP 地址和端口。

被隔离的容器进程,该如何跟其他 Network Namespace 里的容器进程进行交互呢?

  • 为了实现上述目的,Docker 项目会默认在宿主机上创建一个名叫 docker0 的网桥,凡是连接在 docker0 网桥上的容器,就可以通过它来进行通信。
  • 需要使用一种名叫Veth Pair的虚拟设备把这些容器“连接”到 docker0 网桥上。Veth Pair 设备的特点是:它被创建出来后,总是以两张虚拟网卡(Veth Peer)的形式成对出现的。并且,从其中一个“网卡”发出的数据包,可以直接出现在与它对应的另一张“网卡”上,哪怕这两个“网卡”在不同的 Network Namespace 里。这就使得 Veth Pair 常常被用作连接不同 Network Namespace 的“网线”。
  • 流程示意图,如下所示:
    在这里插入图片描述
  • 在默认情况下,被限制在 Network Namespace 里的容器进程,实际上是通过 Veth Pair 设备 + 宿主机网桥的方式,实现了跟同其他容器的数据交换。

  • 当在一台宿主机上,访问该宿主机上的容器的 IP 地址时,这个请求的数据包,也是先根据路由规则到达 docker0 网桥,然后被转发到对应的 Veth Pair 设备,最后出现在容器里。这个过程的示意图,如下所示:
    在这里插入图片描述
  • 当一个容器试图连接到另外一个宿主机时,比如:ping 10.168.0.3,它发出的请求数据包,首先经过 docker0 网桥出现在宿主机上。然后根据宿主机的路由表里的直连路由规则(10.168.0.0/24 via eth0)),对 10.168.0.3 的访问请求就会交给宿主机的 eth0 处理。接下来,这个数据包就会经宿主机的 eth0 网卡转发到宿主机网络上,最终到达 10.168.0.3 对应的宿主机上。当然,这个过程的实现要求这两台宿主机本身是连通的。这个过程的示意图,如下所示:
    在这里插入图片描述

当你遇到容器连不通“外网”的时候,应该先试试 docker0 网桥能不能 ping 通,然后查看一下跟 docker0 和 Veth Pair 设备相关的 iptables 规则是不是有异常,往往就能够找到问题的答案了。

容器跨主机网络

  • 在 Docker 的默认配置下,不同宿主机上的容器通过 IP 地址进行互相访问是根本做不到的。正是为了解决这个容器“跨主通信”的问题,才出现了那么多的容器网络方案。

  • 这些网络方案的工作原理到底是什么?要理解容器“跨主通信”的原理,就一定要先从 Flannel 这个项目说起。

    • Flannel 项目是 CoreOS 公司主推的容器网络方案。事实上,Flannel 项目本身只是一个框架,真正为我们提供容器网络功能的,是 Flannel 的后端实现。目前,Flannel 支持三种后端实现,分别是:
      • VXLAN;
      • host-gw;
      • UDP
    • 这三种不同的后端实现,正代表了三种容器跨主网络的主流实现方法。
  • 例子中,有两台宿主机。

    • 宿主机 Node 1 上有一个容器 container-1,它的 IP 地址是 100.96.1.2,对应的 docker0 网桥的地址是:100.96.1.1/24。
    • 宿主机 Node 2 上有一个容器 container-2,它的 IP 地址是 100.96.2.3,对应的 docker0 网桥的地址是:100.96.2.1/24。
  • 现在的任务,就是让 container-1 访问 container-2

Flannel UDP 模式的跨主通信的基本原理
在这里插入图片描述

  • Flannel UDP 模式提供的其实是一个三层的 Overlay 网络,即:它首先对发出端的 IP 包进行 UDP 封装,然后在接收端进行解封装拿到原始的 IP 包,进而把这个 IP 包转发给目标容器。这就好比,Flannel 在不同宿主机上的两个容器之间打通了一条“隧道”,使得这两个容器可以直接使用 IP 地址进行通信,而无需关心容器和宿主机的分布情况。

  • 相比于两台宿主机之间的直接通信,基于 Flannel UDP 模式的容器通信多了一个额外的步骤,即 flanneld 的处理过程。而这个过程,由于使用到了 flannel0 这个 TUN 设备,仅在发出 IP 包的过程中,就需要经过三次用户态与内核态之间的数据拷贝,如下所示:
    在这里插入图片描述

  • 第一次:用户态的容器进程发出的 IP 包经过 docker0 网桥进入内核态;

  • 第二次:IP 包根据路由表进入 TUN(flannel0)设备,从而回到用户态的 flanneld 进程;

  • 第三次:flanneld 进行 UDP 封包之后重新进入内核态,将 UDP 包通过宿主机的 eth0 发出去。

  • Flannel 进行 UDP 封装(Encapsulation)和解封装(Decapsulation)的过程,也都是在用户态完成的。在 Linux 操作系统中,上述这些上下文切换和用户态操作的代价其实是比较高的,这也正是造成 Flannel UDP 模式性能不好的主要原因。

在进行系统级编程的时候,有一个非常重要的优化原则,就是要减少用户态到内核态的切换次数,并且把核心的处理逻辑都放在内核态进行。

Flannel VXLAN 模式的跨主通信的基本原理

VXLAN,即 Virtual Extensible LAN(虚拟可扩展局域网),是 Linux 内核本身就支持的一种网络虚似化技术。所以说,VXLAN 可以完全在内核态实现上述封装和解封装的工作,从而通过与前面相似的“隧道”机制,构建出覆盖网络(Overlay Network)。

  • VXLAN 的覆盖网络的设计思想是:在现有的三层网络之上,“覆盖”一层虚拟的、由内核 VXLAN 模块负责维护的二层网络,使得连接在这个 VXLAN 二层网络上的“主机”(虚拟机或者容器都可以)之间,可以像在同一个局域网(LAN)里那样自由通信。当然,实际上,这些“主机”可能分布在不同的宿主机上,甚至是分布在不同的物理机房里。
  • 为了能够在二层网络上打通“隧道”,VXLAN 会在宿主机上设置一个特殊的网络设备作为“隧道”的两端。这个设备就叫作 VTEP,即:VXLAN Tunnel End Point(虚拟隧道端点)。
  • VTEP 设备的作用,其实跟 flanneld 进程非常相似。只不过,它进行封装和解封装的对象,是二层数据帧(Ethernet frame);而且这个工作的执行流程,全部是在内核里完成的(因为 VXLAN 本身就是 Linux 内核中的一个模块)。
  • 基于 VTEP 设备进行“隧道”通信的流程,如下所示:
    在这里插入图片描述
  • 图中每台宿主机上名叫 flannel.1 的设备,就是 VXLAN 所需的 VTEP 设备,它既有 IP 地址,也有 MAC 地址。

容器跨主机网络的两种实现方法:UDP 和 VXLAN。有一个共性,那就是用户的容器都连接在 docker0 网桥上。而网络插件则在宿主机上创建了一个特殊的设备(UDP 模式创建的是 TUN 设备,VXLAN 模式创建的则是 VTEP 设备),docker0 与这个设备之间,通过 IP 转发(路由表)进行协作。网络插件真正要做的事情,则是通过某种方法,把不同宿主机上的特殊设备连通,从而达到容器跨主机通信的目的。

Kubernetes网络模型与CNI网络插件

  • Kubernetes 通过一个叫作 CNI 的接口,维护了一个单独的网桥来代替 docker0。这个网桥的名字就叫作:CNI 网桥,它在宿主机上的设备名称默认是:cni0。CNI 网桥只是接管所有 CNI 插件负责的、即 Kubernetes 创建的容器(Pod)。
  • CNI 的设计思想,就是:Kubernetes 在启动 Infra 容器之后,就可以直接调用 CNI 网络插件,为这个 Infra 容器的 Network Namespace,配置符合预期的网络栈。
  • CNI 插件所需的基础可执行文件,可以在宿主机的 /opt/cni/bin 目录下看到,如下所示
ls -al /opt/cni/bin/

在这里插入图片描述

  • CNI 的基础可执行文件,按照功能可以分为三类:
    • 第一类,叫作 Main 插件,它是用来创建具体网络设备的二进制文件。比如,bridge(网桥设备)、ipvlan、loopback(lo 设备)、macvlan、ptp(Veth Pair 设备),以及 vlan。Flannel、Weave 等项目,都属于“网桥”类型的 CNI 插件。所以在具体的实现中,它们往往会调用 bridge 这个二进制文件。
    • 第二类,叫作 IPAM(IP Address Management)插件,它是负责分配 IP 地址的二进制文件。比如,dhcp,这个文件会向 DHCP 服务器发起请求;host-local,则会使用预先配置的 IP 地址段来进行分配。
    • 第三类,是由 CNI 社区维护的内置 CNI 插件。比如:flannel,就是专门为 Flannel 项目提供的 CNI 插件;tuning,是一个通过 sysctl 调整网络设备参数的二进制文件;portmap,是一个通过 iptables 配置端口映射的二进制文件;bandwidth,是一个使用 Token Bucket Filter (TBF) 来进行限流的二进制文件。

CNI 插件的工作原理

  • 当 kubelet 组件需要创建 Pod 的时候,它第一个创建的一定是 Infra 容器。所以在这一步,dockershim 就会先调用 Docker API 创建并启动 Infra 容器,紧接着执行一个叫作 SetUpPod 的方法。这个方法的作用就是:为 CNI 插件准备参数,然后调用 CNI 插件为 Infra 容器配置网络。
  • 这里要调用的 CNI 插件,就是 /opt/cni/bin/flannel;而调用它所需要的参数,分为两部分。
    • 第一部分,是由 dockershim 设置的一组 CNI 环境变量。其中,最重要的环境变量参数叫作:CNI_COMMAND。它的取值只有两种:ADD 和 DEL。这个 ADD 和 DEL 操作,就是 CNI 插件唯一需要实现的两个方法。其中 ADD 操作的含义是:把容器添加到 CNI 网络里;DEL 操作的含义则是:把容器从 CNI 网络里移除掉。而对于网桥类型的 CNI 插件来说,这两个操作意味着把容器以 Veth Pair 的方式“插”到 CNI 网桥上,或者从网桥上“拔”掉。
    • 第二部分,则是 dockershim 从 CNI 配置文件里加载到的、默认插件的配置信息。这个配置信息在 CNI 中被叫作 Network Configuration。dockershim 会把 Network Configuration 以 JSON 数据的格式,通过标准输入(stdin)的方式传递给 Flannel CNI 插件。

Kubernetes 网络模型

  • 所有容器都可以直接使用 IP 地址与其他容器通信,而无需使用 NAT。
  • 所有宿主机都可以直接使用 IP 地址与所有容器通信,而无需使用 NAT。反之亦然。
  • 容器自己“看到”的自己的 IP 地址,和别人(宿主机或者容器)看到的地址是完全一样的。

你知道的越多,你不知道的越多。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入剖析Kubernetes之容器网络(一) 的相关文章

随机推荐

  • 信息安全专业好不好?

    信息安全在我国起步比较晚 国外都已经很普遍了 所以如果现在学习信息安全还可以抓到一波红利 就像很多年前的JAVA一样 而且现在国家很重视安全 很多有利政策 总之安全这块还是可以尽早加入 有前途 初入计算机行业的人或者大学计算机相关专业毕业生
  • dc-7 靶机渗透学习

    信息收集 扫描当前网段 nmap sP 192 168 202 0 24 查看开启的端口服务 nmap A p v 192 168 202 146 访问靶机的80端口 通过Wappalyzer识别出是Drupal 8 先看一下靶机的说明 不
  • 生成6位随机数字字符串的方式

    生成6位随机数字字符串的方式 方法一 方法二 今天在工作中使用到了随机生成6位数字字符串的方式 方法一 一种比较low的使用方法 使用字符串进行拼接 循环6次 话不多说上代码 内联代码片 方法一 字符串拼接随机生成6位随机数 String
  • 联邦学习的过程

    联邦学习的过程分为自治和联合两部分 自治的部分 首先 两个或两个以上的的参与方们在各自终端安装初始化的模型 每个参与方拥有相同的模型 之后参与方们可以使用当地的数据训练模型 由于参与方们拥有不同的数据 最终终端所训练的模型也拥有不同的模型参
  • private static final long serialVersionUID = 1L 的作用

    1 这句话的意思是定义程序序列化ID 2 什么是序列化 Serializable Java的一个接口 用来完成java的序列化和反序列化操作的 任何类型只要实现了Serializable接口 就可以被保存到文件中 或者作为数据流通过网络发送
  • 小程序视频播放组件《video》

    今天花了不少时间实现了在同一个页面上实现多个视频播放的功能 显示在同一个页面 可以上下拉动 效果如下图显示 具体代码如下 video wxml
  • Spring Boot项目中集成Apollo

    要在Spring Boot项目中集成Apollo 你可以按照以下步骤进行操作 步骤1 添加Apollo依赖 在你的Spring Boot项目的pom xml文件中添加Apollo依赖
  • 基于SpringBoot的校园疫情防控系统设计与实现

    1 概述 校园疫情防控系统的开发运用java技术 springboot框架 MIS的总体思想 以及Mysql等技术的支持下共同完成了该系统的开发 实现了校园疫情防控管理的信息化 使用户体验到校园疫情防控管理 管理员管理操作将更加方便 实现目
  • K8S-5--云原生基础/k8s基础及组件/二进制部署k8s集群

    一 云原生基础 CNCF 云原生容器生态系统概要 http dockone io article 3006 13年 docker项目正式发布 14年 kubernetes项目正式发布 15年 Google Redhat微软牵头成立CNCF
  • Linux route详解

    route命令用于显示和操作IP路由表 要实现两个不同的子网之间的通信 需要一台连接两个网络的路由器 或者同时位于两个网络的网关来实现 在Linux系统中 设置路由通常是 为了解决以下问题 该Linux系统在一个局域网中 局域网中有一个网关
  • 当用户在浏览器上输入url后发生了什么

    进行DNS域名解析 进行tcp连接 发起三次握手 发送一个http请求 服务器处理相关的请求 并且返回对应的结果 关闭tcp连接 浏览器将浏览器处理后的结果进行解析 浏览器将解析后的资源进行请求 并且渲染页面
  • 【翻译】为什么你现在比以往更需要混沌工程?

    大约一年前 像餐馆和杂货店这样的实体店正争先恐后地设置送货和路边取货 他们中的很多人都在生产中使用混乱工程 在推出新功能和服务之前迅速寻找失败的原因 教育平台也是如此 在短短一周的时间里 从 好的 变成了 绝对必要 企业混沌工程平台 Gre
  • Android UI设计 屏幕底部的菜单栏 动画切换Activity

    最终效果如下图 点击菜单会切换Activity 有动画效果 从早上起床就研究这个东西 因为之前一直都直接用系统提供的几个控件 从来没搞过图片背景 嵌套布局什么的 今天是第一次 没什么经验 花了一个上午才搞定 简单介绍一下思路 使用Linea
  • std::enable_shared_from_this的原理及意义

    原文 https www cnblogs com lehoho p 9372195 html 和 https www jianshu com p 4444923d79bd enable shared from this是一个模板类 定义于头
  • 【实战练习】汽油辛烷值优化建模(二)(问题一的详细讲解)

    1 问题回顾 问题1为数据处理 需参考近4年的工业数据 见附件一 325个数据样本数据 xlsx 的预处理结果 依 样本确定方法 附件二 对285号和313号数据样本进行预处理 原始数据见附件三 285号和313号样本原始数据 xlsx 并
  • Python3学习笔记(一) 基本数据类型(1)

    首先 Python3的变量不需要声明 曾经说的C语言的变量需要提前声明的好处现在也不是什么好处了 但是变量必须被赋值 赋值之后变量才会被创建 变量没有类型 直接写出来她的名字 里面装的什么内容 就好了 自然而然她就会有一个数据类型 由这里面
  • Java创建多线程的五种写法

    目录 一 lambda表达式 强烈推荐 最简单 基础格式 举例 运行结果 二 继承 Thread 重写 run 基础格式 举例 运行结果 三 实现 Runnable 重写 run 基础格式 举例 运行结果 四 使用匿名内部类 继承 Thre
  • 【华为OD机试python】不开心的小朋友【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 游乐场里增加了一批摇摇车 非常受小朋友欢迎 但是每辆摇摇车同时只能有一个小朋友使用 如果没有空余的摇摇车 需要排队等候 或者直接离开 最后没有玩上的小朋友会非常不开心
  • C++实验03(03)组合类:Triangle类与Point类

    题目描述 定义一个平面坐标系下的点类Point 有整型数据成员x y坐标值 成员函数包括 1 带默认值的构造函数 默认值均为0 2 拷贝构造函数 3 置x y坐标值 4 取x y的坐标值 参数为两个整型量的引用 分别用于获取x y坐标值 5
  • 深入剖析Kubernetes之容器网络(一)

    文章目录 单机容器网络 容器跨主机网络 Kubernetes网络模型与CNI网络插件 单机容器网络 一个 Network Namespace 的网络栈包括 网卡 Network Interface 回环设备 Loopback Device