
简介这份资源面向在 ARM64 架构服务器、开发板或边缘设备上部署 Kubernetes 集群的运维人员和云原生学习者围绕 flannel v0.11.0 版本提供可落地的网络组件材料主要解决节点间容器网络互通、覆盖网络初始化以及容器运行时参数对接等基础问题。压缩包共 3 个文件整体约 8.03MB内含 flanneld 主程序、说明文档和用于生成 Docker 网络参数的脚本分别承担组件运行、配置查阅与运行时参数生成三类用途体量轻便便于在资源受限环境中快速传输和部署。目前已有 455 人学习或下载。读者可以结合说明文档理解 flannel 的启动参数、网络配置思路与容器运行时对接方式也能在实验集群中复现跨节点通信、排查网络不通等问题适合用作旧版本 flannel 部署、维护和排错时的参考材料。1. flannel v0.11.0 的 arm64 二进制包为什么值得单独留一份在 arm64 集群里装网络插件最烦的不是配置有多复杂而是包不对。源码编译要拖一整条工具链容器镜像在离线环境里又拉不下来最后卡在一个“架构不匹配”的报错上前面调好的 kubelet 参数全白费。手上这个flannel-v0.11.0-linux-arm64.tar.gz就是针对这种场景的现成产物Linux、arm64、v0.11.0三个属性定死了它的适用范围也决定了它不能随便往 x86 节点上扔。它解决的是 Kubernetes 集群 Pod 跨节点通信的底层组网问题适合正在搭 arm64 测试集群、边缘节点或国产化硬件环境的运维和平台开发。下面按“它是什么、怎么跑起来、哪里翻车”的顺序拆开讲。2. 拆包看结构三个二进制和一份 CNI 配置的分工这个压缩包不大但里面的东西各司其职。先弄清楚里面有什么、谁依赖谁再谈部署否则很容易出现“二进制跑起来了但 Pod 还是不通”的玄学问题。v0.11.0 这个版本的功能边界也要先划清它属于 flannel 较成熟的迭代后端支持 host-gw、vxlan、udp、ali-vpc 等配置仍然走 ConfigMap 下发没有后来那些实验性开关。2.1 包内文件与运行时角色解压之后典型会看到三个可执行文件和一份 CNI 配置。不同构建批次文件名可能略有差异但角色固定文件作用部署位置是否常驻flanneld主守护进程负责分配子网、维护路由和 FDB 表/opt/bin/或/usr/local/bin/是systemd 托管mk-docker-opts.sh生成 docker 启动参数仅 docker 场景需要任意 PATH 目录否一次性脚本flannelCNI 插件可执行文件被 kubelet 调用/opt/cni/bin/否按需调用10-flannel.conflistCNI 配置声明插件链和 delegate/etc/cni/net.d/否静态配置容易搞混的是flanneld和flannel前者是“大脑”负责跟 apiserver 打交道、拿集群网段、算本机子网、写路由后者是“手脚”kubelet 创建 Pod 沙箱时调用它它再去问 flanneld 要结果。两者缺一或者版本对不上就会出现 Pod 一直 ContainerCreating、describe里报failed to find plugin flannel之类的现象。2.2 为什么选二进制部署而不是直接用 DaemonSet绝大多数人第一反应是kubectl apply一个官方 yaml 了事。但在 arm64 环境里这套流程经常断在镜像上节点没有外网、私有仓库没同步多架构镜像、镜像 tag 和二进制版本错位。二进制部署的好处是把“网络插件”从容器编排里摘出来变成一个普通的 systemd 服务出问题时systemctl status flanneld和journalctl -u flanneld就能看到全貌不用先exec进容器再折腾。代价是你要自己管四件事CNI 目录、网段参数、后端类型、与 kubelet 的启动顺序。这四件事下面逐个落到命令上。选 v0.11.0 的另一个现实理由是配置项稳定网上流传的net-conf.json写法基本通用不会因为版本差异导致字段被静默忽略。2.3 部署前的环境核对动手前先确认三件事能省掉一半排错时间。第一节点架构确实是 arm64uname -m应输出aarch64第二kubelet 的--network-plugin在较新版本里已经移除CNI 目录要由--cni-conf-dir和--cni-bin-dir指定默认分别是/etc/cni/net.d和/opt/cni/bin第三集群的pod-network-cidr必须和 flannel 配置里的Network一致这个值在kubeadm init时就定死了事后改要动 apiserver 和 controller-manager。# 核对架构与内核模块vxlan 后端依赖内核支持 uname -m lsmod | grep vxlan || modprobe vxlan # 确认 CNI 目录存在且 kubelet 指向它们 ls -ld /etc/cni/net.d /opt/cni/bin ps -ef | grep kubelet | grep -o -- --cni-[a-z-]*[^ ]* # 查看集群初始化时定的 Pod 网段 kubectl cluster-info dump | grep -m1 pod-network-cidr第一段确认硬件和内核能力modprobe vxlan失败说明内核裁剪过得换后端或换内核。第二段把 kubelet 实际使用的目录打出来很多人栽在“二进制拷到了/usr/libexec/cnikubelet 却看/opt/cni/bin”。第三段拿到集群网段后面写配置时直接对齐避免出现节点间路由表里有条目但流量黑洞的情况。3. 从解压到 Pod 互通一份可复现的落地流程这一章是完整的操作链放文件、写配置、起服务、验证连通。每一步都给出可抄的命令并说明失败时先看哪里。流程以 vxlan 后端为主线因为它在跨网段、跨云环境的适应性最好同网段场景可以换 host-gw性能更高但要求二层可达。3.1 放置二进制与 CNI 配置先把包解开按角色分发文件。注意flannel这个 CNI 插件必须放进 kubelet 扫描的目录flanneld放系统 PATH 即可但建议固定到/opt/bin方便 systemd 引用绝对路径。tar -xzf flannel-v0.11.0-linux-arm64.tar.gz -C /tmp/flannel-pkg # 主进程与 CNI 插件分开放职责不混 install -m 0755 /tmp/flannel-pkg/flanneld /opt/bin/flanneld install -m 0755 /tmp/flannel-pkg/flannel /opt/cni/bin/flannel install -m 0755 /tmp/flannel-pkg/mk-docker-opts.sh /opt/bin/mk-docker-opts.sh # CNI 配置落位文件名决定加载顺序10 开头保证靠前 install -m 0644 /tmp/flannel-pkg/10-flannel.conflist /etc/cni/net.d/10-flannel.conflistinstall -m比cp多一层权限控制避免拷过去发现没有执行位。CNI 配置文件名前缀是数字kubelet 按字典序选第一个 conflist所以10-是有意为之如果机器上还残留 calico 的10-calico.conflist两个文件会打架必须先清掉旧插件。10-flannel.conflist的内容一般长这样重点是type要和二进制名一致delegate段决定 IPAM 行为{ name: cbr0, cniVersion: 0.3.1, plugins: [ { type: flannel, delegate: { hairpinMode: true, isDefaultGateway: true } }, { type: portmap, capabilities: { portMappings: true } } ] }cniVersion要低于或等于 kubelet 支持的版本0.3.1 在 v0.11.0 时期是主流。hairpinMode打开后同一个 Pod 内通过 Service 访问自己能通做 sidecar 场景必须开。isDefaultGateway让 flannel 给 Pod 配默认路由不走宿主机转发省一层 NAT。portmap是独立插件负责 hostPort 映射镜像里通常自带没有的话 hostPort 会静默失效。3.2 写 net-conf.json 并启动 flanneldflanneld 的配置有两种来源读 apiserver 里的 ConfigMap或读本地文件。二进制部署用后者更直接配合--kube-subnet-mgrfalse走本地子网管理。配置文件放在/etc/kube-flannel/net-conf.json{ Network: 10.244.0.0/16, Backend: { Type: vxlan, VNI: 1, Port: 8472 } }Network必须和kubeadm init --pod-network-cidr的值完全一致写错会出现“flanneld 正常但 Pod 拿不到 IP”。VNI是 vxlan 的网络标识多集群共用物理网络时要错开否则会串包。Port默认 8472安全组和防火墙要放行 UDP 8472这是最容易漏的一条。接着写 systemd unit关键在启动参数和环境变量[Unit] DescriptionFlanneld overlay address etcd agent Afternetwork-online.target Beforedocker.service kubelet.service [Service] Typenotify EnvironmentFile-/run/flannel/subnet.env ExecStart/opt/bin/flanneld \ --ip-masq \ --kube-subnet-mgrfalse \ --subnet-file/run/flannel/subnet.env \ --public-ip$(hostname -I | awk {print $1}) Restartalways RestartSec5 [Install] WantedBymulti-user.targetBefore保证 flanneld 先于 kubelet 就绪否则 kubelet 启动时 CNI 还没准备好节点会报NetworkPluginNotReady。--ip-masq给出集群的流量做 SNAT不开的话 Pod 访问外网会断。--public-ip在多网卡机器上必须显式指定否则 flanneld 可能选到管理网卡导致 vxlan 隧道建在错误的链路上——这是 arm64 边缘设备上最常见的翻车点之一因为这类设备经常有 WiFi、4G、有线三张网卡。启动并观察systemctl daemon-reload systemctl enable --now flanneld systemctl status flanneld --no-pager journalctl -u flanneld -n 50 --no-pager # 确认子网环境文件已生成 cat /run/flannel/subnet.env正常的subnet.env会长这样FLANNEL_SUBNET是节点专属子网每个节点不同FLANNEL_NETWORK10.244.0.0/16 FLANNEL_SUBNET10.244.1.0/24 FLANNEL_MTU1450 FLANNEL_IPMASQtrue看到FLANNEL_SUBNET就说明 flanneld 已经从大网段里切出了本节点的份额。如果文件不存在先看日志里有没有failed to acquire lease那基本是网段冲突或 apiserver 连接问题。3.3 路由、FDB 与连通性验证flanneld 跑起来只是第一步真正决定通不通的是内核里的路由和邻居表。vxlan 后端的原理是每个节点分配一个/24子网flanneld 把“其他节点的子网 → 对应节点 IP”写成路由再通过 vxlan 设备封装二层帧发出去。# 看 vxlan 设备和路由表应能看到其他节点的 /24 网段 ip -d link show flannel.1 ip route | grep 10.244 # 看 FDBvxlan 靠它把目的 MAC 映射到远端 VTEP bridge fdb show dev flannel.1 | grep -v permanentip -d link show flannel.1输出里的vxlan id 1要和配置的VNI对上。路由表里每个远端节点一条/24via后面是 flannel.1 的地址onlink标志表示下一跳不要求直连。FDB 表里应该有远端节点的 MAC 与dst 节点IP的对应关系这条是动态学习的刚启动时可能为空触发一次跨节点通信后才会出现。验证顺序建议从内到外先在同节点起两个 Pod 互 ping验证 CNI 和网桥再跨节点 ping验证 vxlan 隧道最后测 Service 和出网。# 起两个测试 Pod一个留在本节点一个调度到其他节点 kubectl run nettest-a --imagebusybox --restartNever -- sleep 3600 kubectl run nettest-b --imagebusybox --restartNever -- sleep 3600 kubectl get pod -o wide | grep nettest # 跨节点互 ping 与出网测试 kubectl exec nettest-a -- ping -c 3 nettest-b的PodIP kubectl exec nettest-a -- ping -c 3 8.8.8.8 kubectl exec nettest-a -- nslookup kubernetes.default跨节点 ping 不通时先回到ip route看目的网段有没有对应条目再看 FDB 有没有学到 MAC最后确认 UDP 8472 是否被安全组拦了。出网不通但内网通基本是--ip-masq没开或 iptables 规则被其他组件刷掉了。DNS 解析失败则要检查 kube-dns 的 Service IP 是否落在Network网段内。4. 避坑与排查arm64 环境里最容易翻车的五处这一章的每一条都来自实际踩过的坑按“现象 → 原因 → 解决”组织。arm64 的问题往往不在 flannel 本身而在周边环境的不一致所以排查思路是先证伪外围再怀疑插件。4.1 Pod 一直 ContainerCreating事件里说找不到 flannel 插件现象kubectl describe pod的事件里出现failed to find plugin flannel in path [/opt/cni/bin]节点上flanneld却是 active。原因CNI 插件二进制没放对目录或者放了但没有执行权限另一种情况是 kubelet 的--cni-bin-dir被改过和你放的位置不一致。解决先用ps -ef | grep kubelet确认实际的--cni-bin-dir再把flannel拷过去并chmod 0755。改完不需要重启 kubelet下一次 Pod 创建会重新扫描目录但已经卡住的 Pod 要删掉重建。4.2 跨节点 ping 不通同节点正常现象同节点两个 Pod 互通跨节点 100% 丢包ip route里能看到远端网段条目。原因UDP 8472 被防火墙或安全组拦了或者节点有多张网卡flanneld 选的public-ip不是实际承载 vxlan 的那张隧道包发到了错误链路。解决先tcpdump -i any -n udp port 8472在两端抓包看包有没有出去、有没有回来。只有单向包就是链路或安全组问题。多网卡场景在 unit 里显式写--public-ip承载网IP重启 flanneld 后 FDB 会重新学习。4.3 flanneld 反复重启日志报 lease 获取失败现象journalctl -u flanneld里循环出现failed to acquire lease或network is not ready。原因net-conf.json里的Network和集群pod-network-cidr不一致或者集群里已有其他网络插件占用同一网段或者 apiserver 地址配错flanneld 连不上。解决三处对齐——kubeadm初始化参数、net-conf.json的Network、已存在的 ConfigMap如果走过 DaemonSet 部署残留的kube-flannel-cfg会干扰。确认后清掉/var/run/flannel/subnet.env再重启让 flanneld 重新申请。4.4 Pod 能通但 Service 访问超时现象Pod IP 直连正常访问 ClusterIP 超时nslookup也失败。原因kube-proxy 的 iptables 规则没生效或者hairpinMode没开导致回环流量被丢也可能是Network网段和 Service 网段重叠。解决先iptables -t nat -L KUBE-SERVICES -n看规则是否存在不存在就查 kube-proxy 日志。网段重叠要改service-cidr这属于初始化阶段的问题事后调整成本很高建议部署前就用表格把三个网段列出来核对。4.5 arm64 上二进制报 “Exec format error”现象systemctl start flanneld直接失败日志里是Exec format error。原因包不是 arm64 的或者解压时文件损坏也有一种情况是把 amd64 的包混进了 arm64 节点。解决file /opt/bin/flanneld应显示ELF 64-bit LSB executable, ARM aarch64。对不上就重新获取对应架构的包。顺手sha256sum比对一下传输中断导致的半截文件也会报各种奇怪错误。5. 版本边界与验证习惯把 v0.11.0 用稳的几个技巧v0.11.0 不是新版本用它就得接受它的边界。最实际的一条这个版本的 flanneld 对 Kubernetes 新特性适配有限如果你集群的 kubelet 版本很新CNI 配置里的cniVersion别写太高0.3.1 足够写 0.4.0 反而可能被旧插件拒识。另一个边界是它不带 NetworkPolicy 能力需要策略隔离时得叠 calico 或 cilium别指望 flannel 单独扛。验证习惯上我一般按“三层确认法”走一遍比看日志猜快得多层级检查命令正常特征进程层systemctl is-active flanneldactive且 5 分钟内无重启数据面ip route | grep 10.244、bridge fdb show dev flannel.1每个远端节点一条路由FDB 有动态条目业务面跨节点 Pod 互 ping、ClusterIP 访问、出网三项全通才算部署完成三层里任何一层不过就不要往下走否则问题会叠加排查成本翻倍。还有一个容易被忽略的点节点扩容后老节点上的路由和 FDB 不会自动补齐新节点加入后要在老节点上确认ip route是否多了新网段没有的话重启老节点的 flanneld 触发一次全量同步。# 节点扩容后的快速核对脚本在所有老节点上跑一遍 NEW_NODE_SUBNET10.244.5.0/24 if ! ip route | grep -q $NEW_NODE_SUBNET; then echo missing route to $NEW_NODE_SUBNET, restarting flanneld systemctl restart flanneld sleep 3 ip route | grep $NEW_NODE_SUBNET fi这段脚本把“新节点子网”作为参数检查本机路由表里有没有对应条目没有就重启 flanneld 让它重新 watch 集群状态。sleep 3是给 flanneld 留出同步时间实际环境里如果节点多、apiserver 压力大可以适当放宽到 5 到 10 秒。脚本只做检测和兜底重启不做复杂判断避免引入新的不确定性。最后说一个血泪教训有次在 arm64 边缘设备上部署一切指标正常唯独跨节点偶发丢包查了两天才发现是 MTU。vxlan 封装会多出 50 字节开销FLANNEL_MTU默认 1450但那条链路上有一台设备的 MTU 只有 1400导致大包被静默丢弃小包 ping 完全正常。从那以后我每次部署完都会用大包验证一遍ping -s 1400 -M do通不过就把FLANNEL_MTU调小到链路能承载的值再重启 flanneld 让 CNI 配置重新下发。这个习惯帮我省掉了后面无数次“玄学丢包”的排查。希望帮到你。本文还有配套的精品资源点击获取