k8s网络插件之Flannel

news2025/7/19 20:09:40

Flannel简介

Flannel官网:https://github.com/coreos/flannel

Flannel是由CoreOS开源的针对k8s的网络服务,其目的是为解决k8s集群中各主机上Pod之间的通信问题,其借助etcd维护网络IP地址分配,并为每个Node节点分配一个不同的IP地址段。

Flannel在每个节点运行一个名为flanneld的二进制代理程序,它负责从预留的网络中按照指定或者默认的掩码长度为当前节点申请分配一个子网,并将网络配置、已分配的子网和辅助数据(比如主机的公网IP等)存储在Kubernetes API或独立的etcd中。Flannel通过不同的后端来实现跨节点Pod间的通信,目前支持的后端如下:

  • vxlan:使用Linux内核中的封装隧道报文,以Overlay模型支持跨节点的Pod通信,同时该后端支持直接路由模式,在该模式下,位于同一二层网络中的节点上的Pod间通信可通过路由模式直接发送,而跨二层网络的节点之上的Pod间通信仍要使用VXLAN隧道协议转发;因而VXLAN隶属于Overlay网络模型,或者混合网络模型。vxlan模型中,flanneld监听udp 8472端口接受和发送封装的数据包
  • host-gw:类似于VXLAN后端的直接路由模式,但不支持跨二层网络的节点,因此这种模式要求各节点处于同一个二层网络中,不太适用于规模较大的环境,但转发性能较好
  • udp:使用常规UDP报文封装完成隧道转发,性能比vxlan和host-gw相比较差,仅在不支持vxlan和host-gw时使用;UDP后端模式中,flanneld监听UDP 8285端口发送报文

Flannel配置文件

Flannel官方的部署文件默认使用vxlan后端,相关配置定义在kube-flannel名称空间下configmap/kube-flannel-cfg资源对象中,内容如下:

  net-conf.json: |
    {
      "Network": "10.244.0.0/16",	
      "Backend": {		
        "Type": "vxlan"
      }
    }

如上所示,其配置是json格式,常用的键有如下几个:

  • Network:Flannel全局使用的子网,即pod cidr的值
  • SubnetLen:子网分割的长度,在全局子网掩码小于24时(例如16),默认为24
  • SubnetMin:分配给节点使用的起始子网,默认为切割完成后的第一个子网
  • SubnetMax:分给给节点使用的最大子网,默认为切割完成后的最后一个子网
  • Backend:Flannel使用的后端,以及后端的配置

另外,flannel还会在运行的节点上生成一个环境变量文件,默认是/run/flannel/subnet.env,其包含本节点使用的子网、mtu等信息。例如下面的示例:

root@master-01:~# cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.244.0.0/16	#flannel全局网段
FLANNEL_SUBNET=10.244.0.1/24	#本节点子网
FLANNEL_MTU=1450	#容器接口mtu值
FLANNEL_IPMASQ=true	#地址映射

VXLAN后端

在vxlan后端下,flannel会在每个节点创建一个flannel.1的接口做为本节点的隧道出入口的VTEP设备,其中的1表示VNI,因此所有节点上的VTEP均属于同一个大二层域,它们依赖二层网关进行通信。Flannel采用分布式网关模型,它把每个节点都视为到达该节点pod子网的二层网关,相应的路由信息由flanneld自动生成。

Flannel需要在每个节点运行一个flanneld进程,它会基于网络配置获取适用于当前节点的子网租约,还要根据其他节点的子网生成路由信息,以正确的路由数据报文。官方提供的部署文件中,flanneld以Daemonset方式在每个节点运行。

Pod通信流程分析

在这里插入图片描述

如上图所示,两个Pod的通信流程大致如下:

  1. 在client Pod上向nginx Pod发起请求,因为它们不在同一网段,所以报文会根据默认路由到达cni0,此时
    src-ip:10.224.1.9(client-pod) dst-ip:10.224.2.5(nginx-pod)
    src-mac:86:8c:53:15:25:d4(client-pod) dst-mac:86:8c:53:15:25:d4(cni0)

在cni0上抓包如下:
在这里插入图片描述

  1. cni0发现目的地址并非本机Pod地址,自己不能转发。然后会匹配主机路由,发现到达10.244.2.0/24需要通过flannel.1,将报文转给flannel.1
  2. flannel.1收到报文后会将其封装为vxlan报文内层的数据帧,此时
    src-ip:10.224.1.9(client-pod) dst-ip:10.224.2.5(nginx-pod)
    src-mac:d6:60:8c:f3:ba:37(node-01 flannel.1) dst-mac:4a:4a:ee:b9:cb:2d(node-02 flannel.1)

flannel.1上抓包如下:
在这里插入图片描述

  1. 最后数据包通过内核vxlan模块封装成vxlan报文,然后通过节点网卡ens33发往node-02,此时
    inner-src-ip:10.224.1.9(client-pod ) inner-dst-ip:10.224.2.5(nginx-pod)
    inner-src-mac:d6:60:8c:f3:ba:37(node-01 flannel.1) inner-dst-mac:4a:4a:ee:b9:cb:2d(node-02 flannel.1)
    outer-src-ip:192.168.211.11(node-01 ens33) outer-dst-ip:192.168.211.12(node-02 ens33)
    outer-src-mac:00:0c:29:51:81:05(node-01 ens33) outer-dst-mac:00:0c:29:99:52:7b192.168.211.12(node-02 ens33)

在ens33上抓包如下图所示:
在这里插入图片描述

在上面的抓取VXLAN报文中,外层报文目标地址是node-02的ens33接口的地址,但是本地节点上并没有任何路由信息帮助指向目标节点,由flanneld生成的路由中仅指明了到达隧道出口时flannel.1接口的IP地址,那么外层报文的目标地址是如何获取的呢?

  1. node-02收到报文后进行vxlan解封装,然后再按照相反的顺序转发到nginx-pod

此时还存在两个问题:

  • node-01 的flannel.1是如何知道node-02的flannel.1的地址来进行报文封装的呢?通过ARP?

错,Flannel并不依赖ARP进行MAC地址学习,而是由节点上的flanneld进程动态生成相应的解析记录。例如下面的解析记录是在node-01节点上查询的,它们分别指明了集群上其它节点flannel.1接口的MAC地址,PERMANENT表示永久有效
在这里插入图片描述

  • 在node-01 的ens33接口抓取VXLAN报文中,外层报文目标地址是node-02的ens33接口的地址,但是本地节点上并没有任何路由信息帮助指向目标节点,由flanneld生成的路由中仅指明了到达隧道出口时flannel.1接口的IP地址,那么外层报文的目标地址是如何获取的呢?

事实上Flannel把flannel.1接口也作为网桥设备使用,该设备上附加了一个同样由flanneld维护的称为FDB的转发数据库,FDB指定了到达目标节点flannel.1接口需要经由的下一跳IP,该IP是目标Pod所在节点的某接口的IP(在上面的报文中是node-02的ens33接口IP),即VXLAN外部报文的目标IP。

例如下图的转发条目是在node-01上查询的,这些条目分别指定了到达集群中其它节点flannel.1接口时需要经由的下一跳IP地址。
在这里插入图片描述

直接路由模式

VXLAN后端支持DirectRouting模式,即在集群的各节点上添加必要的路由信息,让Pod间的报文通过节点的二层网络直接传送。如下图所示,只有通信双方Pod所在节点不在同一个二层网络时才启用传统的VXLAN隧道方式转发流量。假如k8s集群的节点都位于同一个二层网络中,DirectRouting模式下的Pod通信基本接近于直接使用二层网络。即使节点分布在不同的网络中,合理使用也可以节省一部分隧道开销。
在这里插入图片描述

修改kube-flannel名称空间下configmap/kube-flannel-cfg资源,为VXLAN后端添加Directrouting: true键值对就可以开启DirectRouting模式。如下图:
在这里插入图片描述

修改完成后可以逐个删除之前的flannel Pod以触发更新。更新完成后节点上的路由规则也会发生相应的变动,到达与本节点同一二层网络的其它节点,Pod子网的下一跳地址会由对端flannel1.1接口的地址变为宿主机的物理接口地址,本地用于发出报文的接口也从flannel.1变为本地物理接口。
以node-01为例,启用Directrouting模式后,节点上的路由变成如下图,
在这里插入图片描述
此时,node-01上的Pod访问node-02上的Pod就不需要通过VXLAN封装报文了,直接通过路由即可实现。例如下面抓取的报文所示:
在这里插入图片描述

但是显然,这种模式无法满足跨二层网络节点上Pod的通信需求,因为到达Pod子网的下一跳地址无法指向另一个二层网络中的节点地址。所以节点上依然保留flannel.1接口用于跨二层网络节点上Pod的通信需求。

host-gw后端

host-gw后端通过添加路由信息,使用节点上的二层网络直接发送Pod间的通信报文,其工作方式类似于VXLAN后端的DirectRouting模式,但不具备DirectRouting模式中VXLAN隧道转发能力,这意味着host-gw后端下所有节点必须位于同一个二层网络中。host-gw后端工作模型示意图如下:
在这里插入图片描述

同样,直接修改kube-flannel名称空间下configmap/kube-flannel-cf资源对象,将Backend.Type的值修改为host-gw,然后重建Pod即可启用host-gw后端,如下所示:
在这里插入图片描述

配置完成后,各节点上就会生成类似于VXLAN后端直接路由模式的路由规则,以转发Pod的通信报文,它完全省去了隧道转发的额外开销,所以也不在需要flannel.1接口。但是,如果节点处于不同的二层网络,host-gw后端就无法实现Pod间的通信。因此,相对来说,VXLAN的DirectRouting模式兼具VXLAN后端和host-gw后端的优势,既能保证传输性能,又可以跨二层网络转发Pod报文。

此外,Flannel并不支持为Pod网络添加网络策略以控制Pod间通信的能力,它只能借助额外的支持网络策略的插件实现此功能,Canal网络插件就是为此目的而设立的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/37869.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学生HTML个人网页作业作品 HTML+CSS校园环保(大学生环保网页设计与实现)

🎀 精彩专栏推荐👇🏻👇🏻👇🏻 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业…

redis : 持久化

redis通过将数据放在内存里实现高速访问,为了防止意外情况,其数据也可以存放起来 持久化的实现方式有两种方案:一种是直接保存当前已经存储的数据,相当于复制内存中的数据到硬盘上,需要恢复数据时直接读取即可&#x…

代理模式与动态代理深入理解

一,代理模式的简单认识 1.参与者: 代理对象,被代理对象 代理对象相当于现实生活中的房产中介,被代理对象 相当于 房东 2.目的:保护被代理对象 避免外界直接修改被代理对象,破坏掉被代理对象原本的功能。…

KubeGems容器云平台体验

KubeGems容器云平台体验 KubeGems 是一款开源的企业级多租户容器云平台。围绕云原生社区,KubeGems 提供了多 Kubernetes 集群接入能力,并具备丰富的组件管理和资源成本分析功能,能够帮助企业快速的构建和打造一个本地化、功能强大且低成本的…

关于BigInteger和BigDecimal

BigInteger BigInteger类是用于解决整形类型(含基本数据类型及对应的包装类,)无法表示特别大的数字及运算的问题,即使是占用字节数最多的整形long,能表示的范围也是有限的.理论上,你可以使用BigInteger表示任意整数基于java8中BigInteger的构造方法. BigDecimal的构造方法2 …

Java代码审计基础——RMI原理和反序列化利用链

目录 (一)何为RMI (二)、 RMI的模式与交互过程 0x01 设计模式 0x02 交互过程 0x03 Stub和Skeleton (三)简单的 RMI Demo 1、Server 2、Registry 3、Client 补充——动态类加载机制 几个函数 (…

Java集合框架详解(四)——Map接口、HashMap类、LinkedHashMap类

一、Map接口 Map接口的特点: (1)映射键值对的形式(key和value); (2)Map集合中,key是不能重复的,value是可以重复的; (3)…

解决报错:fatal: Authentication failed for ‘https://github.com/*/*.git/‘

目录 问题 解决 步骤一、 步骤二、 步骤三、 ​步骤四、 ​步骤五、 步骤六、 问题 今天创建一个 github 新仓库,首次上传本地代码时,遇到了一个报错。但是,之前这样操作肯定是没有问题的,毕竟我可以保证用户名和密码都是…

复杂环境下多移动机器人路径规划研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法 …

数据结构 | 顺序栈与链式队【栈与队列的交际舞】

数据结构之栈与队列🌳顺序栈🍃前言🔥栈的结构简介及概述🔥为什么要用顺序栈?🔥结构声明🍃接口算法实现🍞初始化栈🍞销毁栈🍞入栈🍞出栈&#x1f3…

磨金石教育|干货分享:剪辑技法之跳切(上)

有一种剪辑手法划分了传统剪辑与现代剪辑的界限,它就是“跳切”; 跳切,是“切”的一种。属于一种无技巧的剪辑手法。它打破常规状态镜头切换时所遵循的时空和动作连续性要求,以较大幅度的跳跃式镜头组接,突出某些必要内…

【kafka】三、kafka命令行操作

kafka命令行操作 kafka的相关操作命令脚本文件在bin目录下 查看所有的topic kafka-topics.sh --zookeeper hll1:2181 --list 或 kafka-topics.sh --zookeeper 192.168.171.132:2181 --listkafka-topics.sh:topic执行脚本 --zookeeper hll1:2181:需要的…

[carla]把carla世界坐标系 转换为 俯视地图像素坐标系

在下面这篇参考博客中介绍了如何手动获取从carla世界坐标系到俯视地图像素坐标系的旋转平移矩阵.我也是采用了一样的思路和代码,这里把实现的过程以及最后所有地图的变换矩阵记录如下. 参考博客:carla真实世界坐标系与全局俯视地图像素坐标系变换 文章目录代码:1.carla世界坐标…

【表白】html表白代码

目录一.引言二.表白效果展示1.惊喜表白2.烟花表白3.玫瑰花表白4.心形表白5.心加文字6.炫酷的特效一.引言 我们可以用一下好看的网页来表白,下面就有我觉得很有趣的表白代码 下载整套表白文件 二.表白效果展示 1.惊喜表白 2.烟花表白 源码:新建一个文本文…

基于51单片机的温度控制系统数码管显示蜂鸣器报警proteus仿真原理图PCB

功能: 0.本系统采用STC89C52作为单片机 1.系统实时监测并显示当前温度,并通过四位数码管显示 2.超过设定阈值,蜂鸣器将报警,同时控制相应继电器实现降温或者加热 3.系统具备三个功能按键,可更改温度上限和下限 4.采用D…

SpringBoot+Mybatis-Plus+Thymeleaf 实现增删改查+登录/注册

SQL -- student_info create table if not exists student_info ( sid int not null auto_increment comment 学生表主键 primary key, sname varchar(20) not null comment 学生账号登录名、姓名, pwd varchar(32) not null comment 密码, sex varchar(20) not null comment …

AQS源码解析 7.共享模式_CyclicBarrier重复屏障

AQS源码解析 —共享模式_CyclicBarrier重复屏障 简介 CyclicBarrier:循环屏障、循环栅栏,用来进行线程协作,等待线程满足某个计数。构造时设置『计数个数』,每个线程执行到某个需要“同步”的时刻调用 await() 方法进行等待&…

【多目标进化优化】多目标进化群体的分布性

0 前言 \quad\quad进化算法是模拟生物自然进化的人工方法,与大自然生态环境一样,进化的物种也需要平衡发展。因此,设计者必须制定合适的生存规则来维持种群的多样性和分布性。在多目标进化算法中,对于某些问题,Pareto最…

微机-------可编程并行接口8255A

目录 8255A的内部结构8255A控制信息和传输动作的对应关系⭐8255A的控制字一、方式选择控制字①方式0(基本输入输出工作方式)二、端口C置1/置0控制字8255A的工作方式②方式1(选通的输入输出工作方式)③方式2(双向传输方式)⭐⭐8255的编程及应用8255A的内部结构 ①数据总线…

Steam项目推进(二)—— 在项目中使用FairyGUI

一、遇到的问题 昨天把代码大致清理了一遍之后,发现代码中存在很大的一个问题是数据和表现耦合在一起了,如下: using UnityEngine; using UnityEngine.UI;public enum CardStateType {InDeck, InHand, InBattle, InSave, InAbandon }//卡牌…