简介flannel v0.11.0 的 Linux ARM64 预编译安装包面向需要在 ARM64 架构 Linux 环境如树莓派、鲲鹏服务器中部署 Kubernetes 集群、配置容器网络插件的运维与开发人员。该版本为 Pod 间通信提供稳定的 Overlay 网络支持可解决 ARM 设备上 flannel 安装包获取困难、手动交叉编译繁琐等问题。压缩包共 3 个文件核心为可直接执行的 flanneld 主程序并配有 Markdown 格式的使用说明和 Shell 辅助脚本用于快速生成 Docker 启动参数并接入集群整体包仅 8.03MB轻量紧凑适合内网分发与离线部署。已有 454 人学习下载适用于边缘计算、ARM 服务器及 K8s 教学实验等场景。通过该资源可免去源码编译与环境适配步骤配合说明文档即可完成 flannel 网络插件的基础配置并能基于预编译二进制进一步排查 Overlay 网络连通性与路由发布问题提升 ARM 环境下集群网络排障效率。1. 离线装 k8s最容易卡死的不是镜像而是这个 flannel 包某次在 ARM64 机器上搭一个内部模拟项目 X 的生产环境kubeadm 初始化一切正常等到部署完第一个 DeploymentPod 显示 Running可跨节点访问怎么都超时。排查了半天最后发现是 flannel 这个 CNI 插件的镜像和二进制架构不匹配x86 的包推到 ARM 节点上kube-flannel 的 Pod 直接 CrashLoopBackOff网络自然一塌糊涂。从那时起我养成了一个习惯凡是做 ARM 集群离线交付先锁定 flannel 的版本和架构别等集群建完再回头补课。flannel-v0.11.0-linux-arm64.tar.gz 这个压缩包就是给离线部署 k8s 集群准备的网络插件资源它包含了 flanneld 二进制、基础配置文件manifest以及配套镜像导入材料。适合谁适合需要在 ARM64 服务器上装 Kubernetes、又没法直接访问外网镜像仓库的从业者。用它之前先搞明白一件事flannel 在 k8s 里到底扮演什么角色以及 v0.11.0-arm64 这个组合意味着什么。2. flannel 为什么在 ARM64 节点上特殊先拆包再谈安装2.1 先看懂 k8s 网络模型里 flannel 的位置Kubernetes 的 Pod 网络是扁平化虚拟网络每个 Pod 需要拿到一个集群内唯一的 IP且任意两个节点上的 Pod 要能直接通信。这个任务由 CNI 插件负责flannel 是其中最常见的一种实现。它不接管 Service 的负载均衡只解决一件事容器运行时创建 Sandbox 时把 Pod 接入到一个跨节点的虚拟二层网络里。flannel 的机制不复杂核心是三个部分etcd或 k8s API里存放网段分配信息每台节点上的 flanneld 进程负责把本节点的容器网段注册进去再把本节点流量通过某种 Backend通常是 VXLAN 或 host-gw 封装转发到对端节点。所谓 v0.11.0是 flannel 在某个阶段的稳定版本支持 k8s 1.14 及更早版本的控制面交互方式依赖 etcd v3 API 和 kube-subnet-mgr。简单说这个版本追不上如今最新的 k8s 版本但对老版本集群、离线内网环境而言稳定性和踩坑资料的丰富度反而是它的优势。关键点在架构v0.11.0 时代官方发布的 flanneld 二进制是按 CPU 架构分别编译的amd64 和 arm64 各自有独立的产物。镜像 tag 上也可能带 amd64 / arm64 后缀。如果下载了 x86 的 flannel 镜像或二进制塞到 ARM64 节点上在 Kubelet 层会出现exec format error要是镜像能启动运行时也会因为架构指令集不兼容而直接崩溃。这也是我把这个压缩包单独保存一份的原因离线环境里没有第二次下载的机会架构错一次整套流程全卡住。2.2 拿到 tar.gz 后先做这几步核对下载完成后我一般不会直接用先解压看内容确认三条信息可执行文件架构、镜像文件格式、manifest 版本匹配。mkdir /opt/flannel-offline tar -xzf flannel-v0.11.0-linux-arm64.tar.gz -C /opt/flannel-offline cd /opt/flannel-offline file flanneldfile flanneld输出里会出现ARM aarch64字样这就确认了二进制能在目标节点上跑。如果输出是x86-64说明包拿错了。tar.gz 里通常还会有一个flanneld-image目录里面是 docker 镜像的归档文件可能是flanneld-arm64.tar或者flanneld:v0.11.0-arm64.tar。这个文件后续要导入到节点的容器镜像仓库或 containerd 里不能直接docker load就算结束还得核对 tag。cat kube-flannel.yml | grep -E image|NETWORK|Backend | head -n 20这一步是为了确认 manifest 里引用镜像名称和后面导入的镜像 tag 保持一致。很多人在这一行栽跟头镜像文件导入时 tag 带arm64后缀但 manifest 默认写的是flanneld:v0.11.0-amd64结果是本地镜像仓库里根本没有这个 tagKubelet 拉取时直接报ErrImagePull。参数说明grep -E这里过滤的是image:字段和net-conf.json里的关键配置。看到Network: 10.244.0.0/16是正常的这是 flannel 默认的 Pod 网段如果你的业务网段已经被占用后续要改的话需要在kube-flannel.yml里同步修改而不是只改某一个文件。3. 离线安装 flannel从镜像导入到跨节点 Pod 连通三步走3.1 把 flannel 镜像导入到目标节点的容器运行时离线环境里没有公网镜像仓库最常见的做法是把镜像归档文件手动导入到每个节点的本地存储。以 containerd 为主的节点用ctr命令导入以 docker 为主的节点用docker load。这个包对应的是 flanneld 镜像归档文件名可能是flanneld-arm64-v0.11.0.tar导入时要注意命名空间。# 适用于 containerd 运行时命名空间是 k8s.io sudo ctr -n k8s.io images import flanneld-arm64-v0.11.0.tar # 查看导入结果 sudo ctr -n k8s.io images list | grep flannel对于使用 docker 运行的节点则执行docker load -i flanneld-arm64-v0.11.0.tar docker images | grep flannel这里有一个容易错的地方ctr -n k8s.io images import导入的镜像 tag取决于归档文件里保存的 tag。如果导入后显示 tag 是v0.11.0-arm64而你的 manifest 里写的是v0.11.0需要手动打一个 tag 让两者对齐sudo ctr -n k8s.io images tag docker.io/flannel/flanneld:v0.11.0-arm64 docker.io/flannel/flanneld:v0.11.0参数说明-n k8s.io是指定命名空间containerd 在 Kubernetes 场景下默认使用k8s.io这个命名空间如果你用的是crictl pull则不需要指定命名空间。这里 tag 对齐是个关键动作不做的话 Kubelet 调用 CRI 拉镜像时会提示找不到 tag。3.2 修正 manifest 中的架构与调度参数并部署flannel 的 DaemonSet manifest 在老版本里经常直接写死kubernetes.io/os: linux和kubernetes.io/arch: amd64。ARM64 节点上顺手改掉否则调度器会跳过这些节点flannel Pod 根本不会创建。# kube-flannel.yml 中的 DaemonSet spec 片段 spec: template: spec: nodeSelector: beta.kubernetes.io/arch: arm64 # 旧版本写法 # 或者使用新版本写法: # kubernetes.io/os: linux # kubernetes.io/arch: arm64修改完成后执行kubectl apply -f kube-flannel.yml再用下面的命令确认 Pod 状态和日志kubectl get pods -n kube-system -o wide | grep flannel kubectl logs -n kube-system -l appflannel -f日志里出现Subnet set as 10.244.x.0/24说明 flanneld 注册本节点网段成功。这一步的成功标志不只是 Pod Running而是容器日志告诉我们网段已经拿到。3.3 跨节点网络连通性验证Pod Running 不代表网络通了。我习惯按三层来验证先看 flannel.1 虚拟网卡是否创建再看本节点到对端节点的容器网段路由最后启动两个测试 Pod 互相 ping。# 节点上确认虚拟网卡 ip addr show flannel.1 # 看路由表里是否出现了对端节点的 Pod 网段 ip route | grep 10.244 # 创建两个测试 Pod分别调度到两个节点然后 ping 对端 Pod IP kubectl run probing-a --imagebusybox:1.28 --restartNever -- sleep 3600注意点路由表里出现的应该是10.244.x.0/24 dev flannel.1这样的条目。如果你看到的是dev eth0且下一跳是某个节点 IP说明 flannel 走的是 host-gw 模式这种模式下跨二层网络就会失效需要回看后端模式配置。VXLAN 模式依赖 UDP 端口 8472如果节点间防火墙或者安全组没放行这个端口VXLAN 封装报文会被丢弃路由表看着正常但 ping 就是不回包。这个场景我遇到过不止一次排障时第一反应先查 UDP 端口别先怀疑 flannel。4. 避坑镜像拉取失败、VXLAN 不通、老版本与新版 k8s 的兼容性坑 1安装后 kube-flannel Pod 一直 ImagePullBackOff现象kubectl get pods -n kube-system显示ImagePullBackOffkubectl describe pod里报ErrImagePull提示无法拉取quay.io/coreos/flannel:v0.11.0-amd64。原因manifest 里写死了v0.11.0-amd64的镜像 tag而你导入到 containerd / docker 里的镜像是v0.11.0-arm64tag 不匹配导致 Kubelet 在本地找不到镜像转而尝试从远程仓库拉取内网环境又没有远程仓库权限。解决把已导入的镜像打成 manifest 里引用的一致 tag。常见做法是执行ctr -n k8s.io images tag对齐 tag或者直接修改kube-flannel.yml里的 image 字段把amd64改成arm64再重新 apply。两种做法我倾向后者因为让 manifest 与实物版本一致后续交接时不会有歧义。坑 2Pod 间 ping 通但跨节点 TCP 连接卡顿现象从节点 A 的 Pod ping 节点 B 的 Pod能通但用curl访问一个端口始终超时或极慢。查路由表和 ARP 都正常。原因VXLAN 模式下flannel.1 网卡要响应 ARP 请求并建立 FDB 表项。如果节点上运行了多条虚拟网卡或者开启了反向路径过滤rp_filter回包路由会走错网卡TCP 三次握手能完成但数据包传输路径异常。这类问题有一个明显特征UDP 8472 端口有大量丢弃包计数。解决先检查net.ipv4.conf.all.rp_filter和net.ipv4.conf.flannel.1.rp_filter改成 0 或 2再检查/proc/net/vxlan是合理的。我一般把 rp_filter 改成 2这是比较稳妥的宽松模式仍校验但允许不对称路由。改完后sysctl -p生效观察 TCP 连接是否恢复。还不行的话检查节点上是否有 iptables FORWARD 链的 DROP 规则很多安全基线脚本会默认丢弃跨网卡转发流量需要显式放行-o flannel.1和-i flannel.1的流量。坑 3节点重启后 Pod 网络恢复慢甚至要手工重启 flannel现象节点维护重启后节点上所有 Pod 都起来了但新建 Pod 拿不到 IP等待几分钟后 flannel 才恢复正常。原因这是 flannel v0.11.0 与较新 kubelet 之间一个老生常谈的兼容问题。节点启动过程中Kubelet 比 flanneld 先启动Kubelet 想创建 Pod 网络命名空间时CNI 插件要调用 flanneld 提供的子网信息但 flanneld 此时还没完成与 API Server 的通信。此外部分系统上 flannel 的 systemd unit 没有设置Aftercontainerd.service或者没有等待网络就绪。解决把 flanneld 的开机自启顺序调到最后。用 systemd 管理的节点我通常在/etc/systemd/system/flanneld.service里加一行Afternetwork-online.target containerd.service然后执行systemctl enable flanneld.service。同时调整 Kubelet 的--node-ip参数避免节点多网卡情况下 Kubelet 绑定到错误 IP导致 flannel 注册到 API Server 的节点 IP 和实际网卡 IP 不一致。坑 4把容器网段 10.244.0.0/16 和宿主网段配置冲突现象安装 flannel 后宿主机上原本正常的服务无法访问ip route显示流量被劫持到 flannel.1 网卡。原因很多私有云的宿主机网段正好落在 10.0.0.0/8 或 172.16.0.0/12 大段里flannel 默认网段 10.244.0.0/16 可能与宿主机的某个子系统网段重叠。容器网络的路由优先级高于普通路由表导致宿主机访问自身 IP 的流量被打进 flannel 隧道。解决安装前必须先规划好 Pod 网段和节点物理网络确认没有交集。修改方式是在kube-flannel.yml的net-conf.json里把Network改成172.20.0.0/16或其他空闲大段同时要检查 kube-controller-manager 的--cluster-cidr参数两处必须指向相同网段否则 Kubelet 会拒绝为 Pod 分配 IP日志里会报failed to allocate node IP。这也是我反复强调的一个原则flannel 的网络配置不是改一处就生效的涉及 kubeadm 初始化参数、controller-manager 的 cluster-cidr、CNI 配置三个地方。5. 进阶用这个包当模板在 ARM64 上自行构建 flannel 并加固网段配置如果你需要把这个资源套用到稍新一些的 k8s 版本上或者想彻底摆脱对预编译二进制的依赖可以从 flannel 的源码仓库取 v0.11.0 对应 tag在 ARM64 设备上自行构建 flanneld。这是验证这个包是否值得长期保留的好办法也是内网环境最稳妥的兜底方案。# 在 ARM64 构建机上操作 git clone https://github.com/flannel-io/flannel.git cd flannel git checkout v0.11.0 make dist ls dist/构建完成后把生成的flanneld二进制替换掉 tar 包里的对应文件再重新制作镜像归档。这样你就得到一个完全由自己环境产出的 flannel 运行包不依赖任何第三方预编译产物。make dist本质上会调用 go build 并带上对应架构的环境变量如果你要手动构建命令等价于GOARCHarm64 go build -o flanneld .输出的二进制可以用file flanneld再次确认架构。网段加固方面我在生产环境里会把 flannel 的net-conf.json调整为独立网段并且把 Backend 类型从默认的 VXLAN 改为host-gw条件是两个节点处于同一二层网络。host-gw 模式下没有 VXLAN 封装的开销性能更高适合内网物理机直连的拓扑但跨 VLAN 场景必须切回 VXLAN 或者改用其他 CNI。# kube-flannel.yml 中的 ConfigMap 片段示例 net-conf.json: | { Network: 172.20.0.0/16, Backend: { Type: host-gw } }参数说明Network字段决定 flannel 网段分配的上界Backend.Type是数据面封装方式。每个节点根据这个网段划分出/24子网所以集群规模超过 256 个节点时/16网段不够用要开成/12或者更大。这也是另一个容易被忽视的容量规划点Pod 网段的大小其实决定了集群最多能容纳多少节点。从那以后我每次拿到一个 flannel 离线包都会强制走一遍固定动作先file确认架构再解包看 manifest 里引用的镜像 tag然后核对节点容器运行时是 docker 还是 containerd最后才执行导入和 apply。这个流程看着死板但它几乎避免了所有能想到的低级事故——架构错、tag 错、网段冲突全在这一步被拦住。希望帮到你。本文还有配套的精品资源点击获取