ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ARM64节点离线部署flannel:从解压到systemd完整实战

ARM64节点离线部署flannel:从解压到systemd完整实战 简介flannel-v0.11.0-linux-arm64.tar.gz 是面向 ARM64 架构编译的 Kubernetes 网络组件包适用于树莓派、鲲鹏或边缘计算节点上的集群环境可帮助运维和开发人员快速部署 flannel 并实现跨主机容器网络互通。由于官方默认发布的多为 amd64 版本在 ARM 设备上常常需要自行编译本版本免去了这一繁杂流程用户直接解压即可运行核心程序。压缩包共 3 个文件flanneld 是网络守护进程负责建立与管理 VXLAN 等后端通道README.md 给出了版本背景、依赖要求和基本使用指引mk-docker-opts.sh 则是用于生成 Docker 环境变量的辅助脚本能够自动将 flannel 子网信息传递给容器引擎让 Pod 网络与 Docker 配置保持一致。整个资源包约 8.03MB单文件部署非常便捷。目前已有 453 人学习下载适合具备基础 K8s 技能、正在为 ARM 集群配置网络插件的人员。利用这套文件可快速获得可执行的 flanneld、环境配置脚本和说明文档免去手动编译的耗时并减少因网段冲突、变量缺失引发的常见故障帮助读者更顺畅地完成集群网络初始化与调试。1. 先别急着解压这个 ARM64 的 flannel 包到底解决什么问题拿到flannel-v0.11.0-linux-arm64.tar.gz这个文件第一反应通常是tar -xzf解压再说。但在一线搞 Kubernetes 集群的人眼里这个包背后是一个很具体的场景你有一批 ARM64 架构的节点比如鲲鹏、飞腾或者树莓派凑的实验集群需要跑 CNI 网络插件给 Pod 打通网络。网上搜到的 flannel 部署教程大多基于amd64直接拿 x86 的二进制往 ARM 机器上扔只会得到一句exec format error。这个 tar 包解决的问题就是你不用在 ARM64 节点上从源码交叉编译 flannel也不用折腾镜像仓库里偶尔缺失的 arm64 镜像 tag。v0.11.0是 flannel 的一个稳定版本CNI 插件机制在 Kubernetes 里是标准接口这个包拆开就是可执行二进制和配置文件。适合的场景很明确离线环境、ARM64 节点、不打算跑 Docker 镜像而是直接以二进制方式托管 flanneld 的场景。我用这个包的时候主要落在两条线上一是给 K3s 或者自建 K8s 的 ARM64 节点补齐网络插件二是在内网环境里没法拉quay.io/coreos/flannel镜像时直接用二进制方式救急。本篇就照着这条落地路径从解压到验证把能抄的步骤和踩过的坑都写出来。注意这个包名里的arm64是处理器架构不是系统发行版后面所有操作都默认你已经在 aarch64 的 Linux 上。2. 解压和校验拿到 tar.gz 后的前 15 分钟决定后面是否翻车解开一个 tar.gz 本身不复杂但在这个包上头 15 分钟做的几件事直接决定 flannel 能不能在目标集群里跑起来。我先说结论先校验再解压解压后不要急着拷贝二进制先看包里的文件清单和属主信息。这样能避免一半以上的“装上了但起不来”的玄学问题。2.1 校验压缩包的完整性sha256 和 tar 列表是两重保险你在内网或镜像站下载的 tar.gz没法保证传输过程中没有损坏或被人动过手脚。没有官方发布的 sha256 校验值时至少先看一眼 tar 包内部结构是否完整。我一般这样做# 1. 查看文件大小和类型确认是 gzip 压缩的 tar 归档 ls -lh flannel-v0.11.0-linux-arm64.tar.gz file flannel-v0.11.0-linux-arm64.tar.gz # 2. 用 gzip 测试完整性-t 只测试不解压 gzip -t flannel-v0.11.0-linux-arm64.tar.gz echo gzip OK # 3. 列出包内文件清单先看清楚有什么 tar -tzf flannel-v0.11.0-linux-arm64.tar.gz逻辑说明file命令能识别出这是gzip compressed data如果是data或者其他未知类型说明下载的其实不是这个包。gzip -t会读取整个压缩流并校验 CRC如果传输过程中有字节丢失这里会直接报unexpected end of file。tar -t则是解出文件列表用来确认包内是不是有flanneld、flannelCNI 插件、README或LICENSE之类的常规文件。参数说明-t是测试模式不解压内容-z告诉 tar 先用 gzip 解压管道再读取-v不是必须的但能显示更详细的文件权限和属主。用-tzf组合时如果你看到类似flanneld的条目再继续下一步。如果命令报错别犹豫重新下载别在这上面浪费时间。提示如果下载源给了.sha256后缀文件用sha256sum -c校验这才是最可靠的完整性和防篡改验证。只有文件名没有校验文件时才用上面这套降级方案。2.2 解压并检查二进制架构file 和 ldd 帮你挡住 90% 的架构坑解压到目标目录后第一件事不是赶紧 chmod x而是确认这个flanneld真的是 arm64 的以及它依赖的动态库在目标系统上存在。Kubernetes 节点上常见的坑是包名写着 arm64但实际是 armv732 位或者反过来。看file输出最直接# 解压到 /opt/flannel保持包内目录结构 mkdir -p /opt/flannel tar -xzf flannel-v0.11.0-linux-arm64.tar.gz -C /opt/flannel cd /opt/flannel # 确认二进制架构和动态链接信息 file flanneld ldd flanneld || true逻辑说明file会打印出类似ELF 64-bit LSB executable, ARM aarch64的字样。只要看到ARM aarch64就说明架构是对的。如果出现ARM, EABI5或Intel 80386那这个包跟你的节点架构根本不匹配直接停手。ldd列出动态库依赖flannel 通常是静态编译或依赖很少的 glibc 库但如果ldd输出里有not found说明你的系统缺少对应运行库最常见的是 64 位系统缺 32 位兼容库或者 musl 和 glibc 混用。参数说明-C指定解压目标目录效果是cd进去再解压能保持包内相对路径。如果包内直接是文件而非目录可以单独先mkdir再解压避免文件散落到当前目录。ldd后面跟|| true是为了防止脚本在非动态链接的二进制上退出码非零导致中断。2.3 把二进制放到标准路径/opt/cni/bin 和 /opt/flannel 的分工flannel 的运行方式有两种作为 CNI 插件调用和作为独立的 flanneld 守护进程。CNI 插件和守护进程是两套东西不能都塞在同一个目录里不区分。常见的目录分工如下表路径存放内容作用/opt/cni/bin/flannelCNI 插件kubelet 创建 Pod 时调用的网络插件/opt/flannel/flanneld守护进程维护 VXLAN 或 host-gw 路由、订阅 etcd/etc/cni/net.d/10-flannel.conflistCNI 网络配置文件让 kubelet 找到 flannel 插件# 如果包内有 flannel 这个 CNI 插件放到标准目录 install -m 0755 flannel /opt/cni/bin/flannel # flanneld 放到 /opt/flannel 或 /usr/local/bin install -m 0755 flanneld /opt/flannel/flanneld # 验证结果 /opt/flannel/flanneld --version || true /opt/cni/bin/flannel --version || true逻辑说明install命令会按指定权限复制文件并自动创建目标目录。flanneld --version能打印编译版本和 go 版本信息这能反向确认你拿到的确实是 v0.11.0。--version参数在 flannel 的早期版本里是支持的如果输出报错说不认识这个参数也能侧面说明版本比预期老。参数说明-m 0755是常规可执行权限属主是当前 root。不要用chmod x替代install因为后续到 systemd 托管时属主和权限位不一致会带来 SELinux 或权限检查的额外麻烦。到这里包已经安全落地接下来要考虑的是让 flannel 真正跑起来。3. 在 ARM64 节点上把 flanneld 跑起来etcd 后端与 CNI 配置缺一不可二进制放在那里不会自己工作。这个版本的 flannel 需要两个先决条件一个能访问的 etcd 集群一份让 kubelet 能调用 CNI 插件的网络配置文件。很多人卡在这一步很久不是 flannel 本身的问题而是把 flannel 的“网络配置写入”和“CNI 调用链”两条逻辑线搞混了。3.1 先决条件一个能通就行的小规模 etcd不必参照生产标准我见过有人在 ARM64 实验集群上先折腾高可用 etcd建了 3 节点证书认证结果 flannel 还没起来。其实这个场景下只要一个单节点的 etcd 能读写就行。如果你有现成的 K8s 集群也可以直接把 etcd 的 endpoint 指过去。一个最小可用的 etcd 启动参数# 单节点 etcdhttp 方式监听 2379方便内网调试 etcd --name flannel-etcd \ --data-dir /var/lib/etcd/flannel.etcd \ --listen-client-urls http://0.0.0.0:2379 \ --advertise-client-urls http://127.0.0.1:2379逻辑说明flannel 会向 etcd 写入/coreos.com/network/config这个 key里面存的是 Network、Backend 等 JSON 配置。flanneld 启动时读取这个 key 决定用 VXLAN 还是 host-gw。--listen-client-urls监听所有接口是为了兼容多网卡节点但advertise-client-urls写成 127.0.0.1 让 flanneld 从本机访问即可。生产环境不要这样裸奔这里的目的只是快速跑通。参数说明--data-dir指定数据目录重启不丢--name是 etcd 节点名。如果你用的是 K8s 里现成的 etcd把 endpoint 填成https://etcd.kube-system.svc:2379那 flannel 需要带证书参数我没有展开写证书生成因为那不是这篇的主角。3.2 flanneld 启动命令指定 etcd endpoint 和网卡是核心flanneld 的参数在不同版本略有差异但 v0.11.0 的几个核心参数是稳定的。我在 ARM64 节点上最常用的启动命令是/opt/flannel/flanneld \ --etcd-endpointshttp://127.0.0.1:2379 \ --ifaceeth0 \ --ip-masq \ --public-ip192.168.1.20 \ --backend-typevxlan \ --kube-subnet-mgrfalse逻辑说明--etcd-endpoints告诉 flanneld 从哪里读配置和写租约--iface指定用于跨节点通信的物理网卡。在多网卡 ARM 板子上不指定--iface最常见的结果是 flannel 选了 docker0 或 br0导致 VXLAN 流量全走错口跨节点 Pod 不通。--ip-masq开启 SNAT否则 Pod 访问外部网络时会丢包。--kube-subnet-mgrfalse表示用 etcd 作为子网管理后端如果设成 trueflannel 会把子网分配交给 Kubernetes API但你这个包对应的集群角色若是独立 etcd就用 false 更直接。参数说明--public-ip一般可以不填flannel 会自动探测。但 ARM 设备上默认路由经常不明确填一个明确的节点 IP 能避免 flannel 选了内网管理口导致 VXLAN 建立不起来。--backend-type直接强制指定后端类型避免依赖 etcd 里那个 JSON 配置没写好导致默认选到udp后端。UDP 后端性能差还在用udp后端的多半是 etcd 里 config 没写 backend 字段。3.3 写 CNI conflist让 kubelet 知道 flannel 网络长什么样flanneld 本身只负责路由和 VXLAN 设备维护真正给 Pod 设置网络命名空间里 veth 和 IP 的是/opt/cni/bin/flannel这个插件。kubelet 通过/etc/cni/net.d/下的配置文件找到它。文件内容如下{ name: flannel, cniVersion: 0.3.1, plugins: [ { type: flannel, delegate: { hairpinMode: true, isDefaultGateway: true } }, { type: portmap, capabilities: {portMappings: true} } ] }逻辑说明外层是一个插件列表第一项 type 为flannel它不会直接创建 veth而是读取/run/flannel/subnet.envflanneld 生成的子网环境文件然后调用bridge插件完成实际工作。delegate 里的hairpinMode和isDefaultGateway会传给 bridge 插件直接影响同节点 Pod 访问 Service 的 NodePort 时是否通。portmap插件用来支持hostPort如果你的工作负载不用 hostPort可以去掉这一段。参数注意如果 bridge 插件不在/opt/cni/bin下flannel 调用会失败。解压这个 tar 包时我没有看到它把bridge这个 CNI 插件打进包里的打算所以你需要额外准备 bridge、loopback 等 CNI 插件。K8s 发行版自带或单独拉containernetworking/pluginsrelease 包补充。这一步漏掉的报错非常隐蔽failed to find plugin bridge指向的问题不是 flannel 本身而是它的 delegate 依赖缺失。3.4 验证 CNI 链路的最短路径手工调用 flannel 插件前先看 subnet.env手工调 CNI 插件比等 kubelet 报错要快得多。通过手动把 CNI 环境变量填好可以直接看到 flannel 插件是否正常调起了 bridge# 查看 flanneld 生成的子网环境文件 cat /run/flannel/subnet.env # 期望输出类似 # FLANNEL_NETWORK10.5.0.0/16 # FLANNEL_SUBNET10.5.1.0/24 # FLANNEL_MTU1450 # FLANNEL_IPMASQtrue逻辑说明FLANNEL_SUBNET是本节点被分配的 Pod CIDRFLANNEL_MTU是 VXLAN 扣除头部后的可用 MTU。如果subnet.env不存在说明 flanneld 没成功向 etcd 申请到子网问题在 flanneld 而不是 CNI 配置。先 ping 一下 etcd 的 endpoint再看 flanneld 日志这是排查顺序的第一步。参数注意FLANNEL_MTU1450是 VXLAN 常见值如果它显示 1500 而你用的是 vxlan 后端那大概率 flanneld 没读到物理网卡的 MTUVXLAN 会因分片丢包。这个细节后面在避坑章里再展开。4. 验证Pod 网络通不通不是看 flanneld 进程而是看路由表和 VXLAN 设备这一章我用最少的命令带你过一遍验证闭环。很多教程让你systemctl status flanneld看到 active 就收工但那个只能说明进程活着不能说明 Pod 间网络是通的。真正的验证要看三层路由表、VXLAN 设备、跨节点连通性。4.1 检查 flannel.1 设备和路由表是否按预期生成# 查看 VXLAN 设备是否存在 ip -d link show flannel.1 # 查看本节点 Pod 网段路由 ip route | grep flannel # 期望看到类似 # 10.5.0.0/16 dev flannel.1 # 10.5.1.0/24 dev cni0逻辑说明flannel.1是 flanneld 创建的 VXLAN 接口cni0是 bridge 插件生成的网桥。路由表里这两行的含义是本节点的 Pod 网段走cni0其他节点的 Pod 网段统一走flannel.1进行 VXLAN 封装。如果只有 cni0 路由而没有 flannel.1 路由说明 flanneld 虽然活着但没有订阅到其他节点的子网信息多半是 etcd 里数据不对或者 flanneld 启动时--iface选错了。4.2 跨节点 Pod 连通性两个节点间用 ping 验证网络最容易出的问题不是单点配置而是两个节点之间配置不对称。我通常在 Node A 上起一个测试 PodNode B 上起一个测试 Pod然后在 A 的 Pod 里 ping B 的 Pod IP# 在任意节点上 kubectl 执行指定测试 Pod kubectl run test-a --imagebusybox --restartNever -- sleep 3600 kubectl run test-b --imagebusybox --restartNever -- sleep 3600 # 进入 test-a 的 Pod 里 ping test-b 的 Pod IP kubectl exec -it test-a -- ping -c 3 test-b-pod-ip逻辑说明Pod IP 通就说明 VXLAN 或 host-gw 链路正常。不通时不要急着查 flannel先分清是同一节点通不通、跨节点通不通。同一节点通但跨节点不通优先怀疑 VXLAN 端口默认 8472被防火墙挡了或者在公有云安全组没放行 UDP 8472。4.3 用 /run/flannel/subnet.env 反向排查 MTU 问题MTU 问题在跨节点 Pod 网络里症状是ping 小包通、大包不通或者curl卡住但ssh正常。这时检查分片情况和 MTU# 查看 flannel.1 和物理网卡的 MTU ip link show flannel.1 ip link show eth0 # 用 ping 指定包大小测试分片情况 ping -M do -s 1472 -c 3 对端Pod IP # 1472 1500 - 28IPICMP 头部如果这个能通而更大包不通MTU 没问题逻辑说明VXLAN 封装会额外增加约 50 字节头部所以物理网卡 MTU 1500 时Pod 内有效 MTU 是 1450。-M do表示禁止分片-s 1472正好是 MTU 1500 下的最大不分片包。如果 1472 通而 1450 设成 1500那可能 flanneld 没有正确配置 MTU导致 Pod 内发包超过 VXLAN 承载能力。参数说明如果物理网卡 MTU 是 9000巨型帧那么subnet.env里的FLANNEL_MTU会相应变化。不要自己手动改这个文件重启 flanneld 会被覆盖。要改 MTU 应该在 etcd 的 flannel 配置 JSON 里写MTU: 1450或者调物理网卡。5. 避坑与排查ARM64 离线环境下最容易踩的 5 个坑这个包在 ARM64 离线环境里的坑很多不是 flannel 本身的问题而是周边环境差异带来的。下面这些是我在实际部署中碰到过、也在网上被反复问到的按“现象 → 原因 → 解决”的格式写。5.1 现象flanneld 启动报 “Failed to find any valid interface”原因ARM 板子上的网络接口命名不是 eth0而是 enp1s0、end0 之类的体系结构相关命名。flanneld 在--iface未指定时找不到默认接口或找到了 lo 接口。解决先用ip link或ip addr确认实际网卡名然后在启动命令里显式指定--ifaceend0。更好的做法是写进 systemd unit 文件里避免每次启动手输。5.2 现象Pod 创建报 “failed to find plugin bridge”原因这个 flannel tar 包只打了 flanneld 和 flannel CNI 插件不含 bridge、loopback 等基础 CNI 插件。kubelet 调用 flannel 插件后委托给 bridge 插件时找不到二进制。解决从 containernetworking 的 plugins release 里下载对应linux-arm64的包把目录下所有二进制释放到/opt/cni/bin/。没有网的环境里先在能联网的机器上拉好一并拷过去。5.3 现象跨节点 Pod 通但访问 NodePort 不通原因kube-ipvs 或 iptables 的 KUBE-IPVS 链在 flannel 网络未完全就绪时写入或者 hairpin 模式未开启。这个跟 flannel 版本关系不大通常是 CNI conflist 里 delegate 段的 hairpin 设置问题。解决在/etc/cni/net.d/的 conflist 里给 delegate 增加hairpinMode: true然后重启 kubelet 和 flanneld。改配置后不需要重启节点删除冲突 Pod 重建即可。5.4 现象ARM64 节点上 flanneld 启动正常但进程退出码 1日志里有 “connection refused” 指向 127.0.0.1:2379原因etcd 没起来或者 etcd 地址没放行。ARM64 板上有时 etcd 被 systemd 限制网络访问IPAddressDeny或者防火墙规则默认丢弃。解决先curl http://127.0.0.1:2379/health确认 etcd 健康接口有响应。然后检查 systemd unit 里的 IPAddressDeny 和 IPTables 规则把 2379 端口的访问放行。这里的排查顺序是从近到远先本机 etcd再跨主机 etcd。5.5 现象包内没有README但网上教程让你先跑make然后你发现根本没有源码原因这是个 release 二进制包不是源码包。有人把它当成从源码编译的 tarball先解压找 Makefile当然找不到。解决认清压缩包的性质。如果你是开发者想改源码需要去 flannel 仓库找v0.11.0的 source tar 包而不是用这个linux-arm64的构建产物。这个包本身就是拿来即用的别再想着编译了。注意如果你是从某些镜像站下载的包解压后记得看一下所有文件的属主。如果属主不是 root在 systemd 以 root 运行时没问题但在非 root 容器里运行 flanneld 会直接权限报错。6. 把 flanneld 交托给 systemdARM64 离线节点上的收尾动作最后一步把 flanneld 放进 systemd 托管做到开机自启、崩溃自动拉起。ARM64 板子经常断电这个收尾非常必要否则每次重启你都要手动跑一遍那条巨长的命令。6.1 写一个最简 systemd unit 文件[Unit] DescriptionFlanneld for ARM64 Kubernetes Node Afternetwork-online.target etcd.service Wantsnetwork-online.target [Service] Typenotify ExecStart/opt/flannel/flanneld \ --etcd-endpointshttp://127.0.0.1:2379 \ --ifaceeth0 \ --ip-masq \ --backend-typevxlan \ --kube-subnet-mgrfalse Restarton-failure RestartSec10 LimitNOFILE65536 [Install] WantedBymulti-user.target逻辑说明Typenotify依赖 flanneld 通过 sd_notify 通知 systemd 已就绪。不过如果你的 flanneld 编译版本不支持 sd_notifysystemd 会一直等待通知直到超时。我碰到过这种情况保险做法是改成Typesimple配合Restarton-failure就可以了。ExecStart里参数与前面手动启动保持一致RestartSec防止频繁崩溃导致 systemd 进入重启风暴。参数注意LimitNOFILE65536是给 flanneld 打开足够多文件描述符的保险。当节点上 Pod 数量超过 300 个时默认的 1024 文件描述符上限会导致too many open files错误。另外Afteretcd.service只在 etcd 在同一台机器时有效如果你的 etcd 在远端节点这段就删掉改用Afternetwork-online.target即可。6.2 启用并验证开机自启# 重新加载 systemd 配置并启用 systemctl daemon-reload systemctl enable flanneld --now # 检查状态和开机自启是否生效 systemctl status flanneld systemctl is-enabled flanneld逻辑说明enable --now是把WantedBymulti-user.target的软链接写入/etc/systemd/system/同时立即启动服务。is-enabled输出enabled就代表开机自启已经生效。到这一步这个 tar 包里的东西才算是真正在 ARM64 节点上“活”下来了。6.3 最后的验证手段断网重启一次我的习惯是验证完所有配置后执行一次reboot并等节点重新加入集群然后确认 flanneld 自动拉起、Pod 网络自动恢复。这个动作虽然简单但能暴露所有依赖顺序的问题。如果重启后 flanneld 没起来查看启动错误时注意时间戳排序journalctl -u flanneld -b会从这次引导开始输出日志比tail老日志更快定位。# 重启后查看本次引导的 flannel 日志 journalctl -u flanneld -b --no-pager | tail -n 50 # 查看 flannel.1 设备是否重新生成 ip link show flannel.1这样一套走完这个flannel-v0.11.0-linux-arm64.tar.gz包在你的 ARM64 节点上就不只是一个解压出来的目录而是一条稳定的 Pod 网络通道。我一开始调这个包的时候吃了不少亏最深的教训就是任何 CNI 组件都不要只看进程活着路由表和 MTU 永远是最先出卖问题的地方。希望这份操作路径能帮你少走这些弯路。本文还有配套的精品资源点击获取
返回列表