简介:针对ARM64架构Linux服务器上部署Kubernetes集群的运维与开发人员,这份flannel网络插件安装包提供了v0.11.0版本的离线二进制。flannel是K8s中广泛使用的Overlay网络方案,可解决多节点容器间通信与Pod网段划分问题,适合树莓派、国产化服务器等ARM环境快速集成。压缩包内共有3个文件:flanneld主程序、说明文档和Shell环境准备脚本,整体大小约8.03MB。主程序负责实际的数据面转发,脚本用于生成Docker所需网络变量,说明文档收录配置要点,结构虽小但功能完整。目前已有453人学习下载,对需要在ARM设备上快速搭建容器网络的读者来说,省去自行编译步骤,拿来即可使用。借助这份包体,可跳过源码编译的繁琐流程,直接完成flannel的部署与基础调通,为集群网络环境提供稳定起点。对于需要离线部署的ARM集群,可直接归档复用。
1. flannel-v0.11.0-linux-arm64.tar.gz:给 ARM64 节点打通 Pod 网络的那个包
一台 ARM64 服务器加入 Kubernetes 集群后,kubectl get nodes 一直显示 NotReady,coredns 的 Pod 也起不来——这不是节点坏了,而是集群里缺了一个负责 Pod 网络的组件。flannel-v0.11.0-linux-arm64.tar.gz 就是 Flannel 网络插件 v0.11.0 版本针对 ARM64 架构发布的预编译二进制包,解决跨节点 Pod 互通的 Overlay 网络问题。如果你正在维护跑在 ARM 芯片上的集群、边缘节点或离线环境,手里有这个包就意味着不需要现场编译、不需要联网拉代码,解压后直接部署 flanneld 就能把网络面撑起来。这篇文章把这包里的东西拆开,讲清楚怎么装、参数怎么配、出问题怎么看。
2. 拆开这个 tar.gz:v0.11.0 的组件结构与 ARM64 单独发版的原因
2.1 这个压缩包里装的是什么
flannel 的发布方式在不同版本里变过几次。到了 v0.11.0 这个阶段,官方对每个目标平台直接给出 tar.gz 包,里面主要就是编译好的 flanneld 主程序,外加一份说明性质的文档。和源码包不同,这个包不需要你本地装 Go 工具链、不需要交叉编译、也不需要先拉一堆依赖,适合生产节点直接展开使用。
解压后的核心文件是 flanneld 这个可执行二进制。它运行在集群的每个节点上,职责可以拆成四块:
- 从存储里读取整个集群的网络配置(子网段、后端类型、MTU 等)
- 给当前节点从配置的网段里分配一个专属子网
- 按后端类型创建对应的网络设备(比如 vxlan 设备)并写入路由规则
- 持续 watch 其他节点的子网变化,把路由增量同步到本机
在 v0.11.0 中,flanneld 的存储后端同时支持 etcd 和 Kubernetes API。新部署时通常直接走 Kubernetes API,让 flanneld 把子网信息写在集群的节点对象上,省去单独维护一套 etcd 的成本。你在节点上看到的 flanneld 进程参数里,--kube-subnet-mgmt这个开关就是告诉它别去连 etcd,改从 kube-apiserver 读写分配信息。
2.2 为什么 ARM64 要单独出一个包
flanneld 是 Go 写的,理论上可以交叉编译出所有平台的二进制,但发布时每个平台单独打包是更稳妥的做法。ARM64 和 x86_64 的指令集不兼容,一个编译产物不可能通吃两种 CPU。你在一台 aarch64 的服务器上执行 amd64 的 flanneld,直接报 exec format error,连运行的机会都没有。
还有一个容易忽略的点:就算 flanneld 二进制能跑了,容器化部署时镜像也得跟着架构走。v0.11.0 时代镜像 tag 的命名习惯是v0.11.0-arm64这种带架构后缀的方式,而不是用 manifest list 自动匹配。这意味着你在 ARM64 节点上部署 DaemonSet 时,必须确保 yaml 里 image 的 tag 带arm64,否则 kubelet 会从仓库拉一个 amd64 的镜像,节点上跑起来同样是 exec format error,Pod 一直 CrashLoopBackOff。
2.3 v0.11.0 与新版 Flannel 的差异在哪
为什么要强调 v0.11.0 而不是直接用新版?因为如果你手上只有这个包,说明你的部署环境可能比较老,或者因为是离线环境、内网源里只有这个版本。理解它的边界很重要:
- v0.11.0 的默认后端是 VXLAN,UDP 后端仍然存在但性能很差,host-gw 也可以用
- 配置下发主要靠 ConfigMap 里的 net-conf.json,改配置后需要重启 flanneld 才能生效
- 此时 flannel 还不支持后来版本里那些更丰富的指标暴露和链路调试工具
- IPAM 部分用的是内置实现,不会和 Calico 的 IPAM 混用
所以 v0.11.0 的定位很清晰:一个简单、稳定、够用的 Overlay 方案。不加新功能时它可以一直跑,但如果你想上更高级的网络策略,这个版本给不了。
3. 在 ARM64 节点上把 flanneld 跑起来:最小部署步骤与命令
3.1 从获取到校验:别在源头上出错
拿到flannel-v0.11.0-linux-arm64.tar.gz之后,第一件事不是解压,而是校验。发布包一般在同一目录下附带 sha512 校验值,先做完整性校验,避免下载过程中文件被截断或损坏。实践中我遇到过镜像源同步不完整的情况,解压能成功、一执行就段错误,最后花半天才发现包在传输中坏了。
# 下载后先做校验,假设校验文件已放在同一目录 sha512sum flannel-v0.11.0-linux-arm64.tar.gz # 将输出与发布页给出的 SHA512 值逐位比对,一致再继续 # 解压到临时目录 mkdir -p /tmp/flannel-pkg && tar -xzf flannel-v0.11.0-linux-arm64.tar.gz -C /tmp/flannel-pkg # 查看解压内容 ls -lh /tmp/flannel-pkg/ # 正常情况下能看到 flanneld 二进制和少量文本文件sha512sum是 Linux 自带的工具,不需要额外安装。比对哈希这一步在 arm 设备上尤其值得保留,因为 ARM 开发板的存储介质偶尔会出现静默损坏。如果发现校验值不一致,直接删掉重新下载,不要尝试继续安装。
3.2 把 flanneld 放进系统路径并验证可执行
解压之后,常见做法是把 flanneld 放到/opt/bin下,这是 kube-flannel 的 DaemonSet 中 hostPath 挂载的默认位置。如果你手动用 systemd 管理 flanneld,也可以放/usr/local/bin,只要 systemd unit 里的路径对得上就行。接下来要确认这个二进制的架构和版本。
# 将二进制放入约定目录 install -m 0755 /tmp/flannel-pkg/flanneld /opt/bin/flanneld # 确认架构是 aarch64 file /opt/bin/flanneld # 期望输出: ELF 64-bit LSB executable, ARM aarch64 # 确认版本 /opt/bin/flanneld --version # 期望看到 flanneld v0.11.0 相关的版本输出install -m 0755比cp多做了两件事:设置可执行权限、保证属主是 root。aarch64 是 ARM64 在 ELF 格式里的标准标识,看到这个字符串说明包和当前机器匹配。如果file输出里出现 x86-64,那就说明你拿错包了,立即停下部署流程回去重新拉 ARM64 版本。
3.3 用 DaemonSet 方式部署:配置文件与关键参数
生产环境里最常见的做法是使用官方发布页随附的kube-flannel.yml,把它 apply 到集群。这份 manifest 里做了几件关键的事:
- 创建一个名为 kube-flannel-cfg 的 ConfigMap,内容包含 Network 和 Backend 配置
- 定义 flanneld 的 DaemonSet,把
/opt/bin/flanneld挂载进容器,并用 hostNetwork 让 flanneld 直接使用节点网络命名空间 - 给 flanneld 传入
--kube-subnet-mgmt参数,让它使用 Kubernetes API 而不是外部 etcd
在 ARM64 集群上部署时,需要额外确认镜像的 tag 带架构标识。v0.11.0 的 manifest 里镜像 tag 通常是v0.11.0-arm64,如果你拿到的 manifest 里写的是 amd64,直接把 tag 后缀替换掉即可。
# 部署 flannel 到集群 kubectl apply -f kube-flannel.yml # 观察 DaemonSet 是否正常滚动 kubectl -n kube-flannel get pods -o wide # 期望每个节点都有一个 flanneld Pod 处于 Running 状态 # 如果 Pod 一直 ImagePullBackOff,先确认镜像 tag kubectl -n kube-flannel describe pod <flannel-pod-name> | grep -A2 "Events"这里有一个 v0.11.0 特有的细节:如果你的 manifest 是旧版本生成的,它可能在 args 里同时写入了--etcd-endpoints参数,而你的集群又没有独立 etcd 服务。这种情况下 flanneld 会一直尝试连接 etcd 失败,节点永远 NotReady。解决方法是把 args 里和 etcd 相关的参数都去掉,确保只保留--kube-subnet-mgmt或--kubeconfig-file这一类走 Kubernetes API 的参数。
3.4 验证网络是否真的通了
flanneld 启动成功不代表网络就通了,必须做一次实际的跨节点连通性测试。最直接的办法是起两个测试 Pod 分别调度到不同节点,然后在其中一个 Pod 里 ping 另一个 Pod 的 IP。
# 查看节点上 flannel 分配的子网 ip addr show flannel.1 # 期望看到 inet 10.244.x.0/32 或类似地址,x 由实际网段决定 # 查看路由表是否已写入其他节点的子网路由 ip route | grep 10.244 # VXLAN 模式下期望看到通过 flannel.1 设备转发的路由条目 # 在两个不同节点上分别运行测试 Pod,互相 ping 对端 Pod IP kubectl run test-a --image=busybox --restart=Never -- sleep 3600 kubectl run test-b --image=busybox --restart=Never -- sleep 3600 kubectl exec test-a -- ping -c 3 <test-b-pod-ip>在没有独立 etcd、使用--kube-subnet-mgmt的模式下,ip addr show flannel.1能看到当前节点的子网地址,ip route里能看到其他节点的子网路由,这两个现象确认后,跨节点流量才有基础。ping 不通的时候先别急着怀疑 flannel,检查节点防火墙的 FORWARD 链是不是默认 DROP,这是最常见的翻车原因,后面避坑章节细说。
4. 后端类型怎么选:VXLAN、host-gw、UDP 在 ARM 场景的真实取舍
4.1 net-conf.json 里的 Backend 段是唯一的开关
flannel 的后端类型不在启动参数里指定,而是写在网络配置里。在 DaemonSet 部署方式下,这份配置存在于 kube-flannel-cfg 这个 ConfigMap 的 net-conf.json 字段中。v0.11.0 支持三种常用的 Backend:vxlan、host-gw、udp。你改掉 ConfigMap 里的 Type 之后,滚动重启 flanneld Pod 就能让新配置生效。
一个典型的 VXLAN 配置长这样:
{ "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan", "Port": 8472, "VNI": 1, "DirectRouting": false } }这里Network是 Pod 网络的全局网段,每个节点会从这里分到一个/24子网。Port是 VXLAN 报文的 UDP 目标端口,默认 8472,所有节点必须一致。VNI是 VXLAN 网络标识符,同一个二层域里不同 VNI 可以隔离流量,单集群环境保持 1 就行。DirectRouting字段值得单独说:把它设为 true,flannel 会在节点处于同一二层网络时直接走物理路由,不封 VXLAN 头,性能接近 host-gw;跨网段时再退回 VXLAN 封装。
4.2 ARM 场景下 VXLAN 的封装开销不能忽略
ARM64 服务器和开发板一个共同点是 CPU 频率和缓存规模通常不如同代 x86。VXLAN 是软件封装,每个数据包都要经过 UDP 封装和解封装,这部分计算完全吃掉 CPU。在千兆网卡环境下,ARM 节点跑 VXLAN 的 Pod 间带宽大概只有物理带宽的六到七成,小包场景延迟也会明显升高。
这不是 flannel 的问题,任何基于 VXLAN 的方案在 ARM 上都有同样的代价。所以在 ARM 集群里,我一般会先想清楚节点之间的网络拓扑:
- 所有节点在同一二层网络:直接用 host-gw,完全绕开封装开销
- 节点跨三层网段:只能用 vxlan,或者升级网络设备支持 BGP 后换 Calico 的 BGP 模式
- 测试环境、对性能不敏感:vxlan 省心,因为它在三层网络里也能跑
手动把配置从 vxlan 切到 host-gw 的做法,就是修改 ConfigMap 后删掉 flannel Pod 让它重建。切换后flannel.1设备不存在了,路由表变成走物理网卡直接转发。
# 把 net-conf.json 的 Backend.Type 改成 host-gw kubectl -n kube-flannel edit cm kube-flannel-cfg # 删掉 flannel Pod,DaemonSet 会自动拉起新 Pod kubectl -n kube-flannel delete pod -l app=flannel # 验证 vxlan 设备是否消失 ip link show flannel.1 # 期望提示 Device does not exist,说明切换成功 # 验证路由表形态 ip route | grep 10.244 # host-gw 模式下期望看到 via <对端节点IP> dev <物理网卡> 的形式这里有个血泪经验:在物理链路本身不稳定或有环路的环境里,host-gw 的劣势很明显,因为所有跨节点流量直接压在物理网络上,没有隧道隔离。切换之前先确认节点间 ping 延迟正常,否则路由一会通一会断,排查起来比性能差更难受。
4.3 UDP 后端:不要在 ARM 环境里碰它
v0.11.0 里 UDP 后端还能用,它是 flannel 最早期的封装方式,性能比 VXLAN 还差一个量级,因为它走的是用户态封装。我用这个版本在 ARM 开发板上做过一次带宽测试,Pod 间传输只能跑到几十兆,CPU 占用却接近满载。
UDP 后端唯一的价值是在内核不支持 VXLAN 的极老系统上兜底。ARM64 设备上跑的主流内核都已经带 vxlan 模块,这个后端的存在感很低。我在部署时不会主动用 udp,除非遇到modprobe vxlan失败这种极端情况。注意,因为 UDP 后端两端都走用户态转发,MTU 需要留的余量比 VXLAN 还大,具体数值会在避坑章节展开。
4.4 网段和 MTU 的配套调整
不管选哪种 Backend,网络配置里有一个隐藏参数必须跟着调:MTU。物理网卡是 1500 时,VXLAN 要给封装头留空间,Pod 网络的 MTU 设为 1450 比较稳。如果你实际抓包看到分片,再往下调到 1400。
这组数值不是玄学,是给报文头留余量的结果:VXLAN 头加 UDP 头加 IP 头一共 50 字节左右,1500 减掉这段就是 1450。host-gw 不封装,MTU 可以直接保留 1500,这也是它性能好的另一个原因。如果配置里 MTU 写错,最典型的症状是 ping 小包通、但 scp 大文件卡住,因为在 MSS 协商环节出了问题。
5. ARM64 落地避坑:部署 Flannel v0.11.0 的五个高频问题
5.1 镜像 tag 不带架构后缀,Pod 反复 CrashLoopBackOff
现象:kubectl apply 之后,flannel Pod 在 ARM64 节点上一直 ContainerCreating,describe 看到 ImagePullBackOff 或 RunContainerError。
原因:v0.11.0 时代的镜像仓库没有 manifest list 自动选架构的能力。DaemonSet 的 image 如果写flannel:v0.11.0,kubelet 拉下来的是默认的 amd64 镜像,在 aarch64 节点上执行直接报 exec format error。
解决:把镜像 tag 显式改为v0.11.0-arm64,重新 apply。建议同时检查集群节点上的kubernetes.io/arch标签,确认 kubelet 识别到的架构就是 arm64,防止标签错乱导致调度误判。
# 查看节点架构标签 kubectl get nodes --show-labels | grep arch # 如果标签缺失或错误,手动打上 kubectl label node <node-name> kubernetes.io/arch=arm64 --overwrite5.2 flanneld 起不来,日志报 etcd 连接失败
现象:Pod 处于 Running 状态但一直重启,日志里出现Failed to connect to etcd或类似超时信息。
原因:v0.11.0 的默认存储是 etcd。如果你的集群用 kubeadm 搭建并且没有独立 etcd 服务,flanneld 不知道该连谁,就一直卡在初始化阶段。这不是网络问题,是配置里少了一个关键的启动参数。
解决:在 DaemonSet 的 args 里加上--kube-subnet-mgmt,并移除任何--etcd-endpoints参数。改完滚动重启后,日志里出现Subnet added之类信息就正常了。
5.3 Pod 跨节点 ping 不通,但 flanneld 状态正常
现象:节点都 Ready,Pod 也 Running,但在一个 Pod 里 ping 另一个节点的 Pod IP 不通,本节点上的 Pod 互访没问题。
原因:流量出了 Pod 网卡、经过宿主机的 FORWARD 链时被丢了。Kubernetes 默认要求net.ipv4.ip_forward=1,很多系统镜像虽然开了转发,但 iptables 的 FORWARD 策略是 DROP,flannel 的流量恰好经过这条链。
解决:看主机 iptables 默认策略,以及 bridge 相关内核参数。
# 临时放行(重启后失效) iptables -P FORWARD ACCEPT # 持久化配置 sysctl -w net.ipv4.ip_forward=1 sysctl -w net.bridge.bridge-nf-call-iptables=1 echo "net.ipv4.ip_forward=1" >> /etc/sysctl.d/99-flannel.conf echo "net.bridge.bridge-nf-call-iptables=1" >> /etc/sysctl.d/99-flannel.confbridge-nf-call-iptables这个参数影响桥接流量是否经过 iptables。ARM 开发板用的系统镜像经常是裁剪过的,这个值默认是 0,导致 bridge 上的 Pod 流量不匹配任何规则,直接放行不了。两个参数一起设,再配合 FORWARD 策略,跨节点 Pod 通信才能恢复。
5.4 VXLAN 设备创建失败,日志说 module not found
现象:flanneld 日志报错,提示创建 vxlan 设备失败,内核不认识ip-link add vxlan命令。
原因:内核没加载 vxlan 模块。精简版 ARM 内核镜像经常把模块按需加载,而 flannel 启动时系统没有自动帮它做 modprobe。
解决:先手动加载并确认模块存在。
modprobe vxlan lsmod | grep vxlan # 如果 modprobe 失败,说明内核确实没编译该模块,需要换内核或改用 host-gw如果是自编译内核,确认CONFIG_VXLAN被设为 m 或 y。模块加载成功后再重启 flanneld,VXLAN 设备就能创建出来。
5.5 大包不通、小包正常,MTU 背锅
现象:Pod 里 ping 网关通,ping 对端 Pod 通,但传文件一大就卡死,或者 scp 直接中断。
原因:物理链路 MTU 是 1500,VXLAN 封装后实际可用载荷不到 1500。Pod 网络 MTU 如果维持默认的 1500,大包超过承载上限分片后被丢弃,小包没事。
解决:把 net-conf.json 里的 MTU 字段改为 1450,对 host-gw 后端则保持 1500 不动。
{ "Network": "10.244.0.0/16", "MTU": 1450, "Backend": { "Type": "vxlan" } }这个字段加在 Network 旁边,改完记得滚动重启。卡在这条的人不少,因为问题现象很像网线接触不良,容易把排查方向带偏。
6. 一个值得留住的技巧:用 net-conf.json 无损切换后端并量化验证
运行中的 flannel 集群切换后端并不需要重建节点,改 ConfigMap 后滚动重启 flanneld 就能完成。关键在于切换之后的验证方法要高于“能 ping 通”这个层面,否则你无法判断切换到底值不值。
切换完成后,第一件事是看路由形态。VXLAN 模式下,跨节点子网路由走 flannel.1 设备;host-gw 模式下,路由的 dev 变成物理网卡。ip route的输出会直接告诉你当前生效的后端。
第二步是量化性能。在集群里跑一对 iperf3 测试 Pod,分别调度到两个不同节点:
# 在两个节点上分别创建测试 Pod kubectl run iperf-server --image=networkstatic/iperf3 --restart=Never -- -s kubectl run iperf-client --image=networkstatic/iperf3 --restart=Never -- -c <server-pod-ip> -t 30 # 查看测试结果输出,记录带宽值 kubectl logs iperf-client在同样两个节点上,分别记录 VXLAN 和 host-gw 模式下的测速结果。ARM 平台上两者的差距通常非常明显,host-gw 能跑满物理链路带宽,VXLAN 会低一截。如果测下来差距不大,说明你的 CPU 够用,维持 VXLAN 换取跨三层网络的灵活性是划算的。
第三步是回退预案。修改 net-conf.json 前,先把当前内容用kubectl get cm -o yaml存一份副本。切过去发现网络异常,直接 apply 旧配置再滚动重启即可,这是成本最低的后悔药。
我的习惯是:在一台 ARM64 节点上初始化集群时,先默认 VXLAN 跑通全流程,再用这套方法测一轮性能,最后根据网络拓扑决定是否切 host-gw。换后端这件事本身是一条命令,但决定换之前必须用数据说话,别因为某个博客说 host-gw 快就盲目切换,实测结果才是唯一依据。这个流程保存下来,任何新环境上手都能少走弯路,希望帮到你。
本文还有配套的精品资源,点击获取