在Rockchip Arm开发板上构建Docker+K3s+Cilium边缘计算平台
1. 项目概述与核心价值最近在折腾一块基于Rockchip RK3588的Arm开发板想把它打造成一个集轻量级容器编排、安全内网穿透和现代网络管理于一体的边缘计算节点。这个想法听起来有点“缝合怪”但背后的逻辑很清晰在资源受限的边缘设备上我们需要一个既能保证应用隔离与部署效率Docker又能实现跨地域、跨网络的安全组网Tailscale还能提供生产级容器编排能力K3s并且网络性能要足够高效和灵活Cilium的完整方案。这不仅仅是把几个流行工具堆砌在一起而是构建一个面向边缘计算场景的、开箱即用的基础设施层。对于嵌入式开发者、物联网工程师或是喜欢在家搭建Homelab的极客来说在Arm开发板上跑起这套组合拳意味着你可以把这块小小的板子变成一个功能强大的微型数据中心。无论是部署一个家庭媒体服务器集群还是为开发测试环境提供一个隔离的Kubernetes环境甚至是构建一个跨多地的边缘设备管理网络这个方案都提供了一个极具性价比和可玩性的起点。接下来我就把在Rockchip Arm开发板上从零开始搞定Docker、Tailscale、K3s和Cilium的完整过程、踩过的坑以及优化心得毫无保留地分享出来。2. 环境准备与系统调优2.1 硬件与基础系统选型我手头这块板子是Firefly的ROC-RK3588S-PC核心是Rockchip RK3588这是一颗8核4xA76 4xA55的Armv8.2-A处理器性能对于边缘场景绰绰有余。内存我配了16GB LPDDR4存储是一张128GB的A2级别MicroSD卡。这里有个关键点存储性能是整套系统的瓶颈之一。如果你计划频繁进行容器镜像拉取和Pod调度强烈建议使用eMMC模块或者NVMe SSD如果板子支持M.2接口SD卡在长期高IO负载下可能会成为性能短板和寿命担忧。操作系统方面我选择了Ubuntu 22.04 LTS (Jammy Jellyfish) Server版本。为什么不是更轻量的Armbian或Buildroot因为我们需要一个相对完善、软件包丰富的发行版来减少底层依赖的折腾。Ubuntu Server对Arm64的支持已经非常成熟并且其背后的apt软件源能为我们后续安装Docker、Kubernetes相关工具提供极大便利。从Firefly官网下载对应的Ubuntu镜像使用balenaEtcher等工具烧录到SD卡上电启动完成基础的网络配置和用户设置。2.2 系统级优化与内核调整在安装任何软件之前先对系统进行一轮优化这能避免很多后续的玄学问题。首先更新系统并安装一些基础工具包sudo apt update sudo apt upgrade -y sudo apt install -y curl wget git vim htop net-tools jq接下来是关键的内核参数调整。Cilium作为基于eBPF的高性能网络插件对内核版本和配置有要求。虽然Ubuntu 22.04的内核通常是5.15已经包含了对eBPF的良好支持但我们仍需确保一些关键特性被启用。编辑/etc/sysctl.conf文件添加或修改以下参数# 提升网络连接跟踪表大小应对K3s可能产生的大量连接 net.netfilter.nf_conntrack_max 1000000 # 允许IP转发这是容器网络和Tailscale VPN的基石 net.ipv4.ip_forward 1 net.ipv6.conf.all.forwarding 1 # 优化本地端口范围 net.ipv4.ip_local_port_range 1024 65535 # 减少TCP TIME-WAIT状态提升连接复用率 net.ipv4.tcp_tw_reuse 1 # 以下参数对eBPF/Cilium的性能和稳定性有益 net.core.rmem_max 134217728 net.core.wmem_max 134217728 net.core.optmem_max 134217728 kernel.pid_max 4194304保存后执行sudo sysctl -p使配置生效。你可以通过sysctl -a | grep 参数名来检查是否生效。另一个重点是关闭Swap。Kubernetes包括K3s从1.8版本开始就明确要求禁用Swap以保证调度器的行为可预测。虽然有些教程会教你怎么让K3s在开启Swap的情况下运行但那会引入不必要的复杂度。直接关闭它sudo swapoff -a为了防止重启后Swap再次启用需要注释掉/etc/fstab文件中所有包含swap的行。最后检查并确保cgroups的版本。Kubernetes 1.24默认使用cgroups v2。运行stat -fc %T /sys/fs/cgroup/如果返回cgroup2fs说明是v2这是理想状态。如果返回tmpfs你可能需要检查内核启动参数。对于Ubuntu 22.04默认应该就是cgroups v2。3. Docker引擎的安装与配置3.1 安装Docker CE在Arm架构上我们直接使用Docker官方提供的安装脚本是最稳妥的它能自动识别架构并配置正确的软件源。curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh安装完成后将当前用户加入docker组这样就不需要每次都sudo了sudo usermod -aG docker $USER # 需要重新登录或开启新的shell会话才能生效验证安装docker version和docker run --rm hello-world。如果能看到Arm架构的hello-world镜像运行成功说明Docker引擎安装正确。3.2 配置Docker Daemon优化默认的Docker配置可能不适合资源紧张的开发板我们需要进行针对性调整。编辑Docker daemon配置文件/etc/docker/daemon.json如果不存在则创建{ exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 }, storage-driver: overlay2, data-root: /var/lib/docker, iptables: false, live-restore: true, userland-proxy: false, debug: false }这里有几个关键点native.cgroupdriversystemd与系统使用的cgroup驱动保持一致对于使用systemd的Ubuntu这通常是必须的能避免K3s运行时出现cgroup警告。iptables: false这是一个重要的取舍。我们后续会安装Cilium它将完全接管容器网络的iptables规则。如果这里不关闭Docker的iptables管理可能会和Cilium产生规则冲突导致网络不通。这是第一个容易踩坑的地方。userland-proxy: false禁用Docker的userland代理docker-proxy进程。这个进程用于端口映射但会消耗额外的CPU和内存。在Arm开发板上资源宝贵我们可以让内核直接处理通过net.ipv4.ip_forward和后续Cilium/iptables规则关闭它以提升性能。storage-driver确保是overlay2这是目前最推荐且性能较好的存储驱动。修改配置后重启Docker服务sudo systemctl restart docker。再次运行docker info检查Cgroup Driver和iptables等字段是否与配置一致。4. Tailscale的部署与安全组网4.1 安装与登录TailscaleTailscale让我们能轻松建立一个基于WireGuard的加密Mesh网络穿透NAT把分布各处的设备连成一个安全的虚拟局域网。在Arm64设备上安装非常简单curl -fsSL https://tailscale.com/install.sh | sh安装完成后启动Tailscale服务并登录sudo tailscale up执行这条命令后终端会打印出一个认证URL。你需要用浏览器可以在另一台电脑或手机上访问这个URL并用你的Google、GitHub或Microsoft账号登录。登录成功后这台Arm开发板就加入了你的Tailscale网络。验证连接sudo tailscale status。你应该能看到你的设备并分配了一个Tailscale的100.x.x.x网段的IP地址。从网络中的其他Tailscale设备上现在应该能ping通这个Arm板的Tailscale IP了。4.2 配置Tailscale作为K3s的节点IP为了让K3s集群的节点间通信也走Tailscale的安全隧道这对于跨公网的边缘集群至关重要我们需要告诉K3s使用Tailscale分配的IP作为节点的通信地址。首先获取设备的Tailscale IPTAILSCALE_IP$(tailscale ip -4) echo $TAILSCALE_IP记下这个IP例如100.xx.xx.xx。我们会在下一步安装K3s时用到它。另外建议将Tailscale服务设置为开机自启并优化其运行模式sudo systemctl enable --now tailscaled对于资源有限的设备你可以考虑在tailscale up命令中添加--accept-dnsfalse参数如果你不需要Tailscale提供的DNS解析功能这可以节省一点点资源。注意Tailscale的免费版对于个人和小型用途完全足够但需要注意其节点数量限制。如果你的设备需要长期稳定在线确保其网络连接不会频繁中断否则Tailscale可能会认为节点离线。5. K3s轻量级Kubernetes的安装5.1 使用国内镜像源安装K3s ServerK3s是Rancher Labs发布的轻量级Kubernetes发行版非常适合边缘和资源受限环境。由于网络原因直接从Github拉取安装脚本和镜像可能很慢。我们可以使用国内镜像源加速。首先安装K3s的Server节点即控制平面工作节点一体。我们使用以下命令一次性完成安装并配置关键参数# 设置使用国内镜像源 export INSTALL_K3S_MIRRORcn # 指定K3s版本建议使用较新的稳定版 export K3S_VERSIONv1.28.8k3s1 # 使用Tailscale IP作为节点IP和内网通信IP export K3S_NODE_IP$TAILSCALE_IP export K3S_NODE_EXTERNAL_IP$TAILSCALE_IP # 禁用默认的Flannel CNI我们将使用Cilium export INSTALL_K3S_EXEC--flannel-backendnone --disable-network-policy --disabletraefik --disableservicelb # 执行安装脚本 curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | sh -参数解析与避坑指南INSTALL_K3S_MIRRORcn这是最关键的一步能极大提升在国内的下载速度。K3S_NODE_IP和K3S_NODE_EXTERNAL_IP都设置为Tailscale IP。这确保了K3s集群内组件如kubelet、kube-proxy、apiserver都通过Tailscale网络通信实现跨网络组网。--flannel-backendnone --disable-network-policy彻底禁用K3s自带的Flannel CNI和网络策略控制器为安装Cilium扫清障碍。这是第二个关键坑点如果不禁用Cilium和Flannel会冲突。--disabletraefik --disableservicelbK3s默认安装Traefik Ingress Controller和Service LB。我们可以先禁用等Cilium就绪后可以选择安装更灵活的Ingress Controller如nginx-ingress或直接使用Cilium的LB功能。安装完成后K3s服务会自动启动。检查状态sudo systemctl status k3s。5.2 获取Kubeconfig并验证集群安装完成后K3s的kubeconfig文件在/etc/rancher/k3s/k3s.yaml。为了能用kubectl命令管理集群我们需要做两件事将kubeconfig复制到当前用户目录并设置权限mkdir -p ~/.kube sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config sudo chown $USER:$USER ~/.kube/config因为这个kubeconfig默认配置的是访问localhost:6443而我们的apiserver现在监听在Tailscale IP上。需要修改~/.kube/config文件将server:字段的值从https://127.0.0.1:6443改为https://${TAILSCALE_IP}:6443用你的实际IP替换。现在验证集群状态kubectl cluster-info kubectl get nodes -o wide你应该能看到一个Ready状态的节点其INTERNAL-IP就是你设置的Tailscale IP。kubectl get pods -A可以查看所有系统Pod此时由于没有CNIcoredns等Pod会处于Pending或ContainerCreating状态这是正常的。6. Cilium eBPF网络的部署与深度配置6.1 Helm安装CiliumCilium是我们整个网络栈的核心。我们将使用Helm进行安装这样可以灵活配置大量参数。首先安装Helmcurl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg /dev/null echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main | sudo tee /etc/apt/sources.list.d/helm-stable.list sudo apt update sudo apt install helm -y添加Cilium的Helm仓库并更新helm repo add cilium https://helm.cilium.io/ helm repo update在安装之前我们需要根据Arm开发板的环境精心准备一个Helm values配置文件。创建一个名为cilium-values.yaml的文件# cilium-values.yaml operator: replicas: 1 # 为Arm架构指定正确的镜像 image: repository: quay.io/cilium/operator-generic tag: v1.14.8 suffix: digest: # 禁用不需要的功能以节省资源 ipam: mode: kubernetes # 使用Kubernetes Node IP即Tailscale IP作为通信地址 k8sServiceHost: REPlACE_WITH_TAILSCALE_IP k8sServicePort: 6443 # 关键配置Cilium使用正确的接口和路由 devices: eth0 # 如果你的Tailscale虚拟网卡是tailscale0并且希望集群流量也走它可以加上 # devices: eth0,tailscale0 # 但通常我们让Cilium管理物理接口Tailscale IP通过路由表处理 # 启用IPv4 ipv4: enabled: true ipv6: enabled: false # 禁用Hubble可观测性工具以节省资源后续可按需开启 hubble: enabled: false # 设置路由模式对于单节点或同子网节点使用native routingMode: native # 启用KubeProxy替换这是Cilium的核心优势之一 kubeProxyReplacement: strict # 启用主机服务Host Service的负载均衡方便从节点访问ClusterIP hostServices: enabled: true # 启用外部IPs的负载均衡 externalIPs: enabled: true # 启用NodePort服务Cilium将直接处理NodePort流量 nodePort: enabled: true # 配置负载均衡算法Maglev在连接保持和性能上表现较好 loadBalancer: algorithm: maglev # 为Arm架构优化eBPF相关参数 bpf: # 使用legacy主机路由模式兼容性更好 hostRouting: true # 调整Map大小避免内存不足 mapDynamicSizeRatio: 0.0025 # 禁用需要高版本内核的特性5.15内核可能不支持 tproxy: false # 资源限制根据你的板子内存调整 resources: requests: cpu: 100m memory: 200Mi limits: cpu: 500m memory: 512Mi cni: # 配置Cilium作为默认CNI exclusive: true注意将文件中的REPLACE_WITH_TAILSCALE_IP替换为你实际的Tailscale IP地址。6.2 安装Cilium并验证使用Helm安装Ciliumhelm install cilium cilium/cilium --version 1.14.8 \ --namespace kube-system \ -f cilium-values.yaml安装过程可能需要一两分钟因为要拉取Arm架构的Cilium镜像。你可以用kubectl get pods -n kube-system -w来观察Pod启动状态。等到cilium-xxxxxPod显示为Running并且corednsPod也变成Running就基本成功了。运行Cilium的诊断命令来验证安装cilium status --wait如果一切正常你会看到Cilium: OK和KubeProxyReplacement: Strict等字样。再运行kubectl get pods -A所有系统Pod都应该处于Running状态。6.3 关键网络功能测试现在让我们部署一个简单的测试应用验证网络功能是否完整。部署测试Deployment和Servicekubectl create deployment nginx-test --imagenginx:alpine kubectl expose deployment nginx-test --port80 --typeNodePort验证Pod间通信和Service# 获取测试Pod名称 TEST_POD$(kubectl get pods -l appnginx-test -o jsonpath{.items[0].metadata.name}) # 从该Pod内部访问Kubernetes API验证Pod网络 kubectl exec $TEST_POD -- curl -s -I http://kubernetes.default # 获取NodePort端口 NODE_PORT$(kubectl get svc nginx-test -o jsonpath{.spec.ports[0].nodePort}) # 从宿主机开发板上通过Tailscale IP和NodePort访问服务 curl -I http://${TAILSCALE_IP}:${NODE_PORT}如果两条curl命令都返回成功HTTP 200/404等说明Cilium提供的Pod网络、Service包括NodePort都工作正常并且与Tailscale网络集成成功。验证网络策略可选Cilium的强大之处在于其基于eBPF和CIDR/身份的网络安全策略。你可以创建一个策略只允许特定标签的Pod访问nginx-test服务来体验其能力。7. 系统集成、优化与故障排查7.1 组件集成与启动顺序至此Docker、Tailscale、K3s、Cilium四大组件均已就位。理解它们的启动顺序和依赖关系对维护稳定性很重要系统启动加载优化后的内核参数。Tailscale服务 (tailscaled)应作为早期服务启动确保网络连通性。它的systemd单元可以设置Afternetwork-online.target。Docker服务在Tailscale之后启动因为Docker依赖网络环境。K3s服务必须在Docker之后启动因为K3s通过containerd或Docker shim管理容器。K3s的systemd单元里通常有Afterdocker.service如果使用Docker作为运行时。Cilium DaemonSet由Kubernetes在K3s启动后自动调度启动。它依赖于节点的网络就绪。你可以通过systemctl list-dependencies和kubectl get pods -n kube-system --sort-by{.metadata.creationTimestamp}来观察这个顺序。7.2 资源监控与性能调优在资源受限的Arm开发板上监控至关重要。安装一个轻量级的监控栈比如metrics-serverkubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml # 可能需要修改部署参数以适配Arm和自签名证书通常添加--kubelet-insecure-tls参数 kubectl edit deployment metrics-server -n kube-system # 在args部分添加- --kubelet-insecure-tls之后就可以用kubectl top nodes和kubectl top pods查看资源使用情况。针对性能调优Cilium eBPF Map大小如果遇到Cilium日志提示map满可以在cilium-values.yaml中调整bpf.mapDynamicSizeRatio或直接设置bpf.ctGlobalMax等参数但需谨慎避免消耗过多内存。K3s Agent参数如果节点内存小于2GB可以考虑在安装K3s时添加--kubelet-argsystem-reservedmemory200Mi等参数为系统守护进程预留资源。Tailscale ACL如果Tailscale网络内设备很多可以在Tailscale Admin Console中编写ACL访问控制列表减少不必要的广播流量优化性能。7.3 常见问题与排查实录问题一Pod一直处于ContainerCreating状态describe显示“network plugin is not ready”排查首先检查Cilium Pod是否运行正常kubectl get pods -n kube-system -l k8s-appcilium。查看其日志kubectl logs -n kube-system -l k8s-appcilium。可能原因1Cilium启动时无法连接到Kubernetes API。检查cilium-values.yaml中的k8sServiceHost和k8sServicePort是否正确指向了K3s apiserver的Tailscale IP和端口(6443)。可能原因2节点IP配置冲突。确保K3s的K3S_NODE_IP和Cilium识别的节点IP一致。运行kubectl get nodes -o wide和cilium status查看节点IP是否相同。解决核对上述配置重启Cilium Podkubectl delete pods -n kube-system -l k8s-appcilium。问题二通过Tailscale IP无法访问K3s的NodePort服务排查在开发板上执行sudo iptables-save | grep KUBE-NODEPORTS查看Cilium是否成功创建了NodePort规则。也可以检查Cilium的BPF映射表cilium service list。可能原因Cilium的kubeProxyReplacement模式不是strict或者hostServices/nodePort未启用。防火墙可能阻止了Tailscale网卡如tailscale0的流量。解决确认cilium-values.yaml配置正确。检查宿主机防火墙sudo ufw status确保没有阻止相关流量。最简单的方法是暂时禁用防火墙测试sudo ufw disable测试后记得根据安全需求重新配置。问题三系统运行一段时间后内存占用过高排查使用htop或kubectl top命令查看哪个进程或Pod消耗内存最多。可能原因1Cilium的Hubble可观测性功能被启用它会在每个网络包上附加元数据消耗较多内存。如果不需要确保在values文件中hubble.enabled: false。可能原因2K3s的嵌入式SQLite数据库etcd的替代品在频繁写入后可能膨胀。可以定期重启K3s服务sudo systemctl restart k3s来释放内存但这会影响服务。解决对于Cilium禁用Hubble。对于K3s如果内存非常紧张可以考虑使用更轻量的CRI如containerd直接替换Docker并在安装K3s时禁用所有非必需的内置组件。问题四Tailscale连接不稳定时断时续排查在开发板上运行tailscale ping 其他节点IP并查看sudo tailscale status的输出注意是否有延迟或丢包。可能原因开发板所处的网络NAT类型严格或UDP流量被限制。Tailscale基于WireGuardUDP在某些网络环境下可能受限。解决尝试在tailscale up命令中添加--advertise-exit-node或使用中继模式DERP。更根本的方法是优化开发板的网络环境比如使用有线网络代替Wi-Fi或者联系网络管理员开放UDP端口。这套组合方案在Rockchip Arm开发板上跑起来后其稳定性和性能是令人惊喜的。它把一个几百块的开发板变成了一个能够处理复杂容器编排、拥有先进网络能力和安全跨网访问的微型云节点。无论是用于学习Kubernetes和云原生网络还是作为边缘计算的原型平台都提供了一个绝佳的实践环境。在实际部署生产工作负载前务必做好压力测试和长期稳定性运行特别是关注在内存和存储IO方面的表现。