边缘集群部署 - 踩坑速查与版本命令

KubeEdge 云-边部署中遇到具体报错(找不到 loopback、service 不通、502、镜像撑爆磁盘、NFS 卡死、ns 删不掉等)时按症状速查

02-部署安装 / 部署方式 / 边缘集群
CNIloopbackkube-proxyKUBE-SVC502by-designparse messageDeviceStatus forbiddendocker image prune镜像大小containerd rootNFS stale handleshowmountnamespace Terminatingquic websocket 互斥kube-flannel CrashLoopBackOff

边缘集群部署 - 踩坑速查与版本命令

按严重程度排序的其它坑,以及常见坑附录、版本命令速查。配合 06-验证与最大坑-label硬编码 的四大坑一起看。

来源:docs/部署/kubeedge部署边缘集群cube-studio.md 第 10 节 + 附录 A/B。


一、其它踩过的坑(按严重程度)

10.1 CNI 插件只有 flannel,缺 loopback/bridge(⭐⭐⭐ 必中)

  • 症状:pod 一直 ContainerCreatingkubectl describe 看到 Events: <none> 但不报错;journalctl -u edgecoreplugin type="loopback" failed (delete): failed to find plugin "loopback" in path [/opt/cni/bin]
  • 原因:keadm join 只放了 flannel 一个 CNI 插件,kubelet 建/拆 pod sandbox 必须要 loopback
  • 修复:装 containernetworking/plugins v1.4.0(见 05 E.6)。

10.2 kube-proxy kubeconfig 默认是"云端私网 IP"(⭐⭐⭐ 必中)

  • 症状:边缘上 iptables-save | grep KUBE-SVC 空无规则;service ClusterIP / external IP / NodePort 在边缘节点本机都不通;但直接 pod IP 能通。
  • 排查:边缘 kube-proxy pod 日志 failed to list *v1.Service: Get "https://172.30.159.159:6443/...": dial tcp ...: i/o timeout
  • 原因:kubeadm 生成的 kube-system/kube-proxy configmap 里 server: 是 apiserver 监听的私网 IP,边缘经公网连不通。
  • 修复:configmap 的 server 改公网 IP(见 05 E.7)。前提是 kubeadm init --apiserver-cert-extra-sans=<公网 IP>

10.3 Cloud → Edge pod 单向不通(⭐⭐ by-design)

  • 症状:云端 istio ingressgateway → Service → edge pod 路由走不通,返回 502。
  • 排查:云端 ip route 里看不到 edge 节点 pod CIDR(如 10.244.1.0/24)的路由;edge flannel 只显示它主动连 cloud 的 VXLAN,cloud flannel 没有回建。
  • 原因:边缘在 NAT 后面,cloud flannel 无法主动建 VXLAN 隧道到边缘。这是 KubeEdge+NAT 边缘的固有限制。
  • 解决方式
    • 不解决:CubeStudio 已为此设计了单独的 <svc>-external Service(externalIPs=[<边缘内网 IP>]),边缘网内用户直接访问 http://<edge-ip>:<nodeport>/ 即可;
    • 要公网访问的话,自己在边缘上加反向代理(nginx / frp)把流量暴出去。

10.4 cloudcore parse message ... resource type not found(⭐ 忽略)

edgecore 上行 lease/status 消息格式 warning,与 pod-sync 无关,忽略即可。

10.5 cloudcore failed to list *v1beta1.DeviceStatus forbidden(⭐ 老环境需补)

旧版 keadm 生成的 ClusterRole 缺 devices.kubeedge.io 权限。修复kubectl apply -f install/kubernetes/kubeedge/20-cloud-rbac.yaml(该文件 ClusterRole 名 cloudcore-extra,补齐相关 CRD 权限)。

10.6 docker image prune -af 会误删正在使用的镜像(⭐ 容易踩)

docker image prune -af 清所有"没有 running container 使用"的镜像。如果把 docker.service 停了再 prune,所有镜像都被认定 idle 一次性全删。

  • 教训:想从 docker 迁移镜像到 containerd k8s.io,要先 docker save | ctr -n k8s.io images import - 流式迁移,停 docker。

10.7 镜像大小预算(⭐ 容易撑爆 /)

docker images 显示的是解压后大小(如 yolo26 25.4 GB),但拉镜像到 containerd 时经历 "download 压缩态(13.5 GB) + unpack 解压到 overlayfs(25 GB)" 两阶段,峰值磁盘需要约 压缩 + 解压(约 38 GB)。

  • 排查/var/lib/containerd 所在分区剩余空间要有单镜像大小 × 2 的余量,df -h / 检查。
  • 修复:如果 / 分区小,把 containerd root dir 搬到大盘后 systemctl restart containerd
    # /etc/containerd/config.toml
    root  = "/data/containerd"
    state = "/data/containerd-state"
    

10.8 edgecore.yaml 的 quic / websocket.enable 互斥

edgecore 启动验证会检查 websocket.enablequic.enable 不能同时为 true。盲用 sed 's/false/true/g' 会让 edgecore 启动失败。修复:用 python 按 YAML 结构定向改(见 05 E.5 脚本)。


二、常见坑附录

A-1 containerd 2.x 的 mirror 不生效

默认启用 Transfer Service 做 pull,它有独立的 config_path。只配 CRI plugin 的 config_path 对 kubelet 拉镜像不够,必须也配 transfer plugin 的 config_path,或者设 use_local_image_pull = true 强制走 CRI plugin(见 03 A.2)。

A-2 Ubuntu 24.04 无 iptables-legacy / firewalld

init_node.shsystemctl stop firewalld iptables ip6tables nftablesUnit not loaded 可忽略。

A-3 GitHub release 下载超时

国内直连 github.com/releases/download/* 几乎必 timeout。替代前缀:gh-proxy.com(本文到处用)、ghproxy.netmirror.ghproxy.com

A-4 NFS showmount -e timeout 但 mount -t nfs 成功

showmount 走 rpcbind 端口 111,mount NFSv4 只要 2049。安全组只开 2049 的话 showmount 会超时,直接 mount 没问题。

A-4b NFS 挂载存活但 ls /data/nfsd?????????(stale handle)

老方案按"边缘出口公网 IP"做 NFS export 白名单,出口 IP 一变(家宽重拨/4G 切换),边缘 NFS 客户端会 hang 成 stale handle,所有依赖 /data/k8s/... 的 pod 报 failed to prepare subPath for volumeMount "kubeflow-user-workspace" 进入 CreateContainerConfigError

现在 export 已改成 *(见 03 Phase B,注意必须用 * 不是 0.0.0.0/0),不会再因 IP 变化失效。若延续了老的 IP 白名单方案又遇到,临时修复:

# 云端
sed -i 's|^/data/nfs <旧IP>|/data/nfs <新IP>|' /etc/exports
exportfs -ra

# 边缘
umount -f -l /data/nfs
mount -t nfs -o vers=4,rsize=1048576,wsize=1048576,hard,timeo=600 \
  <云端公网IP>:/data/nfs /data/nfs

# 云端:重启所有报错的 pod
kubectl get pods -A | grep CreateContainerConfigError | \
  awk '{print "kubectl delete pod -n", $1, $2, "--grace-period=0 --force"}' | bash

A-5 start.sh 脚本 node 名按 IP grep 匹配不到

脚本假设传入的 $1 是内网 IP 且能在 kubectl get node -o wide 输出里匹配到。本场景传的是公网 IP(用于 SERVICE_EXTERNAL_IP),grep 匹配不到,fallback 成"取第一个节点":

node=$(kubectl get node -o name | head -n 1 | sed 's|node/||')

A-6 istio-ingressgateway 没 Service

install/kubernetes/istio/install-1.15.0.yaml 里只有 Deployment 没有 Service,要手动建 ClusterIP + externalIPs(见 04 C.5)。创建后重启 istiod + ingressgateway 让 envoy 拿到 CA + route。

A-7 cloudcore 升级/重装后 ns 卡 Terminating

kubectl delete ns kubeedge 可能因残留 pod finalizer 卡住,强制 finalize:

kubectl get ns kubeedge -o json | \
  python3 -c 'import json,sys;d=json.load(sys.stdin);d["spec"]["finalizers"]=[];print(json.dumps(d))' | \
  kubectl replace --raw /api/v1/namespaces/kubeedge/finalize -f -

A-8 edgecore.yaml 改 enable 别用全局 sed

edgeStream.enablequic.enablewebsocket.enablemetaServer.enable 各有取值约束(websocket.enable=truequic.enable=true 互斥)。用 python 按 YAML 结构局部改,不要 sed -i 's/false/true/g'

A-9 边缘上 kube-flannel-ds / node-exporter CrashLoopBackOff(无害)

  • kube-flannel:边缘 KubeEdge 自己实现网络(不通过 flannel),但 DaemonSet tolerations: Exists 强制把 pod 调度到 edge 节点,pod 起来发现没 cluster CIDR、没法 watch apiserver 就 crash;
  • node-exporter:依赖 hostNetwork + 一些 kernel proc 节点,KubeEdge edge 节点 kubelet socket 路径不一致。

这两个对 CubeStudio 推理流程完全不影响,可忽略。要彻底干净,加 nodeAffinity 排除 edge 节点:

kubectl patch ds kube-flannel-ds -n kube-flannel \
  -p '{"spec":{"template":{"spec":{"affinity":{"nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"node-role.kubernetes.io/edge","operator":"DoesNotExist"}]}]}}}}}}}'
kubectl patch ds node-exporter -n monitoring \
  -p '{"spec":{"template":{"spec":{"affinity":{"nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"node-role.kubernetes.io/edge","operator":"DoesNotExist"}]}]}}}}}}}'

三、版本命令速查

# 云端
kubectl version --short           # v1.28.15
containerd --version              # 2.2.1
nerdctl --version                 # 1.7.6
keadm version                     # v1.23.0(注意上游打包显示可能为 v1.20.0,不影响)

# 边缘
containerd --version              # 1.7.3
keadm version                     # v1.23.0
kubectl get node edge-pc          # v1.32.x-kubeedge-v1.23.0

以上版本为本次部署实录的实际栈,具体以你自己的环境与源码为准。

最后更新 2026-07-04完整文档以官方仓库为准:GitHub Wiki