实战:Flannel为网络CNI底座的K8S接入Cilium CNI

首发实战:Flannel为网络CNI底座的K8S接入Cilium CNI

背景

又想使用Flannel网络,还想用NetworkPolicy功能,给出的要求也没办法啊调研看看应该怎么实现吧,网络搜索基本没有参考的内容,写出这篇用于记录如何对接适配,同需求也可进行参考。

在以 Flannel 为基础 CNI 的 Kubernetes 集群中接入 Cilium,核心是利用CNI 链式调用(CNI Chaining) 技术,让 Cilium 在保留 Flannel 网络基础能力(如 IP 分配、底层连通性)的同时,叠加其高级功能(如 eBPF 网络策略、可观测性、L7/HTTP 策略等)。这种配置不替换 Flannel 的核心网络功能,而是通过 "链式" 协作实现功能增强。

注:此为typora导入,格式和部分内容可能不美观但流程正确

核心技术原理

Kubernetes 的 CNI 规范支持多插件链式调用 :即一个主 CNI 插件(如 Flannel)负责基础网络配置(IP 分配、Pod 网络接口创建),后续插件(如 Cilium)在其基础上追加功能(如策略 enforcement、流量监控)。

在 Flannel+Cilium 的组合中:

  • Flannel 仍作为 "底座",负责 Pod 的 IP 地址分配(IPAM)、跨节点 Overlay 网络(如 VXLAN)或 Underlay 网络(如 host-gw)的连通性。
  • Cilium 作为 "增强插件",通过 eBPF 技术在内核层拦截 Pod 流量,实现网络策略、流量可视化、负载均衡等高级功能,且不干扰 Flannel 的基础网络逻辑。

在网络上没有寻找到对应的教程,只能自己摸索结合Cilium的官方文档AI辅助以及其他资料多次联调测验解决其中各自坑,最终完成此需求并编写文档流程。

K8S及组件版本准备

以下所使用的版本都是已经查询后完成兼容性问题版本,过程中不会遇见各种因为不支持遇见的坑

K8S安装这里不做说明直接略过,以纯净的K8S为例,部署了K8S的v1.23.6版本

shell 复制代码
kubectl version --short

安装完成后,没有CNI组件K8S集群是没有准备好的异常状态,CoreDNS组件也是启动失败,基础环境就在此情况下进行。

Flannel版本

Cilium版本

Helm版本

Flannel安装

这里的安装采用K8S中文社区中的Flannel地址

下载地址:https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

需要更改Pod的IP地址段或者网络类型可以wget下来之后编辑修改,如果不用的话可以直接kubectl apply

shell 复制代码
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

flannel会创建个kube-flannel命名空间存放组件,查看Flannel是否安装完成

shell 复制代码
kubectl  get pod -n kube-flannel

删除coredns重新查看状态是否正常

shell 复制代码
kubectl  delete  pod  coredns-6d8c4cb4d-rpzcw   coredns-6d8c4cb4d-5kgv9     -n kube-system
kubectl  get pod -n kube-system

查看K8S现在的节点状态确保正常

shell 复制代码
kubectl  get nodes

测验网络环境就省略了,自己测试确保Flannel组件正常即可

更改Flannel的网络模式

Cilium 依赖 eBPF 在 Linux 内核层直接处理网络流量(如策略 enforcement、负载均衡等)。

当 Flannel 使用 vxlan 时,数据包会被 VXLAN 封装,导致 Cilium 的 eBPF 程序无法直接解析原始数据包的内容(如源 / 目的 IP、端口等),从而无法正常工作(例如网络策略失效、流量跟踪异常)。

不将模式改成host-gw模式,coredns组件将会启动失败无法正常工作Pod无法互通失去网络组件功能。

1. 技术冲突的核心:VXLAN 封装与 eBPF 数据路径的矛盾

Cilium 的核心优势依赖于 eBPF 技术在 Linux 内核层直接处理网络流量,实现细粒度的网络策略、流量可视化、负载均衡等功能。这要求 Cilium 能够直接解析原始数据包的内容(如源 / 目的 IP、端口、协议等)。

而 Flannel 的 vxlan 模式会对数据包进行VXLAN 隧道封装(在原始数据包外层添加 VXLAN 头部),导致:

  • Cilium 的 eBPF 程序无法直接读取原始数据包的信息,无法执行网络策略、流量跟踪等操作。
  • 封装后的数据包会绕过 Cilium 的 eBPF 数据路径,导致功能失效(例如策略不生效、 Hubble 监控无数据)。
2. host-gw 模式为何兼容?

Flannel 的 host-gw 模式基于主机路由表转发流量,不进行任何隧道封装,数据包保持原始格式。这种模式下:

  • 数据包直接通过物理网络层(L2/L3)转发,Cilium 的 eBPF 程序可以正常解析原始流量。
  • Cilium 能够在数据包经过主机时拦截并处理,确保网络策略、监控等功能正常工作。
3. 操作步骤

将Flannel的网络模式改成host-gw,如果是把文件下载了就直接改yaml

shell 复制代码
kubectl  edit  cm  kube-flannel-cfg -n kube-flannel

更改完成后一定要进行重启操作,先重启Flannel

shell 复制代码
# 重启 Flannel DaemonSet
kubectl rollout restart daemonset/kube-flannel-ds -n kube-flannel

# 验证重启结果
kubectl get pods -n kube-flannel | grep flannel

接着重启coredns

shell 复制代码
# 重启 CoreDNS Deployment(会滚动重启 Pod)
kubectl rollout restart deployment/coredns -n kube-system

# 验证验证验证重启结果
kubectl get pods -n kube-system | grep coredns

Cilium适配接入当前K8S环境

因为是使用Helm进行部署,需要先把Helm工具下载

下载地址:https://get.helm.sh/helm-v3.18.2-linux-amd64.tar.gz

shell 复制代码
wget https://get.helm.sh/helm-v3.18.2-linux-amd64.tar.gz
mv  linux-amd64/helm  /usr/local/bin/
helm version

简化更改配置以及简单部署的最佳方式是使用Helm,这里Cilium的部署就以Helm包的方式进行。

下载地址:https://github.com/cilium/cilium/archive/refs/tags/v1.15.0.tar.gz

shell 复制代码
wget https://github.com/cilium/cilium/archive/refs/tags/v1.15.0.tar.gz
tar xf v1.15.0.tar.gz 

解压之后,实际我们用到的配置文件的路径在这里

shell 复制代码
ls cilium-1.15.0/install/kubernetes/cilium/

为了精细化配置以及确保配置内容无异常,这里通过修改values.yaml文件方式部署启动。

0. 完整修改项汇总

列举部分要配置的参数以供参考,后面有全部要修改的配置内容以及步骤

配置路径 修改后值 核心作用 与 Flannel 的关联
cni.chainingMode "flannel" 启用 Cilium 与 Flannel 的链式集成 Cilium 作为上层插件工作,复用 Flannel 构建的底层网络(如 Pod 网段、跨节点隧道)
cni.exclusive false 不独占 CNI 配置目录 保留 Flannel 的 CNI 配置文件(如 10-flannel.conflist),避免被 Cilium 覆盖
tunnel false 禁用 Cilium 自身的隧道功能 避免与 Flannel 的 VXLAN 隧道冲突(双重隧道会导致流量异常)
routingMode "native" 使用原生路由模式 依赖 Flannel 已配置的节点路由,Cilium 仅优化转发路径,不创建独立隧道
ipam.mode "kubernetes" 禁用 Cilium 的 IP 地址管理 由 Flannel 负责 Pod IP 分配,Cilium 不再生成独立的 IP 池
ipv4NativeRoutingCIDR "10.244.0.0/16" 声明与 Flannel 一致的 Pod CIDR 确保 Cilium 识别 Flannel 管理的网段,避免地址冲突
kubeProxyReplacement "false" 禁用 Cilium 对 kube-proxy 的替换 保留 kube-proxy 处理 Service 转发,与 Flannel 依赖的 Service 逻辑兼容
autoDirectNodeRoutes false 禁用 Cilium 自动生成节点路由 节点间路由由 Flannel 管理,避免 Cilium 生成的路由覆盖 Flannel 规则

1. CNI 链式部署配置(关键)

需明确启用 Cilium 与 Flannel 的链式集成,确保 Cilium 在 Flannel 基础上工作而非替换它。

yaml 复制代码
cni:
  # 启用CNI配置安装(必须为true,否则Cilium无法注入链式配置)
  install: true
  # 禁用Cilium对CNI目录的独占,避免覆盖Flannel配置
  exclusive: false
  # 指定链式模式为Flannel(Cilium将作为Flannel的上层补充)
  chainingMode: "flannel"
  # 链式目标自动关联Flannel(无需手动指定,chainingMode=flannel时默认生效)
  chainingTarget: ~

2. 路由与隧道模式配置(避免冲突)

Flannel 通常使用 VXLAN 隧道,需禁用 Cilium 的隧道功能,改用原生路由模式,避免网络叠加冲突。

yaml 复制代码
# 手动添加配置禁用自身隧道,避免Cilium开启影响 Flannel 功能
tunnel: false
# 手动添加配置,允许CiliumC添加补充路由,不影响 Flannel 功能
hostRouting: true
# 路由模式:使用原生路由(依赖Flannel的底层网络)
routingMode: "native"
# 隧道协议:配置Cilium的隧道为空(避免与Flannel冲突)
tunnelProtocol: ""
# 禁用Cilium的自动节点路由(由Flannel管理节点间路由)
autoDirectNodeRoutes: false

3. IPAM 配置(交由 Flannel 管理)

Flannel 已负责 Pod IP 分配,需禁用 Cilium 的 IPAM 功能,避免 IP 管理冲突。

yaml 复制代码
ipam:
  # IPAM模式:设为"kubernetes",不使用Cilium的IP地址管理(由Flannel负责)
  mode: "kubernetes"
  # CIDR地址会读取kubernetes的配置,以防万一可以配置上或者清空
  clusterPoolIPv4PodCIDRList: ["10.244.0.0/16"]

4.配置Flannel的CIDR(CIDR声明)

CIDR需将其设置为 Flannel 使用的 Pod CIDR (即 Flannel 为集群分配的 Pod 网段)。

Flannel 默认 Pod CIDR 通常为 10.244.0.0/16,但需根据你的集群实际配置调整(可通过 kubectl get cm kube-flannel-cfg -n kube-flannel -oyaml 查看 Flannel 的 net-conf.json 确认)。

yaml 复制代码
# 配置为Flannel的Pod CIDR(示例为默认值,需根据实际情况调整)
ipv4NativeRoutingCIDR: "10.244.0.0/16"

ipMasqAgent:
  enabled: false  # 禁用ip-masq-agent

5. Kube-proxy 兼容配置

Flannel 依赖 kube-proxy 实现 Service 代理,需禁用 Cilium 的 kube-proxy 替换功能。

yaml 复制代码
# 禁用Cilium的kube-proxy替换(保持kube-proxy运行)
kubeProxyReplacement: "false"

6.其他建议配置

1. 禁用冲突的网络功能

Cilium 的部分网络功能可能与 Flannel 冲突,需按需禁用:

yaml 复制代码
# 禁用Cilium的负载均衡加速(由kube-proxy和Flannel处理)
loadBalancer:
  acceleration: "disabled"

# 禁用Cilium的BGP功能(Flannel不依赖BGP)
bgp:
  enabled: false
bgpControlPlane:
  enabled: false

# 禁用网络加密(如需加密可单独配置,但需避免与Flannel冲突)
encryption:
  enabled: false
2. 资源与调度配置(可选)

根据集群规模调整 Cilium 的资源限制,确保与 Flannel 共存时资源充足:

yaml 复制代码
agent:
  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: 1000m
      memory: 1Gi

operator:
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      cpu: 500m
      memory: 512Mi
3. K8S的api地址(可选)

不写的话也会通过服务发现找到,但为了更加精准识别可以加上,以防其他问题出现。

yaml 复制代码
# K8S的apiserver IP地址
k8sServiceHost: ""
# K8S的服务端口
k8sServicePort: ""

7.部署Cilium

Helm部署命令

shell 复制代码
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --version 1.15.0 \
  --namespace kube-system \
  -f values.yaml

Helm更新命令

shell 复制代码
helm upgrade cilium cilium/cilium --version 1.15.0 \
  --namespace kube-system \
  -f values.yaml

更新后要重启Cilium组件

shell 复制代码
# 重启 Cilium DaemonSet
kubectl rollout restart daemonset/cilium -n kube-system

# 验证重启结果(确保所有 Pod 状态为 Running)
kubectl get pods -n kube-system | grep cilium

Heml删除命令

shell 复制代码
helm uninstall cilium -n kube-system

这里执行下安装命令

复制代码
helm install cilium cilium/cilium --version 1.15.0  -namespace kube-system -f values.yaml

完成之后查看Cilium是否启动成功

shell 复制代码
kubectl  get pod -n kube-system

Cilium和coredns组件都为Running状态,这样就部署完成了。

查看Cilium的各项配置是否正常,其中不能出现 routing-mode: tunnel,会造成配置冲突导致coredns启动失败

shell 复制代码
kubectl -n kube-system get cm cilium-config -o yaml

重启网络CNI组件日志检查

Flannel重启

shell 复制代码
kubectl rollout restart daemonset/kube-flannel-ds -n kube-flannel
kubectl get pods -n kube-flannel | grep flannel
kubectl  logs -f kube-flannel-ds-kbqf7  -n kube-flannel

Flannel日志输出关键项解读

  1. 核心配置与模式确认
  • 后端模式Found network config - Backend type: host-gw
    明确显示 Flannel 使用host-gw模式(基于主机路由转发,无隧道封装),符合与 Cilium 兼容的要求(此前提到 vxlan 模式会冲突)。
  • 子网管理Starting kube subnet manager
    Flannel 使用 Kubernetes 子网管理器,从节点的n.Spec.PodCIDRs中获取并管理子网:10.244.0.0/2410.244.1.0/2410.244.2.0/24,这是集群内 Pod 的 IP 网段。
  1. 网络接口与 IP 配置
  • 节点网络接口Using interface with name ens33 and address 192.168.2.13
    Flannel 自动检测到主机的默认网络接口为ens33,绑定的物理 IP 为192.168.2.13(作为节点间通信的网关地址)。
  • 节点标注验证flannel.alpha.coreos.com/backend-type: "host-gw"
    节点k8s-node2的 annotations 确认了后端模式为host-gw,且公网 IP(实际为物理机 IP)为192.168.2.13,与接口配置一致。
  1. 路由规则配置
  • 子网路由添加
    • Subnet added: 10.244.0.0/24 via 192.168.2.11
    • Subnet added: 10.244.1.0/24 via 192.168.2.12
      Flannel 为集群内其他节点的 Pod 子网添加路由规则,通过对应节点的物理 IP(192.168.2.11192.168.2.12)转发流量。
  • 路由存在性检查Route to ... already exists, skipping.
    已存在的路由规则不会重复添加,避免冲突,确保路由表简洁。
  1. 网络规则与清理
  • iptables 模式启动Starting flannel in iptables mode...
    Flannel 使用 iptables 配置网络规则(如转发策略),并将默认FORWARD链策略设为ACCEPT,确保 Pod 间流量可正常转发。
  • 规则清理Cleaning-up nftables rules...
    启动时清理旧的 nftables 规则,避免残留规则干扰当前配置。
  1. 非关键警告
  • no subnet found for key: FLANNEL_IPV6_NETWORK
    提示未配置 IPv6 子网,属于正常现象(若集群仅使用 IPv4,可忽略此警告)。

总结

Flannel 以host-gw模式正常运行,成功加载子网配置、添加节点间路由,并完成 iptables 规则初始化,与 Cilium 的兼容性基础已满足。日志中无错误信息,所有核心功能(子网管理、路由转发、网络规则)均正常启动。

cilium重启

shell 复制代码
kubectl rollout restart daemonset/cilium -n kube-system
kubectl get pods -n kube-system | grep cilium
kubectl logs -f cilium-operator-774958bf7f-gftc9   -n kube-system

测验NetworkPolicy功能

Flannel是没有NetworkPolicy功能的,这里测验正好来确认Cilium的功能是否正常

创建两个命名空间

shell 复制代码
kubectl create ns ns-a
kubectl create ns ns-b

跑个nginx用于测验

nginx-a

shell 复制代码
[root@k8smaster network]# cat ns-a-deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-a
  namespace: ns-a
spec:
  selector:
    matchLabels:
      app: nginx-a
  template:
    metadata:
      labels:
        app: nginx-a
    spec:
      containers:
      - name: nginx-a
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.14.2
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-a
  namespace: ns-a
spec:
  selector:
    app: nginx-a
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

两个命名空间都创建个测试Pod用于访问

netshoot-a

yaml 复制代码
[root@k8smaster network]# cat netshoot-a.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: netshoot-a
  namespace: ns-a
spec:
  selector:
    matchLabels:
      app: netshoot-a
  replicas: 1
  template:
    metadata:
      labels:
        app: netshoot-a
    spec:
      containers:
      - name: pod1
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nicolaka/netshoot:v0.13
        imagePullPolicy: IfNotPresent
        command: ["sleep", "3600"] # 容器启动后保持运行状态

netshoot-b

yaml 复制代码
[root@k8smaster network]# cat netshoot-b.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: netshoot-b
  namespace: ns-b
spec:
  selector:
    matchLabels:
      app: netshoot-b
  replicas: 1
  template:
    metadata:
      labels:
        app: netshoot-b
    spec:
      containers:
      - name: pod1
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nicolaka/netshoot:v0.13
        imagePullPolicy: IfNotPresent
        command: ["sleep", "3600"] # 容器启动后保持运行状态

tshoot-b

yaml 复制代码
[root@k8smaster network]# cat netshoot-b.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: netshoot-b
  namespace: ns-b
spec:
  selector:
    matchLabels:
      app: netshoot-b
  replicas: 1
  template:
    metadata:
      labels:
        app: netshoot-b
    spec:
      containers:
      - name: pod1
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nicolaka/netshoot:v0.13
        imagePullPolicy: IfNotPresent
        command: ["sleep", "3600"] # 容器启动后保持运行状态
相关推荐
LDG_AGI6 小时前
【推荐系统】深度学习训练框架(二):深入剖析Spark Cluster模式下DDP网络配置解析
大数据·网络·人工智能·深度学习·算法·机器学习·spark
华普微HOPERF11 小时前
Matter协议,如何塑造更宜居、流畅的智能家居网络?
服务器·网络·智能家居
せいしゅん青春之我15 小时前
【JavaEE初阶】TCP核心机制3——连接管理
网络·网络协议·tcp/ip·java-ee
KubeSphere 云原生15 小时前
云原生周刊:在 Kubernetes 上运行机器学习
云原生·容器·kubernetes
码界奇点15 小时前
通往Docker之路从单机到容器编排的架构演进全景
docker·容器·架构
阿Y加油吧16 小时前
Docker从入门到实战——含容器部署、docker基础、项目部署
运维·docker·容器
victory043117 小时前
progen2 docker镜像打包命令文档
运维·docker·容器
clear sky .17 小时前
ETH, Lwip,Tcp之间关系
服务器·网络·tcp/ip
我叫汪枫17 小时前
《从点击到响应:HTTP 请求是如何传出去的》
网络·网络协议·http